Carousel – это вспомогательный объект движения для создания пользовательских представлений карусели, которые показывают список элементов, которые пользователь может просматривать. По сравнению с другими способами реализации таких представлений, этот помощник позволяет быстро создавать сложные изменения движения и размеров для вашего Carousel, используя преимущества MotionLayout.
Carousel с горизонтальными изображениями.
Виджет Carousel поддерживает списки с началом и концом, а также циклические списки.
Как работает карусель с MotionLayout
Предположим, вы хотите создать горизонтальный вид Carousel с увеличенным центральным элементом:
Carousel, в центре которого показано более крупное изображение.
Этот базовый макет содержит несколько представлений, представляющих элементы Carousel:
Создайте компонент MotionLayout со следующими тремя состояниями и присвойте им идентификаторы:
- предыдущий
- start
- next
Если состояние start соответствует базовому макету, то в состояниях previous и next элементы Carousel сдвигаются на один влево и вправо соответственно.
Например, возьмем пять представлений на рисунке 3 и предположим, что в начальном состоянии представления B, C и D видны, а A и E находятся за пределами экрана. Настройте предыдущее состояние так, чтобы позиции A, B, C и D находились там, где были B, C, D и E, а представления перемещались слева направо. В состоянии next должно произойти обратное: B, C, D и E перемещаются туда, где были A, B, C и D, а представления перемещаются справа налево. Это показано на рисунке 4.
Carousel переходов по пролистыванию.
Важно, чтобы новые представления заканчивались точно там, где начинаются исходные.
Carousel создает иллюзию бесконечной коллекции элементов, перемещая фактические представления обратно туда, где они были, но повторно инициализируя их с новым соответствующим контентом. Этот механизм показан на схеме ниже. Обратите внимание на значения item #.
Carousel переходов между экранами и сбросов состояния.
Переходы
Определив эти три набора ограничений в файле сцены движения, создайте два перехода – вперед и назад – между состояниями start и next, а также между состояниями start и previous. Добавьте обработчик 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, примененный между состояниями start и previous.app:carousel_forwardTransition– идентификаторTransition, применяемый между состояниями start и next.
Например, в 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.