Tonespy
Tonespy

Reputation: 3407

Disabling User dragging on BottomSheet

I am trying to disable user dragging on BottomSheet. The reason I want to disable is two things. 1. It's preventing the ListView from scrolling downward, 2. I don't want users to dismiss using dragging but with a button on the BottomSheetView. This is what I've done

 bottomSheetBehavior = BottomSheetBehavior.from(bottomAnc);
    bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
        @Override
        public void onStateChanged(@NonNull View bottomSheet, int newState) {
            if (newState == BottomSheetBehavior.STATE_EXPANDED) {
                //Log.e("BottomSheet", "Expanded");
            } else if (newState == BottomSheetBehavior.STATE_COLLAPSED) {
                //Log.e("BottomSheet", "Collapsed");
            }
        }

        @Override
        public void onSlide(@NonNull View bottomSheet, float slideOffset) {
            // React to dragging events
            bottomSheet.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    int action = MotionEventCompat.getActionMasked(event);
                    switch (action) {
                        case MotionEvent.ACTION_DOWN:
                            return false;
                        default:
                            return true;
                    }
                }
            });
        }
    });

The bottomSheetLayout

    <?xml version="1.0" encoding="utf-8"?><FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
app:behavior_hideable="true"
app:behavior_peekHeight="0dp"
app:layout_behavior="@string/bottom_sheet_behavior"
android:id="@+id/bottomSheet">

<android.support.v7.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:elevation="10dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center_vertical">

            <TextView
                android:id="@+id/text1"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="Order Items"
                android:layout_margin="16dp"
                android:textAppearance="@android:style/TextAppearance.Large"/>


            <Button
                android:layout_width="50dp"
                android:layout_height="wrap_content"
                android:layout_marginRight="5dp"
                android:background="@drawable/bg_accept"/>

            <Button
                android:layout_width="50dp"
                android:layout_height="wrap_content"
                android:layout_marginRight="8dp"
                android:background="@drawable/bg_cancel"/>

        </LinearLayout>

        <ListView
            android:id="@+id/item_edit"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/white"
            android:divider="@color/md_divider_black"
            android:dividerHeight="1dp"/>

    </LinearLayout>

</android.support.v7.widget.CardView>

Upvotes: 133

Views: 136427

Answers (30)

Muahmmad Tayyib
Muahmmad Tayyib

Reputation: 739

Here is SO answer link that is a 3 liner solution, that can also work for bottom sheet view.

I'm also writing quoting the method here that it uses:

public static void autoWrapBSContent(Dialog bDialog) {
bDialog.setOnShowListener((DialogInterface.OnShowListener) dialogInterface -> {
    BottomSheetDialog dialog = (BottomSheetDialog) dialogInterface;
    View bottomSheet = dialog.findViewById(com.google.android.material.R.id.design_bottom_sheet);
    if (bottomSheet != null) {
        dialog.getBehavior().setPeekHeight(bottomSheet.getHeight());
        ((View) bottomSheet.getParent().getParent()).requestLayout();
    }
});

}

Upvotes: 0

Dhaval Parmar
Dhaval Parmar

Reputation: 18978

EDIT 22-05-2023

Please use addBottomSheetCallback instead setBottomSheetCallback

Thanks, @abedullah


check the state in onStateChanged method of setBottomSheetCallback if state is BottomSheetBehavior.STATE_DRAGGING then change it to BottomSheetBehavior.STATE_EXPANDED this way you can stop STATE_DRAGGING by user. like below

final BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
        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) {
            }
        });

use button to open close bottom sheet like below

fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (behavior.getState() == BottomSheetBehavior.STATE_HIDDEN) {
                    behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
                } else {
                    behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
                }
            }
        });

don't use setPeekHeight or app:behavior_peekHeight

by above way you can reach your goal

Upvotes: 86

The fastest solution is only write this. bottomSheet.getBehavior().setDraggable(false);

Upvotes: 2

Kshitij Patil
Kshitij Patil

Reputation: 162

When you have a class extending BottomSheetDialogFragment

