Carousel — это вспомогательный объект для создания пользовательских карусельных представлений, отображающих список элементов, которые пользователь может просматривать. По сравнению с другими способами реализации таких представлений, этот вспомогательный объект позволяет быстро создавать сложные анимационные и пространственные изменения для вашей Carousel , используя преимущества MotionLayout .
Carousel с пейзажными фотографиями. Виджет Carousel поддерживает списки с началом и концом, а также списки с циклическим переносом элементов.
Как работает карусель с MotionLayout
Предположим, вы хотите создать горизонтальную Carousel выкладку с увеличенным центральным элементом:

Carousel изображений, показывающей увеличенное изображение в центре. Эта базовая структура содержит несколько представлений, отображающих элементы Carousel :

Создайте MotionLayout со следующими тремя состояниями и присвойте им идентификаторы:
- предыдущий
- начинать
- следующий
Если начальное состояние соответствует базовой компоновке, то в предыдущем и следующем состояниях элементы Carousel сдвигаются на один элемент влево и вправо соответственно.
Например, возьмем пять изображений на рисунке 3 и предположим, что в исходном состоянии видны изображения B, C и D, а A и E находятся за пределами экрана. Настроим предыдущее состояние так, чтобы положения A, B, C и D соответствовали положениям B, C, D и E, а изображения перемещались слева направо. В следующем состоянии должно произойти обратное: B, C, D и E переместятся туда, где находились A, B, C и D, а изображения будут перемещаться справа налево. Это показано на рисунке 4:

Carousel . Крайне важно, чтобы элементы в итоге оказались точно там, где начинались исходные элементы. Carousel создает иллюзию бесконечной коллекции элементов, перемещая исходные элементы обратно на прежнее место, но инициализируя их новым соответствующим содержимым. Следующая диаграмма демонстрирует этот механизм. Обратите внимание на значения "номер элемента":

Carousel и сброс состояния.Переходы
Определив эти три набора ограничений в файле сцены движения, создайте два перехода — вперед и назад — между начальным и следующим состояниями, а также между начальным и предыдущим состояниями. Добавьте обработчик 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предыдущего состояния. -
app:carousel_nextState: идентификаторConstraintSetследующего состояния. -
app:carousel_backwardTransition: идентификаторTransition, применяемого между начальным и предыдущим состояниями. -
app:carousel_forwardTransition: идентификаторTransition, применяемого между начальным и следующим состояниями.
Например, в вашем 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 в коде:
Котлин
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"
Примеры
Дополнительные примеры использования вспомогательной функции Carousel можно найти в примерах проектов на GitHub.
