android - 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);
我不认为这是一个有效的答案,因为以这种方式使用线程会使代码不可预测。还在等待一个好的答案
解决方案
使用OnGlobalLayoutListener
代替Handler
:
nameEt.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener{
override fun onGlobalLayout() {
nameEt.viewTreeObserver.removeOnGlobalLayoutListener(this)
nameEt.requestFocus()
}
})
在这种情况下,您不需要额外的显式调用 dialog.getWindow().setSoftInputMode(..)
。
推荐阅读
- sql - 如何在查询生成器中选择带有对象的查询表列
- vb.net - 在 VB.Net 中循环浏览 xml 数据
- python - 如何将一维数组组合到二维数组的末尾
- reactjs - 使用 esp32 从 Wifi 接入点模式切换到站模式
- python - 错误:Visual Studio Code 中未安装模块“笔记本”
- typescript - “找不到‘@wdio/sync’的类型定义文件。” 当它出现时
- sql - 在 SQL Server 中进行透视时获取自定义列名
- java - XSSF 无法解析为类型
- vba - 紧凑的拆分/共享 Access DB
- javascript - 有没有办法在 package.json 中对依赖项进行分组?