Merk: Denne artikkelen var basert på versjonen av materialkomponenter 1.2.0-beta01 pr 1. juni 2020 .





I løpet av de tre og et halvt årene jeg jobbet med et lite Android-team på HASHTAGS, er en av de viktigste tingene som motiverer meg til å komme på jobb hver dag, friheten og tilliten fra vårt firma til å takle et problem på den måten vi anser best.



Friheten til å undersøke og utforske mange forskjellige løsninger på et problem vi anser nødvendig, mens vi tar en tidsramme for å levere på produktoppdateringer, gjør at vi kan finne den beste løsningen for både våre kunder og vår programvare.



En slik utfordring innebar å bygge en brukergrensesnittkomponent for vår nye Mobile Reporting-funksjon. Denne nye komponenten var en månedsvelger, som tillot brukerne våre å ramme et datoperiode for en analyserapport.

Startstedet vi valgte var det eksisterende Materialkomponentbibliotek . I stedet for å starte fra bunnen av, vedlikeholdes dette biblioteket aktivt og samsvarer med materialspesifikasjonene. Med dette biblioteket som grunnlag kan vi sannsynligvis redusere mengden logikk vi måtte skrive selv.

I denne artikkelen vil jeg dekke hvordan vi nærmet oss denne prosessen, noen unike faktorer for å bygge Sprout Android-appen, noen få 'gotchas' som kom opp (og ble løst) underveis, og hva du skal vite om du er jobber med et lignende prosjekt.



Introduksjon

Android Material Components 1.1.0 Utgivelse introduserte en ny dato plukker brukergrensesnittkomponent. Et av de velkomne tilleggene til denne nye MaterialDatePicker over AppCompat CalendarView er muligheten til å velge et datoperiode ved hjelp av enten en kalendervisning eller et tekstinntastingsfelt.



Den gamle AppCompat CalendarView var ikke veldig fleksibel. Det var en god komponent for den begrensede brukssaken den var ment å løse; det vil si å velge en enkelt dato og valgfrie minimums- og maksimumsdatoer for å spesifisere et tillatt datointervall.

Den nye MaterialDatePicker ble bygget med mer fleksibilitet for å tillate bruk av utvidet funksjonalitet. Det fungerer gjennom en rekke grensesnitt som man kan implementere for å tilpasse og endre plukkerens oppførsel.



Denne atferdsendringen gjøres på kjøretid gjennom et sett med bygningsmønsterfunksjoner på MaterialDatePicker.Builder klasse.



Dette betyr at vi er i stand til å utvide grunnatferden til dette MaterialDatePicker gjennom komponerbare grensesnittkomponenter.



Merk: Selv om det er en rekke forskjellige komponenter, MaterialDatePicker benytter, i denne artikkelen vil vi bare dekke komponenten for valg av dato.


bibelsk betydning av 444

Valg av datoområde

HASHTAGS Android-teamet var i ferd med å bygge vår Analytics Reports-seksjon.

Denne nye delen lar brukerne våre velge et sett med filtre og et sett med datoperioder som rapporten vil dekke.

MaterialDatePicker kom med noen forhåndsbygde komponenter som vi kunne utnytte for å oppnå brukssaken.

For det vanligste tilfellet vårt, å la brukeren velge et datoperiode, den forhåndsbygde MaterialDatePicker ville være tilstrekkelig:

Med denne kodeblokken får vi en datovelger som lar brukerne velge et datoperiode.

Månedlig datovelger

En av HASHTAGS-rapportene som har mer unikt datovalg, er Twitter Trends Report.

Denne rapporten skiller seg fra de andre ved at i stedet for å tillate noen form for datointervall, håndhever den en enkelt månedsvalg, noe som betyr at en bruker bare kan velge mars 2020 mot 3. mars til 16. mars 2020.

Webappen vår håndterer dette ved å bruke et rullegardinformularfelt:

MaterialDatePicker har ikke en måte å håndheve en slik begrensning med den forhåndsbygde Material Date Range Picker diskutert i forrige avsnitt. Heldigvis ble MaterialDatePicker bygget med komponerbare deler som gjør at vi kan utvide standardadferden for vår spesielle brukssak.

Dato valg oppførsel

MaterialDatePicker utnytter a DateSelector som grensesnittet som brukes for valglogikken til plukkeren.

Fra Javadoc:

