Disabling User Dragging on Bottomsheet

Disabling User dragging on BottomSheet

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.

How to disable BottomSheetDialogFragment dragging

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.

Disable BottomSheet Drag

Change the onInterceptTouchEvent function return value from Ray W solution to this:

@Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
return super.onInterceptTouchEvent(parent, child, event) && mAllowUserDragging;
}

One more thing, if you have a ListView in BottomSheetLayout, then scrolling items in ListView will change the bottomSheetBehavior state to "STATE_DRAGGING" from "STATE_EXPANDED".
Sample code piece:

@Override
public void onBackPressed() {
if(isBottomViewOpen){ // set this bool in behavior callback
behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}else {
super.onBackPressed();
}
}

Restrict bottom sheet swipe down

private class ScrollTouchListener implements View.OnTouchListener {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mVideoDetailsView.setNestedScrollingEnabled(true);
activityLockBehavior.setAllowUserDragging(false);
break;
case MotionEvent.ACTION_MOVE:
mVideoDetailsView.setNestedScrollingEnabled(true);
activityLockBehavior.setAllowUserDragging(false);
break;
case MotionEvent.ACTION_UP:
mVideoDetailsView.setNestedScrollingEnabled(false);
activityLockBehavior.setAllowUserDragging(true);
break;
}
return false;
}
}

Added this scroll listener to nested scrollview

mNestedScrollView.setOnTouchListener(new ScrollTouchListener());


Related Topics



Leave a reply



Submit