One common miss I see in most of the answers is you should not create local variable of BottomSheetBehavior, updating fields on local variable won't reflect on the actual dialog behavior. So IMO, following code won't work

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    val dialog = super.onCreateDialog(savedInstanceState)
    dialog.setOnShowListener {
        val bottomSheet = it.findViewById<View>(
                com.google.android.material.R.id.design_bottom_sheet
            ) as FrameLayout
        val behavior = BottomSheetBehavior.from(bottomSheet)
        behavior.isDraggable = false
    }
    return dialog
}

But this should work

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    val dialog = super.onCreateDialog(savedInstanceState)
    dialog.setOnShowListener {
        it as BottomSheetDialog
        it.behavior.isDraggable = false
    }
    return dialog
}

Upvotes: 3

leeJB
leeJB

Reputation: 1535

implementation 'com.google.android.material:material:1.2.0-alpha05'

you can disable dragging the BottomSheet like this.

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    val dialog = BottomSheetDialog(requireContext(), theme)
    dialog.setOnShowListener {
        setBottomSheetExpanded(dialog)
    }
    return dialog
}

open fun setBottomSheetExpanded(bottomSheetDialog: BottomSheetDialog) {
    val bottomSheet =
        bottomSheetDialog.findViewById<View>(R.id.design_bottom_sheet) as FrameLayout?
    bottomSheet?.let {
        val behavior: BottomSheetBehavior<*> = BottomSheetBehavior.from(bottomSheet)
        val layoutParams = bottomSheet.layoutParams
        bottomSheet.layoutParams = layoutParams
        behavior.state = BottomSheetBehavior.STATE_EXPANDED
        behavior.isDraggable = false / true
    }

}

Edited) The library was updated! you can use new library version

implementation 'com.google.android.material:material:1.4.0'

The examples are the same, good luck and good code

Upvotes: 68

durgeshtrivedi
durgeshtrivedi

Reputation: 56

private fun bottomSheetBehaviour(bottomSheet: BottomSheetDialog) {
    bottomSheet.setOnShowListener {

        val bottomSheetDialog = it as BottomSheetDialog
        val parentLayout =
            bottomSheetDialog.findViewById<View>(com.google.android.material.R.id.design_bottom_sheet)
        parentLayout?.let { parentView ->
            val behaviour = BottomSheetBehavior.from(parentView)
            setupFullHeight(parentView)
            behaviour.isDraggable = false
            behaviour.peekHeight = parentView.height
            behaviour.state = BottomSheetBehavior.STATE_EXPANDED
        }
        bottomSheet.setCancelable(false)
    }
}
  • behaviour.peekHeight = parentView.height
  • bottomSheet.setCancelable(false)

The above 2 line help me to fix the behaviour for BottomSheetDialogFragment

Upvotes: 0

Kratos
Kratos

Reputation: 339

val behavior = BottomSheetBehavior.from(bottomSheet)
behaviour.isDraggable = false

Upvotes: 4

Faizan Haidar Khan
Faizan Haidar Khan

Reputation: 1215

For Dialogs extended with BottomSheetDialogFragment(), simply use these

To Disable Swipe Feature

if (dialog?.window != null) {
   dialog!!.setCancelable(false)
}

To Enable Swipe Feature

if (dialog?.window != null) {
   dialog!!.setCancelable(true)
}

Upvotes: 3

Bilal Khan
Bilal Khan

Reputation: 141

To prevent user from dragging the bottom sheet to dismiss/open

    bottomSheetDialog_OverView = new BottomSheetDialog(context);
    View dialogView = View.inflate(context, R.layout.dialog_overview, null);
    bottomSheetDialog_OverView.getBehavior().setDraggable(false);

Upvotes: 2

Gourav Anvekar
Gourav Anvekar

Reputation: 76

Call this method in your onCreateView function to make the bottomsheet non-dismissable, non-cancellable, and non-draggable (use whatever applies to your use case):

    private fun disableDialog() {
        this.dialog?.let { bottomSheet ->
            // Disable dismiss on outside touch
            bottomSheet.setCanceledOnTouchOutside(false)

            // Hide the cancel button
            bottomSheet.setCancelable(false)

            // Disable back key press
            bottomSheet.setOnKeyListener { _, keyCode, _ ->
                keyCode == KeyEvent.KEYCODE_BACK
            }

            // Make it non-draggable
            bottomSheet.setOnShowListener {
                (it as BottomSheetDialog).behavior.setDraggable(false)
            }
        }
    }

Upvotes: 3

Shvedkov Ivan
Shvedkov Ivan

Reputation: 39

FYI: Following Material UI best practices, you have to create you own class, extending BottomSheetDialogFragment. Inside this class you can override onStart method and add this code in it:

dialog?.let {
            val bottomSheet = it.findViewById<View>(
                com.google.android.material.R.id.design_bottom_sheet
            ) as FrameLayout
            val behavior = BottomSheetBehavior.from(bottomSheet)

            behavior.state = BottomSheetBehavior.STATE_EXPANDED
            behavior.isDraggable = false
        }

Worked perfectly for me

Upvotes: 1

Jan Rozenbajgier
Jan Rozenbajgier

Reputation: 644

You can use android.app.Dialog with Gravity.BOTTOM of Window instead:

Dialog dialog = new Dialog(this);
dialog.getWindow().getAttributes().gravity = Gravity.BOTTOM;
dialog.show();

and if you want animation like in BottomSheetDialog add this to your styles.xml

<style name="BottomSheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
    <item name="bottomSheetStyle">@style/bottomSheetStyleWrapper</item>
</style>

<style name="bottomSheetStyleWrapper" parent="Widget.Design.BottomSheet.Modal">
    <item name="android:background">@android:color/transparent</item>
</style>

and in Java code:

Dialog dialog = new Dialog(this, R.style.BottomSheetDialog);

Upvotes: 0

Ram Chhabra
Ram Chhabra

Reputation: 441

BottomSheetDialog calcDialog = new BottomSheetDialog(this);
View view = getLayoutInflater().inflate(R.layout.bottom_sheet_calc, null);
calcDialog.setContentView(view);
calcDialog.setCancelable(false);

Upvotes: -1

F.Mysir
F.Mysir

Reputation: 4176

With 'com.google.android.material:material:1.2.0-alpha06'

Works great with NestedScrollView and RecyclerView

Example code:

    LinearLayout contentLayout = findViewById(R.id.contentLayout);
    sheetBehavior = BottomSheetBehavior.from(contentLayout);
    sheetBehavior.setDraggable(false);

Upvotes: 7

Sattar Hummatli
Sattar Hummatli

Reputation: 1408

A sample with BottomSheetDialogFragment. It works perfectly.

Edit 09/04/2020: Replaced depreciated setBottomSheetCallback() with addBottomSheetCallback()

class FragMenuBDrawer : BottomSheetDialogFragment() {

    ...

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog

        dialog.setOnShowListener {
            val bottomSheet = (it as BottomSheetDialog).findViewById<View>(com.google.android.material.R.id.design_bottom_sheet) as FrameLayout?
            val behavior = BottomSheetBehavior.from(bottomSheet!!)
            behavior.state = BottomSheetBehavior.STATE_EXPANDED

            behavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
                override fun onStateChanged(bottomSheet: View, newState: Int) {
                    if (newState == BottomSheetBehavior.STATE_DRAGGING) {
                        behavior.state = BottomSheetBehavior.STATE_EXPANDED
                    }
                }

                override fun onSlide(bottomSheet: View, slideOffset: Float) {}
            })
        }

        // Do something with your dialog like setContentView() or whatever
        return dialog
    }

    ...
}

Upvotes: 6

rana_sadam
rana_sadam

Reputation: 1226

I have the same issue in BottomSheetDialogFragment and apply many solutions using the behavior of dialog but none of those solve my issue and then I solved it but setting setCancelable(false); at the time of initialization of dialog.

DialogEndRide dialogCompleteRide = new DialogEndRide();
dialogCompleteRide.setCancelable(false);
dialogCompleteRide.show(getChildFragmentManager(), "");

This will disable gesture on BottomSheetDialogFragment and you can dismiss dialog programmatically by using dismiss(); function.

Upvotes: 1

Henry Tokin
Henry Tokin

Reputation: 7

Simply use : bottomSheet.dismissOnDraggingDownSheet = false

