BottomSheetDialogFragment - How to set expanded height (or min top offset)

后端 未结 5 1674
执笔经年
执笔经年 2020-12-12 18:13

I create a BottomSheetDialogFragment and I want to adjust it\'s maximum expanded height. How can I do that? I can retrieve the BottomSheetBehaviour

相关标签:
5条回答
  • 2020-12-12 18:21

    Its works for me. Add code on BottomSheetDialogFragment's onViewCreated() methode

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        view.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
            override fun onGlobalLayout() {
    
                view.viewTreeObserver.removeOnGlobalLayoutListener(this)
    
                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!!)
                behavior.state = BottomSheetBehavior.STATE_EXPANDED
    
                val newHeight = activity?.window?.decorView?.measuredHeight
                val viewGroupLayoutParams = bottomSheet.layoutParams
                viewGroupLayoutParams.height = newHeight ?: 0
                bottomSheet.layoutParams = viewGroupLayoutParams
            }
        })
        dialogView = view
    }
    

    Don't forget to remove viewTreeObserver.

    override fun onDestroyView() {
        dialogView?.viewTreeObserver?.addOnGlobalLayoutListener(null)
        super.onDestroyView()
    }
    
    0 讨论(0)
  • 2020-12-12 18:22

    The height is being wrapped because of the inflated view is added to the FrameLayout which has layout_height=wrap_content. See FrameLayout (R.id.design_bottom_sheet) at https://github.com/dandar3/android-support-design/blob/master/res/layout/design_bottom_sheet_dialog.xml.

    The class below makes the bottom sheet full screen, background transparent and fully expanded to the top.

    public class FullScreenBottomSheetDialogFragment extends BottomSheetDialogFragment {
    
    
        @CallSuper
        @Override
        public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
            ButterKnife.bind(this, view);
        }
    
    
        @Override
        public void onStart() {
            super.onStart();
            Dialog dialog = getDialog();
    
            if (dialog != null) {
                View bottomSheet = dialog.findViewById(R.id.design_bottom_sheet);
                bottomSheet.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
            }
            View view = getView();
            view.post(() -> {
                View parent = (View) view.getParent();
                CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) (parent).getLayoutParams();
                CoordinatorLayout.Behavior behavior = params.getBehavior();
                BottomSheetBehavior bottomSheetBehavior = (BottomSheetBehavior) behavior;
                bottomSheetBehavior.setPeekHeight(view.getMeasuredHeight());
                ((View)bottomSheet.getParent()).setBackgroundColor(Color.TRANSPARENT)
    
            });
        }
    
    }
    

    --- EDIT Aug 30, 2018 --- I realized a year later that the background was coloured on a wrong view. This dragged the background along with the content while a user was dragging the dialog. I fixed it so that the parent view of the bottom sheet is coloured.

    0 讨论(0)
  • 2020-12-12 18:35

    Kotlin

    In my case I need to define a fixed height and I did the following:

    val bottomSheet: View? = dialog.findViewById(R.id.design_bottom_sheet)
    BottomSheetBehavior.from(bottomSheet!!).peekHeight = 250
    

    this way you also have access to any property of the BottomSheetBehavior such as halfExpandedRatio

    0 讨论(0)
  • 2020-12-12 18:44

    I found a much simpler answer; in your example where you obtain the FrameLayout for the bottom sheet using this code

    View bottomSheet = dialog.findViewById(R.id.design_bottom_sheet);
    

    you can then set the height on the layout params for that View to whatever height you want to set the expanded height to.

    bottomSheet.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
    
    0 讨论(0)
  • 2020-12-12 18:47

    BIG UPDATE Avoiding duplicated code I'm giving a link to the full answer in where you can find all the explanation about how to get full behavior like Google Maps.


    I want to adjust it's maximum expanded height. How can I do that?

    Both BottomSheet and BottomSheetDialogFragment use a BottomSheetBehavior that you can found in Support Library 23.x

    That Java class has 2 different uses for mMinOffset, one of them is used to define the area of the parent it will use to draw his content (maybe a NestedScrollView). And the other use if for define the expanded anchor point, I mean, if you slide it up form STATE_COLLAPSEDit will animate your BottomSheetuntil he reached this anchor point BUT if you can still keep sliding up to cover all parent height (CoordiantorLayout Height).

    If you took a look at BottomSheetDialog you will see this method:

    private View wrapInBottomSheet(int layoutResId, View view, ViewGroup.LayoutParams params) {
        final CoordinatorLayout coordinator = (CoordinatorLayout) View.inflate(getContext(),
                android.support.design.R.layout.design_bottom_sheet_dialog, null);
        if (layoutResId != 0 && view == null) {
            view = getLayoutInflater().inflate(layoutResId, coordinator, false);
        }
        FrameLayout bottomSheet = (FrameLayout) coordinator.findViewById(android.support.design.R.id.design_bottom_sheet);
        BottomSheetBehavior.from(bottomSheet).setBottomSheetCallback(mBottomSheetCallback);
        if (params == null) {
            bottomSheet.addView(view);
        } else {
            bottomSheet.addView(view, params);
        }
        // We treat the CoordinatorLayout as outside the dialog though it is technically inside
        if (shouldWindowCloseOnTouchOutside()) {
            final View finalView = view;
            coordinator.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (isShowing() &&
                            MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_UP &&
                            !coordinator.isPointInChildBounds(finalView,
                                    (int) event.getX(), (int) event.getY())) {
                        cancel();
                        return true;
                    }
                    return false;
                }
            });
        }
        return coordinator;
    }
    



    No idea which one of those 2 behaviors you want but if you need the second one follow those steps:

    1. Create a Java class and extend it from CoordinatorLayout.Behavior<V>
    2. Copy paste code from default BottomSheetBehavior file to your new one.
    3. Modify the method clampViewPositionVertical with the following code:

      @Override
      public int clampViewPositionVertical(View child, int top, int dy) {
          return constrain(top, mMinOffset, mHideable ? mParentHeight : mMaxOffset);
      }
      int constrain(int amount, int low, int high) {
          return amount < low ? low : (amount > high ? high : amount);
      }
      
    4. Add a new state

      public static final int STATE_ANCHOR_POINT = X;
      
    5. Modify the next methods: onLayoutChild, onStopNestedScroll, BottomSheetBehavior<V> from(V view) and setState (optional)

    And here is how its looks like:
    [CustomBottomSheetBehavior]

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