如何在小于19的API上安全地请求FocusChange上的showDropDown?

时间:2019-06-01 11:37:43

标签: android drop-down-menu crash screen-orientation android-api-levels

方向更改(旋转)时,我发生了Android应用程序崩溃,因为焦点更改尝试在已经丢失其父窗口的AppCompatAutoCompleteTextView上呈现一个下拉列表(我想)

  

原因:android.view.WindowManager $ BadTokenException:无法添加   窗口-令牌null无效;您的活动正在进行吗?

仅当方向改变时焦点已经在该视图中时,才会发生这种情况...我有点惊讶的是,当旋转设备(模拟器)时,该视图收到焦点更改事件。

有关视图的XML格式如下:

<androidx.appcompat.widget.AppCompatAutoCompleteTextView
    android:id="@+id/dropdown_view"
    android:inputType="textAutoComplete"
    android:selectAllOnFocus="true"/>

崩溃的视图的onFocusChangeListener在androidx.fragment.app.Fragment()中的onViewCreated中声明:

   override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        ...
        dropdownView.setOnFocusChangeListener { view, hasFocus ->
            if (hasFocus) {
                editUnitView.showDropDown() //<<< Crash here on rotation, Caused by: android.view.WindowManager$BadTokenException: 
                                            //    Unable to add window -- token null is not valid; is your activity running?
            } else {
                editUnitView.dismissDropDown()
            }
        }
        ...
    }

如果我在 onPause onStop 中将onFocusChangeListener = null设置,似乎并不能阻止上述监听器被调用!

无论如何,我发现一个似乎有效的修复程序:

dropdownView.setOnFocusChangeListener { view, hasFocus ->
    if(view.isAttachedToWindow) { // Requires API 19
        if (hasFocus) {
            editUnitView.showDropDown()
        } else {
            editUnitView.dismissDropDown()
        }
    }
}   

可悲的是,我的目标是API 15,我想保留这一点。

我的问题: 您是否有任何想法或建议,如何实施一种保护措施,不要求将下拉菜单(或其他任何内容)呈现给已经消失的窗口?特别是API级别<19。

1 个答案:

答案 0 :(得分:0)

您可以将ViewCompat.isAttachedToWindow()用于与view.isAttachedToWindow相同的目的,但要使用API​​ <19