Reputation: 3407
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
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
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
Reputation: 21
The fastest solution is only write this.
bottomSheet.getBehavior().setDraggable(false);
Upvotes: 2
Reputation: 162
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
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
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)
}
}
The above 2 line help me to fix the behaviour for BottomSheetDialogFragment
Upvotes: 0
Reputation: 339
val behavior = BottomSheetBehavior.from(bottomSheet)
behaviour.isDraggable = false
Upvotes: 4
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
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
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
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
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
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
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
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
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
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
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.
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
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
Reputation: 1135
Expected behavior:
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
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
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;
}
}
<?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>
<?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>
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);
}
}
Upvotes: 1
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
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
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
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
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
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
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
Reputation: 819
BottomSheetDialog
to your project and rename to MyBottomSheetDialog
getBottomSheetBehavior
to MyBottomSheetDialog
MyBottomSheetDialog
instead BottomSheetDialog
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