显示/隐藏键盘以及AlertDialog

时间:2019-06-07 15:53:10

标签: android android-layout

在我的应用中,我将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,这时延迟开始变得明显。

(原因可能是其中一个对话框在其自定义布局中使用了自己的“确定” /“取消”按钮,而其他对话框则使用了setPositiveButtonsetNegativeButton。原因与布局有关。)< / p>

我不知道这些值是否适用于所有设备/在所有情况下。如果不同的CPU或同一CPU上的甚至不同的负载导致调度程序采取不同的行动,而我的黑客再次开始失败怎么办?为了安全起见,我应该将延迟时间提高到200ms吗?对于非常慢的设备,可能要500ms? (那时候非常值得注意。)谁知道!

我无法想象这种情况如此罕见以至于需要进行此类黑客攻击。我只想显示一个弹出对话框,然后让用户在其中输入一些值。

有人知道干净的解决方案吗?完全放弃AlertDialog并使用其他功能吗?还是使用DialogFragment也许可以解决我的烦恼?

谢谢。

1 个答案:

答案 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);
    }

}