android - 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 中显示建议)才能在锁屏上正常工作。
解决方案
我发现如果弹窗输入法模式为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);
推荐阅读
- wordpress - 安装谷歌翻译后页面部分网址不起作用
- php - 如何获得仅活跃的学生总数
- c++ - 由于 HID 句柄无效(Windows HID C++ API),HidD_* 函数全部失败
- sql - InfluxQL:名为 Group 的标签导致悲伤
- circleci - CircleCI - 基于 ENV 变量的条件
- r - 在cowplot中调整和定位ggplots
- java - 我构建了包含第三方库的库,我想从应用程序中使用该第三方库
- openlayers-6 - 使用多个标记居中和缩小视图
- java - 由于错误无法加载插件:“Jar 不包含 plugin.yml”
- sql - 使用连接查询进行聚合的技巧