我正在尝试禁用BottomSheet
上的用户拖动。我想禁用的原因是两件事。 1.它阻止ListView
向下滚动,2。我不希望用户使用拖动而忽略BottomSheetView
上的按钮。这就是我所做的
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;
}
}
});
}
});
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>
答案 0 :(得分:56)
现在已经不再适用了,但我会把它留在这里:
import android.content.Context;
import android.support.design.widget.BottomSheetBehavior;
import android.support.design.widget.CoordinatorLayout;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
* Created by vitaliiobideiko on 10/5/16.
*/
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时才能使用它。您可以编辑它并创建布尔标志来调用super
方法而不是return false
。
答案 1 :(得分:50)
检查onStateChanged
setBottomSheetCallback
方法中的状态,如果状态为BottomSheetBehavior.STATE_DRAGGING
,则将其更改为BottomSheetBehavior.STATE_EXPANDED
,这样您就可以停止STATE_DRAGGING
用户。如下所示
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) {
}
});
使用按钮打开如下所示的近底页
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);
}
}
});
请勿使用setPeekHeight
或app:behavior_peekHeight
通过上述方式,您可以实现目标
答案 2 :(得分:30)
好吧,所以接受的答案对我不起作用。但是,Виталий Обидейко's answer启发了我的最终解决方案。
首先,我创建了以下自定义BottomSheetBehavior。它会覆盖涉及触摸的所有方法,如果锁定则返回false(或不执行任何操作)。否则,它就像一个普通的BottomSheetBehavior。这会禁用用户向下拖动的功能,并且不会影响更改代码中的状态。
<强> LockableBottomSheetBehavior.java 强>
public class LockableBottomSheetBehavior<V extends View> extends BottomSheetBehavior<V> {
private boolean mLocked = false;
public LockableBottomSheetBehavior() {}
public LockableBottomSheetBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setLocked(boolean locked) {
mLocked = locked;
}
@Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
boolean handled = false;
if (!mLocked) {
handled = super.onInterceptTouchEvent(parent, child, event);
}
return handled;
}
@Override
public boolean onTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
boolean handled = false;
if (!mLocked) {
handled = super.onTouchEvent(parent, child, event);
}
return handled;
}
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, V child, View directTargetChild, View target, int nestedScrollAxes) {
boolean handled = false;
if (!mLocked) {
handled = super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
}
return handled;
}
@Override
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dx, int dy, int[] consumed) {
if (!mLocked) {
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);
}
}
@Override
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target) {
if (!mLocked) {
super.onStopNestedScroll(coordinatorLayout, child, target);
}
}
@Override
public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, V child, View target, float velocityX, float velocityY) {
boolean handled = false;
if (!mLocked) {
handled = super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY);
}
return handled;
}
}
以下是如何使用它的示例。在我的情况下,我需要它,以便在展开时锁定底部页。
<强> activity_home.xml 强>
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|snap"
app:titleEnabled="false"/>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"/>
</android.support.design.widget.AppBarLayout>
<!-- Use layout_behavior to set your Behavior-->
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
app:layout_behavior="com.myapppackage.LockableBottomSheetBehavior"/>
</android.support.design.widget.CoordinatorLayout>
<强> HomeActivity.java 强>
public class HomeActivity extends AppCompatActivity {
BottomSheetBehavior mBottomSheetBehavior;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
recyclerView.setAdapter(new SomeAdapter());
mBottomSheetBehavior = BottomSheetBehavior.from(recyclerView);
mBottomSheetBehavior.setBottomSheetCallback(new MyBottomSheetCallback());
}
class MyBottomSheetCallback extends BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_EXPANDED) {
if (mBottomSheetBehavior instanceof LockableBottomSheetBehavior) {
((LockableBottomSheetBehavior) mBottomSheetBehavior).setLocked(true);
}
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {}
});
}
希望这有助于消除很多困惑!
答案 3 :(得分:21)
我最后编写了一个解决方法来解决动态禁用用户拖动的用例,其中BottomSheetBehavior被子类化以覆盖onInterceptTouchEvent,并在自定义标志(在本例中为mAllowUserDragging)设置为false时忽略它:
import android.content.Context;
import android.support.design.widget.BottomSheetBehavior;
import android.support.design.widget.CoordinatorLayout;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class WABottomSheetBehavior<V extends View> extends BottomSheetBehavior<V> {
private boolean mAllowUserDragging = true;
/**
* Default constructor for instantiating BottomSheetBehaviors.
*/
public WABottomSheetBehavior() {
super();
}
/**
* Default constructor for inflating BottomSheetBehaviors from layout.
*
* @param context The {@link Context}.
* @param attrs The {@link AttributeSet}.
*/
public WABottomSheetBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setAllowUserDragging(boolean allowUserDragging) {
mAllowUserDragging = allowUserDragging;
}
@Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
if (!mAllowUserDragging) {
return false;
}
return super.onInterceptTouchEvent(parent, child, event);
}
}
在你的布局xml:
<FrameLayout
android:id="@+id/bottom_sheet_frag_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:behavior_hideable="true"
app:behavior_peekHeight="@dimen/bottom_sheet_peek_height"
app:elevation="@dimen/bottom_sheet_elevation"
app:layout_behavior="com.example.ray.WABottomSheetBehavior" />
到目前为止,这是根据需要禁用用户拖动底部表格的最一致行为解决方案。
依赖于在onStateChanged回调中触发另一个setState调用的所有其他解决方案导致BottomSheet进入错误状态,或导致重大的UX问题(在Runnable中发布setState调用的情况)。
希望这有助于某人:)
雷
答案 4 :(得分:10)
implementation 'com.google.android.material:material:1.2.0-alpha05'
您可以禁用像这样拖动BottomSheet。
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
//another code
this.bottomSheetBehavior = BottomSheetBehavior.from(view)
this.bottomSheetBehavior.state = STATE_EXPANDED
this.bottomSheetBehavior.isDraggable = false // disable dragging
//another code
this.bottomSheetbehavior.isDraggable = true //draggable
(kotlin),我希望这个答案能解决您的问题。
已编辑)库已更新!您可以使用新的库版本
implementation 'com.google.android.material:material:1.2.1'
例子都是一样的,祝你好运和好的代码
答案 5 :(得分:7)
接受的答案并不适用于我使用的第一个测试设备。反弹并不顺利。仅在用户释放拖动后才将状态设置为STATE_EXPANDED似乎更好。以下是我的版本:
final BottomSheetBehavior behavior = BottomSheetBehavior.from(findViewById(R.id.bottomSheet));
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState > BottomSheetBehavior.STATE_DRAGGING)
bottomSheet.post(new Runnable() {
@Override public void run() {
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
答案 6 :(得分:6)
将此代码添加到 BottomSheetBehavior 对象。拖动将被禁用。 对我来说很好。
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) {
}
});
答案 7 :(得分:5)
要锁定BottomSheet并避免用户将其滑出,这就是我所做的
public void showBottomSheet() {
bsb.setHideable(false);
bsb.setState(BottomSheetBehavior.STATE_EXPANDED);
}
public void hideBottomSheet() {
bsb.setHideable(true);
bsb.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
对我来说效果很好。
答案 8 :(得分:4)
迟到的回答,但是,这对我有用,这与其他人建议的有点不同。
您可以尝试将cancelable
属性设置为false,即
setCancelable(false);
然后手动处理您要在setupDialog
方法中关闭对话框的事件。
@Override
public void setupDialog(final Dialog dialog, final int style) {
// handle back button
dialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
@Override
public boolean onKey(final DialogInterface dialog, final int keyCode, final KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
dialog.dismiss();
}
return true;
}
});
// handle touching outside of the dialog
final View touchOutsideView = getDialog().getWindow().getDecorView().findViewById(android.support.design.R.id.touch_outside);
touchOutsideView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
dialog.dismiss();
}
});
}
这适用于对话框片段中的ListView,这是我在其他解决方案中遇到的问题。
答案 9 :(得分:4)
锁定拖动的简便方法是setPeekHeight与视图高度相同。 例如:
private LinearLayout bottomSheet;
private BottomSheetBehavior bottomBehavior;
@Override
public void onResume() {
super.onResume();
bottomBehavior = BottomSheetBehavior.from((bottomSheet);
bottomBehavior.setPeekHeight(bottomSheet.getHeight());
bottomBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
答案 10 :(得分:3)
带有BottomSheetDialogFragment的示例。它运作完美。
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.setBottomSheetCallback(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
}
...
}
答案 11 :(得分:3)
禁用底部工作表时,无需阻止所有事件。您只能阻止ACTION_MOVE事件。这就是为什么要使用像这样的自定义底页行为
public class BottomSheetBehaviorWithDisabledState<V extends View> extends BottomSheetBehavior<V> {
private boolean enable = true;
/**
* Default constructor for instantiating BottomSheetBehaviors.
*/
public BottomSheetBehaviorWithDisabledState() {
super();
}
/**
* Default constructor for inflating BottomSheetBehaviors from layout.
*
* @param context The {@link Context}.
* @param attrs The {@link AttributeSet}.
*/
public BottomSheetBehaviorWithDisabledState(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setEnable(boolean enable){
this.enable = enable;
}
@Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
if (!enable && event.getAction() == MotionEvent.ACTION_MOVE){
return false;
}
return super.onInterceptTouchEvent(parent, child, event);
}
}
答案 12 :(得分:2)
这基本上是顶部正确答案的kotlin版本:
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
}
答案 13 :(得分:2)
使用'com.google.android.material:material:1.2.0-alpha06'
与NestedScrollView
和RecyclerView
完美搭配
示例代码:
LinearLayout contentLayout = findViewById(R.id.contentLayout);
sheetBehavior = BottomSheetBehavior.from(contentLayout);
sheetBehavior.setDraggable(false);
答案 14 :(得分:2)
我找到了惊人的解决方案。最初的问题是,一旦bottomSheet进入HIDDEN状态,那么它就不会出现在bottomSheetDialog.show()中。 但是我希望在show()方法上显示对话框,并且还希望用户能够将其向下滑动以使其感觉像是底页。以下就是我做的..
BottomSheetDialog itemTypeDialog = new BottomSheetDialog(this);
View bottomSheetView = getLayoutInflater().inflate(R.layout.dialog_bottomsheet, null);
itemTypeDialog.setContentView(bottomSheetView);
BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from((View) bottomSheetView.getParent());
bottomSheetBehavior.setBottomSheetCallback(bottomSheetCallback); // You can also attach the listener here itself.
BottomSheetBehavior.BottomSheetCallback bottomSheetCallback = new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
Log.d(TAG, "BottomSheetCallback: " + newState);
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
itemTypeDialog.dismiss();
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
};
答案 15 :(得分:2)
预期行为:
代码:
class MyBottomSheet : BottomSheetDialogFragment () {
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
disableBottomSheetDraggableBehavior()
}
private fun disableBottomSheetDraggableBehavior() {
this.isCancelable = false
this.dialog?.setCanceledOnTouchOutside(true)
}
}
答案 16 :(得分:1)
BottomSheetDialog
复制到您的项目并重命名为MyBottomSheetDialog
getBottomSheetBehavior
添加到MyBottomSheetDialog
MyBottomSheetDialog
代替BottomSheetDialog
像这样的代码
public class MyBottomSheetDialog extends AppCompatDialog {
// some code
public BottomSheetBehavior<FrameLayout> getBottomSheetBehavior() {
return mBehavior;
}
// more 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) {
}
答案 17 :(得分:1)
以下是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
}
}
然后每当你想使用时:
val bottomSheetBehavior by lazy {
CustomBottomSheetBehavior.from(bottom_sheet_main)
}
bottom_sheet_main
是使用Kotlin Android Extensions的实际视图。
答案 18 :(得分:1)
将bottomSheet onClickListener设置为null。
bottomSheet.setOnClickListener(null);
此行仅禁用有关bottomSheet的所有操作,并且不影响内部视图。
答案 19 :(得分:1)
accepted answer的解决方案最适合我,但是有一个问题:在底部工作表视图后面的视图开始对触摸事件做出反应,如果在底部工作区发生了触摸事件,没有儿童意见。 换句话说,就像您在下图中看到的那样,当用户在底部页面内滑动手指时,地图就会开始对此做出反应。
为解决此问题,我通过在底部工作表视图上设置onInterceptTouchEvent
来修改了touchListener
方法(其余代码与接受的解决方案相同)。
override fun onInterceptTouchEvent(
parent: CoordinatorLayout,
child: V, event: MotionEvent
): Boolean {
child.setOnTouchListener { v, event ->
true
}
return false
}
答案 20 :(得分:0)
这是google的第一个结果,所以我相信将简单的解决方案放在这里是唯一的公平
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")
}
}
,而不仅仅是在onCreateView()
实现中从BottomSheetDialogFragment
调用它
答案 21 :(得分:0)
您可以将 android.app.Dialog
与 Gravity.BOTTOM
的 Window
一起使用:
Dialog dialog = new Dialog(this);
dialog.getWindow().getAttributes().gravity = Gravity.BOTTOM;
dialog.show();
如果您想要BottomSheetDialog
中的动画,请将其添加到您的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>
在 Java 代码中:
Dialog dialog = new Dialog(this, R.style.BottomSheetDialog);
答案 22 :(得分:0)
首先,我想感谢所有尝试给出答案的人。我只是通过解决这个问题来写这个答案。我将描述如何通过从这里获得帮助来逐步做到这一点。
可视化效果:点击按钮Show BottomSheet
后,您将看到第二个屏幕。现在,您将看到 BottomSheet 已被锁定以进行拖动。但是,如果您单击国家/地区列表,则 BottomSheet 将隐藏。这就是描述,现在让我们深入研究代码。
首先,将设计支持库添加到您的 build.gradle 文件中:
实现'com.android.support:design:28.0.0'
UserLockBottomSheetBehavior.java :信用:James Davis(感谢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);
}
}
答案 23 :(得分:0)
我在BottomSheetDialogFragment中遇到了相同的问题,并使用对话框的行为应用了许多解决方案,但没有一个解决了我的问题,然后我解决了这个问题,但是在对话框初始化时设置了setCancelable(false);
。
DialogEndRide dialogCompleteRide = new DialogEndRide();
dialogCompleteRide.setCancelable(false);
dialogCompleteRide.show(getChildFragmentManager(), "");
这将禁用BottomSheetDialogFragment上的手势,您可以使用dismiss();
函数以编程方式关闭对话框。
答案 24 :(得分:0)
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();
答案 25 :(得分:0)
尝试一下。
1)创建底页,并在
之类的java类中声明变量private BottomSheetBehavior sheetBehavior;
2)sheetBehavior = BottomSheetBehavior.from(bottomSheet);
3)在底部的回调函数中添加以下几行。
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) {
}
});
答案 26 :(得分:0)
以防万一将来有人可以提供帮助,对我来说,最好的解决方法是创建新样式并分配:
<style name="BottomSheetDialogTheme" parent="BaseBottomSheetDialog">
<item name="android:windowCloseOnTouchOutside">false</item>
</style>
,然后在BottomSheetDialogFragment类内部覆盖该方法:
override fun getTheme(): Int = R.style.BottomSheetDialogTheme
答案 27 :(得分:0)
调整peakHeight
的值对我有用。
如果将其扩大,我将peakheight设置为底页的高度。
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
}
}
答案 28 :(得分:-1)
BottomSheetDialog calcDialog = new BottomSheetDialog(this);
View view = getLayoutInflater().inflate(R.layout.bottom_sheet_calc, null);
calcDialog.setContentView(view);
calcDialog.setCancelable(false);
答案 29 :(得分:-2)
只需使用:
bottomSheet.dismissOnDraggingDownSheet = false
从Material.io网站复制:
let viewController: ViewController = ViewController()
let bottomSheet: MDCBottomSheetController = MDCBottomSheetController(contentViewController: viewController)
// ****该行可通过拖动bottomSheet ****来防止被关闭
bottomSheet.dismissOnDraggingDownSheet = false
present(bottomSheet, animated: true, completion: nil)