天使の数を見つけてください
Sproutでのエンジニアリング:Androidの月のピッカーの構築
注:この記事は、マテリアルコンポーネントバージョンに基づいています 1.2.0-beta01 現在 2020年6月1日 。
HASHTAGSで小さなAndroidチームで働いていた3年半の間に、私が毎日仕事に就く動機の1つは、私たちが最善と考える方法で問題に取り組む自由と信頼です。
製品のアップデートを提供するための時間枠を考慮しながら、必要と思われる問題に対するさまざまなソリューションを調査および調査する自由により、お客様とソフトウェアの両方に最適なソリューションを見つけることができます。
そのような課題の1つは、新しいモバイルレポート機能のUIコンポーネントを構築することでした。この新しいコンポーネントは月のピッカーであり、ユーザーは分析レポートの日付範囲を指定できました。

私たちが選んだ出発点は既存のものでした 材料コンポーネントライブラリ 。このライブラリは、最初から始めるのではなく、積極的に維持され、材料の仕様に準拠しています。このライブラリを基盤として、自分で作成する必要のあるロジックの量を減らすことができる可能性があります。
この記事では、このプロセスにどのように取り組んだか、Sprout Androidアプリを構築する際のいくつかの固有の要因、途中で発生した(そして修正された)いくつかの「落とし穴」、およびあなたが同様のプロジェクトに取り組んでいます。
前書き
Androidマテリアルコンポーネント 1.1.0リリース 新しい日付ピッカーUIコンポーネントが導入されました。この新しいMaterialDatePicker
の歓迎すべき追加の1つAppCompat上CalendarView
カレンダービューまたはテキスト入力フィールドのいずれかを使用して日付の範囲を選択する機能です。
古いAppCompatCalendarViewはあまり柔軟性がありませんでした。これは、解決することを目的とした限られたユースケースに適したコンポーネントでした。つまり、単一の日付とオプションの最小および最大日付を選択して、許可される日付範囲の範囲を指定します。
新しいMaterialDatePickerは、動作の拡張機能を使用できるように、より柔軟に構築されました。これは、ピッカーの動作を微調整および変更するために実装できる一連のインターフェースを介して機能します。
この動作の変更は、実行時にMaterialDatePicker.Builder
上の一連のビルダーパターン関数を介して行われます。クラス。
これは、このMaterialDatePicker
の基本的な動作を拡張できることを意味します。構成可能なインターフェースコンポーネントを介して。
注:さまざまなコンポーネントがありますが、MaterialDatePicker
を利用して、この記事では日付選択コンポーネントのみを取り上げます。
3はどういう意味ですか
日付範囲ピッカー
HASHTAGS Androidチームは、アナリティクスレポートセクションを作成中です。
この新しいセクションでは、ユーザーがレポートの対象となる一連のフィルターと一連の日付範囲を選択できるようになります。


MaterialDatePicker
ユースケースを達成するために活用できるいくつかのビルド済みコンポーネントが付属しています。
最も一般的なケースでは、ユーザーが日付の範囲を選択できるようにするために、事前に作成されたMaterialDatePicker
十分でしょう:
このコードブロックを使用すると、ユーザーが日付範囲を選択できる日付ピッカーを取得できます。

毎月の日付ピッカー
よりユニークな日付選択があるハッシュタグレポートの1つは、Twitterトレンドレポートです。
このレポートは、他のレポートとは異なり、任意の種類の日付範囲を許可する代わりに、1か月の選択を強制します。つまり、ユーザーは2020年3月と2020年3月3日から3月16日までしか選択できません。
私たちのウェブアプリは、ドロップダウンフォームフィールドを使用してこれを処理します。

