MaterialAutoCompleteTextView切换主题后自动展开下拉列表求助
MaterialAutoCompleteTextView切换主题后自动展开下拉列表的解决办法
问题详情
使用MaterialAutoCompleteTextView实现主题选择下拉框,初始启动时已保存的主题值能正确显示在控件中;但选择主题触发切换后,Fragment及其视图会重建,此时下拉列表会自动展开。直接在setText()后调用dismissDropDown()无效,仅postDelayed延迟关闭有效,但会出现UI闪烁,需要正规解决方法。
相关代码
XML布局
<com.google.android.material.textfield.TextInputLayout android:id="@+id/chooseThemeContainer" style="@style/ChooseThemeInputLayout" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:layout_marginEnd="16dp" android:hint="@string/theme" android:textColorHint="@color/textLink" app:endIconTint="@color/textLink" app:layout_constraintEnd_toStartOf="@id/saveName" app:layout_constraintStart_toStartOf="@id/avatar" app:layout_constraintTop_toBottomOf="@id/avatar"> <com.google.android.material.textfield.MaterialAutoCompleteTextView android:id="@+id/chooseTheme" android:layout_width="match_parent" android:layout_height="match_parent" android:drawableTint="@color/textLink" android:inputType="none" android:textColorHint="@color/textLink" android:textColor="@color/textLink"/> </com.google.android.material.textfield.TextInputLayout>
Fragment初始化代码
private fun initChangeThemeEditText() { viewModel.themeItems.observe(viewLifecycleOwner) { items -> binding.chooseTheme.setSimpleItems(items) val selectedIndex = when (themeController.themeType) { ThemeController.ThemeType.AS_SYSTEM -> 0 ThemeController.ThemeType.DAY -> 1 ThemeController.ThemeType.NIGHT -> 2 } binding.chooseTheme.setText(items[selectedIndex], false) } }
ViewModel代码
private val _themeItems = MutableLiveData<Array<String>>() val themeItems: LiveData<Array<String>> = _themeItems init { val items = arrayOf( resourceProvider.getString(stringResources.theme_as_system), resourceProvider.getString(stringResources.theme_day), resourceProvider.getString(stringResources.theme_night) ) _themeItems.value = items }
可行解决方案
方案1:监听视图布局完成后关闭下拉
利用ViewTreeObserver监听控件布局完成事件,确保控件完全初始化后再关闭下拉,避免延迟闪烁:
private fun initChangeThemeEditText() { viewModel.themeItems.observe(viewLifecycleOwner) { items -> binding.chooseTheme.setSimpleItems(items) val selectedIndex = when (themeController.themeType) { ThemeController.ThemeType.AS_SYSTEM -> 0 ThemeController.ThemeType.DAY -> 1 ThemeController.ThemeType.NIGHT -> 2 } binding.chooseTheme.setText(items[selectedIndex], false) // 监听布局完成,确保控件就绪后关闭下拉 binding.chooseTheme.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { // 移除监听防止重复触发 binding.chooseTheme.viewTreeObserver.removeOnGlobalLayoutListener(this) binding.chooseTheme.dismissDropDown() } }) } }
方案2:临时禁用并恢复TextInputLayout的下拉图标
主题重建时TextInputLayout的endIcon可能被误触发导致下拉展开,可临时禁用图标,设置文本后再恢复:
private fun initChangeThemeEditText() { viewModel.themeItems.observe(viewLifecycleOwner) { items -> binding.chooseTheme.setSimpleItems(items) val selectedIndex = when (themeController.themeType) { ThemeController.ThemeType.AS_SYSTEM -> 0 ThemeController.ThemeType.DAY -> 1 ThemeController.ThemeType.NIGHT -> 2 } // 临时关闭下拉图标 binding.chooseThemeContainer.endIconMode = TextInputLayout.END_ICON_NONE binding.chooseTheme.setText(items[selectedIndex], false) // 恢复下拉图标并关闭下拉 binding.chooseThemeContainer.endIconMode = TextInputLayout.END_ICON_DROPDOWN_MENU binding.chooseTheme.dismissDropDown() } }
方案3:阻止控件自动获取焦点
视图重建后控件可能自动获取焦点触发下拉,可通过设置焦点属性或清除焦点解决:
private fun initChangeThemeEditText() { viewModel.themeItems.observe(viewLifecycleOwner) { items -> binding.chooseTheme.setSimpleItems(items) val selectedIndex = when (themeController.themeType) { ThemeController.ThemeType.AS_SYSTEM -> 0 ThemeController.ThemeType.DAY -> 1 ThemeController.ThemeType.NIGHT -> 2 } binding.chooseTheme.setText(items[selectedIndex], false) // 清除控件焦点,避免触发下拉 binding.chooseTheme.clearFocus() // 或者设置控件仅触摸时可聚焦,防止自动获取焦点 binding.chooseTheme.isFocusable = false binding.chooseTheme.isFocusableInTouchMode = true } }
内容的提问来源于stack exchange,提问作者djes
相关产品推荐
相关产品推荐

