Uwaga: ten artykuł dotyczy wersji Material Components 1.2.0-beta01 od 1 czerwca 2020 r .





W ciągu trzech i pół roku pracy w małym zespole Android w HASHTAGS, jedną z głównych rzeczy, która motywuje mnie do codziennego podejmowania pracy, jest wolność i zaufanie naszej firmy do rozwiązywania problemów w sposób, który uznamy za najlepszy.



Swoboda badania i eksplorowania wielu różnych rozwiązań problemu, który uważamy za niezbędny, przy uwzględnieniu ram czasowych na dostarczanie aktualizacji produktów, pozwala nam znaleźć najlepsze rozwiązanie zarówno dla naszych klientów, jak i dla naszego oprogramowania.



Jednym z takich wyzwań było stworzenie komponentu interfejsu użytkownika dla naszej nowej funkcji raportowania mobilnego. Ten nowy komponent był selektorem miesiąca, co pozwoliło naszym użytkownikom określić zakres dat w raporcie analitycznym.

Miejscem wyjścia, które wybraliśmy, było istniejące Biblioteka komponentów materiałów . Zamiast zaczynać od zera, ta biblioteka jest aktywnie utrzymywana i dostosowana do specyfikacji materiałów. Mając tę ​​bibliotekę jako podstawę, prawdopodobnie moglibyśmy zmniejszyć ilość logiki, którą musielibyśmy sami napisać.

W tym artykule opiszę, jak podeszliśmy do tego procesu, kilka wyjątkowych czynników podczas tworzenia aplikacji Sprout na Androida, kilka „usterek”, które pojawiły się (i zostały naprawione) po drodze oraz co warto wiedzieć, jeśli pracuję nad podobnym projektem.



Wprowadzenie

Składniki materiałów dla systemu Android Wersja 1.1.0 wprowadzono nowy składnik interfejsu użytkownika selektora dat. Jeden z mile widzianych dodatków tego nowego MaterialDatePicker przez AppCompat CalendarView to możliwość wybrania zakresu dat przy użyciu widoku kalendarza lub pola tekstowego.



Stary AppCompat CalendarView nie był zbyt elastyczny. Był to dobry komponent w przypadku ograniczonego użycia, który miał rozwiązać; to znaczy wybranie pojedynczej daty i opcjonalnych dat minimalnych i maksymalnych w celu określenia dozwolonego zakresu dat.

Nowy MaterialDatePicker został zbudowany z większą elastycznością, aby umożliwić korzystanie z rozszerzonej funkcjonalności zachowania. Działa poprzez szereg interfejsów, które można by zaimplementować, aby dostosować i zmodyfikować zachowanie selektora.



Ta modyfikacja zachowania jest wykonywana w czasie wykonywania za pomocą zestawu funkcji wzorca konstruktora w MaterialDatePicker.Builder klasa.



Oznacza to, że możemy rozszerzyć podstawowe zachowanie tego MaterialDatePicker poprzez komponowalne komponenty interfejsu.



Uwaga: Chociaż istnieje wiele różnych składników, MaterialDatePicker wykorzystuje, w tym artykule zajmiemy się tylko komponentem wyboru daty.


55555 czyli numerologia

Selektor zakresu dat

Zespół HASHTAGS Android był w trakcie tworzenia sekcji raportów analitycznych.

Ta nowa sekcja umożliwiłaby naszym użytkownikom wybranie zestawu filtrów i zestawu zakresów dat, które obejmowałby raport.

MaterialDatePicker przyszedł z kilkoma gotowymi komponentami, które mogliśmy wykorzystać, aby zrealizować nasz przypadek użycia.

W naszym najczęstszym przypadku, w którym użytkownik może wybrać zakres dat, wbudowany format MaterialDatePicker wystarczy:

Dzięki temu blokowi kodu otrzymujemy selektor dat, który pozwala użytkownikom wybrać zakres dat.

Miesięczny selektor dat

Jednym z raportów HASHTAGS, który ma bardziej unikalny wybór dat, jest raport trendów na Twitterze.

Ten raport różni się od innych tym, że zamiast zezwalać na dowolny zakres dat, wymusza wybór jednego miesiąca, co oznacza, że ​​użytkownik może wybrać tylko marzec 2020 r. W porównaniu z 3 marca do 16 marca 2020 r.

Nasza aplikacja internetowa radzi sobie z tym za pomocą rozwijanego pola formularza:

MaterialDatePicker nie ma sposobu na wymuszenie takiego ograniczenia za pomocą gotowego selektora zakresu dat materiału omówionego w poprzedniej sekcji. Na szczęście MaterialDatePicker został zbudowany z części, które można komponować, co pozwala nam rozszerzyć domyślne zachowanie dla naszego konkretnego przypadku użycia.

Zachowanie przy wyborze daty

MaterialDatePicker wykorzystuje a DateSelector jako interfejs używany do logiki wyboru selektora.

Z Javadoc:

„Interfejs dla użytkowników {@link MaterialCalendar} aby kontrolować sposób wyświetlania i zwracania zaznaczeń w Kalendarzu… ”

Zauważysz, że MaterialDatePicker.Builder.dateRangePicker() zwraca instancję konstruktora RangeDateSelector, której użyliśmy w powyższym przykładzie.

Ta klasa jest gotowym selektorem, który implementuje DateSelector.

Burza mózgów dotycząca miesięcznego wyboru daty

W naszym przypadku chcieliśmy, aby nasi użytkownicy wybrali cały miesiąc jako wybrany zakres dat; na przykład Maj 2020, kwiecień 2020 itd.

Myśleliśmy, że wstępnie skompilowany RangeDateSelector wspomniany powyżej zapewnił nam większość drogi. Komponent pozwolił użytkownikowi wybrać zakres dat i wymusić rozszerzenie uwiązany .

Jedyne, czego brakowało, to sposób na wymuszenie wyboru automatycznego wybierania całego miesiąca. Domyślne zachowanie RangeDateSelector czy użytkownik wybiera datę rozpoczęcia i datę zakończenia.

Chcieliśmy zachować takie zachowanie, aby gdy użytkownik wybierał dzień miesiąca, selektor automatycznie wybierał cały miesiąc jako zakres dat.

Rozwiązaniem, na które zdecydowaliśmy się było rozszerzenie RangeDateSelector a następnie zastąp sposób wybierania dni, aby zamiast tego automatycznie wybierał cały miesiąc.

Na szczęście jest funkcja, którą możemy nadpisać z poziomu interfejsu DateSelector zadzwoniono: select(selection: Long).

Ta funkcja zostanie wywołana, gdy użytkownik wybierze dzień w selektorze, a wybrany dzień zostanie przekazany w milisekundach UTC od epoki.

Wdrażanie miesięcznego zachowania wyboru daty

Implementacja okazała się najprostsza, ponieważ mamy jasną funkcję, którą możemy nadpisać, aby uzyskać pożądane zachowanie.

Podstawowa logika będzie taka:

  1. Użytkownik wybiera dzień.
  2. select() funkcja jest wywoływana z wybranym dniem w pliku Długo Milisekundy UTC od epoki.
  3. Znajdź pierwszy i ostatni dzień miesiąca z podanego nam dnia.
  4. Zadzwoń do super.select(1st of month) & super.select(last day of month)
  5. Zachowanie rodzica z RangeDateSelector powinien działać zgodnie z oczekiwaniami, a jako zakres dat wybierz miesiąc.

Kładąc wszystko razem

Teraz, gdy mamy nasze własne MonthRangeDateSelector, możemy skonfigurować nasze MaterialDatePicker.

Aby rozwinąć przykład, możemy przetworzyć wynik wyboru w następujący sposób:

Wynik będzie wyglądał następująco:

Gotchas

Był tylko jeden poważny problem, który utrudniał osiągnięcie tego rozwiązania.

Podstawowe komponenty użyte do zbudowania naszego MonthRangeDateSelector były klasą RangeDateSelector i interfejs DateSelector. Wersja biblioteki użytej w tym artykule (1.2.0-beta01) ograniczyła widoczność tych dwóch plików, aby zniechęcić do ich rozszerzania lub wdrażania.

W rezultacie, chociaż mogliśmy pomyślnie skompilować nasz nowy MonthRangeDateSelector, kompilator pokazał bardzo przerażające ostrzeżenie, aby nas od tego zniechęcić:

Jednym ze sposobów ukrycia tego ostrzeżenia kompilatora jest dodanie @Suppress('RestrictedApi') tak:

To doświadczenie pokazuje, że chociaż biblioteka składników materiałów dostarczyła społeczności programistów Androida kilka świetnych nowych składników, nadal trwają prace.

Dużą częścią tej biblioteki jest otwartość na opinie społeczności Androida! Po odkryciu tego ograniczenia widoczności komponentu otworzyłem plik kwestia w projekcie Github, a nawet otworzył plik PR aby od razu się tym zająć.

Ta otwarta pętla opinii między zespołem Material Components a społecznością Androida zapewnia doskonałą współpracę i wyniki dla wszystkich.

Wniosek

Nowy MaterialDatePicker ma świetną funkcjonalność, która prawdopodobnie obejmie większość przypadków użycia wyboru daty.

Jednak najlepszą częścią tego w przypadku czegoś takiego jak AppCompat CalendarView jest to, że jest zbudowany w sposób umożliwiający kompozycję. Dlatego można go łatwo rozszerzyć i zmodyfikować pod kątem konkretnych przypadków użycia, podczas gdy znacznie trudniej byłoby osiągnąć takie rzeczy w CalendarView.

Szczególne podziękowania

Chciałbym zwrócić uwagę na kilka osób, które pomogły w recenzowaniu tego artykułu:

Podziel Się Z Przyjaciółmi: