如何实现TextView文本折叠时的LayoutTransition.CHANGING动画?
TextView折叠无动画问题的解决方案
问题说明
为评论场景实现「查看更多」功能时,TextView文本展开有动画效果,但折叠时无动画。尝试切换LayoutTransition类型未解决,需实现折叠时的平滑动画。
相关代码
Fragment代码
private var extended = false override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val testTextView = view.findViewById<TextView>(R.id.test_text) val container = view.findViewById<ConstraintLayout>(R.id.text_view_container) val comment = /* 长文本内容 */ // 启用文本变化动画 container.layoutTransition.enableTransitionType( LayoutTransition.CHANGING ) if ((comment.length ?: 0) <= 200) { testTextView.text = comment } else { testTextView.text = comment.substring( 0, if (comment.length < 200) comment.length else 200 ) } testTextView.setOnClickListener { extended = !extended if (extended) { testTextView.text = comment } else { testTextView.text = comment.substring( 0, (if (comment.length < 200) comment.length else 200) ) } } }
XML代码
<androidx.constraintlayout.widget.ConstraintLayout 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" android:id="@+id/fragment_blank_root" tools:context=".BlankFragment"> <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/text_view_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:animateLayoutChanges="true" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> <TextView android:id="@+id/test_text" android:layout_width="match_parent" android:layout_height="match_parent" android:text="@string/hello_blank_fragment" /> </androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
解决思路与方案
问题根源
默认LayoutTransition.CHANGING动画仅处理视图尺寸增大的场景,折叠时的尺寸缩小未被触发;同时TextView设置layout_height="match_parent"会导致容器无法准确捕捉文本高度变化。
修复步骤
调整TextView布局参数
将TextView的layout_height改为wrap_content,让高度随文本内容动态变化,确保容器能检测到高度改变:<TextView android:id="@+id/test_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hello_blank_fragment" />手动触发过渡动画
在修改文本前调用TransitionManager.beginDelayedTransition(container),强制系统捕捉视图变化并执行动画,替代仅依赖默认LayoutTransition的方式:testTextView.setOnClickListener { extended = !extended // 触发过渡动画 TransitionManager.beginDelayedTransition(container) testTextView.text = if (extended) comment else comment.substring(0, 200) }可选:自定义缩小动画
如果需要更精细的动画控制,可自定义LayoutTransition添加尺寸缩小的Animator:override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val testTextView = view.findViewById<TextView>(R.id.test_text) val container = view.findViewById<ConstraintLayout>(R.id.text_view_container) val comment = /* 长文本内容 */ // 自定义LayoutTransition val layoutTransition = LayoutTransition() // 保留原有增大动画 layoutTransition.setAnimator(LayoutTransition.CHANGING, layoutTransition.getAnimator(LayoutTransition.CHANGING)) // 添加缩小动画 val shrinkAnimator = ValueAnimator.ofInt(0, 0) shrinkAnimator.addUpdateListener { animation -> val height = animation.animatedValue as Int testTextView.layoutParams.height = height testTextView.requestLayout() } layoutTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, shrinkAnimator) container.layoutTransition = layoutTransition // 初始化文本 testTextView.text = if (comment.length <=200) comment else comment.substring(0,200) testTextView.setOnClickListener { extended = !extended TransitionManager.beginDelayedTransition(container) testTextView.text = if (extended) comment else comment.substring(0,200) } }
注意事项
- 保留容器的
android:animateLayoutChanges="true"属性,这是布局动画生效的基础。 - 避免给TextView设置固定高度,否则高度变化无法被系统检测到。
内容的提问来源于stack exchange,提问作者Abed Sako
相关产品推荐
相关产品推荐

