MotionLayout滑动视图时TextView行数异常变化的问题求助
问题描述
我用MotionLayout实现视图从右向左滑动的效果,在motionScene.xml里配置了两个过渡动画(分别对应按钮和容器,逻辑一致)。但滑动过程中,容器内的TextView行数会不断变化(从多行变为3行)。我希望滑动时能像DrawerLayout那样,始终展示最终状态(3行)的内容,但不能通过设置android:maxLines="3"(或搭配android:ellipsize="end")实现。试过固定视图尺寸、用translationX把视图移出屏幕再恢复,都没成功。请问怎么用MotionLayout实现这个需求?
相关代码
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" app:layoutDescription="@xml/activity_main_scene"> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline" android:layout_width="0dp" android:layout_height="0dp" android:orientation="vertical" app:layout_constraintGuide_percent="0.3" /> <androidx.appcompat.widget.AppCompatTextView android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/bg_rounded_left_12dp_gray333" android:gravity="center" android:padding="10dp" android:text="T\ne\ns\nt" android:textColor="@color/white" android:textSize="18dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@id/container" app:layout_constraintTop_toTopOf="parent" tools:ignore="HardcodedText,SpUsage" /> <include android:id="@+id/container" layout="@layout/view_item_container" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toBottomOf="parent" /> </androidx.constraintlayout.motion.widget.MotionLayout>
activity_main_scene.xml
<?xml version="1.0" encoding="utf-8"?> <MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/container" android:layout_width="wrap_content" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/container" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> <Transition app:constraintSetEnd="@id/end" app:constraintSetStart="@+id/start" app:duration="500"> <OnSwipe app:touchAnchorId="@+id/container" app:dragDirection="dragLeft" app:touchAnchorSide="left" /> </Transition> <Transition app:constraintSetEnd="@id/end" app:constraintSetStart="@+id/start" app:duration="500"> <OnSwipe app:touchAnchorId="@+id/button" app:dragDirection="dragLeft" app:touchAnchorSide="left" /> </Transition> </MotionScene>
解决方案
核心是让TextView始终基于最终状态的宽度排版,不跟随滑动过程中容器的宽度变化,以下是三种可行方案:
方案1:固定TextView的最终宽度
在view_item_container.xml中,给目标TextView设置与容器最终状态一致的固定宽度(比如全屏宽度):
<TextView ... android:width="match_parent" android:layout_width="wrap_content" />
TextView会始终以全屏宽度计算行数,滑动时只控制容器的显示范围,排版不会变化。
方案2:通过translationX控制滑动,固定容器宽度
- 在
activity_main.xml的MotionLayout根节点添加裁剪属性:
android:clipChildren="true"
- 修改
motionScene.xml的约束集,让容器宽度始终为全屏,通过translationX控制显示位置:
<ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/container" android:layout_width="match_parent" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" android:translationX="70%" /> <!-- 初始状态向右偏移,仅显示部分内容 --> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/container" android:layout_width="match_parent" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" android:translationX="0" /> <!-- 最终状态无偏移,全屏显示 --> </ConstraintSet>
滑动时容器宽度不变,TextView基于全屏排版为3行,超出屏幕的部分被裁剪,视觉效果和DrawerLayout一致。
方案3:用KeyAttribute强制TextView保持3行
在Transition中添加KeyAttribute,全程强制TextView的maxLines为3(无需在布局文件中设置,满足你的限制条件):
<Transition app:constraintSetEnd="@id/end" app:constraintSetStart="@+id/start" app:duration="500"> <OnSwipe app:touchAnchorId="@+id/container" app:dragDirection="dragLeft" app:touchAnchorSide="left" /> <!-- 动画全程强制TextView保持3行 --> <KeyAttribute app:framePosition="0" android:maxLines="3" app:target="@id/your_textview_id" /> <KeyAttribute app:framePosition="100" android:maxLines="3" app:target="@id/your_textview_id" /> </Transition>
内容的提问来源于stack exchange,提问作者CodingBruceLee
相关产品推荐
相关产品推荐

