问题描述
我正在研究BottomSheetDialogFragment我的要求是创建底部菜单, 如果我单击外部片段区域它应该不取消对话框并应持续存在.
问题: 和片段外的事件应传播到下部片段视图/片段.
我已经在下面尝试过(不适用于底段fragment): 允许外部触摸进行对话fragment
要停止在下面尝试的对话框取消(我致电setCancelable(boolean) in BottomDialogFragment的onStart()):
@Override public void setCancelable(boolean cancelable) { super.setCancelable(cancelable); BottomSheetDialog dialog = (BottomSheetDialog) getDialog(); dialog.setCanceledOnTouchOutside(cancelable); View bottomSheetView = dialog.getWindow().getDecorView().findViewById(R.id.design_bottom_sheet); BottomSheetBehavior.from(bottomSheetView).setHideable(cancelable); }
编辑:发现难以使用坐标布局的难道.底部表格的最佳解决方案是此处
推荐答案
您应该使用android.support.design.widget.BottomSheetBehavior.
但是,如果您想在其他类中拥有bottomSheet,我建议您使用Fragment,在此fragment中打开bottomSheet
打开片段以这种方式.
在您的片段中,在以下代码中打开bottomSheet:
in onInitViews
var mBottomSheetBehavior = BottomSheetBehavior.from(bottomSheetCoordinatorLayout) mBottomSheetBehavior!!.state = BottomSheetBehavior.STATE_HIDDEN mBottomSheetBehavior!!.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { override fun onStateChanged(bottomSheet: View, newState: Int) { when (newState) { BottomSheetBehavior.STATE_HIDDEN -> { fragmentManager?.popBackStack() } //BottomSheetBehavior.STATE_COLLAPSED -> "Collapsed" //BottomSheetBehavior.STATE_DRAGGING -> "Dragging..." //BottomSheetBehavior.STATE_EXPANDED -> "Expanded" //BottomSheetBehavior.STATE_SETTLING -> "Settling..." } } override fun onSlide(bottomSheet: View, slideOffset: Float) { //text_view_state!!.text = "Sliding..." } })
,您的layout应该像这样:
<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:layoutDirection="ltr"> <android.support.design.widget.CoordinatorLayout android:id="@+id/bottomSheetCoordinatorLayout" android:layout_width="match_parent" android:layout_height="wrap_content" app:behavior_hideable="true" app:behavior_peekHeight="55dp" app:layout_behavior="@string/bottom_sheet_behavior"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/top_radius_primary_color" android:paddingStart="@dimen/material_size_32" android:paddingEnd="@dimen/material_size_32"> </RelativeLayout> </android.support.design.widget.CoordinatorLayout> </android.support.design.widget.CoordinatorLayout>
我希望它能帮助您
其他推荐答案
尝试 在BottomSheetDialog中的代码:
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { return (super.onCreateDialog(savedInstanceState) as BottomSheetDialog).apply { setCanceledOnTouchOutside(false) } }
或通过<CoordinatorLayout>包裹<CoordinatorLayout>
其他推荐答案
pankaj kumar所说,默认情况下这是不可能的.但是,我找到了一个有效的解决方法,可以在底部纸上打开底部的同时
,允许触摸到底部纸外面的视图您可以覆盖BottomSheetDialog的布局,例如:
值/refs.xml
<resources xmlns:tools="http://schemas.android.com/tools"> <item name="design_bottom_sheet_dialog" type="layout" tools:override="true">@layout/custom_design_bottom_sheet_dialog</item> </resources>
布局/custom_design_bottom_sheet_dialog.xml
<?xml version="1.0" encoding="utf-8"?> <!-- ~ This is an override of the design_bottom_sheet_dialog from material library --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="wrap_content"> <androidx.coordinatorlayout.widget.CoordinatorLayout android:id="@+id/coordinator" android:layout_width="match_parent" android:layout_height="wrap_content"> <View android:id="@+id/touch_outside" android:layout_width="0dp" android:layout_height="0dp" android:visibility="gone" android:importantForAccessibility="no" android:soundEffectsEnabled="false" tools:ignore="UnusedAttribute"/> <FrameLayout android:id="@+id/design_bottom_sheet" style="?attr/bottomSheetStyle" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal|top" app:layout_behavior="@string/bottom_sheet_behavior"/> </androidx.coordinatorlayout.widget.CoordinatorLayout> </FrameLayout>
yourcustombottomsheetdialogfragment
override fun onStart() { super.onStart() // Set layout for custom bottom sheet by allowing background touches dialog?.window?.apply { setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL) attributes = attributes.apply { gravity = Gravity.BOTTOM } setDimAmount(0.0f) } }
这样做,对话框具有wrap_content高度,标志允许通过此对话框之外的视图来处理触摸
问题描述
I am working on BottomSheetDialogFragment my requirement is to create Bottom menu, Where if I click outside fragment area it should not cancel the Dialog and should persist.
ISSUE: And Event outside the Fragment should propagate to the lower fragment view/fragment.
I have already tried below(doesn't work for BottomDialogFragment): Allow outside touch for DialogFragment
To stop the dialog cancel i tried Below(i call setCancelable(boolean) in onStart() of BottomDialogFragment):
@Override public void setCancelable(boolean cancelable) { super.setCancelable(cancelable); BottomSheetDialog dialog = (BottomSheetDialog) getDialog(); dialog.setCanceledOnTouchOutside(cancelable); View bottomSheetView = dialog.getWindow().getDecorView().findViewById(R.id.design_bottom_sheet); BottomSheetBehavior.from(bottomSheetView).setHideable(cancelable); }
EDIT: Found it the hard way there is no other go then using Coordinate layout.The best solution for BottomSheetDialog is here
- This Solution solve's the issue but bring's in one more issue. i.e all the actionMode event's are not navigated while all other app event's are.
- And this is my best solution to the problem
推荐答案
you should use android.support.design.widget.BottomSheetBehavior.
but if you want to have a bottomSheet in other class I suggest you use a Fragment and in this fragment open your bottomSheet
open your fragment in this way.
And in your fragment, open your bottomSheet in the following code:
in onInitViews
var mBottomSheetBehavior = BottomSheetBehavior.from(bottomSheetCoordinatorLayout) mBottomSheetBehavior!!.state = BottomSheetBehavior.STATE_HIDDEN mBottomSheetBehavior!!.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { override fun onStateChanged(bottomSheet: View, newState: Int) { when (newState) { BottomSheetBehavior.STATE_HIDDEN -> { fragmentManager?.popBackStack() } //BottomSheetBehavior.STATE_COLLAPSED -> "Collapsed" //BottomSheetBehavior.STATE_DRAGGING -> "Dragging..." //BottomSheetBehavior.STATE_EXPANDED -> "Expanded" //BottomSheetBehavior.STATE_SETTLING -> "Settling..." } } override fun onSlide(bottomSheet: View, slideOffset: Float) { //text_view_state!!.text = "Sliding..." } })
And your layout should be like this:
<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:layoutDirection="ltr"> <android.support.design.widget.CoordinatorLayout android:id="@+id/bottomSheetCoordinatorLayout" android:layout_width="match_parent" android:layout_height="wrap_content" app:behavior_hideable="true" app:behavior_peekHeight="55dp" app:layout_behavior="@string/bottom_sheet_behavior"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/top_radius_primary_color" android:paddingStart="@dimen/material_size_32" android:paddingEnd="@dimen/material_size_32"> </RelativeLayout> </android.support.design.widget.CoordinatorLayout> </android.support.design.widget.CoordinatorLayout>
I hope it helps you
其他推荐答案
Try code below in your BottomSheetDialog:
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { return (super.onCreateDialog(savedInstanceState) as BottomSheetDialog).apply { setCanceledOnTouchOutside(false) } }
or wrap by <CoordinatorLayout> for instance your <ConstraintLayout> and implement <layout /> and attach to BottomSheetBehavior.
其他推荐答案
As been said by Pankaj Kumar, this is not possible by default. However, I found a workaround that works and allows touches to views outside of the bottom sheet while keeping the bottom sheet open
You can override the layout of the BottomSheetDialog like so:
values/refs.xml
<resources xmlns:tools="http://schemas.android.com/tools"> <item name="design_bottom_sheet_dialog" type="layout" tools:override="true">@layout/custom_design_bottom_sheet_dialog</item> </resources>
layout/custom_design_bottom_sheet_dialog.xml
<?xml version="1.0" encoding="utf-8"?> <!-- ~ This is an override of the design_bottom_sheet_dialog from material library --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="wrap_content"> <androidx.coordinatorlayout.widget.CoordinatorLayout android:id="@+id/coordinator" android:layout_width="match_parent" android:layout_height="wrap_content"> <View android:id="@+id/touch_outside" android:layout_width="0dp" android:layout_height="0dp" android:visibility="gone" android:importantForAccessibility="no" android:soundEffectsEnabled="false" tools:ignore="UnusedAttribute"/> <FrameLayout android:id="@+id/design_bottom_sheet" style="?attr/bottomSheetStyle" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal|top" app:layout_behavior="@string/bottom_sheet_behavior"/> </androidx.coordinatorlayout.widget.CoordinatorLayout> </FrameLayout>
YourCustomBottomSheetDialogFragment
override fun onStart() { super.onStart() // Set layout for custom bottom sheet by allowing background touches dialog?.window?.apply { setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL) attributes = attributes.apply { gravity = Gravity.BOTTOM } setDimAmount(0.0f) } }
By doing this, the dialog has a wrap_content height and the flags allow touches to be handled by views outside of this dialog