显示带有EditText的完整底部表单,位于键盘上方。

99
我正在实现一个UI,其中底部工作表将出现在键盘上方,其中包含一个EditText供用户输入值。问题是该视图被键盘部分覆盖,覆盖了底部的底部表单。
这是Bottom Sheet而没有键盘。 Bottom Sheet 这是显示键盘的底部表格。 enter image description here 什么方法最好确保整个底部表单被显示?
谢谢。

在声明活动的清单文件中的活动内,使用“android:windowSoftInputMode =”stateHidden“”,可以防止键盘弹出,直到您触摸EditText。 - brahmy adigopula
我需要键盘显示出来,这样人们就可以输入他们的值。 - advice
2
试试这个:https://dev59.com/6Ok5XIcBkEYKwwoY9-t1#50948146 - Ivan Shafran
请参见 https://dev59.com/6Ok5XIcBkEYKwwoY9-t1。 - CoolMind
2
只需将此代码添加到您的BottomSheetDialogFragment中:"getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)" - Tarique Anowar
显示剩余2条评论
19个回答

177

只是转载了@jblejder的问题,链接为Keyboard hides BottomSheetDialogFragment,因为它对我有效,以便让其他人更容易找到:

我发现最方便的方法是创建样式来更改此设置:

<style name="DialogStyle" parent="Theme.Design.Light.BottomSheetDialog">
    <item name="android:windowIsFloating">false</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
    <item name="android:windowSoftInputMode">adjustResize</item>
</style>

将以下代码设置在BottomSheetDialogFragment的onCreate方法中:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setStyle(DialogFragment.STYLE_NORMAL, R.style.DialogStyle)
}

这是在我的设备上的样子:

在此输入图像描述

==== 更新 ====

正如评论中已经多次提到的那样,您可能还需要将BottomSheetDialog的状态设置为STATE_EXPANDED,就像下面Nordknight的答案一样。

dialog = new BottomSheetDialog(getContext(), R.style.BottomSheetDialog);  
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    BottomSheetDialog d = (BottomSheetDialog) dialog;
                    FrameLayout bottomSheet = d.findViewById(R.id.design_bottom_sheet);
                    BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
                    bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
                }
            },0);
        }
    });

6
对我没有用。在出现键盘之前,一个键盘出现在EditText上方,所以EditText被提起并允许输入,但不能按下下面的“按钮”。应用了你的解决方法后,什么都没有改变。 - CoolMind
4
只有当底部表单片段布局的根是ScrollView时才能正常工作。 - Yaswant Narayan
4
动态底部面板的效果非常好。只需在声明时设置样式即可。BottomSheetDialog bd = new BottomSheetDialog(this, R.style.DialogStyle); - kabayaba
1
它可以工作,但您需要将状态扩展到BottomSheetDialog => 此解决方案+https://dev59.com/TlYN5IYBdhLWcg3wEErU#50798800 - M Moersalin
5
请将以下代码添加到onCreateDialog()中,同时与上面在OnCreateView()方法中的样式一起:override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val bottomSheetDialog = super.onCreateDialog(savedInstanceState) if (bottomSheetDialog is BottomSheetDialog) { bottomSheetDialog.behavior.skipCollapsed = true bottomSheetDialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED } return bottomSheetDialog } - Prasad Mhapankar
显示剩余4条评论

21
这可能是一个冗余的答案,仅仅指出了问题。如果你正在使用BottomSheetDialogFragment,唯一的方法是将属性android:windowIsFloating启用为true。这将使整个窗口位于试图占据其后面空间的任何内容之上。
<style name="BottomSheetDialogThemeNoFloating" parent="Theme.Design.Light.BottomSheetDialog">
        <item name="android:windowIsFloating">false</item>
        <item name="android:windowSoftInputMode">adjustResize|stateVisible</item>
</style>

然后在您对话框的onCreate()中,设置此样式。

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // set the window no floating style
        setStyle(DialogFragment.STYLE_NORMAL, R.style.AppRoundedBottomSheetDialogThemeNoFloating)
}

对于那些经常使用底部表格并可能希望处理EditText和软键盘重叠的人来说,这非常方便。

注意:mikepenz的KeyboardUtil类在某些手机上存在问题,即使为提供的整个内容视图提供了底部填充,输入字段的内容视图仍会自动推到键盘上方。


4
当我使用BottomSheetDialogFragment时,这对我很有效。 - Sagar Patel
如果我这样做,我就看不到我的圆角半径了。 - Sachin Mandhare
请问这个样式 XML 应该放在哪里?请提供路径。 - SimpleGuy
4
你说要将它设置为“true”,但是写的是<item name="android:windowIsFloating">false</item>。到底应该选哪一个? - mathematics-and-caffeine

9
dialog = new BottomSheetDialog(getContext(), R.style.BottomSheetDialog);  
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    BottomSheetDialog d = (BottomSheetDialog) dialog;
                    FrameLayout bottomSheet = d.findViewById(R.id.design_bottom_sheet);
                    BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
                    bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
                }
            },0);
        }
    });

这段代码在Fragment的onCreateView方法中运行良好(感谢ADM)


1
它提醒了 https://dev59.com/KVcO5IYBdhLWcg3wkiVN#45706484(但在我的情况下不起作用)。 - CoolMind

9
一些答案看起来比其他答案更有效,但在使用新的Material Design组件而不是旧的支持库以及使用Kotlin时,需要进行修改。
希望这能帮助到某些人。
BottomSheetDialog(this, R.style.DialogStyle).apply {
    setContentView(layoutInflater.inflate(R.layout.bottom_sheet, null))
    window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
    findViewById<EditText>(R.id.time_et)?.requestFocus()

    show()
}

layout/bottom_sheet.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#ffffff"
        android:padding="16dp">

    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">


        <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">

            <View
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1" />

            <LinearLayout
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="5"
                    android:orientation="vertical">

                <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Time"
                        android:textColor="#000000"
                        android:textSize="24sp"
                        android:textStyle="bold" />

                <LinearLayout
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="8dp"
                        android:orientation="horizontal">

                    <EditText
                            android:id="@+id/time_et"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:inputType="numberSigned"
                            android:minWidth="50dp"
                            android:text="15" />

                    <TextView
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_marginLeft="8dp"
                            android:text="min" />

                </LinearLayout>


            </LinearLayout>

        </LinearLayout>


        <Button
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="16dp"
                android:background="#000"
                android:text="Save"
                android:textColor="#fff" />

    </LinearLayout>

</ScrollView>

styles.xml(针对使用statusBarColor的v-21进行拆分)

    <style name="DialogStyle" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
        <item name="android:windowIsFloating">false</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
        <item name="android:windowSoftInputMode">adjustResize</item>
    </style>

2
这是唯一适用于我的 DialogStyle,我使用 BottomSheetDialogFragment。 - Dantalian
设置windowSoftInputMode,特别是对于BottomSheetDialogFragment,这对我起到了作用。<item name="android:windowSoftInputMode">adjustResize</item> - isles1217

7
      private fun enterMobileNumberPopUp() {                                         
    val dialog = BottomSheetDialog(this,R.style.DialogStyle)
    val view = layoutInflater.inflate(R.layout.layout_otp, null)
    dialog.setContentView(view)
    dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
    dialog.show()}
  • 这是处理底部弹出框最简单和最好的方法,您可以在方法中调用它enter image description here
<style name="DialogStyle" parent="Theme.Design.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowSoftInputMode">adjustResize</item>

样式参考


7

对于此类情况,可以使用 BottomSheetDialog。它会在软键盘打开时打开,并将焦点放在编辑文本上。但是用户仍然可以关闭软键盘,而对话框将被重置为底部。再次聚焦将使对话框出现在软键盘顶部。

 public void showDialog()  {
    final BottomSheetDialog dialog=new BottomSheetDialog(this);
    dialog.setContentView(R.layout.item_dialog);
    dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
    dialog.show();
}

你可以使BottomSheetDialog在键盘上方展开。但是为此,你需要在软键盘打开后调用它。展开的代码是:
 BottomSheetDialog d = (BottomSheetDialog) dialog;
            FrameLayout bottomSheet = (FrameLayout) d.findViewById(android.support.design.R.id.design_bottom_sheet);
            BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);

我已经在DialogInterface.OnShowListener()上进行了测试,但它没有起作用。通过1秒的延迟测试,它可以工作。但延迟不是解决方案。您需要找出应该在哪个操作上扩展对话框。

 final BottomSheetDialog dialog=new BottomSheetDialog(this);
    dialog.setContentView(R.layout.item_dialog);
    dialog.getWindow().setSoftInputMode(
            WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE|
                    WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            FrameLayout bottomSheet = (FrameLayout) dialog.findViewById(android.support.design.R.id.design_bottom_sheet);
            BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);
        }
    },2000);
    dialog.show();

1
使用 BottomSheetDialog,但它仍然覆盖了 EditText 下面的底部区域。 - advice
2
我正在尝试展示整个BottomSheetDialog,这样我就可以在EditText下方放置其他内容并且仍然能够看到它们。 - advice
1
我尝试了你的“expand”代码并加入了计时器,但对我没有任何影响。 - advice
我已经使用handler.postDelay()测试过了,它可以正常工作。不过试一下查看BottomSheetFragment,也许它能满足你的需求。 - ADM
我之前也使用了 handler.postDelayed(),并且在此之前我也使用了 BottomSheetFragment,但似乎问题依旧存在。 - advice
显示剩余2条评论

6
        bottomSheetDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);

一定能够正常工作。


你从哪里获得bottomSheetDialog? - AtomicallyBeyond
从 Material 的 BottomSheetDialog 类中,你可以在文档中找到它,但要使其在移动键盘上方,您需要编写提到的代码。 - Abdullah Razzaq

6
对于使用 Material Components 主题的人,这是一个更新后的答案,并且还改进了答案,以消除在每个对话框的 onCreate() 中添加任何内容的需要。
在您的主 AppTheme 样式中,您可以添加属性 bottomSheetDialogTheme,将样式应用于所有 BottomSheetDialogFragments:
 <style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
    <item name="colorPrimary">@color/primary</item>
    <item name="colorPrimaryDark">@color/primary_dark</item>
    <item name="colorAccent">@color/accent</item>
    <item name="bottomSheetDialogTheme">@style/BottomSheetDialogStyle</item>
  </style>

因此,不需要在您的BottomSheetDialogFragment代码中添加任何内容。

然后,就像以前的回答一样,您的对话框样式需要与Material Components库相匹配(否则会得到一些外观奇怪的按钮、编辑框等):

 <style name="BottomSheetDialogStyle" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
    <item name="android:windowIsFloating">false</item>
    <item name="android:windowSoftInputMode">adjustResize</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
    <item name="colorPrimary">@color/primary</item>
    <item name="colorPrimaryDark">@color/primary_dark</item>
    <item name="colorAccent">@color/accent</item>
  </style>

请注意,我在这里添加了我的应用程序主题颜色;由于Android样式中不能多重继承,您可能希望在此定义这些颜色,以便任何按钮和强调与您的应用程序的其余部分保持一致。

5

如果您正在使用底部表单片段,覆盖getTheme().setStyle对我来说没有起作用。请将整个布局包装在NestedScrollView中。

themes.xml

<style name="BottomSheetDialogStyle" parent="Theme.Design.BottomSheetDialog">
        <item name="android:windowBackground">@null</item>
        <item name="android:windowIsFloating">false</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
        <item name="bottomSheetStyle">@style/bottomSheetBackground</item>
        <item name="android:windowSoftInputMode">adjustResize|stateVisible</item>
    </style>

底部弹出式片段

@Override
public int getTheme() {
    return R.style.BottomSheetDialogStyle;
}

5
只需编程写出以下内容。
override fun setupDialog(dialog: Dialog, style: Int) {
        super.setupDialog(dialog, style)
        dialog.window?.setSoftInputMode(             WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE or 
      WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
      );
      }

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