“Grensesnitt for brukere av {@link MaterialCalendar} for å kontrollere hvordan kalenderen viser og returnerer valg ... ”

Du vil merke at MaterialDatePicker.Builder.dateRangePicker() returnerer en byggeinstans av RangeDateSelector, som vi brukte i eksemplet ovenfor.

Denne klassen er en forhåndsbygd velger som implementerer DateSelector.

Brainstorming en månedlig valg av datovalg

For vårt brukstilfelle ønsket vi en måte å få brukerne våre til å velge en hel måned som valgt datointervall; f.eks. Mai 2020, April 2020, etc.

Vi trodde at den ferdigbygde RangeDateSelector referert til ovenfor fikk oss det meste av veien dit. Komponenten tillot en bruker å velge et datoperiode og håndheve en bundet .

Det eneste som manglet var en måte å håndheve et utvalg for å automatisk velge hele måneden. Standard oppførsel av RangeDateSelector har brukeren velge startdato og sluttdato.

Vi ønsket atferd slik at når en bruker velger en dag i måneden, velger velgeren automatisk hele måneden som datoperiode.

Løsningen vi bestemte oss for var å utvide RangeDateSelector og overstyr deretter valg av dagvalg for å automatisk velge hele måneden i stedet.

Heldigvis er det en funksjon vi kan overstyre fra grensesnittet DateSelector kalt: select(selection: Long).

Denne funksjonen vil bli påkalt når en bruker velger en dag i plukkeren, med den valgte dagen passert i UTC millisekunder fra epoken.

Implementering av en månedlig oppføringsdato

Implementeringen viste seg å være den enkleste delen, siden vi har en klar funksjon vi kan overstyre for å få den oppførselen vi ønsker.

Den grunnleggende logikken vil være denne:

  1. Bruker velger en dag.
  2. select() funksjon påkalles med den valgte dagen i a Lang UTC millisekunder fra epoken.
  3. Finn den første og siste dagen i måneden fra den gitte dagen gått til oss.
  4. Ring til super.select(1st of month) & super.select(last day of month)
  5. Foreldrenes atferd fra RangeDateSelector skal fungere som forventet, og velg måneden som datoperiode.

Sette alt sammen

Nå som vi har tilpasset MonthRangeDateSelector, kan vi sette opp MaterialDatePicker.

For å ta eksemplet videre kan vi behandle resultatet av valget slik:

Resultatet vil se slik ut:

Gotchas

Det var bare ett hovedproblem som gjorde det vanskelig å komme fram til denne løsningen.

De primære komponentene som ble brukt til å bygge vår MonthRangeDateSelector var klassen RangeDateSelector og grensesnittet DateSelector. Versjonen av biblioteket som ble brukt i denne artikkelen (1.2.0-beta01) begrenset synligheten til disse to filene for å motvirke utvidelse eller implementering av dem.

Som et resultat, selv om vi med hell kunne kompilere den nye MonthRangeDateSelector, viste kompilatoren en veldig skummel advarsel for å motvirke oss fra å gjøre det:

En måte å skjule denne kompilatorvarselen på er å legge til en @Suppress('RestrictedApi') som så:

Denne erfaringen illustrerer hvordan, selv om Material Components Library har levert noen flotte nye komponenter til Android Developer Community, er det fortsatt et pågående arbeid.

En stor del av dette biblioteket er åpenheten for tilbakemeldinger fra Android-fellesskapet! Etter å ha oppdaget denne komponentens siktbegrensning, åpnet jeg en utgave på Github-prosjektet, og til og med åpnet en PR for å ta tak i det med en gang.

Denne åpne tilbakemeldingssløyfen mellom Material Components Team og Android Community gir et godt samarbeid og resultater for alle.

Konklusjon

Den nye MaterialDatePicker har noen gode funksjoner som ikke kommer ut av boksen som sannsynligvis vil dekke de fleste bruksområder for datovalg.

Den beste delen av det over noe som AppCompat CalendarView er imidlertid at det er bygget på en komponerbar måte. Derfor kan den lett utvides og modifiseres for spesifikke bruksområder, mens det ville være mye vanskeligere å oppnå slike ting i CalendarView.

Spesiell takk

Jeg vil trekke frem noen som hjalp fagfellevurderingen av denne artikkelen:

Del Med Vennene Dine: