如何允许BottomSheetDialog的外部触摸?[英] How to Allow outside touch for BottomSheetDialog?

本文是小编为大家收集整理的关于如何允许BottomSheetDialog的外部触摸?的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我正在研究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高度,标志允许通过此对话框之外的视图来处理触摸

本文地址:https://www.itbaoku.cn/post/2091061.html

问题描述

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);
    }

reference

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