如何在键盘显示时调整AlertDialog的大小

40

我有一个包含大约10个控件(文本和TextView)的AlertDialog 对话框,这些控件都在带有ScrollViewAlertDialog 中,并且还有2个按钮(积极和消极)。问题是当软键盘弹出时,两个按钮被键盘遮挡了。

我正在寻找一种像是在我的内部视图或对话框上重新绘制的功能。下面是我所说内容的屏幕截图。

图片描述

7个回答

118

如果您的对话框是使用对话框主题之一的活动,则可以通过为活动的windowSoftInputMode参数设置adjustResize标志来实现此行为。

我正在使用:

android:windowSoftInputMode="adjustResize|stateHidden"

我认为你仍然可以在常规对话框中使用此标志,但是我不确定如何应用它。您可能需要使用自定义主题创建AlertDialog,该主题继承正确的父主题并设置该标志,或者您可能需要使用ContextThemeWrappers等工具。

或者您可以直接使用Window#setSoftInputMode

alertDialog.getWindow().setSoftInputMode(
    WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);

9
最后一行对我来说可行,理想情况下,我认为这就是问题的核心,并且这是正确的答案。所选的答案更像是一个设计改变建议,而不是正确答案。对于这个答案点赞。 - Jayshil Dave
7
如果您有自定义样式,您也可以将其作为样式定义的一个元素,如下所示:<style name="Theme.MyDialog" parent="@android:style/Theme.Dialog"><item name="android:windowSoftInputMode">adjustResize|stateHidden</item></style>。 - ChristophK
1
这个答案应该被采纳。最后一行代码对我很有帮助。非常感谢! - Bogdan Zurac
1
也适用于FragmentDialog! - Bojan Radivojevic
需要设置对话框本身的SoftInputMode。这个需要设置一百万次。 - Eugen Timm
代码的最后一行解决了问题,我尝试在Activity的onCreate中执行并在清单文件中设置它,但我猜它们不共享同一个窗口。 - Eric Van Der Dijs

18

我发现了一个最佳处理方法。由于这是一个对话,因此代码

alertDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);

不太有效。

除了这段代码,你还必须为此对话框设置一个对话框样式。样式应该像下面这样:

<style name="DialogStyle" parent="@android:style/Theme.Black.NoTitleBar.Fullscreen">
    <item name="android:windowFullscreen">false</item>
    ......
    ......
</style>

注意,属性parent像活动的样式一样设置为Theme.Black.NoTitleBar.Fullscreen,而属性android:windowFullScreen应该是false

现在,当软键盘切换时,对话框将会被重新调整大小。


1
这对我有用,但我使用了 parent="Theme.AppCompat.Light.Dialog.Alert",但将 "android:windowFullscreen" 设置为 false 确实起到了作用...谢谢。 - CrandellWS

4

除了 adjustPan 之外,其他的都没有用。

根据文档说明:

活动的主窗口不会被调整大小以腾出空间给软键盘。相反,窗口的内容会自动滚动,以便当前焦点永远不会被键盘遮挡,用户始终可以看到他们正在输入什么。这通常比调整大小不太理想,因为用户可能需要关闭软键盘才能访问并与窗口的被遮挡部分进行交互。

因此,在您的 onCreate() 或 onCreateView() 方法中,只需简单地使用它即可:

getDialog().getWindow().setSoftInputMode(
            WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);

或者在我们处理对话框的活动中,只需在清单中放置android:windowSoftInputMode="adjustPan",并在每个编辑框中使用android:windowSoftInputMode="adjustResize|stateHidden",这将帮助用户轻松地导航到下一个文本框。

需要注意的点:

永远不要使用MATCH_PARENT来使对话框全屏,因为在这里adjustPan不起作用。如果有人想要让对话框适应屏幕,请使用高度为0.96的点(不要超过此值),这样键盘就可以正确地到达编辑框。我像下面这样做:

@Override
public void onStart()
{
    super.onStart();
    Dialog dialog = getDialog();
    if (dialog != null)
    {
        //int height = ViewGroup.LayoutParams.MATCH_PARENT;
        int width = ViewGroup.LayoutParams.MATCH_PARENT;
        Display display = getActivity().getWindowManager().getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        //int width = (int)(size.x * 0.96);
        int h = (int)(size.y * 0.96);

        dialog.getWindow().setLayout(width, h);
    }
}

如果我使用总高度(MATCH_PARENT),那么软键盘会挤压对话框。但是,如果我使用高度点数(这里是0.96,几乎接近于MATCH_PARENT),则它将正常工作。

希望能帮到某些人 :)


2
也许你不需要调整对话框的大小。
将 android:imeOptions="actionNext" 添加到 EditText(除了最后一个)(它会在键盘上添加“下一步”按钮 - 转到下一个 EditText)。
并将 android:imeOptions="actionDone" 添加到最后一个 EditText(“完成”按钮 - 隐藏键盘)。
现在用户应该能够点击按钮。
如果您正在代码中创建文本框,请使用 EditText#setImeOptions 函数。
希望这可以帮到你。

2
谢谢提供信息,但实际用户行为不完全如此。也就是说,他们有自由只填写一个或多个文本框,而不必全部填写。 - Sanj

0

立即显示键盘并调整大小:

editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus) {
            dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        }
    }
});

0
你被迫将它设置为弹出式吗?弹出式看起来太大了,你可能只想将其作为单独的活动。通常,弹出窗口用于提供简短的问题或语句,并带有一些选项,而不是完整的数据输入表单。由于你无法看到大型弹出窗口后面的内容,因此也没有暴露任何底层控件。

3
尽管你的答案听起来对我来说是正确的,但它并没有涉及边缘情况。那么平板电脑上的中等大小的对话框呢? - nmr
没错,从截图来看我也认为是手持设备。如果你要为平板电脑设计单独的用户界面,我想一个中等大小的对话框可能会起作用,但总的来说,对话框应该仅用于非常小的数据输入和通知。如果你想把某个东西做成表格,最好将其作为单独的活动。 - Stealth Rabbi
4
但这并没有回答这个问题。 - ViliusK
1
@ViliusK 我知道这并不是针对他的确切问题的回答,但我提供了一种替代的用户界面建议,让用户界面更清洁,易于实现。如果他不喜欢这个建议,那么由他作为发帖人来投票否决或忽略它。 - Stealth Rabbi

0
对于那些和我处于同样情况的人。
在我的情况下,问题出在活动中具有这些属性的样式上。
<style name="SomeStyleName">
   <item name="android:windowTranslucentStatus">true</item>
   <item name="android:windowTranslucentNavigation">true</item>
</style>

如果windowTranslucentStatuswindowTranslucentNavigation都为true,键盘会覆盖对话框。
因此,我将这些值覆盖为false,仅适用于materialAlertDialog。(在您的情况下可能是AlertDialog或Dialog)
<style name="SomeStyleName">
   <item name="android:windowTranslucentStatus">true</item>
   <item name="android:windowTranslucentNavigation">true</item>
   <item name="materialAlertDialogTheme">@style/TranslucentMaterialAlertDialogTheme</item>
</style>

<style name="TranslucentMaterialAlertDialogTheme" parent="ThemeOverlay.MaterialComponents.MaterialAlertDialog">
   <item name="android:windowTranslucentStatus">false</item>
   <item name="android:windowTranslucentNavigation">false</item>
</style>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接