MaterialDatePicker
前のセクションで説明したビルド済みの材料日付範囲ピッカーを使用して、このような制限を適用する方法はありません。幸い、MaterialDatePickerは、特定のユースケースのデフォルトの動作を拡張できる構成可能なパーツで構築されています。
日付選択動作
MaterialDatePicker
DateSelector
を活用しますピッカーの選択ロジックに使用されるインターフェースとして。
Javadocから:
「{@link MaterialCalendar}
のユーザー向けのインターフェースカレンダーの表示方法と選択範囲の返送方法を制御するには…」
MaterialDatePicker.Builder.dateRangePicker()
に気付くでしょう上記の例で使用したRangeDateSelector
のビルダーインスタンスを返します。
このクラスは、DateSelector
を実装するビルド済みのセレクターです。
毎月の日付選択行動のブレインストーミング
私たちのユースケースでは、ユーザーが選択した日付範囲として1か月全体を選択できるようにする方法が必要でした。例えば2020年5月、2020年4月など。
事前に構築されたRangeDateSelector
と思いました上で参照したところ、ほとんどの方法でそこにたどり着きました。このコンポーネントにより、ユーザーは日付範囲を選択して、 バウンド 。
欠けていたのは、月全体を自動選択するための選択を強制する方法だけでした。 RangeDateSelector
のデフォルトの動作ユーザーに開始日と終了日を選択させます。
ユーザーが月の日を選択すると、ピッカーが月全体を日付範囲として自動選択するような動作が必要でした。

私たちが決めた解決策は、RangeDateSelector
を拡張することでした。次に、日の選択動作をオーバーライドして、代わりに月全体を自動選択します。
幸いなことに、インターフェースからオーバーライドできる関数がありますDateSelector
呼び出された:select(selection: Long)
。
この関数は、ユーザーがピッカーで日を選択したときに呼び出され、選択した日はエポックからUTCミリ秒で渡されます。
毎月の日付選択動作の実装
実装は最も単純な部分であることが判明しました。これは、必要な動作を取得するためにオーバーライドできる明確な関数があるためです。
基本的なロジックは次のとおりです。
- ユーザーが日を選択します。
select()
関数は、で選択された日に呼び出されます 長いです エポックからのUTCミリ秒。- 私たちに渡された特定の日から月の最初と最後の日を見つけます。
super.select(1st of month)
に電話をかけます&super.select(last day of month)
RangeDateSelector
からの親の動作期待どおりに機能するはずであり、日付範囲として月を選択します。
すべてを一緒に入れて
カスタムMonthRangeDateSelector
ができたので、MaterialDatePicker
を設定できます。
例をさらに進めるために、次のように選択の結果を処理できます。
結果は次のようになります。

ガッチャ
この解決策にたどり着くのを困難にした大きな問題が1つだけありました。
MonthRangeDateSelector
の構築に使用される主要コンポーネントクラスでしたRangeDateSelector
およびインターフェースDateSelector
。この記事で使用されているライブラリのバージョン(1.2.0-beta01)は、これら2つのファイルの可視性を制限し、それらの拡張または実装を阻止しました。
その結果、新しいMonthRangeDateSelector
を正常にコンパイルできましたが、コンパイラーは非常に恐ろしい警告を表示して、コンパイルを思いとどまらせました。

このコンパイラ警告を非表示にする1つの方法は、@Suppress('RestrictedApi')
を追加することです。そのようです:

この経験は、マテリアルコンポーネントライブラリがAndroidデベロッパーコミュニティにいくつかの優れた新しいコンポーネントを提供したにもかかわらず、それがまだ進行中の作業であることを示しています。
このライブラリの大部分は、Androidコミュニティからのフィードバックに対するオープン性です。このコンポーネントの可視性の制限を発見した後、私は 問題 Githubプロジェクトで、さらには PR すぐに対処します。
マテリアルコンポーネントチームとAndroidコミュニティの間のこのオープンなフィードバックループは、すべての人に素晴らしいコラボレーションと結果をもたらします。
結論
新しいMaterialDatePicker
日付選択のほとんどのユースケースをカバーする可能性が高い、すぐに使用できる優れた機能がいくつかあります。
ただし、AppCompat CalendarViewのようなものよりも優れている点は、構成可能な方法で構築されていることです。したがって、特定のユースケースに合わせて簡単に拡張および変更できますが、CalendarView
でそのようなことを実現するのははるかに困難です。
特別な感謝
この記事の査読に協力してくれた人々に焦点を当てたいと思います。
友達と共有してください: