Android开发:点击MotionLayout实现的Carousel轮播卡片全屏效果求助
实现方案
1. 调整MotionScene配置
首先修改你当前引用的@xml/demo_020_carousel_scene文件,新增两组状态和对应的过渡动画:
- 新增
carousel_normal状态:保留你原有的轮播卡片约束、尺寸、边距配置,所有额外详情View的visibility设为gone - 新增
carousel_fullscreen状态:将当前选中卡片的约束修改为匹配父布局宽高,取消边距,额外详情View的visibility设为visible,调整内部元素的位置适配全屏布局 - 新增
normal_to_fullscreen过渡:设置动画时长300-500ms,插值器用DecelerateInterpolator保证平滑效果
对应MotionScene示例代码片段:
<Transition android:id="@+id/normal_to_fullscreen" app:constraintSetStart="@id/carousel_normal" app:constraintSetEnd="@id/carousel_fullscreen" app:duration="400" app:interpolator="android.view.animation.DecelerateInterpolator" />
2. 绑定卡片点击事件
在你的Activity/Fragment中,给所有轮播卡片的根布局(即imageView0到imageView4这几个LinearLayout)设置统一的点击事件,触发逻辑如下:
// 先获取Carousel实例 val carousel = findViewById<Carousel>(R.id.carousel) val motionLayout = findViewById<MotionLayout>(R.id.motion_layout_carousel) // 给每个卡片设置点击事件 listOf(R.id.imageView0, R.id.imageView1, R.id.imageView2, R.id.imageView3, R.id.imageView4).forEach { id -> findViewById<LinearLayout>(id).setOnClickListener { // 判断点击的卡片是否是当前选中的项 val currentPosition = carousel.currentIndex // 适配5个复用卡片的索引映射 val clickedViewIndex = when(id) { R.id.imageView0 -> currentPosition -2 R.id.imageView1 -> currentPosition -1 R.id.imageView2 -> currentPosition R.id.imageView3 -> currentPosition +1 R.id.imageView4 -> currentPosition +2 else -> -1 } if (clickedViewIndex == currentPosition) { // 点击的是当前选中卡片,触发全屏过渡 motionLayout.transitionToState(R.id.carousel_fullscreen) // 过渡期间禁用Carousel滑动,避免冲突 carousel.isEnabled = false // 给当前选中的卡片填充额外的全屏数据 fillFullScreenData(currentPosition) } } }
3. 添加返回逻辑
全屏状态下新增返回普通轮播状态的逻辑即可:
// 监听返回键或者全屏状态下的关闭按钮点击 override fun onBackPressed() { if (motionLayout.currentState == R.id.carousel_fullscreen) { motionLayout.transitionToState(R.id.carousel_normal) // 过渡完成后重新启用Carousel滑动 motionLayout.addTransitionListener(object : MotionLayout.TransitionListener { override fun onTransitionCompleted(motionLayout: MotionLayout?, currentId: Int) { if (currentId == R.id.carousel_normal) { carousel.isEnabled = true motionLayout?.removeTransitionListener(this) } } // 其余回调空实现即可 override fun onTransitionStarted(p0: MotionLayout?, p1: Int, p2: Int) {} override fun onTransitionChange(p0: MotionLayout?, p1: Int, p2: Int, p3: Float) {} override fun onTransitionTrigger(p0: MotionLayout?, p1: Int, p2: Boolean, p3: Float) {} }) return } super.onBackPressed() }
你提供的Carousel布局参考代码
<androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/motion_layout_carousel" android:layout_width="match_parent" android:layout_height="wrap_content" android:visibility="invisible" app:layout_constraintTop_toBottomOf="@+id/player_image_with_elements" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layoutDescription="@xml/demo_020_carousel_scene"> <LinearLayout android:id="@+id/imageView0" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="5dp" android:orientation="vertical" android:scaleType="centerCrop" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/imageView1" app:layout_constraintTop_toTopOf="parent"> <include layout="@layout/match_statistic" android:background="@drawable/layout_rounded" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> <LinearLayout android:id="@+id/imageView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="5dp" android:orientation="vertical" android:scaleType="centerCrop" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/imageView2" app:layout_constraintTop_toTopOf="parent"> <include layout="@layout/match_statistic" android:background="@drawable/layout_rounded" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> <LinearLayout android:id="@+id/imageView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:scaleType="centerCrop" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> <include layout="@layout/match_statistic" android:background="@drawable/layout_rounded" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> <LinearLayout android:id="@+id/imageView3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="5dp" android:orientation="vertical" android:scaleType="centerCrop" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toEndOf="@+id/imageView2" app:layout_constraintTop_toTopOf="parent"> <include layout="@layout/match_statistic" android:background="@drawable/layout_rounded" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> <LinearLayout android:id="@+id/imageView4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="5dp" android:orientation="vertical" android:scaleType="centerCrop" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toEndOf="@+id/imageView3" app:layout_constraintTop_toTopOf="parent"> <include layout="@layout/match_statistic" android:background="@drawable/layout_rounded" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_begin="50dp" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_end="50dp" /> <androidx.constraintlayout.helper.widget.Carousel android:id="@+id/carousel" android:layout_width="wrap_content" android:layout_height="wrap_content" app:carousel_backwardTransition="@+id/backward" app:carousel_firstView="@+id/imageView2" app:carousel_forwardTransition="@+id/forward" app:carousel_nextState="@+id/next" app:carousel_previousState="@+id/previous" app:carousel_touchUpMode="carryVelocity" app:carousel_touchUp_dampeningFactor="0.8" app:constraint_referenced_ids="imageView0,imageView1,imageView2,imageView3,imageView4" /> </androidx.constraintlayout.motion.widget.MotionLayout>
内容的提问来源于stack exchange,提问作者Valentin Cerneanu
相关产品推荐
相关产品推荐

