当输入焦点移入或移出可编辑文本字段时,Android 会显示或 隐藏输入(例如屏幕键盘), 适当的选择。系统还会决定您的界面和文本字段在上方的显示方式 输入方法例如,当屏幕上的垂直空间为 那么文本字段可能会填满输入法上方的所有空间。
对于大多数应用来说,这些默认行为就足够了。在某些情况下 但您可能希望更好地控制输入法的可见性 对布局的影响本课将介绍如何控制和响应 输入法可见性。
在 activity 启动时显示软键盘
尽管在 则不会显示软键盘。这种行为是适当的 因为输入文本可能不是 activity 中的主要任务。但是,如果 比如在登录屏幕中,输入文本是主要任务, 可能希望默认显示软键盘。
如需在 Activity 启动时显示输入法,请将
android:windowSoftInputMode
属性
值为 "stateVisible"
的 <activity>
元素。例如:
<application ... >
<activity
android:windowSoftInputMode="stateVisible" ... >
...
</activity>
...
</application>
指定界面的响应方式
当屏幕上显示软键盘时,这会减少空间 自定义属性由系统决定如何调整 部分,但可能不会做得很好。为了确保最佳行为 指定您希望系统如何在 剩余空间
如需在 activity 中声明您的首选处理方式,请使用
清单的 <activity>
元素中的 android:windowSoftInputMode
属性
其中设置了一个“调整”值。
例如,要确保系统将布局大小调整为
这样就能确保布局内容可供访问
需要滚动 - 使用 "adjustResize"
:
<application ... >
<activity
android:windowSoftInputMode="adjustResize" ... >
...
</activity>
...
</application>
您可以将调整规范与初始软键盘结合使用 可见性规范:
<activity
android:windowSoftInputMode="stateVisible|adjustResize" ... >
...
</activity>
如果界面包含"adjustResize"
用户可能需要在输入文本之后或过程中立即访问。对于
例如,如果您使用相对布局将按钮栏放置在
屏幕,使用 "adjustResize"
可调整布局大小,以显示按钮栏
。
按需显示软键盘
如果您想在 activity 的生命周期中通过某个方法确保
输入法是否可见,则可以使用
InputMethodManager
进行显示。
例如,以下方法接受一个
View
,用户应在其中
打字、打电话
requestFocus()
:
然后调用 showSoftInput()
以打开输入法:
Kotlin
fun showSoftKeyboard(view: View) { if (view.requestFocus()) { val imm = getSystemService(InputMethodManager::class.java) imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT) } }
Java
public void showSoftKeyboard(View view) { if (view.requestFocus()) { InputMethodManager imm = getSystemService(InputMethodManager.class); imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT); } }
可靠地显示软键盘
有些情况下(例如当 activity 启动时),
使用 InputMethodManager.showSoftInput()
显示软键盘
可能导致用户无法看到软件键盘。
使用 showSoftInput()
时,软键盘的可见性取决于
用于以下条件:
视图必须已连接到软件键盘。(反过来, 需要窗口聚焦和编辑器 来请求视图焦点
View.requestFocus()
)。可见性还会受到
android:windowSoftInputMode
的影响showSoftInput()
使用的属性和标记。
在某些用例中,例如当 activity 启动时,部分用例
不符合必需的条件。系统不会将该视图视为
连接到软件键盘时,会忽略 showSoftInput()
调用,
并且对用户不可见。
为确保软件键盘可靠地显示,您可以使用以下代码 替代方案:
- (推荐)使用
WindowInsetsControllerCompat
。此对象 在Activity.onCreate()
期间显示软键盘,如 以下代码段中。系统会保证将此通话安排在相应时段 目标。
Kotlin
editText.requestFocus() WindowCompat.getInsetsController(window, editText)!!.show(WindowInsetsCompat.Type.ime())
Java
editText.requestFocus(); WindowCompat.getInsetsController(getWindow(), editText).show(WindowInsetsCompat.Type.ime());
- 发布一个可运行对象。这可确保您的应用等到收到
在调用之前来自
View.onWindowFocusChanged()
的窗口焦点事件showSoftInput()
。
Kotlin
class MyEditText : EditText() { ... override fun onWindowFocusChanged(hasWindowFocus: Boolean) { if (hasWindowFocus) { requestFocus() post { val imm: InputMethodManager = getSystemService(InputMethodManager::class.java) imm.showSoftInput(this, 0) } } } }
Java
public class MyEditText extends EditText { ... @Override public void onWindowFocusChanged(boolean hasWindowFocus) { if (hasWindowFocus) { requestFocus(); post(() -> { InputMethodManager imm = getSystemService(InputMethodManager.class); imm.showSoftInput(this, 0); }); } } }
谨慎处理运行时可见性标志
在运行时切换软键盘可见性时,请注意不要将某些
标志值传递到这些方法中。例如,如果应用需要
通话时显示软键盘
Activity.onCreate()
期间:View.getWindowInsetsController().show(ime())
activity 启动时,应用开发者应小心谨慎,切勿将
SOFT_INPUT_STATE_HIDDEN
或 SOFT_INPUT_STATE_ALWAYS_HIDDEN
标志
以防软键盘意外隐藏。
系统通常会自动隐藏软键盘
在大多数情况下,系统会处理隐藏软键盘的操作。这个 可以是以下任意一种:
- 用户在文本字段中完成任务。
- 用户按下返回键或使用返回导航滑动手势。
- 用户导航到另一个应用,并且该应用已设置
SOFT_INPUT_STATE_HIDDEN
或SOFT_INPUT_STATE_ALWAYS_HIDDEN
标志 在视图获得焦点时触发。
根据以前的系统行为手动隐藏软键盘
在某些情况下,您的应用必须手动隐藏软键盘,例如
例如,在
View.OnFocusChangeListener.onFocusChange
。谨慎使用这一技巧
;关闭软键盘意外影响用户体验。
如果您的应用手动隐藏软键盘,您需要知道 以显式方式或隐式方式显示软键盘:
之后被视为明确显示软键盘。 对
showSoftInput()
的调用。反之,则认为软键盘已隐式显示在 以下任一情况:
- 在应用
android:windowSoftInputMode
。 - 您的应用将
SHOW_IMPLICIT
传递给showSoftInput()
。
- 在应用
通常,无论如何选择 hideSoftInputFromWindow()
都会隐藏软键盘
请求中包含 HIDE_IMPLICIT_ONLY
可以限定为仅关闭隐式请求的软键盘。
在软键盘顶部显示对话框或叠加视图
在某些情况下,编辑器 activity 可能需要创建一个不可修改的 对话框或叠加窗口。
您的应用具有几个选项,具体如以下部分所述。
总之,请确保正确处理软键盘的窗口标记 定位时间范围,使其满足以下预期 关于垂直(z 层)排序:
- 无标志(正常情况):位于软键盘层之后,可以接收文本。
FLAG_NOT_FOCUSABLE
:位于软键盘层之上,但无法接收文本。FLAG_ALT_FOCUSABLE_IM
:在软键盘层之上,可以聚焦,但不连接到 软键盘。还会阻止其下的所有视图连接到 软键盘。这对于显示不使用文本的应用对话框非常有用 输入层。FLAG_NOT_FOCUSABLE
和FLAG_ALT_FOCUSABLE_IM
:位于软键盘层之后,但无法接收文本。FLAG_NOT_FOCUSABLE
和FLAG_NOT_TOUCH_MODAL
:位于软键盘顶部,允许触摸事件“穿过” 切换到软键盘上。
创建对话框
使用 FLAG_ALT_FOCUSABLE_IM
dialog 窗口标志,用于将对话框置于软键盘之上;以及用于
阻止软键盘获得焦点:
Kotlin
val content = TextView(this) content.text = "Non-editable dialog on top of soft keyboard" content.gravity = Gravity.CENTER val builder = AlertDialog.Builder(this) .setTitle("Soft keyboard layering demo") .setView(content) mDialog = builder.create() mDialog!!.window!! .addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) mDialog!!.show()
Java
TextView content = new TextView(this); content.setText("Non-editable dialog on top of soft keyboard"); content.setGravity(Gravity.CENTER); final AlertDialog.Builder builder = new AlertDialog.Builder(this) .setTitle("Soft keyboard layering demo") .setView(content); mDialog = builder.create(); mDialog.getWindow().addFlags(FLAG_ALT_FOCUSABLE_IM); mDialog.show();
创建叠加层视图
创建指定 TYPE_APPLICATION_OVERLAY
的叠加层视图
窗口类型和 FLAG_ALT_FOCUSABLE_IM
针对软键盘的 Activity 设置的窗口标志。
Kotlin
val params = WindowManager.LayoutParams( width, /* Overlay window width */ height, /* Overlay window height */ WindowManager.LayoutParams.TYPE_APPLICATION, /* Overlay window type */ WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM /* No need to allow for text input on top of the soft keyboard */ or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, /* Allow touch event send to soft keyboard behind the overlay */ PixelFormat.TRANSLUCENT ) params.title = "Overlay window" mOverlayView!!.layoutParams = params windowManager.addView(mOverlayView, params)
Java
WindowManager.LayoutParams params = new WindowManager.LayoutParams( width, /* Overlay window width */ height, /* Overlay window height */ TYPE_APPLICATION, /* Overlay window type */ FLAG_ALT_FOCUSABLE_IM /* No need to allow for text input on top of the soft keyboard */ | FLAG_NOT_TOUCH_MODAL, /* Allow touch event send to soft keyboard behind the overlay */ PixelFormat.TRANSLUCENT); params.setTitle("Overlay window"); mOverlayView.setLayoutParams(params); getWindowManager().addView(mOverlayView, params);
在软键盘下方显示对话框或视图
您的应用可能需要创建一个对话框或窗口,其中包含 以下属性:
- 显示在编辑器 activity 请求的软键盘下方 使其不受文本输入的影响。
- 始终知晓软键盘边衬区大小的变化 调整对话框或窗口的布局。
在这种情况下,您的应用会提供多种选项。以下部分 介绍这些选项
创建对话框
通过同时设置 FLAG_NOT_FOCUSABLE
来创建对话框
窗口标志和 FLAG_ALT_FOCUSABLE_IM
窗口标志:
Kotlin
val content = TextView(this) content.text = "Non-editable dialog behind soft keyboard" content.gravity = Gravity.CENTER val builder = AlertDialog.Builder(this) .setTitle("Soft keyboard layering demo") .setView(content) mDialog = builder.create() mDialog!!.window!! .addFlags(FLAG_NOT_FOCUSABLE or FLAG_ALT_FOCUSABLE_IM) mDialog!!.show()
Java
TextView content = new TextView(this); content.setText("Non-editable dialog behind soft keyboard"); content.setGravity(Gravity.CENTER); final AlertDialog.Builder builder = new AlertDialog.Builder(this) .setTitle("Soft keyboard layering demo") .setView(content); mDialog = builder.create(); mDialog.getWindow() .addFlags(FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM); mDialog.show();
创建叠加层视图
通过同时设置 FLAG_NOT_FOCUSABLE
来创建叠加层视图
窗口标志和 FLAG_ALT_FOCUSABLE_IM
窗口标志:
Kotlin
val params = WindowManager.LayoutParams( width, /* Overlay window width */ height, /* Overlay window height */ WindowManager.LayoutParams.TYPE_APPLICATION, /* Overlay window type */ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, PixelFormat.TRANSLUCENT ) params.title = "Overlay window" mOverlayView!!.layoutParams = params windowManager.addView(mOverlayView, params)
Java
WindowManager.LayoutParams params = new WindowManager.LayoutParams( width, /* Overlay window width */ height, /* Overlay window height */ TYPE_APPLICATION, /* Overlay window type */ FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM, PixelFormat.TRANSLUCENT); params.setTitle("Overlay window"); mOverlayView.setLayoutParams(params); getWindowManager().addView(mOverlayView, params);