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
создаёт иллюзию бесконечной коллекции элементов, возвращая представления на прежнее место, но при этом заново инициализируя их новым соответствующим содержимым. Этот механизм показан на следующей диаграмме. Обратите внимание на значения «item #»:

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. } })
Ява
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.