首页 > 解决方案 > DialogFragment 将 EditText 焦点放在为 API 28 打开的对话框上

问题描述

我想关注TextInputEditText布局中的第一个并在显示对话框时自动显示软键盘

我的目标是 API 级别 28。

布局:

        <com.google.android.material.textfield.TextInputLayout
            android:id="@+id/d_add_edit_name_til"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/activity_vertical_margin"
            android:layout_marginTop="@dimen/activity_vertical_margin"
            android:layout_marginEnd="@dimen/activity_vertical_margin"
            android:theme="@style/TextInputLayoutAppearance"
            >
            <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/d_add_edit_name_et"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="User email"
                android:imeOptions="actionDone"
                android:inputType="textCapSentences"
                android:singleLine="true"
                android:focusableInTouchMode="true"
                android:focusable="true"
            >
                <requestFocus />
            </com.google.android.material.textfield.TextInputEditText>
        </com.google.android.material.textfield.TextInputLayout>

DialogFragment代码:

@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
    final Dialog dialog = super.onCreateDialog(savedInstanceState);
    dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
    dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
    return dialog;
}

....

@Override
public void onResume(){
    super.onResume();

    int dialogWidth = Functions.convertDpToPixel(300,activity);
    int dialogHeight = Functions.convertDpToPixel(250,activity);

    new Handler().post(() -> {
        getDialog().getWindow().setLayout(dialogWidth, dialogHeight);
    });
}

该线程的答案帮助我解决了 API < 28 的问题。

我从Android 9 更改文档中了解到:

此外,活动不再隐含地在触摸模式下分配初始焦点。相反,如果需要,您可以明确请求初始焦点。

显式请求初始焦点的一种方法(如这里所讨论的)是<requestFocus />在内部添加标签EditText,但对于 API 级别 28 + 仍然没有成功DialogFragment

*注意DialogFragment来自 andoridx 库 ( androidx.fragment.app.DialogFragment)

还有谁有相同的问题吗?

编辑: 我设法使这项工作的唯一方法是将以下代码添加到onViewCreated

    new Handler().postDelayed(() -> {
        nameEt.requestFocus();
        InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.showSoftInput(nameEt, InputMethodManager.SHOW_IMPLICIT);
    },200);

我不认为这是一个有效的答案,因为以这种方式使用线程会使代码不可预测。还在等待一个好的答案

标签: androidandroid-dialogfragmentandroid-9.0-pie

解决方案


使用OnGlobalLayoutListener代替Handler

nameEt.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener{
            override fun onGlobalLayout() {
                nameEt.viewTreeObserver.removeOnGlobalLayoutListener(this)
                nameEt.requestFocus()
            }
        })

在这种情况下,您不需要额外的显式调用 dialog.getWindow().setSoftInputMode(..)


推荐阅读