多行TextView右侧字符截断,但SharedElementTransition期间无此问题
- 特定标准文本(无自定义字体/斜体)的MaterialTextView右侧字符被截断,例如“nitrosoethane”显示为“ntrosoethane”
- 临时修复(设置文本阴影、自定义TextView)可解决截断,但SharedElementReturnTransition存在异常:返回调用Activity时,动画过程中文本换行位置正常,但动画结束后跳回截断状态,破坏过渡效果
- 测量发现仅SharedElementEnterTransition时
measuredWidth更大,其余参数(文本、字体、字号等)动画前后一致 - 两个TextView均位于RecyclerView中,调用Activity的TextView的
transitionName为动态设置
调用Activity的TextView布局
<com.google.android.material.textview.MaterialTextView android:id="@+id/name" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginEnd="8dp" android:elevation="4dp" android:ellipsize="end" android:textColor="@color/text_primary" android:textSize="18sp" app:layout_constraintEnd_toStartOf="@+id/image" app:layout_constraintStart_toStartOf="@+id/card" app:layout_constraintTop_toBottomOf="@+id/formula" tools:text="Magnesium Chloride" />
目标Activity的TextView布局
<com.google.android.material.textview.MaterialTextView android:id="@+id/anim_name" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginEnd="8dp" android:elevation="4dp" android:ellipsize="end" android:textColor="@color/text_primary" android:textSize="18sp" android:transitionName="@string/history_anim_name_tran" app:layout_constraintEnd_toStartOf="@+id/dummy_thumb" app:layout_constraintStart_toStartOf="@id/background" app:layout_constraintTop_toTopOf="@+id/name" tools:text="Magnesium Chloride" />
解决方案
1. 修复文本截断的根本问题
文本截断多由字符测量精度偏差或内边距计算异常导致,可尝试:
- 给TextView添加微小的
android:paddingEnd(如1dp),强制预留右侧空间:android:paddingEnd="1dp" - 禁用默认字体padding:
android:includeFontPadding="false" - 若不需要省略号,替换
android:ellipsize="end"为android:ellipsize="none",避免系统截断逻辑冲突
2. 解决SharedElementReturnTransition位置跳变
由于两个TextView分属不同RecyclerView,且动态设置transitionName,易出现视图状态不一致:
- 对齐布局参数:检查两个TextView的父容器宽度、约束关系(当前调用方绑定
card,目标绑定background,可能存在宽度差异),确保布局约束完全匹配 - 返回时强制刷新视图:在调用Activity的
onActivityReenter中触发TextView重新测量:override fun onActivityReenter(resultCode: Int, data: Intent?) { super.onActivityReenter(resultCode, data) val targetViewHolder = recyclerView.findViewHolderForAdapterPosition(targetPos) ?: return val textView = targetViewHolder.itemView.findViewById<MaterialTextView>(R.id.name) textView.post { textView.requestLayout() textView.invalidate() } } - 禁用过渡重叠:启动Activity时关闭返回过渡的重叠优化,避免状态冲突:
val options = ActivityOptionsCompat.makeSceneTransitionAnimation(this, textView, transitionName) val returnTransition = TransitionInflater.from(this).inflateTransition(R.transition.shared_element) returnTransition.setAllowReturnTransitionOverlap(false) WindowCompat.setSharedElementReturnTransition(window, returnTransition) startActivity(intent, options.toBundle())
3. RecyclerView复用问题处理
RecyclerView的item复用可能干扰过渡状态,可临时禁用目标item复用:
// 启动Activity前 val targetViewHolder = recyclerView.findViewHolderForAdapterPosition(targetPos) targetViewHolder?.setIsRecyclable(false) // 返回后恢复(如onResume中) override fun onResume() { super.onResume() val targetViewHolder = recyclerView.findViewHolderForAdapterPosition(targetPos) targetViewHolder?.setIsRecyclable(true) }
内容的提问来源于stack exchange,提问作者Michael P
相关产品推荐
相关产品推荐

