更新TextView时Spinner自动关闭,如何解决该问题?
解决:更新TextView时Spinner自动关闭的问题
问题场景
在ConstraintLayout中放置了TextView(用作每秒更新的计时器)和Spinner,每次更新TextView文本时,已展开的Spinner都会自动收起。试过以下方案均无效:
- 替换TextView为Chronometer,问题依旧;
- 为TextView设置
android:focusable="false",无改善; - 通过
View.post延迟更新文本,代码如下:
binding.lastUpdateTimer.post { binding.lastUpdateTimer.text = displayTime binding.lastUpdateTimer.setBackgroundColor(Color.rgb(76, 175, 80)) }
核心原因
TextView更新文本时触发了布局重绘,导致Spinner的PopupWindow失去焦点,被系统自动收回。
有效解决方法
方法1:使用setTextKeepState替代setText
setTextKeepState会保留View的内部状态,避免因文本更新触发不必要的布局重绘,从而不会干扰Spinner的PopupWindow:
binding.lastUpdateTimer.setTextKeepState(displayTime) binding.lastUpdateTimer.setBackgroundColor(Color.rgb(76, 175, 80))
方法2:自定义Spinner阻止PopupWindow意外关闭
创建自定义Spinner类,重写onDetachedFromWindow方法,确保PopupWindow显示时不被销毁:
class PersistentSpinner(context: Context, attrs: AttributeSet?) : AppCompatSpinner(context, attrs) { private var popupWindow: PopupWindow? = null override fun performClick(): Boolean { val result = super.performClick() // 反射获取PopupWindow实例 try { val field = AppCompatSpinner::class.java.getDeclaredField("mPopup") field.isAccessible = true popupWindow = field.get(this) as PopupWindow } catch (e: Exception) { e.printStackTrace() } return result } override fun onDetachedFromWindow() { // 若PopupWindow正在显示,跳过父类的销毁逻辑 if (popupWindow?.isShowing == true) { return } super.onDetachedFromWindow() } }
然后在布局中替换原Spinner:
<com.your.package.name.PersistentSpinner android:id="@+id/nap_spinner" android:layout_width="0dp" android:layout_height="0dp" android:entries="@array/nap_types" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" />
方法3:优化布局减少重绘范围
给TextView添加android:willNotDraw="true",标记该View不需要额外绘制,减少重绘触发的概率;同时固定TextView的最小尺寸,避免文本更新导致父布局重新计算:
<TextView android:id="@+id/lastUpdateTimer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:willNotDraw="true" android:minWidth="60dp" <!-- 根据实际需求设置固定最小宽度 --> ... />
内容的提问来源于stack exchange,提问作者Aloha
相关产品推荐
相关产品推荐

