在我的应用中,我将AlertDialog实例与包含文本字段的自定义视图一起使用,以使用户可以在模式对话框中输入值。
问题是,似乎没有干净,简单,可靠的方法来确保在显示AlertDialog时弹出键盘,而在关闭对话框时又消失。
到目前为止,我正在使用以下内容来显示键盘:
// 'dialog' is the AlertDialog instance
Window window = dialog.getWindow();
if (window != null) {
window.setSoftInputMode(SOFT_INPUT_STATE_VISIBLE);
}
dialog.show();
这已经有点脏了,但是可以持续工作,所以我不能抱怨。但是,再次隐藏键盘是很棘手的。首先,我有以下实用方法:
public static void hideKeyboard(Activity activity) {
InputMethodManager imm = getIMM(activity);
IBinder windowToken = activity.getWindow().getDecorView().getWindowToken();
imm.hideSoftInputFromWindow(windowToken, HIDE_IMPLICIT_ONLY);
}
在我的AlertDialog的按钮回调中仅调用该函数(最高活动为activity
参数)不起作用。为了使实用程序方法能够完成预期的工作,我必须在短暂的延迟后调用它。
Util.runAfterTimeout(5, () -> Util.hideKeyboard(activity));
(runAfterTimeout
方法以给定的超时时间(以毫秒为单位)在主线程循环程序上调用给定的Runnable。)
在这一点上,代码真的开始发臭了。但是,情况变得更糟。
使用我的AlertDialog变体之一,超时时间为5毫秒。这太短了,以至于对人类来说都是直接的。
我的另一个AlertDialogs需要更长的超时时间。似乎开始工作约100ms,这时延迟开始变得明显。
(原因可能是其中一个对话框在其自定义布局中使用了自己的“确定” /“取消”按钮,而其他对话框则使用了setPositiveButton
和setNegativeButton
。原因与布局有关。)< / p>
我不知道这些值是否适用于所有设备/在所有情况下。如果不同的CPU或同一CPU上的甚至不同的负载导致调度程序采取不同的行动,而我的黑客再次开始失败怎么办?为了安全起见,我应该将延迟时间提高到200ms吗?对于非常慢的设备,可能要500ms? (那时候非常值得注意。)谁知道!
我无法想象这种情况如此罕见以至于需要进行此类黑客攻击。我只想显示一个弹出对话框,然后让用户在其中输入一些值。
有人知道干净的解决方案吗?完全放弃AlertDialog并使用其他功能吗?还是使用DialogFragment也许可以解决我的烦恼?
谢谢。
答案 0 :(得分:0)
您可以检查此示例。它在片段和活动方面都可以正常工作。
* @param context of the application
*/
public static void showKeyBoard(Context context) {
try {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @param context context of the application
* @param contextualView contextual view of the fragment/activity
*/
public static void hideKeyBoard(Context context, View contextualView) {
try {
InputMethodManager imm = (InputMethodManager) context.getSystemService(
Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.hideSoftInputFromWindow(contextualView.getWindowToken(), 0);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void showSingleInput(String title, String previousText, SingleEditTextInput.TextInputListener listener) {
SingleEditTextInput singleEditTextInput = new SingleEditTextInput();
Bundle args = new Bundle();
args.putString("DIALOG_TITLE", title);
args.putString("PREVIOUS_TEXT", previousText);
singleEditTextInput.setArguments(args);
singleEditTextInput.setListener(listener);
singleEditTextInput.show(fragmentManager, POP_UP_DIALOG);
}
public class SingleEditTextInput extends DialogFragment {
private String title = null, previousString = null;
TextInputListener listener;
Context mContext;
private Button btnSubmit;
private Button btnCancel;
EditText editText;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
mContext = getActivity();
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
AlertDialog alertDialog = builder.create();
alertDialog.setView(initView());
alertDialog.setCanceledOnTouchOutside(false);
btnSubmit.setOnClickListener(view -> {
String input;
input = editText.getText().toString().trim();
if (input!=null) {
hideKeyBoard(mContext, editText.findFocus());
dismiss();
listener.onClickSubmit(input);
} else
ToastMsg.getInstance(getActivity()).Show(getResources().getString(R.string.description_error));
});
btnCancel.setOnClickListener(view -> {
hideKeyBoard(mContext, editText);
dismiss();
});
editText.addTextChangedListener(textWatcher);
return alertDialog;
}
@Override
public void onPause() {
super.onPause();
hideKeyBoard(mContext, editText.findFocus());
}
private TextWatcher textWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (s.toString().trim().length() > 0) {
btnSubmit.setEnabled(true);
} else {
btnSubmit.setEnabled(false);
}
}
@Override
public void afterTextChanged(Editable s) {
}
};
private View initView() {
View mView;
mView = LayoutInflater.from(mContext).inflate(R.layout.l_single_edittext, null);
TextView tvTitle = mView.findViewById(R.id.tv_dialog_title);
editText = mView.findViewById(R.id.et_input);
btnSubmit = mView.findViewById(R.id.btn_next);
btnSubmit.setText(R.string.ok);
btnCancel = mView.findViewById(R.id.btn_back);
btnCancel.setText(R.string.cancel_text);
if (getArguments() != null) {
title = getArguments().getString("DIALOG_TITLE", "");
previousString = getArguments().getString("PREVIOUS_TEXT", "");
}
if (title!=null) {
tvTitle.setText(title);
}
if (previousString!=null) {
editText.setText(previousString);
}
showKeyBoard(mContext);
return mView;
}
public void setListener(TextInputListener dialogListener) {
this.listener = dialogListener;
}
public interface TextInputListener {
void onClickSubmit(String input);
}
}