Copied from Material.io website :

let viewController: ViewController = ViewController() let bottomSheet: MDCBottomSheetController = MDCBottomSheetController(contentViewController: viewController)

// **** This line prevents dismiss by dragging bottomSheet ****

bottomSheet.dismissOnDraggingDownSheet = false

present(bottomSheet, animated: true, completion: nil)

Upvotes: -2

Myroslav
Myroslav

Reputation: 1237

The solution from accepted answer did mostly worked for me, but with one issue: views, which are behind the bottom sheet view, started to react on touch events, if touch event is happening on bottom sheet's area, which is free of child views. In other words, as you may see in image below, when user slides finger inside bottom sheet, then map starts to react on it.

bottom sheet touch area

To fix the issue, I've modified onInterceptTouchEvent method by setting touchListener on bottom sheet view (rest of code remains the same as in accepted solution).

override fun onInterceptTouchEvent(
        parent: CoordinatorLayout,
        child: V, event: MotionEvent
    ): Boolean {
        child.setOnTouchListener { v, event ->
            true
        }
        return false
    }

Upvotes: 1

Yosef
Yosef

Reputation: 1303

this is the first result in google so I believe its only fair to put the simple solution in here:

   private fun disableDragToDismiss() {
    if (dialog is BottomSheetDialog) {
        val bsDialog = dialog as BottomSheetDialog
        bsDialog.behavior.isHideable = false
    } else {
        Log.d(TAG, " BottomSheetDialog with dialog that is not BottomSheetDialog")
    }
}

and than just call it from onCreateView() in the BottomSheetDialogFragment implementation

Upvotes: 1

Alif
Alif

Reputation: 1135

Expected behavior:

  • BottomSheet does not close on drag-down
  • BottomSheet closes if touched outside of the dialog window

Code:

class MyBottomSheet : BottomSheetDialogFragment () {

   override fun onActivityCreated(savedInstanceState: Bundle?) {
       super.onActivityCreated(savedInstanceState)
       disableBottomSheetDraggableBehavior()
   }

   private fun disableBottomSheetDraggableBehavior() {
      this.isCancelable = false
      this.dialog?.setCanceledOnTouchOutside(true)
   }

 }

Upvotes: 10

Vitalii Obideiko
Vitalii Obideiko

Reputation: 1943

It can be now no longer relevant, but I will leave it here:

import android.content.Context
import android.util.AttributeSet
import androidx.coordinatorlayout.widget.CoordinatorLayout
import android.view.MotionEvent
import android.view.View
import com.google.android.material.bottomsheet.BottomSheetBehavior

@Suppress("unused")
class LockableBottomSheetBehavior<V : View> : BottomSheetBehavior<V> {
    constructor() : super()
    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)

    var swipeEnabled = true

    override fun onInterceptTouchEvent(
        parent: CoordinatorLayout,
        child: V,
        event: MotionEvent
    ): Boolean {
        return if (swipeEnabled) {
            super.onInterceptTouchEvent(parent, child, event)
        } else {
            false
        }
    }

    override fun onTouchEvent(parent: CoordinatorLayout, child: V, event: MotionEvent): Boolean {
        return if (swipeEnabled) {
            super.onTouchEvent(parent, child, event)
        } else {
            false
        }
    }

    override fun onStartNestedScroll(
        coordinatorLayout: CoordinatorLayout,
        child: V,
        directTargetChild: View,
        target: View,
        axes: Int,
        type: Int
    ): Boolean {
        return if (swipeEnabled) {
            super.onStartNestedScroll(
                coordinatorLayout,
                child,
                directTargetChild,
                target,
                axes,
                type
            )
        } else {
            false
        }
    }

    override fun onNestedPreScroll(
        coordinatorLayout: CoordinatorLayout,
        child: V,
        target: View,
        dx: Int,
        dy: Int,
        consumed: IntArray,
        type: Int
    ) {
        if (swipeEnabled) {
            super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type)
        }
    }

    override fun onStopNestedScroll(
        coordinatorLayout: CoordinatorLayout,
        child: V,
        target: View,
        type: Int
    ) {
        if (swipeEnabled) {
            super.onStopNestedScroll(coordinatorLayout, child, target, type)
        }
    }

    override fun onNestedPreFling(
        coordinatorLayout: CoordinatorLayout,
        child: V,
        target: View,
        velocityX: Float,
        velocityY: Float
    ): Boolean {
        return if (swipeEnabled) {
            super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY)
        } else {
            false
        }
    }
}

And use it in your xml file:

app:layout_behavior="com.your.package.LockableBottomSheetBehavior"

It disables all users actions, it can be used when you want control BottomSheet only programmatically.

Upvotes: 107

Shahadat Hossain
Shahadat Hossain

Reputation: 543

At first, I just wanna give thanks to all of you who tried to give an answer. I am just writing this answer by solving this problem as I want. I'm going to describe how I do that step by step by taking help from here.

Visualization: After clicking on the Button Show BottomSheet you will see the second screen. Now you will see that BottomSheet is just locked up for dragging. But if you click on the Country List the BottomSheet will hide. This was the description now let's dig into the Code.

  • At first, add the design support library to your build.gradle file:

    implementation 'com.android.support:design:28.0.0'

  • UserLockBottomSheetBehavior.java: Credit: James Davis (Thanks Man)

public class UserLockBottomSheetBehavior<V extends View> extends BottomSheetBehavior<V> {

    public UserLockBottomSheetBehavior() {
        super();
    }

    public UserLockBottomSheetBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
        return false;
    }

    @Override
    public boolean onTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
        return false;
    }

    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, V child, View directTargetChild, View target, int nestedScrollAxes) {
        return false;
    }

    @Override
    public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dx, int dy, int[] consumed) {
    }

    @Override
    public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target) {
    }

    @Override
    public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, V child, View target, float velocityX, float velocityY) {
        return false;
    }

}
  • bottomsheet.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/bottomSheet"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center_vertical"
    android:orientation="vertical"
    app:behavior_hideable="true"
    app:layout_behavior="com.samsolution.custombottomsheet.UserLockBottomSheetBehavior">

 <RelativeLayout
     android:id="@+id/minimizeLayout"
     android:background="@color/colorPrimary"
     android:layout_width="match_parent"
     android:layout_height="?android:attr/actionBarSize">

     <TextView
         android:layout_centerHorizontal="true"
         android:padding="16dp"
         android:layout_width="wrap_content"
         android:layout_height="?android:attr/actionBarSize"
         android:gravity="center_horizontal|center"
         android:text="Country List"
         android:textColor="#FFFFFF"
         android:textStyle="bold" />
 </RelativeLayout>

    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ListView
            android:id="@+id/homeCountryList"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </android.support.v7.widget.CardView>

</LinearLayout>
  • activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFFFFF"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_gravity="center"
        android:onClick="showCountryListFromBottomSheet">

        <Button
            android:layout_gravity="center"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@android:color/holo_red_light"
            android:onClick="showCountryListFromBottomSheet"
            android:padding="16dp"
            android:text="Show BottomSheet"
            android:textAllCaps="false"
            android:textColor="#ffffff" />

    </LinearLayout>

    <include layout="@layout/bootomsheet" />

</android.support.design.widget.CoordinatorLayout>
  • MainActivity.java
public class MainActivity extends AppCompatActivity {

    private BottomSheetBehavior<LinearLayout> bottomSheetBehavior;                                  // BottomSheet Instance
    LinearLayout bottomsheetlayout;
    String[] list = {"A", "B", "C", "D", "A", "B", "C", "D","A", "B", "C", "D","A", "B", "C", "D","A", "B", "C", "D"};

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

        bottomsheetlayout = findViewById(R.id.bottomSheet);
        bottomSheetBehavior = BottomSheetBehavior.from(bottomsheetlayout);

        ListView listView = findViewById(R.id.homeCountryList);
        ArrayAdapter<String> adapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,list);
        listView.setAdapter(adapter);

        bottomSheetHide();                                                                          //BottomSheet get hide first time

        RelativeLayout minimizeLayoutIV;                                                            // It will hide the bottomSheet Layout
        minimizeLayoutIV = findViewById(R.id.minimizeLayout);
        minimizeLayoutIV.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               bottomSheetHide();
            }
        });
    }

    public void showCountryListFromBottomSheet(View view) {
        bottomSheetBehavior.setHideable(false);
        bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
    }

    public void bottomSheetHide(){
        bottomSheetBehavior.setHideable(true);
        bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
    }
}

First Screen Second Screen

Upvotes: 1

SRBhagwat
SRBhagwat

Reputation: 1521

    LayoutInflater inflater = LayoutInflater.from(context);
            View view = inflater.inflate(R.layout.bottomsheet_view_profile_image, null);
            BottomSheetDialog dialog = new BottomSheetDialog(context);
            dialog.setContentView(view);
            dialog.setCancelable(false);


            BottomSheetBehavior behavior = BottomSheetBehavior
                    .from(((View) view.getParent()));
            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) {
                }
            });
            behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
            behavior.setSkipCollapsed(true);
            dialog.show();

Upvotes: 0

Surendar D
Surendar D

Reputation: 5644

Try this.

1) Create bottom sheet and declare the variable in your java class like

private BottomSheetBehavior sheetBehavior;

2) sheetBehavior = BottomSheetBehavior.from(bottomSheet);

3) In the bottom sheet callback function add the following lines.

sheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
            @Override
            public void onStateChanged(@NonNull View bottomSheet, int newState) {
                switch (newState) {
                    case BottomSheetBehavior.STATE_HIDDEN:
                        Log.d(TAG, "--------------  STATE_HIDDEN");
                        break;
                    case BottomSheetBehavior.STATE_EXPANDED: {
                        Log.d(TAG, "--------------  STATE_EXPANDED");
                    }
                    break;
                    case BottomSheetBehavior.STATE_COLLAPSED: {
                        Log.d(TAG, "--------------  STATE_COLLAPSED");
                    }
                    break;
                    case BottomSheetBehavior.STATE_DRAGGING:
                        sheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
                        break;
                    case BottomSheetBehavior.STATE_SETTLING:
                        Log.d(TAG, "--------------  STATE_SETTLING");
                        break;
                }
            }

            @Override
            public void onSlide(@NonNull View bottomSheet, float slideOffset) {

            }
        });

Upvotes: 3

Metwalli
Metwalli

Reputation: 1891

This is basically the kotlin version of the right answer at the top:

    class LockedBottomSheetBehavior<V : View>(context: Context, attrs: AttributeSet) :
        BottomSheetBehavior<V>(context, attrs) {

    companion object {
        fun <V : View> from(view: V): LockedBottomSheetBehavior<*> {
            val params = view.layoutParams as? CoordinatorLayout.LayoutParams
                    ?: throw IllegalArgumentException("The view is not a child of CoordinatorLayout")
            return params.behavior as? LockedBottomSheetBehavior<*>
                    ?: throw IllegalArgumentException(
                            "The view is not associated with BottomSheetBehavior")
        }
    }

    override fun onInterceptTouchEvent(
            parent: CoordinatorLayout,
            child: V, event: MotionEvent
    ) = false

    override fun onTouchEvent(
            parent: CoordinatorLayout,
            child: V,
            event: MotionEvent
    ) = false

    override fun onStartNestedScroll(
            coordinatorLayout: CoordinatorLayout,
            child: V,
            directTargetChild: View,
            target: View,
            axes: Int,
            type: Int) = false

    override fun onNestedPreScroll(
            coordinatorLayout: CoordinatorLayout,
            child: V,
            target: View,
            dx: Int,
            dy: Int,
            consumed: IntArray,
            type: Int) {
    }

    override fun onStopNestedScroll(
            coordinatorLayout: CoordinatorLayout,
            child: V,
            target: View,
            type: Int) {
    }

    override fun onNestedPreFling(
            coordinatorLayout: CoordinatorLayout,
            child: V,
            target: View,
            velocityX: Float,
            velocityY: Float
    ) = false
}

Upvotes: 3

pz64_
pz64_

Reputation: 2252

Adjusting the peakHeight value worked for me.

