Carousel
是一个运动辅助对象,用于构建自定义轮播视图,显示用户可以浏览的元素列表。与实现此类视图的其他方式相比,这个辅助对象可让您利用 MotionLayout
快速为 Carousel
创建复杂的运动和尺寸变化。
Carousel
示例。Carousel
微件支持带开始和结束的列表以及循环环绕列表。
带有 MotionLayout 的 Carousel 工作原理
假设您要构建一个水平 Carousel
视图,并使中心项放大

Carousel
示例。此基本布局包含多个视图,这些视图表示 Carousel
项

创建一个具有以下三种状态的 MotionLayout
并为其指定 ID
- previous
- start
- next
如果 start 状态对应于基本布局,则在 previous 状态和 next 状态下,Carousel
项分别向左和向右移动一位。
例如,取图 3 中的五个视图,假设在 start 状态下,视图 B、C 和 D 可见,而 A 和 E 在屏幕外。设置 previous 状态,使 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
辅助对象添加到布局中,并按照您实现 previous 和 next 动画的相同顺序引用视图。
为 Carousel
辅助对象设置以下属性
app:carousel_firstView
:表示Carousel
第一个元素的视图,在此示例中为 C。app:carousel_previousState
:previous 状态的ConstraintSet
ID。app:carousel_nextState
:next 状态的ConstraintSet
ID。app:carousel_backwardTransition
:应用于 start 状态和 previous 状态之间的Transition
ID。app:carousel_forwardTransition
:应用于 start 状态和 next 状态之间的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
中当前“selected”的项,可能需要隐藏表示之前或之后项的视图,以便正确考虑 Carousel
的 start 和 end。 Carousel
辅助对象会自动处理此问题。默认情况下,在这种情况下它会将这些视图标记为 View.INVISIBLE
,因此整体布局不会改变。
还有另一种模式,在这种模式下,Carousel
辅助对象会将这些视图标记为 View.GONE
。您可以使用以下属性设置此模式
app:carousel_emptyViewsBehavior="gone"
示例
有关使用 Carousel 辅助对象的更多示例,请参阅 GitHub 上的示例项目。