Set state of BottomSheetDialogFragment to expanded

前端 未结 14 759
有刺的猬
有刺的猬 2020-11-30 19:11

How do you set the state of a fragment extending BottomSheetDialogFragment to expanded using BottomSheetBehavior#setState(STATE_EXPANDED) using the

相关标签:
14条回答
  • 2020-11-30 19:50

    All results with using onShow() cause random render bug when soft keyboard is displayed. See screenshot bellow - BottomSheet dialog is not at bottom of screen but is placed like keyboard was displayed. This problem is not occurs always but quite often.

    UPDATE

    My solution with reflection of private member is unnecessary. Using postDelayed (with about 100 ms) for creating and showing dialog after hide soft keyboard is better solution. Then the above solutions with onShow() are ok.

    Utils.hideSoftKeyboard(this);
    mView.postDelayed(new Runnable() {
        @Override
        public void run() {
            MyBottomSheetDialog dialog = new MyBottomSheetDialog();
            dialog.setListener(MyActivity.this);
            dialog.show(getSupportFragmentManager(), TAG_BOTTOM_SHEET_DLG);
        }
    }, 100);
    

    So I implement other solution, but it requires using reflection, because BottomSheetDialog has all members as private. But it solves render bug. BottomSheetDialogFragment class is only AppCompatDialogFragment with onCreateDialog method which create BottomSheetDialog. I create own child of AppCompatDialogFragment which create my class extends BottomSheetDialog and which solves access to private behavior member and set it in onStart method to STATE_EXPANDED state.

    public class ExpandedBottomSheetDialog extends BottomSheetDialog {
    
        protected BottomSheetBehavior<FrameLayout> mBehavior;
    
        public ExpandedBottomSheetDialog(@NonNull Context context, @StyleRes int theme) {
            super(context, theme);
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            try {
                Field privateField = BottomSheetDialog.class.getDeclaredField("mBehavior");
                privateField.setAccessible(true);
                mBehavior = (BottomSheetBehavior<FrameLayout>) privateField.get(this);
            } catch (NoSuchFieldException e) {
                // do nothing
            } catch (IllegalAccessException e) {
                // do nothing
            }
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            if (mBehavior != null) {
                mBehavior.setSkipCollapsed(true);
                mBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
            }
        }
    }
    
    
    public class AddAttachmentBottomSheetDialog extends AppCompatDialogFragment {
    
        ....
    
        @NonNull
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            return new ExpandedBottomSheetDialog(getContext(), getTheme());
        }
    
        ....
    }
    
    0 讨论(0)
  • 2020-11-30 19:51

    A simplistic and elegant solution:

    BottomSheetDialogFragment could be subclassed to address this:

    class NonCollapsableBottomSheetDialogFragment extends BottomSheetDialogFragment {
    
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            final BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
    
            bottomSheetDialog.setOnShowListener(new DialogInterface.OnShowListener() {
                @Override
                public void onShow(DialogInterface dialog) {
                    FrameLayout bottomSheet = bottomSheetDialog.findViewById(com.google.android.material.R.id.design_bottom_sheet);
    
                    BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
                    behavior.setSkipCollapsed(true);
                    behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
                }
            });
            return bottomSheetDialog;
        }
    }
    

    So extend this class instead of BottomSheetDialogFragment to create your own bottom sheet.

    Note

    Change com.google.android.material.R.id.design_bottom_sheet to android.support.design.R.id.design_bottom_sheet if your project uses old Android support libraries.

    0 讨论(0)
提交回复
热议问题