Bemærk: Denne artikel var baseret på Material Components version 1.2.0-beta01 fra 1. juni 2020 .

I mine tre og et halvt år, der arbejder på et lille Android-team hos HASHTAGS, er en af ​​de vigtigste ting, der motiverer mig til at komme på arbejde hver dag, friheden og tilliden fra vores firma til at tackle et problem på den måde, vi finder bedst.

Friheden til at undersøge og udforske mange forskellige løsninger på et problem, som vi finder nødvendigt, mens vi tager højde for en tidsramme til levering af produktopdateringer, gør det muligt for os at finde den bedste løsning til både vores kunder og vores software.

En sådan udfordring involverede opbygning af en UI-komponent til vores nye Mobile Reporting-funktion. Denne nye komponent var en månedsvælger, som tillod vores brugere at udvide et datointerval til en analyserapport.

Startstedet, vi valgte, var det eksisterende Material Components Library . I stedet for at starte fra bunden vedligeholdes dette bibliotek aktivt og stemmer overens med materialespecifikationerne. Med dette bibliotek som fundament kunne vi sandsynligvis reducere den mængde logik, vi selv skulle skrive.

I denne artikel vil jeg dække, hvordan vi nærmede os denne proces, nogle unikke faktorer i opbygningen til Sprout Android-appen, et par 'gotchas', der kom op (og blev løst) undervejs, og hvad man skal vide, hvis du er arbejder på et lignende projekt.

Introduktion

Android Material Components 1.1.0 Udgivelse introducerede en ny Date Picker UI-komponent. En af de velkomne tilføjelser til dette nye MaterialDatePicker over AppCompat CalendarView er muligheden for at vælge et datointerval ved hjælp af enten en kalendervisning eller et tekstinputfelt.

Den gamle AppCompat CalendarView var ikke særlig fleksibel. Det var en god komponent til den begrænsede brugssag, den var beregnet til at løse; det vil sige at vælge en enkelt dato og valgfri minimums- og maksimumdatoer for at angive et tilladt tidsinterval bundet.

Den nye MaterialDatePicker blev bygget med mere fleksibilitet for at tillade brug af udvidet funktionalitet af adfærd. Det fungerer gennem en række grænseflader, som man kunne implementere for at finjustere og ændre plukkerens opførsel.

Denne adfærdsændring udføres ved kørsel gennem et sæt bygmønsterfunktioner på MaterialDatePicker.Builder klasse.

Dette betyder, at vi er i stand til at udvide basisadfærden for dette MaterialDatePicker gennem komponerbare interface-komponenter.

Bemærk: Mens der er en række forskellige komponenter, MaterialDatePicker bruger, i denne artikel vil vi kun dække komponenten til datavalg.

Valg af datointerval

HASHTAGS Android-teamet var i færd med at opbygge vores afdeling for Analytics-rapporter.

Dette nye afsnit giver vores brugere mulighed for at vælge et sæt filtre og et sæt datointervaller, som rapporten dækker.

MaterialDatePicker kom med nogle forudbyggede komponenter, som vi kunne udnytte for at udføre vores brugssag.

For vores mest almindelige tilfælde, hvor brugeren kan vælge et datointerval, den forudbyggede MaterialDatePicker ville være tilstrækkeligt:

Med denne kodeblok får vi en datovælger, der giver brugerne mulighed for at vælge et datointerval.

Månedlig datovælger

En af de HASHTAGS rapporter, der har en mere unik dato, er Twitter Trends Report.

Denne rapport adskiller sig fra de andre ved, at den i stedet for at tillade enhver form for datointerval håndhæver en enkelt måned, hvilket betyder, at en bruger kun kan vælge marts 2020 mod 3. marts til 16. marts 2020.

Vores webapp håndterer dette ved hjælp af et dropdown-formularfelt:

MaterialDatePicker har ikke en måde at håndhæve en sådan begrænsning på med det forudbyggede materiale datointervalvælger diskuteret i det foregående afsnit. Heldigvis blev MaterialDatePicker bygget med komponerbare dele, der giver os mulighed for at udvide standardadfærden til vores særlige brugssag.

Dato valg adfærd

MaterialDatePicker udnytter a DateSelector som grænsefladen, der bruges til udvælgelseslogikken for plukkeren.

Fra Javadoc:

