You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 20:13:12