Ontdek Uw Aantal Engel
Engineering bij Sprout: een Android-maandkiezer bouwen
Opmerking: dit artikel was gebaseerd op de versie van Material Components 1.2.0-beta01 vanaf 1 juni 2020
In mijn drieënhalf jaar werken in een klein Android-team bij HASHTAGS, is een van de belangrijkste dingen die me motiveren om elke dag aan het werk te komen, de vrijheid en het vertrouwen van ons bedrijf om een probleem aan te pakken op de manier die we het beste achten.
De vrijheid om veel verschillende oplossingen te onderzoeken en te verkennen voor een probleem dat we nodig achten, terwijl we rekening houden met een tijdsbestek voor het leveren van productupdates, stelt ons in staat om de beste oplossing te vinden voor zowel onze klanten als onze software.
Een van die uitdagingen was het bouwen van een UI-component voor onze nieuwe Mobile Reporting-functie. Deze nieuwe component was een maandkiezer, waardoor onze gebruikers een datumbereik konden bepalen voor een analyserapport.
De startplaats die we kozen was de bestaande Materiaalcomponentenbibliotheek In plaats van helemaal opnieuw te beginnen, wordt deze bibliotheek actief onderhouden en afgestemd op de materiaalspecificaties. Met deze bibliotheek als basis kunnen we waarschijnlijk de hoeveelheid logica verminderen die we zelf zouden moeten schrijven.
In dit artikel zal ik bespreken hoe we dit proces hebben aangepakt, enkele unieke factoren bij het bouwen voor de Sprout Android-app, een paar 'valstrikken' die onderweg naar voren kwamen (en werden opgelost) en wat u moet weten als u werken aan een soortgelijk project.
Invoering
De Android-materiaalcomponenten 1.1.0 vrijgave introduceerde een nieuwe UI-component voor Datumkiezer. Een van de welkome toevoegingen van deze nieuwe MaterialDatePicker via de AppCompat CalendarView is de mogelijkheid om een datumbereik te selecteren met behulp van een kalenderweergave of een tekstinvoerveld.
De oude AppCompat CalendarView was niet erg flexibel. Het was een goede component voor de beperkte gebruikscasus die het moest oplossen; dat wil zeggen, het selecteren van een enkele datum en optionele minimum- en maximumdatums om een toegestaan datumbereik op te geven.
De nieuwe MaterialDatePicker is gebouwd met meer flexibiliteit om het gebruik van uitgebreide functionaliteit van gedrag mogelijk te maken. Het werkt via een reeks interfaces die men zou kunnen implementeren om het gedrag van de kiezer aan te passen en aan te passen.
Deze gedragswijziging wordt tijdens runtime uitgevoerd via een set van builderpatroonfuncties op de MaterialDatePicker.Builder klasse.
Dit betekent dat we het basisgedrag van deze MaterialDatePicker kunnen uitbreiden via samenstelbare interfacecomponenten.
Opmerking: hoewel er een aantal verschillende componenten zijn, is de MaterialDatePicker gebruikt, behandelen we in dit artikel alleen de component Datumselectie.
engelennummers 88
Datumbereikkiezer
Het HASHTAGS Android-team was bezig met het opbouwen van onze sectie Analytics-rapporten.
In dit nieuwe gedeelte kunnen onze gebruikers een reeks filters en een reeks datumbereiken selecteren die in het rapport worden behandeld.
Het MaterialDatePicker werd geleverd met een aantal vooraf gebouwde componenten die we konden gebruiken om onze use-case te bereiken.
Voor ons meest voorkomende geval, waarbij een gebruiker een datumbereik kan selecteren, is de voorgebouwde MaterialDatePicker zou voldoende zijn:
Met dit codeblok krijgen we een datumkiezer waarmee gebruikers een datumbereik kunnen selecteren.
Maandelijkse datumkiezer
Een van de HASHTAGS-rapporten met een meer unieke datumselectie is het Twitter Trends-rapport.
Dit rapport verschilt van de andere doordat het in plaats van elk soort datumbereik toe te staan, een selectie van één maand afdwingt, wat betekent dat een gebruiker alleen maart 2020 versus 3 maart tot 16 maart 2020 kan selecteren.
Onze web-app regelt dit door een dropdown-formulierveld te gebruiken:
Het MaterialDatePicker heeft geen manier om een dergelijke beperking af te dwingen met de vooraf gebouwde materiaaldatumbereikkiezer die in de vorige sectie is besproken. Gelukkig is MaterialDatePicker gebouwd met samenstelbare onderdelen waarmee we het standaardgedrag voor ons specifieke gebruik kunnen uitbreiden.
Datum selectie gedrag
Het MaterialDatePicker maakt gebruik van een DateSelector als de interface die wordt gebruikt voor de selectielogica van de picker.
Van de Javadoc:
“Interface voor gebruikers van {@link MaterialCalendar} om te bepalen hoe de kalender selecties weergeeft en retourneert ... '
U zult zien dat de MaterialDatePicker.Builder.dateRangePicker() geeft een builder-instantie van RangeDateSelector terug, die we in het bovenstaande voorbeeld hebben gebruikt.
Deze klasse is een vooraf gebouwde selector die DateSelector implementeert.
Brainstormen over een maandelijks datumselectiegedrag
Voor ons geval wilden we een manier om onze gebruikers een hele maand te laten selecteren als een geselecteerd datumbereik; bijv. Mei 2020, april 2020, enz.
We dachten dat de voorgebouwde RangeDateSelector waarnaar hierboven wordt verwezen, bracht ons daar het grootste deel van de weg. Met de component kon een gebruiker een datumbereik selecteren en een gebonden
Het enige dat ontbrak, was een manier om een selectie af te dwingen om de hele maand automatisch te selecteren. Het standaardgedrag van RangeDateSelector laat de gebruiker een startdatum en een einddatum selecteren.
We wilden een gedrag zodat wanneer een gebruiker een dag in de maand selecteert, de kiezer automatisch de hele maand als datumbereik selecteert.
De oplossing die we hebben gekozen, was om de RangeDateSelector en overschrijf vervolgens het dagselectiegedrag om in plaats daarvan automatisch de hele maand te selecteren.
Gelukkig is er een functie die we kunnen overschrijven via de interface DateSelector genaamd: select(selection: Long).
Deze functie wordt aangeroepen wanneer een gebruiker een dag in de kiezer selecteert, waarbij de geselecteerde dag is verstreken in UTC milliseconden vanaf het tijdperk.
Een maandelijks datumselectiegedrag implementeren
De implementatie bleek het eenvoudigste deel te zijn, aangezien we een duidelijke functie hebben die we kunnen overschrijven om het gewenste gedrag te krijgen.
De basislogica zal deze zijn:
- Gebruiker selecteert een dag.
- Het
select()functie wordt aangeroepen met de geselecteerde dag in een Lang UTC milliseconden vanaf het tijdperk. - Zoek de eerste en laatste dag van de maand vanaf de opgegeven dag die aan ons is verstreken.
- Bel naar
super.select(1st of month) - Het oudergedrag van
super.select(last day of month)zou moeten werken zoals verwacht, en selecteer de maand als datumbereik.
Alles bij elkaar
Nu we onze Custom RangeDateSelector hebben, kunnen we onze MonthRangeDateSelector instellen.
Om het voorbeeld verder te zetten, kunnen we het resultaat van de selectie als volgt verwerken:
Het resultaat ziet er als volgt uit:
Gotchas
Er was slechts één groot probleem dat het moeilijk maakte om tot deze oplossing te komen.
De primaire componenten die zijn gebruikt om onze MaterialDatePicker waren de klas MonthRangeDateSelector en de interface RangeDateSelector. De versie van de bibliotheek die in dit artikel wordt gebruikt (1.2.0-beta01) beperkte de zichtbaarheid van deze twee bestanden om uitbreiding of implementatie ervan te ontmoedigen.
Als gevolg hiervan, hoewel we met succes onze nieuwe DateSelector konden compileren, liet de compiler een zeer enge waarschuwing zien om ons ervan te weerhouden dit te doen:
Een manier om deze compilerwaarschuwing te verbergen, is door een MonthRangeDateSelector zo:
Deze ervaring illustreert hoe, hoewel de Material Components Library een aantal geweldige nieuwe componenten aan de Android Developer Community heeft geleverd, er nog steeds aan wordt gewerkt.
Een groot deel van deze bibliotheek is de openheid voor feedback van de Android-community! Nadat ik deze beperking van de zichtbaarheid van het onderdeel had ontdekt, opende ik een kwestie op het Github-project en zelfs een PR om het meteen aan te pakken.
Deze open feedbacklus tussen het Material Components-team en de Android-community zorgt voor geweldige samenwerking en resultaten voor iedereen.
Gevolgtrekking
De nieuwe @Suppress('RestrictedApi') heeft een aantal geweldige kant-en-klare functionaliteit die waarschijnlijk de meeste gevallen van datumselectie zal dekken.
Het beste van iets als de AppCompat CalendarView is echter dat het op een samenstelbare manier is gebouwd. Daarom kan het gemakkelijk worden uitgebreid en aangepast voor specifieke gebruikssituaties, terwijl het veel moeilijker zou zijn om dergelijke dingen te bereiken in de MaterialDatePicker.
Speciale dank
Ik wil graag enkele mensen uitlichten die hebben geholpen bij het beoordelen van dit artikel:
- Nick Rout ( Github
- Mike Wolfson ( Github
- Ryan Phillips ( LinkedIn
- Lucas Moellers ( Github
- Met Patel ( LinkedIn
Deel Het Met Je Vrienden: