Nota: questo articolo era basato sulla versione dei componenti del materiale 1.2.0-beta01 come di 1 giugno 2020 .



Nei miei tre anni e mezzo di lavoro in un piccolo team Android presso HASHTAGS, una delle cose principali che mi motiva a entrare nel mondo del lavoro ogni giorno è la libertà e la fiducia della nostra azienda nell'affrontare un problema nel modo che preferiamo.



La libertà di ricercare ed esplorare molte soluzioni diverse a un problema che riteniamo necessario, tenendo conto di un periodo di tempo per fornire gli aggiornamenti del prodotto, ci consente di trovare la soluzione migliore sia per i nostri clienti che per il nostro software.





Una di queste sfide consisteva nella creazione di un componente dell'interfaccia utente per la nostra nuova funzione di reporting mobile. Questo nuovo componente era un selettore di mese, che consentiva ai nostri utenti di definire un intervallo di date per un rapporto di analisi.

Il punto di partenza che abbiamo scelto era l'esistente Libreria dei componenti dei materiali . Piuttosto che partire da zero, questa libreria viene mantenuta attivamente e si allinea con le specifiche del materiale. Con questa libreria come base, potremmo probabilmente ridurre la quantità di logica che dovremmo scrivere da soli.

In questo articolo, tratterò come ci siamo avvicinati a questo processo, alcuni fattori unici nella creazione dell'app Sprout per Android, alcuni 'trucchi' che sono emersi (e sono stati risolti) lungo il percorso e cosa sapere se sei lavorando su un progetto simile.



introduzione

I componenti del materiale Android Versione 1.1.0 introdotto un nuovo componente dell'interfaccia utente di selezione data. Una delle gradite aggiunte di questo nuovo MaterialDatePicker su AppCompat CalendarView è la possibilità di selezionare un intervallo di date utilizzando una visualizzazione calendario o un campo di immissione testo.



Il vecchio AppCompat CalendarView non era molto flessibile. Era un buon componente per il caso d'uso limitato che avrebbe dovuto risolvere; ovvero selezionando una singola data e date minime e massime facoltative per specificare un limite di intervallo di date consentito.

Il nuovo MaterialDatePicker è stato creato con maggiore flessibilità per consentire l'uso di funzionalità di comportamento estese. Funziona attraverso una serie di interfacce che è possibile implementare per modificare e modificare il comportamento del selettore.



Questa modifica del comportamento viene eseguita in fase di esecuzione tramite una serie di funzioni del pattern builder su MaterialDatePicker.Builder classe.



Ciò significa che siamo in grado di estendere il comportamento di base di questo MaterialDatePicker attraverso componenti di interfaccia componibili.



Nota: sebbene siano presenti diversi componenti, i MaterialDatePicker utilizza, in questo articolo tratteremo solo il componente di selezione della data.

Selettore intervallo di date

Il team Android di HASHTAGS stava creando la nostra sezione dei rapporti di analisi.

Questa nuova sezione consentirebbe ai nostri utenti di selezionare una serie di filtri e una serie di intervalli di date che il rapporto dovrebbe coprire.

Il MaterialDatePicker è stato fornito con alcuni componenti predefiniti che potremmo sfruttare per realizzare il nostro caso d'uso.

Per il nostro caso più comune, consentendo a un utente di selezionare un intervallo di date, il pre-costruito MaterialDatePicker sarebbe sufficiente:

Con questo blocco di codice, otteniamo un selettore di date che consente agli utenti di selezionare un intervallo di date.

Selezione data mensile

Uno dei report HASHTAGS che ha una selezione di date più unica è il Twitter Trends Report.

Questo rapporto differisce dagli altri in quanto invece di consentire qualsiasi tipo di intervallo di date, applica una selezione di un solo mese, il che significa che un utente può selezionare solo marzo 2020 rispetto al 3 marzo al 16 marzo 2020.

La nostra app web gestisce questo utilizzando un campo modulo a discesa:

Il MaterialDatePicker non dispone di un modo per applicare tale restrizione con il Selettore intervallo date materiale predefinito discusso nella sezione precedente. Fortunatamente, MaterialDatePicker è stato costruito con parti componibili che ci consentono di espandere il comportamento predefinito per il nostro caso d'uso particolare.

Comportamento di selezione della data

Il MaterialDatePicker sfrutta un DateSelector come interfaccia utilizzata per la logica di selezione del picker.

Dal Javadoc:

“Interfaccia per utenti di {@link MaterialCalendar} per controllare come il calendario visualizza e restituisce le selezioni ... '

Noterai che MaterialDatePicker.Builder.dateRangePicker() restituisce un'istanza del builder di RangeDateSelector, che abbiamo usato nell'esempio sopra.

Questa classe è un selettore predefinito che implementa DateSelector.

Brainstorming su un comportamento di selezione della data mensile

Per il nostro caso d'uso, volevamo un modo per far selezionare ai nostri utenti un intero mese come intervallo di date selezionato; per esempio. Maggio 2020, aprile 2020, ecc.

Abbiamo pensato che il pre-costruito RangeDateSelector a cui si fa riferimento sopra ci ha portato quasi a destinazione. Il componente consentiva a un utente di selezionare un intervallo di date e di applicare un limite .

L'unica cosa che mancava era un modo per imporre una selezione per la selezione automatica dell'intero mese. Il comportamento predefinito di RangeDateSelector fa selezionare all'utente una data di inizio e una data di fine.

Volevamo un comportamento in modo che quando un utente seleziona un giorno del mese, il selettore selezionerà automaticamente l'intero mese come intervallo di date.

La soluzione che abbiamo deciso è stata di estendere il RangeDateSelector e quindi sovrascrivi il comportamento di selezione del giorno per selezionare automaticamente l'intero mese.

Fortunatamente, esiste una funzione che possiamo sovrascrivere dall'interfaccia DateSelector chiamato: select(selection: Long).

Questa funzione verrà richiamata quando un utente seleziona un giorno nel selettore, con il giorno selezionato trascorso in millisecondi UTC dall'epoca.

Implementazione di un comportamento di selezione della data mensile

L'implementazione si è rivelata la parte più semplice, poiché abbiamo una funzione chiara che possiamo sovrascrivere per ottenere il comportamento che vogliamo.

La logica di base sarà questa:

  1. L'utente seleziona un giorno.
  2. Il select() la funzione viene invocata con il giorno selezionato in a Lungo Millisecondi UTC dall'epoca.
  3. Trova il primo e l'ultimo giorno del mese dal giorno in cui ci è passato.
  4. Effettua una chiamata a super.select(1st of month) & super.select(last day of month)
  5. Il comportamento genitore da RangeDateSelector dovrebbe funzionare come previsto e selezionare il mese come intervallo di date.

Mettere tutto insieme

Ora che abbiamo il nostro Custom MonthRangeDateSelector, possiamo impostare il nostro MaterialDatePicker.

Per prendere ulteriormente l'esempio, possiamo elaborare il risultato della selezione in questo modo:

Il risultato sarà simile a questo:

Trabocchetti

C'era solo un grosso problema che rendeva difficile arrivare a questa soluzione.

I componenti primari utilizzati per costruire il nostro MonthRangeDateSelector erano la classe RangeDateSelector e l'interfaccia DateSelector. La versione della libreria utilizzata in questo articolo (1.2.0-beta01) limitava la visibilità di questi due file, per scoraggiarne l'estensione o l'implementazione.

Di conseguenza, anche se abbiamo potuto compilare con successo il nostro nuovo MonthRangeDateSelector, il compilatore ha mostrato un avvertimento molto spaventoso per scoraggiarci dal farlo:

Un modo per nascondere questo avviso del compilatore è aggiungere un @Suppress('RestrictedApi') così:

Questa esperienza illustra come, anche se la libreria dei componenti dei materiali ha fornito alcuni ottimi nuovi componenti alla comunità degli sviluppatori Android, è ancora un lavoro in corso.


significato biblico di 444

Una parte importante di questa libreria è l'apertura al feedback della community Android! Dopo aver scoperto questa limitazione della visibilità dei componenti, ho aperto un file problema sul progetto Github e ha persino aperto un file PR per affrontarlo subito.

Questo ciclo di feedback aperto tra il team di Material Components e la community Android genera grande collaborazione e risultati per tutti.

Conclusione

Il nuovo MaterialDatePicker ha alcune ottime funzionalità pronte all'uso che probabilmente copriranno la maggior parte dei casi d'uso della selezione della data.

Tuttavia, la parte migliore di qualcosa come AppCompat CalendarView è che è costruito in modo componibile. Pertanto, può essere facilmente esteso e modificato per casi d'uso specifici, mentre sarebbe molto più difficile realizzare tali cose nel CalendarView.

Ringraziamenti speciali

Vorrei evidenziare alcune persone che hanno contribuito alla revisione tra pari di questo articolo: