android 如何允许BottomSheetDialog的外部触摸?

mqxuamgl  于 2023-03-16  发布在  Android
关注(0)|答案(5)|浏览(265)

我正在BottomSheetDialogFragment上工作,我的要求是创建底部菜单,如果我 * 点击碎片区域外 *,它应该不取消对话框,并应持续存在。
问题:片段外部的事件应传播到较低的片段视图/片段。
我已经尝试了以下(不工作的BottomDialogFragment):Allow outside touch for DialogFragment
为了停止对话框cancel,我尝试了以下操作(我在BottomDialogFragment的onStart()中调用setCancelable(boolean)):

@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
编辑:发现它的艰难方式没有其他去然后使用坐标布局。最好的解决方案为BottomSheetDialog是here

  • This解决方案解决了这个问题,但带来了另一个问题,即所有actionMode事件都没有导航,而所有其他应用程序事件都有导航。
  • 而这是我对这个问题最好的solution
svdrlsy4

svdrlsy41#

BottomSheetDialog中尝试以下代码

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
     return (super.onCreateDialog(savedInstanceState) as BottomSheetDialog).apply {
         setCanceledOnTouchOutside(false)
     }
 }

或者用<CoordinatorLayout> Package ,例如您的<ConstraintLayout>,然后实现<layout />并附加到BottomSheetBehavior

a11xaf1n

a11xaf1n2#

正如Pankaj Kumar所说,默认情况下这是不可能的。但是,我找到了一个工作区,允许在保持底部工作表打开的同时触摸底部工作表以外的视图
您可以覆盖BottomSheetDialog的布局,如下所示:

值/引用.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>

布局/自定义设计底部工作表对话框.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>

您的自定义底部工作表对话框片段

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的高度,并且标志允许由该对话框之外的视图处理触摸

bpzcxfmw

bpzcxfmw3#

这在使用BottomSheetDialogFragment之前是不可能的。BottomSheetDialogFragment是一个对话框,作为每个对话框的行为,它不允许用户在对话框后面的任何视图上拦截,尽管用户可以看到。
因此,要实现这一点,你需要使用Fragment而不是BottomSheetDialogFragment。是的,这将需要大量的代码更改:)如果你想拦截后面的视图,你必须没有BottomSheetDialogFragment

kwvwclae

kwvwclae4#

您应该使用android.support.design.widget.BottomSheetBehavior
但是如果你想在其他类中有一个bottomSheet,我建议你使用Fragment,并在这个fragment中打开你的bottomSheet
打开你的片段in this way
在您的片段中,使用以下代码打开bottomSheet
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>

希望对你有帮助

cwdobuhd

cwdobuhd5#

如上所述,我们不能直接使用BottomSheetDialogFragment或BottomSheetDialog来达到允许触摸外部的效果。
但是我们可以借助BottomSheetDialogFragment中的Dialog和BottomSheetCallback来实现。(光说不练,代码给你看)

class BottomPanelFragment : BottomSheetDialogFragment() {

 override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    
      val dialog = Dialog(requireActivity(), R.style.ChargeMapDialog)
        val view = requireActivity().layoutInflater.inflate(
            R.layout.fragment_around_charge_station_info,
            null
        )
        dialog.setContentView(view)

        dialog.window?.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
        dialog.window?.setFlags(WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH)

        dialog.window?.setDimAmount(0F)
        dialog.setCancelable(false)
        dialog.setCanceledOnTouchOutside(false)

  }   

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

对应xml文件:

<androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    // notes:app:layout_behavior="@string/bottom_sheet_behavior"
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/fill_100"
        app:behavior_hideable="false"
        app:behavior_peekHeight="@dimen/dp_80"
        app:layout_behavior="@string/bottom_sheet_behavior">
        >

        <ImageView
            android:id="@+id/iv_charge_station"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/dp_24"
            android:layout_marginTop="@dimen/dp_20"
            android:src="@drawable/ic_charge_station_flag"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/tv_charge_station_info"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/dp_24"
            android:layout_marginTop="@dimen/dp_8"
            android:text="Welcome driving the Tesla model-S"
            android:textColor="@color/gray_400"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/iv_charge_station" />

        <TextView
            android:id="@+id/tv_select_area"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/dp_24"
            android:layout_marginEnd="@dimen/dp_20"
            android:drawablePadding="@dimen/dp_4"
            android:gravity="center"
            android:text="Los Angeles"
            android:textColor="@color/text_700"
            android:textSize="@dimen/sp_12"
            app:drawableEndCompat="@drawable/ic_arrow_down"
            app:layout_constraintBottom_toBottomOf="@id/iv_charge_station"
            app:layout_constraintEnd_toStartOf="@id/tv_select_charge_operator"
            app:layout_constraintTop_toTopOf="@id/iv_charge_station" />

        <TextView
            android:id="@+id/tv_select_charge_operator"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="16dp"
            android:layout_marginEnd="@dimen/dp_24"
            android:drawablePadding="@dimen/dp_4"
            android:gravity="center"
            android:text="select"
            android:textColor="@color/text_700"
            android:textSize="@dimen/sp_12"
            app:drawableEndCompat="@drawable/ic_arrow_down"
            app:layout_constraintBottom_toBottomOf="@id/iv_charge_station"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="@id/iv_charge_station" />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv_charge_station"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginHorizontal="@dimen/dp_24"
            android:layout_marginVertical="@dimen/dp_20"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintTop_toBottomOf="@id/tv_charge_station_info"
            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
            tools:itemCount="3"
            tools:listitem="@layout/item_charge_station" />
    </androidx.constraintlayout.widget.ConstraintLayout>

    </androidx.coordinatorlayout.widget.CoordinatorLayout>

和样式. xml

<style name="ChargeMapDialog" parent="android:Theme.Dialog">
        <item name="android:windowFrame">@null</item>
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowBackground">@color/color_transparent</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:backgroundDimEnabled">false</item>
        <item name="android:windowCloseOnTouchOutside">false</item>
    </style>

相关问题