Show entire bottom sheet with EditText above Keyboard

AndroidAndroid LayoutAndroid SoftkeyboardBottom Sheet

Android Problem Overview


I'm implementing a UI where a bottom sheet will appear above the keyboard with an EditText for the user to enter a value. The problem is the View is being partially overlapped by the keyboard, covering up the bottom of the bottom sheet.

Here is the Bottom Sheet and no keyboard.

Bottom Sheet

Here is the Bottom Sheet with the keyboard showing.

enter image description here

What's the best method to ensure the entire Bottom Sheet is shown?

Thanks.

Android Solutions


Solution 1 - Android

Just reposting @jblejder from this question https://stackoverflow.com/questions/44625365/keyboard-hides-bottomsheetdialogfragment/50948146#50948146 since it worked for me, to make it easier for others to find:

The most convenient way that I found to change this is by creating style:

<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>

And set this in onCreate method of your BottomSheetDialogFragment:

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

This is how it looks on my device:

enter image description here

==== UPDATE ====

As already mentioned in the Comments a few times, you might also need to set the state of the BottomSheetDialog to STATE_EXPANDED like in Nordknight's answer below

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);
        }
    });

Solution 2 - Android

This might be a redundant answer. Although just pointing out the issue. If you're using BottomSheetDialogFragment, the only way is to enable the attribute android:windowIsFloating to true. This will enable the whole window to be on top of whatever is trying to take the space behind it.

<style name="BottomSheetDialogThemeNoFloating" parent="Theme.Design.Light.BottomSheetDialog">
        <item name="android:windowIsFloating">false</item>
        <item name="android:windowSoftInputMode">adjustResize|stateVisible</item>
</style>

Then in your onCreate() of your dialog, set this style.

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

This is handy for those who frequently use bottom sheets and may want to deal with EditText and soft keyboard overlapping each other.

Note: The class KeyboardUtil by mikepenz has an issue in which on certain phones, the content view with input field is automatically pushed above keyboard despite giving bottom padding to the whole content view supplied.

Solution 3 - Android

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);
        }
    });

This code works fine at Fragment's onCreateView method (thanks for ADM)

Solution 4 - Android

Some answers seem to do the trick better than others but will need modification when using the new material design components instead of the older support libraries while also using kotlin

Hope this will help someone.

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>

styes.xml (Split for v-21 for using statusBarColor)

    <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>

Solution 5 - Android

A BottomSheetDialog can be helpful for this. it will open with Softkeyboard open with focus on edit text.But user can still close the Softkeyboard and Dialog will be reset to Bottom. Again focusing will make dialog appear at top of Softkeyboard.

 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();
}

You can make the BottomSheetDialog expanded over keyboard . But for this you need to call it after SoftKeyboard Open. the Expand code is .

 BottomSheetDialog d = (BottomSheetDialog) dialog;
            FrameLayout bottomSheet = (FrameLayout) d.findViewById(android.support.design.R.id.design_bottom_sheet);
            BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);

I have tested it on DialogInterface.OnShowListener() but its not working . Tested with it 1 second delay its working . But Delay is not the solution . You need to figure out the on which action you should expand the dialog.

 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();

Solution 6 - Android

An updated answer for those using Material Components theme, and also an improved answer to remove the need to add anything into each dialog's onCreate().

In your main AppTheme style, you can add the attribute bottomSheetDialogTheme to apply the style to all of your 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>

So with the above, no need to add anything to your BottomSheetDialogFragment code.

