Show entire bottom sheet with EditText above Keyboard

后端 未结 8 1318
北恋
北恋 2020-11-30 21:27

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 overlap

相关标签:
8条回答
  • 2020-11-30 21:50

    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);
                }
            }
        }
    
    0 讨论(0)
  • 2020-11-30 21:54
    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)

    0 讨论(0)
  • 2020-11-30 22:01

    Just reposting @jblejder from this question Keyboard hides BottomSheetDialogFragment 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:

    ==== 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);
            }
        });
    
    0 讨论(0)
  • 2020-11-30 22:05

    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>
    
    0 讨论(0)
  • 2020-11-30 22:07

    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)
        }
    
    0 讨论(0)
  • 2020-11-30 22:09

    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();
    
    0 讨论(0)
提交回复
热议问题