Carousel
は、ユーザーがスクロールできる要素のリストを表示するカスタム カルーセル ビューを構築するためのモーション ヘルパー オブジェクトです。このようなビューを実装する他の方法と比較して、このヘルパーを使用すると、MotionLayout
を利用して Carousel
の複雑なモーションとディメンションの変更をすばやく作成できます。
Carousel
の例。Carousel
ウィジェットは、開始と終了のあるリストと、循環型のラップアラウンド リストをサポートしています。
MotionLayout を使用したカルーセルの仕組み
中央のアイテムが拡大された水平方向の Carousel
ビューを作成するとします。

Carousel
の例。この基本レイアウトには、Carousel
アイテムを表す複数のビューが含まれています。

次の 3 つの状態を持つ MotionLayout
を作成し、ID を付与します。
- 前へ
- start
- 次へ
開始状態がベース レイアウトに対応している場合、前の状態と次の状態では、Carousel
項目がそれぞれ 1 つ左と右にシフトします。
たとえば、図 3 の 5 つのビューを考えます。開始状態では、ビュー B、C、D が表示され、A と E は画面外にあるとします。A、B、C、D の位置が B、C、D、E の位置になるように、前の状態を設定します。ビューは左から右に移動します。次の状態では、B、C、D、E が A、B、C、D のあった場所に移動し、ビューが右から左に移動するという、逆の処理が行われる必要があります。これらを図 4 に示します。

Carousel
スワイプ遷移。
ビューが元のビューの開始位置と正確に一致することが重要です。Carousel
は、実際のビューを元の位置に戻し、新しい一致するコンテンツで再初期化することで、要素の無限コレクションの錯覚を生み出します。次の図は、このメカニズムを示しています。(「item #」の値に注意してください)。

Carousel
スワイプの遷移と状態のリセット。
切り替え効果
モーション シーン ファイルで定義された 3 つの制約セットを使用して、start 状態と next 状態の間、および start 状態と previous 状態の間に、順方向と逆方向の 2 つのトランジションを作成します。次の例に示すように、ジェスチャーに応じてトランジションをトリガーする OnSwipe
ハンドラを追加します。
<Transition
motion:constraintSetStart="@id/start"
motion:constraintSetEnd="@+id/next"
motion:duration="1000"
android:id="@+id/forward">
<OnSwipe
motion:dragDirection="dragLeft"
motion:touchAnchorSide="left" />
</Transition>
<Transition
motion:constraintSetStart="@+id/start"
motion:constraintSetEnd="@+id/previous"
android:id="@+id/backward">
<OnSwipe
motion:dragDirection="dragRight"
motion:touchAnchorSide="right" />
</Transition>
カルーセルを追加する
この基本的なモーション シーンを作成したら、レイアウトに Carousel
ヘルパーを追加し、前後のアニメーションを実装するのと同じ順序でビューを参照します。
Carousel
ヘルパーに次の属性を設定します。
app:carousel_firstView
:Carousel
の最初の要素を表すビュー(この例では C)。app:carousel_previousState
: 前の状態のConstraintSet
ID。app:carousel_nextState
: 次の状態のConstraintSet
ID。app:carousel_backwardTransition
: 開始状態と前の状態の間で適用されるTransition
ID。app:carousel_forwardTransition
: 開始状態と次の状態の間に適用されるTransition
ID。
たとえば、レイアウト XML ファイルに次のような記述があるとします。
<androidx.constraintlayout.motion.widget.MotionLayout ... >
<ImageView android:id="@+id/imageView0" .. />
<ImageView android:id="@+id/imageView1" .. />
<ImageView android:id="@+id/imageView2" .. />
<ImageView android:id="@+id/imageView3" .. />
<ImageView android:id="@+id/imageView4" .. />
<androidx.constraintlayout.helper.widget.Carousel
android:id="@+id/carousel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:carousel_forwardTransition="@+id/forward"
app:carousel_backwardTransition="@+id/backward"
app:carousel_previousState="@+id/previous"
app:carousel_nextState="@+id/next"
app:carousel_infinite="true"
app:carousel_firstView="@+id/imageView2"
app:constraint_referenced_ids="imageView0,imageView1,imageView2,imageView3,imageView4" />
</androidx.constraintlayout.motion.widget.MotionLayout>
コードで Carousel
アダプタを設定します。
Kotlin
carousel.setAdapter(object : Carousel.Adapter { override fun count(): Int { // Return the number of items in the Carousel. } override fun populate(view: View, index: Int) { // Implement this to populate the view at the given index. } override fun onNewItem(index: Int) { // Called when an item is set. } })
Java
carousel.setAdapter(new Carousel.Adapter() { @Override public int count() { // Return the number of items in the Carousel. } @Override public void populate(View view, int index) { // Populate the view at the given index. } @Override public void onNewItem(int index) { // Called when an item is set. } });
その他の注意事項
Carousel
で現在「選択」されている項目によっては、Carousel
の開始と終了を正しく考慮するために、前後の項目を表すビューを非表示にする必要がある場合があります。Carousel
ヘルパーはこれを自動的に処理します。デフォルトでは、このような状況ではビューが View.INVISIBLE
としてマークされるため、レイアウト全体は変わりません。
Carousel
ヘルパーがビューを View.GONE
としてマークする代替モードもあります。このモードは、次のプロパティを使用して設定できます。
app:carousel_emptyViewsBehavior="gone"
例
カルーセル ヘルパーを使用したその他の例については、GitHub のサンプル プロジェクトをご覧ください。