And then, as previous answers, your Dialog style, noting to also match the style to the same Material Components library (or you'll get some weird looking buttons, edittexts etc):

 <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>

Note that I am adding my app theme colors back in here; as you can't have multiple inheritance in Android styles, you may want these colors defining here so any buttons and accents align with the rest of your app.

Solution 7 - Android

This one working

 BottomSheetDialog dialog = new BottomSheetDialog(this, R.style.DialogStyle);
    View sheetView = getLayoutInflater().inflate(R.layout.dialog_remark, null);
    Objects.requireNonNull(dialog.getWindow())
            .setSoftInputMode(SOFT_INPUT_STATE_VISIBLE);
    dialog.setContentView(sheetView);
    dialog.setOnShowListener(new DialogInterface.OnShowListener() {
        @Override
        public void onShow(DialogInterface dialog) {
            BottomSheetDialog d = (BottomSheetDialog) dialog;
            View bottomSheetInternal = d.findViewById(com.google.android.material.R.id.design_bottom_sheet);
            BottomSheetBehavior.from(bottomSheetInternal).setState(BottomSheetBehavior.STATE_EXPANDED);
        }
    });
    dialog.show();

add this style to your styles.xml

 <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">adjustPan</item>
</style>

add your layout like this

 <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
android:id="@+id/scrollview"

    android:layout_height="match_parent">

    <androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"

        android:layout_margin="8dp">

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

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_margin="8dp"
                android:fontFamily="@font/montserratmedium"
                android:text="Add Remarks"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="8dp"
                android:layout_marginTop="24dp"
                android:fontFamily="@font/montserratmedium"
                android:text="Branch"
                android:textColor="#8B8B8B"
                android:textSize="18sp" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="8dp"
                android:layout_marginTop="8dp"
                android:fontFamily="@font/montserratmedium"
                android:text="BLR-CO-SINDHUBHAVAN-384"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="8dp"
                android:layout_marginTop="24dp"
                android:fontFamily="@font/montserratmedium"
                android:text="Enter Remarks"
                android:textColor="#8B8B8B"
                android:textSize="18sp" />


            <EditText

                android:id="@+id/input_remark"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="10dp"
                android:layout_marginTop="8dp"
                android:background="@drawable/remark_inputbg"
                android:gravity="start"

                android:inputType="textMultiLine"
                android:lines="5" />

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <LinearLayout
                    android:id="@+id/action"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal"
                    android:weightSum="2">

                    <Button
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_margin="8dp"
                        android:layout_weight="1"
                        android:background="@drawable/reset_bg"
                        android:padding="8dp"
                        android:text="CANCEL" />

                    <Button
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_margin="8dp"
                        android:layout_weight="1"
                        android:background="#4F4DBB"
                        android:padding="8dp"
                        android:text="CANCEL"
                        android:textColor="@android:color/white" />
                </LinearLayout>
            </RelativeLayout>


        </LinearLayout>

    </androidx.cardview.widget.CardView>

</ScrollView>

Solution 8 - Android

      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()}
  • THIS IS THE MOST EASY WAY AND BEST WAY TO HANDLE BOTTOM SHEET DIALOG YOU CAN CALL THIS IN METHOD 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>

Style reference

Solution 9 - Android

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

It will work for sure.

Solution 10 - Android

Try this solution:
https://stackoverflow.com/a/45197761/18311024

Using NestedScrollView as root layout work for me.

Solution 11 - Android

For this, I found an AlertDialog worked best. While it doesn't sit flush against the bottom or side of the screen, it still looks good enough.

First, create the AlertDialog with your view.

val view = LayoutInflater.from(context).inflate(R.layout.alert, null)

dialog = AlertDialog.Builder(context)
             .setView(view)
             .create()

Next, set the gravity.

    dialog.window.attributes.gravity = Gravity.BOTTOM

And finally, show it.

dialog.show()

You can also bind the keyboard to stay with the dialog, by using an onDismissListener.

After showing the AlertDialog, I force up the keyboard.

Call this method, passing in your EditText.

fun showKeyboard(view: View?) {
        if (view == null) return;

        val imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
    }

And for dismissing within the onDismissListener.

private fun hideKeyboard() {
        val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0)
    }

Solution 12 - Android

My answer might be useful for someone who is still looking for solution. If keyboard is covering edittext in BottomSheetDialogFragment then in setupDialog() method create instance of a class KeyboardUtil and pass your rootview.

    @Override
    public void setupDialog(final Dialog dialog, int style) {
        super.setupDialog(dialog, style);
        View view = View.inflate(getActivity(), R.layout.reopen_dialog_layout, null);
        new KeyboardUtil(getActivity(), view);
}

Create a new class

    public class KeyboardUtil {
        private View decorView;
        private View contentView;
        //a small helper to allow showing the editText focus
        ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Rect r = new Rect();
                //r will be populated with the coordinates of your view that area still visible.
                decorView.getWindowVisibleDisplayFrame(r);
    
                //get screen height and calculate the difference with the useable area from the r
                int height = decorView.getContext().getResources().getDisplayMetrics().heightPixels;
                int diff = height - r.bottom;
    
                //if it could be a keyboard add the padding to the view
                if (diff != 0) {
                    // if the use-able screen height differs from the total screen height we assume that it shows a keyboard now
                    //check if the padding is 0 (if yes set the padding for the keyboard)
                    if (contentView.getPaddingBottom() != diff) {
                        //set the padding of the contentView for the keyboard
                        contentView.setPadding(0, 0, 0, diff);
                    }
                } else {
                    //check if the padding is != 0 (if yes reset the padding)
                    if (contentView.getPaddingBottom() != 0) {
                        //reset the padding of the contentView
                        contentView.setPadding(0, 0, 0, 0);
                    }
                }
            }
        };
    
        public KeyboardUtil(Activity act, View contentView) {
            this.decorView = act.getWindow().getDecorView();
            this.contentView = contentView;
    
            //only required on newer android versions. it was working on API level 19
            if (Build.VERSION.SDK_INT >= 19) {
                decorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
            }
        }
    
        /**
         * Helper to hide the keyboard
         *
         * @param act
         */
        public static void hideKeyboard(Activity act) {
            if (act != null && act.getCurrentFocus() != null) {
                InputMethodManager inputMethodManager = (InputMethodManager) act.getSystemService(Activity.INPUT_METHOD_SERVICE);
                inputMethodManager.hideSoftInputFromWindow(act.getCurrentFocus().getWindowToken(), 0);
            }
        }
    
        public void enable() {
            if (Build.VERSION.SDK_INT >= 19) {
                decorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
            }
        }
    
        public void disable() {
            if (Build.VERSION.SDK_INT >= 19) {
                decorView.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
            }
        }
    }

Solution 13 - Android

Kotlin, +viewBinding, +by using the accepted answer's dialog style

val bottomSheet = BottomSheetDialog(this, R.style.BottomSheetDialogStyle)
val binding = [YourSheetBinding].inflate(LayoutInflater.from(YourActivity.this))
bottomSheet.setContentView(binding.root)
bottomSheet.behavior.state = BottomSheetBehavior.STATE_EXPANDED
bottomSheet.show()

Solution 14 - Android

See https://stackoverflow.com/a/61813321/2914140:

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog
    dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
    return dialog
}

But if a layout is not tall enough, you can use https://stackoverflow.com/a/66287187/2914140 instead. It will open BottomSheetDialog almost fullscreen:

<style name="BottomSheetDialogTheme" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
  <item name="android:windowIsFloating">false</item>
  <item name="android:windowSoftInputMode">adjustResize|stateVisible</item>
</style>

Solution 15 - Android

Fiddling with BottomSheetDialogFragmentwasn't really worth it. So I just changed it to a simple DialogFragment and just set its gravity to bottom:

window.setGravity(Gravity.BOTTOM);

Worked like a charm.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionadviceView Question on Stackoverflow
Solution 1 - AndroidDistraView Answer on Stackoverflow
Solution 2 - AndroidDebdeepView Answer on Stackoverflow
Solution 3 - AndroidAliaksei PakaliukView Answer on Stackoverflow
Solution 4 - AndroidxdbasView Answer on Stackoverflow
Solution 5 - AndroidADMView Answer on Stackoverflow
Solution 6 - AndroidVin NormanView Answer on Stackoverflow
Solution 7 - AndroidArunachalam kView Answer on Stackoverflow
Solution 8 - AndroidRushikesh ChavanView Answer on Stackoverflow
Solution 9 - AndroidAbdullah RazzaqView Answer on Stackoverflow
Solution 10 - Androidyuyu linView Answer on Stackoverflow
Solution 11 - AndroidadviceView Answer on Stackoverflow
Solution 12 - AndroidFatal ExceptionView Answer on Stackoverflow
Solution 13 - AndroidAmosView Answer on Stackoverflow
Solution 14 - AndroidCoolMindView Answer on Stackoverflow
Solution 15 - AndroidsoshialView Answer on Stackoverflow