33

I'm trying to show a BottomSheetDialogFragment with a few EditText fields for the user to enter information. I want to show it directly above the keyboard, but it keeps covering up the contents.

This is what happens when I bring up the BottomSheetDialogFragment, you can see it's selecting Card Number EditText, but covering the other content.

BottomSheetDialogFragment covering up content

Ideally, this is what I'm looking for, you can see both EditTexts, and the padding of the View.

BottomSheetDialogFragment not covering up content

I've tried a lot of solutions revolving around windowSoftInputMode, but nothing seems to work. I've set it to adjustResize for the parent Activity and the actual BottomSheetDialogFragment via

dialog.window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)

And I've also tried modifying my layout, changing it from a FrameLayout, to a ScrollView to a CoordinatorLayout to see if that had any effect on the position of the layout, but nothing seems to work.

If anyone knows how to accomplish this, that would be greatly appreciated, thank you.

advice
  • 5,778
  • 10
  • 33
  • 60

8 Answers8

38

Maybe a late answer but would probably help.

Nothing else worked for me. But this solution is working

Inside styles:

<style>  // main theme
    <item name="bottomSheetDialogTheme">@style/BottomSheetDialogTheme</item>
    ........ // rest of the code
</style>

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

Here android:windowIsFloating should be false & android:windowSoftInputMode must be adjustResize

<style name="AppModalStyle" parent="Widget.Design.BottomSheet.Modal">
    <item name="android:background">@drawable/rounded_corner_dialog</item>
</style>

Note: This part is optional but if things don't work perfectly then Wrap layout inside NestedScrollView

<androidx.core.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    
     <--Rest of the layout-->
</androidx.core.widget.NestedScrollView>

On some devices this solution wasn't enough. Adding this to code solved my problem completely.

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    dialog?.setOnShowListener {
        val dialog = it as BottomSheetDialog
        val bottomSheet = dialog.findViewById<View>(R.id.design_bottom_sheet)
        bottomSheet?.let { sheet ->
            dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
            sheet.parent.parent.requestLayout()
        }
    }
}
Muhammad Umair Shafique
  • 2,475
  • 1
  • 30
  • 39
3

This following step might be helpful to resolve your problems.

First add the following line on your EditText in xml file

android:imeOptions="actionSend|flagNoEnterAction"

For example:

<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:inputType="number"
    android:hint="Card number"
    android:imeOptions="actionSend|flagNoEnterAction"/>

Then add the following line on activity tag in AndroidManifest.xml file

android:windowSoftInputMode="stateVisible|adjustResize"

For example:

<activity android:name=".stack.MainActivity"
    android:windowSoftInputMode="stateVisible|adjustResize">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

you can finds more details about On-Screen input method from here.

CoolMind
  • 26,736
  • 15
  • 188
  • 224
3

Try this BottomSheetDialogFragment:

import android.graphics.Rect; 
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.BottomSheetBehavior;
import android.support.design.widget.BottomSheetDialog;
import android.support.design.widget.BottomSheetDialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;

public class TestBottomSheetDialog extends BottomSheetDialogFragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View fragmentView = LayoutInflater.from(getContext()).inflate(R.layout.fragment_bottom_sheet, container, false);
        if (getDialog().getWindow() != null) {
           getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        }
        if (getActivity() != null) {
            View decorView = getActivity().getWindow().getDecorView();
            decorView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
                Rect displayFrame = new Rect();
                decorView.getWindowVisibleDisplayFrame(displayFrame);
                int height = decorView.getContext().getResources().getDisplayMetrics().heightPixels;
                int heightDifference = height - displayFrame.bottom;
                if (heightDifference != 0) {
                    if (fragmentView.getPaddingBottom() != heightDifference) {
                        fragmentView.setPadding(0, 0, 0, heightDifference);
                    }
                } else {
                    if (fragmentView.getPaddingBottom() != 0) {
                        fragmentView.setPadding(0, 0, 0, 0);
                    }
                }
            });
        }
        getDialog().setOnShowListener(dialog -> {
            BottomSheetDialog d = (BottomSheetDialog) dialog;
            View bottomSheetInternal = d.findViewById(android.support.design.R.id.design_bottom_sheet);
            if (bottomSheetInternal == null) return;
             BottomSheetBehavior.from(bottomSheetInternal).setState(BottomSheetBehavior.STATE_EXPANDED);
        });
        return fragmentView;
    }
}
Vitali
  • 694
  • 5
  • 12
  • Probably this is similar to https://stackoverflow.com/questions/46551405/how-to-change-the-default-height-of-bottomsheet-dialog-fragment, but I didn't check. – CoolMind May 06 '19 at 13:55
2

I finally changed the height of dialog when keyboard is open and resized it to normal when it closes.

KeyboardVisibilityEvent library: https://android-arsenal.com/details/1/2519

  KeyboardVisibilityEvent.setEventListener(activity) { isOpen ->
            setDialogHeight(isOpen)
  }

Support min SDK version is 14 for 2.0.0

And set dialog height to 80% when the keyboard opens:

    /**
     * Changes size of dialog based on keyboard visibility state
     */
    private fun setDialogHeight(expanded: Boolean) {
        val dialog = dialog as BottomSheetDialog?
        val bottomSheet =
            dialog!!.findViewById<View>(com.google.android.material.R.id.design_bottom_sheet) as FrameLayout?
        val behavior = BottomSheetBehavior.from(bottomSheet!!)

        val displayMetrics = activity!!.resources.displayMetrics

        val width = displayMetrics.widthPixels
        val height = displayMetrics.heightPixels

        val maxHeight = (height * 0.88).toInt()

        behavior.peekHeight = if (expanded) maxHeight else -1
    }
Morteza Rastgoo
  • 6,772
  • 7
  • 40
  • 61
1

Adding padding to the virtual keyboard is not supported by the Android OS itself, but there are hacky ways to have it.

One way would be to listen to the edittext's focus, and scroll the ScrollView a bit more like so:

edittext.setOnFocusChangeListener(new OnFocusChangeListener() {

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus)
             scrollView.scrollBy(0, 100);

    });

As I said, this way is hacky and not recommended.

Another way (which depends on your layout and Is better if you get it working) would be to set windowSoftInputMode to adjustPan or adjustResize (depending on your layout) for your activity in AndroidManifest.xml.

Adib Faramarzi
  • 3,798
  • 3
  • 29
  • 44
1

I had to enlarge a layout height. A programmatical method from How to change the default height of bottomsheet dialog fragment? didn't help, so I simply changed the layout.

<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <View
        android:id="@+id/top_space"
        android:layout_width="match_parent"
        android:layout_height="10dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />

    <!-- Other views -->

    <View
        android:id="@+id/bottom_space"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/button"
        app:layout_constraintVertical_weight="1"
        />

</android.support.constraint.ConstraintLayout>
CoolMind
  • 26,736
  • 15
  • 188
  • 224
0

Add following style in theme.xml

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

Set this theme to BottomSheet onCreate method.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setStyle(DialogFragment.STYLE_NORMAL,R.style.BottomSheetDialogTheme)
}
Saiful Islam Sajib
  • 2,243
  • 1
  • 12
  • 17
0

these answers work on most devices but on some specific devices it doesn't. What I did here was add a padding to the last element when the keyboard is open.

  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Sep 15 '22 at 18:47