“Interface til brugere af {@link MaterialCalendar} for at kontrollere, hvordan kalenderen viser og returnerer valg ... ”

Du vil bemærke, at MaterialDatePicker.Builder.dateRangePicker() returnerer en bygherreinstans af RangeDateSelector, som vi brugte i eksemplet ovenfor.

Denne klasse er en forudbygget vælger, der implementerer DateSelector.

Brainstorming af en månedlig datoudvælgelsesadfærd

I vores brugssag ønskede vi en måde at få vores brugere til at vælge en hel måned som et valgt datointerval; for eksempel. Maj 2020, April 2020 osv.

Vi troede, at den forudbyggede RangeDateSelector henvist til ovenfor fik os det meste af vejen derhen. Komponenten tillod en bruger at vælge et datointerval og håndhæve et bundet .

Det eneste der manglede var en måde at håndhæve et valg til automatisk at vælge hele måneden. Standardadfærden for RangeDateSelector har brugeren valgt en startdato og en slutdato.

Vi ønskede en adfærd, så når en bruger vælger en dag i måneden, vælger vælgeren derefter automatisk hele måneden som datointerval.

Den løsning, vi besluttede for, var at udvide RangeDateSelector og tilsidesæt derefter valg af dagsvalg for automatisk at vælge hele måneden i stedet.

Heldigvis er der en funktion, vi kan tilsidesætte fra grænsefladen DateSelector kaldet: select(selection: Long).

Denne funktion vil blive påkaldt, når en bruger vælger en dag i plukkeren, med den valgte dag bestået i UTC millisekunder fra epoken.

Implementering af en månedlig datoudvælgelsesadfærd

Implementeringen viste sig at være den enkleste del, da vi har en klar funktion, som vi kan tilsidesætte for at få den adfærd, vi ønsker.

Den grundlæggende logik er denne:

  1. Brugeren vælger en dag.
  2. select() funktion påkaldes med den valgte dag i a Lang UTC millisekunder fra epoken.
  3. Find den første og sidste dag i måneden fra den givne dag, der er sendt til os.
  4. Foretag et opkald til super.select(1st of month) & super.select(last day of month)
  5. Forældrenes adfærd fra RangeDateSelector skal fungere som forventet, og vælg måneden som et datointerval.

Samler det hele

Nu hvor vi har vores brugerdefinerede MonthRangeDateSelector, kan vi konfigurere vores MaterialDatePicker.

For at tage eksemplet videre kan vi behandle resultatet af markeringen sådan:

Resultatet vil se sådan ud:

Gotchas

Der var kun et stort problem, der gjorde det vanskeligt at nå frem til denne løsning.

De primære komponenter, der blev brugt til at bygge vores MonthRangeDateSelector var klassen RangeDateSelector og grænsefladen DateSelector. Den version af biblioteket, der blev brugt i denne artikel (1.2.0-beta01), begrænsede synligheden af ​​disse to filer for at modvirke udvidelse eller implementering af dem.

Som et resultat, selvom vi med succes kunne kompilere vores nye MonthRangeDateSelector, viste compileren en meget skræmmende advarsel for at afskrække os fra at gøre det:

En måde at skjule denne kompilatoradvarsel på er at tilføje et @Suppress('RestrictedApi') ligesom:

Denne erfaring illustrerer, at selvom Material Components Library har leveret nogle fantastiske nye komponenter til Android Developer Community, er det stadig et igangværende arbejde.


hvor mange hashtags kan jeg bruge på instagram

En stor del af dette bibliotek er åbenheden for feedback fra Android Community! Efter at have opdaget denne komponents synlighedsbegrænsning åbnede jeg en problem på Github-projektet og åbnede endda en PR for at adressere det med det samme.

Denne åbne feedbacksløjfe mellem Material Components Team og Android Community skaber godt samarbejde og resultater for alle.

Konklusion

Den nye MaterialDatePicker har noget godt ud af boksen funktionalitet, der sandsynligvis vil dække de fleste anvendelsestilfælde af dato valg.

Den bedste del af det over noget som AppCompat CalendarView er imidlertid, at det er bygget på en komponerbar måde. Derfor kan den let udvides og modificeres til specifikke brugssager, hvorimod det ville være meget sværere at udføre sådanne ting i CalendarView.

Specielt tak

Jeg vil gerne fremhæve nogle mennesker, der har hjulpet peer-review denne artikel: