Показать / скрыть клавиатуру вместе с AlertDialog - PullRequest
0 голосов
/ 07 июня 2019

В моем приложении я использую экземпляры 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);
}

Простой вызов этого (с самым верхним действием в качестве аргумента activity) в функции обратного вызова кнопки моего AlertDialog не работает.Чтобы служебный метод выполнял то, для чего он предназначен, я должен вызывать его после небольшой задержки.

Util.runAfterTimeout(5, () -> Util.hideKeyboard(activity));

(Метод runAfterTimeout вызывает заданный Runnable в петлителе основного потока с заданным временем ожидания вмиллисекунды.)

В этот момент код действительно начинает вонять.Однако становится все хуже.

С одним из моих вариантов AlertDialog работает тайм-аут в 5 миллисекунд.Это достаточно коротко, чтобы показаться человеку немедленным.

Еще один из моих AlertDialogs нуждается в более высоком тайм-ауте.Кажется, он начинает работать около 100 мс, после чего задержка начинает становиться заметной.

(Возможно, причина в том, что один из диалоговых окон использует свои собственные кнопки ok / cancel в своей пользовательской компоновке, тогда как другой используетsetPositiveButton и setNegativeButton. Причины связаны с компоновкой.)

Я не знаю, будут ли эти значения работать на всех устройствах / во всех ситуациях.Что если другой процессор или даже другая нагрузка на тот же процессор заставляет планировщик работать по-разному, и мой хак снова начинает проваливаться?Должен ли я увеличить задержку до 200 мс, чтобы быть в безопасности?Может быть, до 500 мс для очень медленных устройств?(Это очень заметно в тот момент.) Кто знает!

Я не могу представить, чтобы этот сценарий был настолько редким, чтобы оправдывать такие взломы.Я просто хочу показать всплывающее диалоговое окно и позволить пользователю ввести в него некоторые значения.

Кто-нибудь знает чистое решение?Дитч AlertDialog целиком и возможно использовать что-то еще?Или использование DialogFragment, возможно, решит мои проблемы?

Заранее спасибо.

1 Ответ

0 голосов
/ 07 июня 2019

Вы можете проверить этот пример.Работает отлично по фрагментам и активности.

* @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);
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...