How to disable BottomSheetDialogFragment dragging

29,254

Solution 1

Having created MyActivity as follows:

public class MyActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);

        new MyBottomSheetFragment().show(getSupportFragmentManager(), "tag");
    }

    public static class MyBottomSheetFragment extends BottomSheetDialogFragment {

        @Override
        public void setupDialog(Dialog dialog, int style) {
            BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) dialog;
            bottomSheetDialog.setContentView(R.layout.sample);

            try {
                Field behaviorField = bottomSheetDialog.getClass().getDeclaredField("behavior");
                behaviorField.setAccessible(true);
                final BottomSheetBehavior behavior = (BottomSheetBehavior) behaviorField.get(bottomSheetDialog);
                behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {

                    @Override
                    public void onStateChanged(@NonNull View bottomSheet, int newState) {
                        if (newState == BottomSheetBehavior.STATE_DRAGGING{ 
                            behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
                        }
                    }

                    @Override
                    public void onSlide(@NonNull View bottomSheet, float slideOffset) {
                    }
                });
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
}

Where R.layout.sample is a simple layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <View
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="#e479da" />

    <View
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="#798de4" />

    <View
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="#e4db79" />

</LinearLayout>

You'll get following output:

A part of solution is borrowed from this answer.

Solution 2

There is simpler way of achieving the same after material design 1.2.0 was released.

https://developer.android.com/reference/com/google/android/material/bottomsheet/BottomSheetBehavior#setdraggable

When calling from BottomSheetDialogFragment:

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val bottomSheetDialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog
        bottomSheetDialog.setOnShowListener {
            val bottomSheet = bottomSheetDialog
                .findViewById<FrameLayout>(com.google.android.material.R.id.design_bottom_sheet)

            if (bottomSheet != null) {
                val behavior: BottomSheetBehavior<*> = BottomSheetBehavior.from(bottomSheet)
                behavior.isDraggable = false
            }
        }
        return bottomSheetDialog
    }

Or with styling:

    <style name="SomeStyle" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
        <item name="behavior_draggable">false</item>
    </style>

And then in onCreate of your dialog fragment:

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

Solution 3

Too late but worth to share.

  behavior.setDraggable(false)

This line did the job.

Solution 4

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
    //Disable dragging by set isDraggable to false
    val bottomSheetDialog = dialog as BottomSheetDialog
    val bottomSheetBehavior = bottomSheetDialog.behavior
    bottomSheetBehavior.isDraggable = false
}

Solution 5

If you want to disable BottomSheetDialog dragging, try to set setCancelable(false).

Share:
29,254
FarshidABZ
Author by

FarshidABZ

Updated on October 16, 2021

Comments

  • FarshidABZ
    FarshidABZ over 2 years

    How to disable BottomSheetDialogFragment dragging by finger?

    I saw similar questions, but they're all about BottomSheet not BottomSheetDialogFragment.

  • FarshidABZ
    FarshidABZ over 6 years
    This is good sample code, but there are some issues. First, setupDialog isn't the BottomSheetDialogFragment method. Second, I have a recycler view in my bottom sheet view, and when I drag bottom sheet from recyclerView's blank spaces bottom sheet slides down.
  • azizbekian
    azizbekian over 6 years
    setupDialog() is a method from DialogFragment class. Have substituted it with onCreateDialog(). Cannot understand your use case. Can you post a simple project at github with that behavior?
  • Ahmad Reza Enshaee
    Ahmad Reza Enshaee over 5 years
    it works in my case, just had a problem where clicking on the outside field would become disabled after setting cancelable to false. thanks. +1
  • axita.savani
    axita.savani about 5 years
    it's getting warning in my fragment: java.lang.NoSuchFieldException: No field mBehavior in class Landroid/support/design/widget/BottomSheetDialog; (declaration of 'android.support.design.widget.BottomSheetDialog' ) System.err: at java.lang.Class.getDeclaredField(Native Method)
  • Tamoxin
    Tamoxin about 5 years
    The field's name is behavior, no mBehavior. That's why you are getting that error.
  • azizbekian
    azizbekian about 5 years
    Thanks, @MarcoCarrizales, updated answer from mBehavior to behavior.
  • Tamoxin
    Tamoxin about 5 years
    I also changed the code to be in setupDialog() instead of onCreateDialog()
  • Tamoxin
    Tamoxin about 5 years
    @sagarsuri I just posted the Kotlin version with data binding of this answer. I hope you find it useful.
  • FarshidABZ
    FarshidABZ over 4 years
    And how can we get bottomSheetBehavior object?
  • Dilavar Malek
    Dilavar Malek over 4 years
    please check answer
  • Andrey Uglev
    Andrey Uglev over 4 years
    what class has isDraggable?
  • Devendra Singh
    Devendra Singh over 4 years
    final BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet); stackoverflow.com/questions/35618998/…
  • C.Schone
    C.Schone over 3 years
    This is the correct answer and should have way more up votes!
  • lasec0203
    lasec0203 over 3 years
    @AndreyUglev it comes from BottomSheetDialog.behavior.
  • DIRTY DAVE
    DIRTY DAVE over 3 years
    Using the styling is way better than the other answers. Thanks!
  • Bugs Happen
    Bugs Happen about 3 years
    Answer by @jakubbialkowski below is better in my opinion.
  • Stephen Ruda
    Stephen Ruda almost 3 years
    This is the correct answer. This method was added in a new version of the material library. I am using com.google.android.material:material:1.3.0 and I have the setDraggable() method. I did not have the method when I was on version 1.1.0. It is in the documentation as well... developer.android.com/reference/com/google/android/material/‌​…
  • Saka
    Saka almost 3 years
    isDraggable in Kotlin. if you use Java use setDraggable(boolean draggable)
  • Nishant Jalan
    Nishant Jalan over 2 years
    Simplest and most elegant.
  • Steffen Funke
    Steffen Funke over 2 years
    Not too late, perfect timing :)