I set the peakheight as the height of bottomsheet if it is expanded.

    private val bottomSheetCallback = object : BottomSheetBehavior.BottomSheetCallback() {
    override fun onSlide(bottomSheet: View, slideOffset: Float) {

    }

    override fun onStateChanged(bottomSheet: View, newState: Int) {
        if (newState == BottomSheetBehavior.STATE_EXPANDED)
            bottomSheetBehavior.peekHeight = bottomSheet.height
    }
}

Upvotes: 0

Kaushik R
Kaushik R

Reputation: 192

Add this code to BottomSheetBehavior object. Dragging will be disabled. Works fine for me.

final BottomSheetBehavior behavior = BottomSheetBehavior.from((View) view.getParent());
    behavior.setHideable(false);
    behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {

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

      }
      @Override
      public void onSlide(@NonNull View bottomSheet, float slideOffset) {

      }
});

Upvotes: 7

Hashem Jahangiri
Hashem Jahangiri

Reputation: 157

set bottomSheet onClickListener to null.

bottomSheet.setOnClickListener(null);

this line disables all action about bottomSheet only and does not effect on inner view.

Upvotes: 3

Rodrigo Queiroz
Rodrigo Queiroz

Reputation: 2844

Here is a working version of the top solution in Kotlin:

import android.support.design.widget.BottomSheetBehavior
import android.support.design.widget.CoordinatorLayout
import android.view.MotionEvent
import android.view.View

class CustomBottomSheetBehavior<V : View> : BottomSheetBehavior<V>() {

    @Suppress("UNCHECKED_CAST")
    companion object {
        fun <V : View> from(view: V): CustomBottomSheetBehavior<V> {
            val params = view.layoutParams as? CoordinatorLayout.LayoutParams ?:
                throw IllegalArgumentException("The view is not a child of CoordinatorLayout")
                params.behavior as? BottomSheetBehavior<V> ?:
                    throw IllegalArgumentException("The view is not associated with BottomSheetBehavior")
                params.behavior = CustomBottomSheetBehavior<V>()
            return params.behavior as CustomBottomSheetBehavior<V>
        }
    }

    override fun onInterceptTouchEvent(parent: CoordinatorLayout, child: V, event: MotionEvent): Boolean {
        return false
    }

    override fun onTouchEvent(parent: CoordinatorLayout, child: V, event: MotionEvent): Boolean {
        return false
    }

    override fun onStartNestedScroll(coordinatorLayout: CoordinatorLayout, child: V, directTargetChild: View, target: View, axes: Int, type: Int): Boolean {
        return false
    }

    override fun onNestedPreScroll(coordinatorLayout: CoordinatorLayout, child: V, target: View, dx: Int, dy: Int, consumed: IntArray, type: Int) {}

    override fun onStopNestedScroll(coordinatorLayout: CoordinatorLayout, child: V, target: View, type: Int) {}

    override fun onNestedPreFling(coordinatorLayout: CoordinatorLayout, child: V, target: View, velocityX: Float, velocityY: Float): Boolean {
        return false
    }
}

Then whenever you wanna use:

val bottomSheetBehavior by lazy {
    CustomBottomSheetBehavior.from(bottom_sheet_main)
}

The bottom_sheet_main is the actual view using Kotlin Android Extensions.

Upvotes: 3

aotian16
aotian16

Reputation: 819

  1. Copy BottomSheetDialog to your project and rename to MyBottomSheetDialog
  2. add getBottomSheetBehavior to MyBottomSheetDialog
  3. use MyBottomSheetDialog instead BottomSheetDialog
  4. bottomSheetBehavior.setBottomSheetCallback

code like this

public class MyBottomSheetDialog extends AppCompatDialog {

    // some code

    public BottomSheetBehavior<FrameLayout> getBottomSheetBehavior() {
        return mBehavior;
    }

    // more code

in your code

    final BottomSheetBehavior<FrameLayout> bottomSheetBehavior = myBottomSheetDialog.getBottomSheetBehavior();
    bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
        @Override
        public void onStateChanged(@NonNull View bottomSheet, int newState) {
            if (newState == BottomSheetBehavior.STATE_DRAGGING) {
                bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
            }
        }

        @Override
        public void onSlide(@NonNull View bottomSheet, float slideOffset) {

        }

Upvotes: 2

Related Questions