首页 > 解决方案 > ListPopupWindow 关闭软键盘

问题描述

在锁屏应用程序上工作时,我看到一个非常奇怪的行为:显示 ListPopupWindow 会强制软键盘关闭。这只发生在“锁屏”活动上(活动窗口标志设置为 FLAG_SHOW_WHEN_LOCKED|FLAG_DISMISS_KEYGUARD)并且仅在设置了键盘保护密码/密码时才会发生。

这是一个代码示例:

editText.setOnFocusChangeListener((v, hasFocus) -> {
        ListPopupWindow popupWindow = new ListPopupWindow(getContext());
        popupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
        popupWindow.setAdapter(new ArrayAdapter(
            getContext(), android.R.layout.simple_dropdown_item_1line, Arrays.asList("aaa", "bbb", "ccc")));
        popupWindow.setAnchorView(editText);
        popupWindow.show();
});

当弹出列表出现时,键盘立即消失。

请注意,同时 PopupWindow 工作正常:

editText.setOnFocusChangeListener((v, hasFocus) ->  {
        PopupWindow popupWindow = new PopupWindow(getContext());
        popupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
        popupWindow.setContentView(new TextClock(getContext()));
        popupWindow.showAsDropDown(editText);
});

弹出窗口和键盘都是可见的。

知道如何避免这种键盘消失吗?最后,我需要一个 SearchView(它在 ListPopupWindow 中显示建议)才能在锁屏上正常工作。

标签: androidlockscreenandroid-popupwindow

解决方案


我发现如果弹窗输入法模式为INPUT_METHOD_FROM_FOCUSABLE,键盘没有关闭。

SearchView 包含 AutoCompleteTextView,它将其建议弹出输入法模式更改为 INPUT_METHOD_NEEDED 或 INPUT_METHOD_NOT_NEEDED。所以解决方法是保持 PopupWindow.mInputMethodMode = INPUT_METHOD_FROM_FOCUSABLE。

我通过创建一个覆盖 setInputMethodMode() 的自定义 PopupWindow 解决了这个问题:

public class SearchSuggestionPopupWindow extends PopupWindow {

    SearchSuggestionPopupWindow(final Context context, final PopupWindow original) {
        super(context);

        setElevation(original.getElevation());

        setAnimationStyle(original.getAnimationStyle());

        setBackgroundDrawable(original.getBackground());

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            setOverlapAnchor(original.getOverlapAnchor());
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            setEnterTransition(original.getEnterTransition());
            setExitTransition(original.getExitTransition());
        }
    }

    @Override
    public void setInputMethodMode(final int mode) {
        super.setInputMethodMode(PopupWindow.INPUT_METHOD_FROM_FOCUSABLE);
    }
}

那么就需要从SearchView中获取AutoCompleteTextView:

final AutoCompleteTextView textView = searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text);

并替换自定义弹出窗口:

final Field listPopupField = AutoCompleteTextView.class.getDeclaredField("mPopup");
listPopupField.setAccessible(true);
final ListPopupWindow listPopup = (ListPopupWindow) listPopupField.get(textView);

final Field popupField = ListPopupWindow.class.getDeclaredField("mPopup");
popupField.setAccessible(true);
final PopupWindow popup = (PopupWindow) popupField.get(listPopup);
final PopupWindow customPopup = new SearchSuggestionPopupWindow(textView.getContext(), popup);
popupField.set(listPopup, customPopup);

推荐阅读