Carousel
— это вспомогательный объект движения для создания пользовательских представлений карусели, которые показывают список элементов, которые пользователь может просмотреть. По сравнению с другими способами реализации таких представлений, этот помощник позволяет быстро создавать сложные изменения движения и размеров для вашей Carousel
, используя преимущества MotionLayout
.
Виджет Carousel
поддерживает списки с началом и концом, а также циклические списки.
Как работает карусель с MotionLayout
Предположим, вы хотите создать горизонтальную 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
создает иллюзию бесконечной коллекции элементов, перемещая фактические представления обратно туда, где они были, но повторно инициализируя их с новым соответствующим содержимым. На следующей диаграмме показан этот механизм. Обратите внимание на значения «item #»):
Переходы
Используя эти три набора ограничений, определенные в файле сцены движения, создайте два перехода — вперед и назад — между начальным и следующим состояниями, а также начальным и предыдущим состояниями. Добавьте обработчик 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. } })
Ява
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.