Android - 如何禁用底部 STATE_HALF_EXPANDED 状态 sheet
Android - How to disable STATE_HALF_EXPANDED state of a bottom sheet
我有一个底部 sheet 应该在两个状态之间,STATE_COLLAPSED
和 STATE_EXPANDED
折叠时高度应为 200dp
,展开时为全屏。
所以我将 BottomSheetBehavior
设置为
isFitToContents = false
peekHeight = 200dp
我不得不在 halfExpandedRatio
中设置一个值,否则在 STATE_HALF_EXPANDED
时底部 sheet 将占据屏幕的一半。
我正在与 com.google.android.material:material:1.1.0-rc01
一起工作
有没有办法禁用 STATE_HALF_EXPANDED
状态?
或者我实际上应该设置 skipCollapsed=true
,根据比率计算出 200dp 的含义并使用 STATE_HALF_EXPANDED
和 STATE_EXPANDED
而不是 STATE_COLLAPSED
和 STATE_EXPANDED
尝试在您的 BottomSheetBehavior
上设置 addBottomSheetCallback
,当您检测到 STATE_HALF_EXPANDED
状态时,调用 setState(STATE_HIDDEN)
因此每当底部 sheet 尝试到达中途状态,它就会关闭。
半膨胀率的值必须设置为0到1之间的某个值不包含,因此将此值设置为一定小于的某个非常低的数字你的窥视高度,说“0.0001f”。使用此值,您甚至不应该看到 STATE_HALF_EXPANDED
状态。状态将在 STATE_EXPANDED
和 STATE_COLLAPSED
之间波动。
备选方案
上面的解决方案有效并有效地禁用了 STATE_HALF_EXPANDED
状态,但它是 hackish (IMO) 并且将来可能会崩溃。例如,如果强制执行介于 peek 高度和全高之间的半扩展比率的合理值怎么办?那就麻烦了。
OP 规定的要求是底部 sheet 应该在窥视高度和全高之间过渡。 peek 高度没有问题,但 OP 指定 isFitToContents = false
以达到全高。 (我假设他的底部 sheet 可能比可用的 space 短。)
不幸的是,当 isFitToContents == false
引入了一个额外的 "half-height" 行为时,OP 想要避免,因此这个问题。
除了 "half-height" 行为之外,还引入了另一种行为,即 "expanded offset." 扩展偏移量指定底部 sheet 将停止在全屏下方多远。例如,100f
的值将在完全展开时在底部 sheet 的顶部留下 100px
边框。扩展偏移量的默认值为零。
我不知道 isFitToContents == false
引入了除上述行为之外的任何行为。
那么,鉴于这些要求,我们能否在指定 isFitToContents == true
的同时设计一个在窥视高度和全高之间移动的底部 sheet,从而避免 "half height" 问题?不需要非零扩展偏移量,因此我们不必担心。
这是一个简短的演示应用程序,演示了我们可以使用右下 sheet 结构满足这些要求:
MainActivity5.kt
class MainActivity5 : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main5)
val bottomSheet = findViewById<LinearLayout>(R.id.bottom_sheet)
val sheetBehavior: BottomSheetBehavior<LinearLayout> = BottomSheetBehavior.from(bottomSheet)
sheetBehavior.isFitToContents = true // the default
sheetBehavior.peekHeight = 200
// Log the states the bottom sheet passes through.
sheetBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
override fun onStateChanged(bottomSheet: View, newState: Int) {
Log.d("MainActivity", "<<<< $newState = ${translateSheetState(newState)}")
}
override fun onSlide(bottomSheet: View, slideOffset: Float) {}
})
}
}
BaseActivity.kt
open class BaseActivity : AppCompatActivity() {
protected fun translateSheetState(state: Int): String {
return when (state) {
BottomSheetBehavior.STATE_COLLAPSED -> "STATE_COLLAPSED"
BottomSheetBehavior.STATE_DRAGGING -> "STATE_DRAGGING"
BottomSheetBehavior.STATE_EXPANDED -> "STATE_EXPANDED"
BottomSheetBehavior.STATE_HALF_EXPANDED -> "STATE_HALF_EXPANDED"
BottomSheetBehavior.STATE_HIDDEN -> "STATE_HIDDEN"
BottomSheetBehavior.STATE_SETTLING -> "STATE_SETTLING"
else -> "Unknown state: $state"
}
}
}
activity_main5.xml
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_orange_light"
android:orientation="vertical"
android:scrollbars="none"
app:layout_behavior="@string/bottom_sheet_behavior">
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="@string/short_text"
android:textSize="16sp" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
如果我们有一个长底部 sheet 那么下面的结构可以滚动它:
activity_main6.xml
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_orange_light"
android:orientation="vertical"
android:scrollbars="none"
app:layout_behavior="@string/bottom_sheet_behavior">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="@string/long_text"
android:textSize="16sp" />
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
我有一个类似的用例,其中布局必须是高度的三分之一。我尝试了以下方法,效果很好。
<androidx.coordinatorlayout.widget.CoordinatorLayout 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/bottom_sheet_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/grey"
android:clickable="true">
<LinearLayout
android:id="@+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/rounded_bottom_sheet_background"
android:orientation="vertical"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
我不得不动态更改这些,所以我在底部设置了以下内容 sheet 但你也可以在 xml 中这样做:
bottomSheet.setPeekHeight(200);// 200px
bottomSheet.setHideable(false);
为了解散,我使用以下函数向我的片段添加了动画:
fragmentTransaction.setCustomAnimations(
R.anim.fade_in,
R.anim.fade_out,
R.anim.fade_in,
R.anim.fade_out)
希望对您有所帮助
尝试设置 BottomSheetBehavior
.setHalfExpandedRatio(0f)
. There is not much else which would affect STATE_HALF_EXPANDED
, unless explicitly setting the state with .setState(). It should also be possible to create a custom Behavior
, which extends CoordinatorLayout.Behavior<View>
and does not have STATE_HALF_EXPANDED
. eg. Intercepting everything with CoordinatorLayout Behaviors.
如果你想尝试上面的图片,你可以按照下面的代码,可能会对你有所帮助!!!
public class CollectionsBottomSheet extends BottomSheetDialogFragment {
private BottomSheetBehavior mBehavior;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
View view = View.inflate(getContext(), R.layout.collections_layout, null);
LinearLayout linearLayout = view.findViewById(R.id.root);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) linearLayout.getLayoutParams();
params.height = getScreenHeight();
linearLayout.setLayoutParams(params);
dialog.setContentView(view);
mBehavior = BottomSheetBehavior.from((View) view.getParent());
return dialog;
}
@Override
public void onStart() {
super.onStart();
mBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
public static int getScreenHeight() {
return Resources.getSystem().getDisplayMetrics().heightPixels;
}
}
xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:fitsSystemWindows="true">
<LinearLayout
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/filter_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_cancel"
android:drawableLeft="@drawable/ic_cancel"
android:drawablePadding="30dp"
android:gravity="center_vertical"
android:padding="12dp"
android:text="Filters"
android:textColor="@color/black"
android:textSize="18sp" />
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:layout_marginRight="10dp"
android:padding="5dp"
android:text="Reset ALL"
android:textColor="#6f6f6f"
android:textSize="12sp" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#d8dbdb" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/sort_background"
android:drawableStart="@drawable/ic_star"
android:drawableLeft="@drawable/ic_star"
android:drawablePadding="15dp"
android:padding="15dp"
android:text="GUEST RATINGS"
android:textColor="#6f6f6f"
android:textSize="16sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/sort_background"
android:drawableStart="@drawable/ic_money"
android:drawableLeft="@drawable/ic_money"
android:drawablePadding="15dp"
android:padding="15dp"
android:text="PRICE RANGE"
android:textColor="#6f6f6f"
android:textSize="16sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/sort_background"
android:drawableStart="@drawable/ic_loan"
android:drawableLeft="@drawable/ic_star"
android:drawablePadding="15dp"
android:padding="15dp"
android:text="PAY AT HOTEL"
android:textColor="#6f6f6f"
android:textSize="16sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/sort_background"
android:drawableStart="@drawable/ic_folder"
android:drawableLeft="@drawable/ic_folder"
android:drawablePadding="15dp"
android:padding="15dp"
android:text="COLLECTIONS"
android:textColor="#6f6f6f"
android:textSize="16sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/sort_background"
android:drawableStart="@drawable/ic_perm_identity_black_24dp"
android:drawableLeft="@drawable/ic_perm_identity_black_24dp"
android:drawablePadding="15dp"
android:padding="15dp"
android:text="FACILITIES"
android:textColor="#6f6f6f"
android:textSize="16sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/sort_background"
android:drawableStart="@drawable/ic_apartment"
android:drawableLeft="@drawable/ic_apartment"
android:drawablePadding="15dp"
android:padding="15dp"
android:text="CATEGORIES"
android:textColor="#6f6f6f"
android:textSize="16sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/sort_background"
android:drawableStart="@drawable/ic_hotel_building"
android:drawableLeft="@drawable/ic_hotel_building"
android:drawablePadding="15dp"
android:padding="15dp"
android:text="ACCOMMODATION TYPE"
android:textColor="#6f6f6f"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>
我尝试了不同的方法,但没有一种技术是完美的。我尝试拦截 BottomSheetBehavior.BottomSheetCallback {}
中的事件并根据自定义逻辑调用 dismiss()
但它导致了一个问题。
所以,最后,在我的 BottomSheetDialogFragment
中,我添加了 bottomSheetBehavior.isDraggable = false
,这导致通过触摸拖动底部 sheet 而且,我我自己处理了对话的解雇。在空白区域对话框中无论如何都会被解雇。
请注意,底部 sheet 仍会随着动画展开。太棒了!
覆盖乐趣 onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState)
dialog.setOnShowListener {
val bottomSheetDialog = it as BottomSheetDialog
val bottomSheet =
bottomSheetDialog.findViewById<View>(com.google.android.material.R.id.design_bottom_sheet)
?: return@setOnShowListener
//Making background to transparent to avoid white background to given space margin.
bottomSheet.setBackgroundColor(ContextCompat.getColor(context!!, R.color.transparent))
val inflatedView = fragmentProfileDialogBinding.root
val parent = inflatedView.parent as View
val bottomSheetBehavior = BottomSheetBehavior.from(parent)
bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
bottomSheetBehavior.isDraggable = false
}
return dialog
}
我正在使用 material 库版本 1.1.0 并且 BottomSheetBehavior
class 有这个 属性 skipCollapsed
,如果你将它设置为 true
底部 sheet 将跳过 STATE_HALF_EXPANDED
.
这是我的代码:
class FilterBottomSheet : BottomSheetDialogFragment() {
private lateinit var behavior: BottomSheetBehavior<View>
override fun onStart() {
super.onStart()
behavior.state = BottomSheetBehavior.STATE_EXPANDED
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog
val view = View.inflate(requireContext(), R.layout.filter_bottom_sheet, null)
val params = view.root.layoutParams as LinearLayout.LayoutParams?
params?.height = getScreenHeight()
view.root.layoutParams = params
dialog.setContentView(view)
behavior = BottomSheetBehavior.from(view.parent as View)
behavior.skipCollapsed = true
return dialog
}
private fun getScreenHeight(): Int = Resources.getSystem().displayMetrics.heightPixels
}
根据其他答案,您可以通过在底部 sheet 上设置 app:behavior_skipCollapsed="true"
在 XML 中禁用此功能。例如,在我的用例中:
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/bottom_sheet"
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"
app:behavior_skipCollapsed="true"
app:behavior_hideable="true"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
android:background="@color/colorTransparent">
在 Kotlin 中,要禁用 STATE_HALF_EXPANDED
,您可以使用类似的解决方案,方法是访问 BottomSheetDialogFragment
的 BottomSheetBehavior
并设置 skipCollapsed = true
.
为此,您可以覆盖 onViewCreated
`BottomSheetDialogFragment 实现的方法并访问对话框的行为对象。
示例(代码在您的 BottomSheetDialogFragment
实现中):
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
dialog?.let {
val sheet = it as BottomSheetDialog
sheet.behavior.state = BottomSheetBehavior.STATE_EXPANDED
sheet.behavior.skipCollapsed = true
}
}
我有一个底部 sheet 应该在两个状态之间,STATE_COLLAPSED
和 STATE_EXPANDED
折叠时高度应为 200dp
,展开时为全屏。
所以我将 BottomSheetBehavior
设置为
isFitToContents = false
peekHeight = 200dp
我不得不在 halfExpandedRatio
中设置一个值,否则在 STATE_HALF_EXPANDED
时底部 sheet 将占据屏幕的一半。
我正在与 com.google.android.material:material:1.1.0-rc01
有没有办法禁用 STATE_HALF_EXPANDED
状态?
或者我实际上应该设置 skipCollapsed=true
,根据比率计算出 200dp 的含义并使用 STATE_HALF_EXPANDED
和 STATE_EXPANDED
而不是 STATE_COLLAPSED
和 STATE_EXPANDED
尝试在您的 BottomSheetBehavior
上设置 addBottomSheetCallback
,当您检测到 STATE_HALF_EXPANDED
状态时,调用 setState(STATE_HIDDEN)
因此每当底部 sheet 尝试到达中途状态,它就会关闭。
半膨胀率的值必须设置为0到1之间的某个值不包含,因此将此值设置为一定小于的某个非常低的数字你的窥视高度,说“0.0001f”。使用此值,您甚至不应该看到 STATE_HALF_EXPANDED
状态。状态将在 STATE_EXPANDED
和 STATE_COLLAPSED
之间波动。
备选方案
上面的解决方案有效并有效地禁用了 STATE_HALF_EXPANDED
状态,但它是 hackish (IMO) 并且将来可能会崩溃。例如,如果强制执行介于 peek 高度和全高之间的半扩展比率的合理值怎么办?那就麻烦了。
OP 规定的要求是底部 sheet 应该在窥视高度和全高之间过渡。 peek 高度没有问题,但 OP 指定 isFitToContents = false
以达到全高。 (我假设他的底部 sheet 可能比可用的 space 短。)
不幸的是,当 isFitToContents == false
引入了一个额外的 "half-height" 行为时,OP 想要避免,因此这个问题。
除了 "half-height" 行为之外,还引入了另一种行为,即 "expanded offset." 扩展偏移量指定底部 sheet 将停止在全屏下方多远。例如,100f
的值将在完全展开时在底部 sheet 的顶部留下 100px
边框。扩展偏移量的默认值为零。
我不知道 isFitToContents == false
引入了除上述行为之外的任何行为。
那么,鉴于这些要求,我们能否在指定 isFitToContents == true
的同时设计一个在窥视高度和全高之间移动的底部 sheet,从而避免 "half height" 问题?不需要非零扩展偏移量,因此我们不必担心。
这是一个简短的演示应用程序,演示了我们可以使用右下 sheet 结构满足这些要求:
MainActivity5.kt
class MainActivity5 : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main5)
val bottomSheet = findViewById<LinearLayout>(R.id.bottom_sheet)
val sheetBehavior: BottomSheetBehavior<LinearLayout> = BottomSheetBehavior.from(bottomSheet)
sheetBehavior.isFitToContents = true // the default
sheetBehavior.peekHeight = 200
// Log the states the bottom sheet passes through.
sheetBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
override fun onStateChanged(bottomSheet: View, newState: Int) {
Log.d("MainActivity", "<<<< $newState = ${translateSheetState(newState)}")
}
override fun onSlide(bottomSheet: View, slideOffset: Float) {}
})
}
}
BaseActivity.kt
open class BaseActivity : AppCompatActivity() {
protected fun translateSheetState(state: Int): String {
return when (state) {
BottomSheetBehavior.STATE_COLLAPSED -> "STATE_COLLAPSED"
BottomSheetBehavior.STATE_DRAGGING -> "STATE_DRAGGING"
BottomSheetBehavior.STATE_EXPANDED -> "STATE_EXPANDED"
BottomSheetBehavior.STATE_HALF_EXPANDED -> "STATE_HALF_EXPANDED"
BottomSheetBehavior.STATE_HIDDEN -> "STATE_HIDDEN"
BottomSheetBehavior.STATE_SETTLING -> "STATE_SETTLING"
else -> "Unknown state: $state"
}
}
}
activity_main5.xml
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_orange_light"
android:orientation="vertical"
android:scrollbars="none"
app:layout_behavior="@string/bottom_sheet_behavior">
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="@string/short_text"
android:textSize="16sp" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
如果我们有一个长底部 sheet 那么下面的结构可以滚动它:
activity_main6.xml
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_orange_light"
android:orientation="vertical"
android:scrollbars="none"
app:layout_behavior="@string/bottom_sheet_behavior">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="@string/long_text"
android:textSize="16sp" />
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
我有一个类似的用例,其中布局必须是高度的三分之一。我尝试了以下方法,效果很好。
<androidx.coordinatorlayout.widget.CoordinatorLayout 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/bottom_sheet_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/grey"
android:clickable="true">
<LinearLayout
android:id="@+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/rounded_bottom_sheet_background"
android:orientation="vertical"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
我不得不动态更改这些,所以我在底部设置了以下内容 sheet 但你也可以在 xml 中这样做:
bottomSheet.setPeekHeight(200);// 200px
bottomSheet.setHideable(false);
为了解散,我使用以下函数向我的片段添加了动画:
fragmentTransaction.setCustomAnimations(
R.anim.fade_in,
R.anim.fade_out,
R.anim.fade_in,
R.anim.fade_out)
希望对您有所帮助
尝试设置 BottomSheetBehavior
.setHalfExpandedRatio(0f)
. There is not much else which would affect STATE_HALF_EXPANDED
, unless explicitly setting the state with .setState(). It should also be possible to create a custom Behavior
, which extends CoordinatorLayout.Behavior<View>
and does not have STATE_HALF_EXPANDED
. eg. Intercepting everything with CoordinatorLayout Behaviors.
如果你想尝试上面的图片,你可以按照下面的代码,可能会对你有所帮助!!!
public class CollectionsBottomSheet extends BottomSheetDialogFragment {
private BottomSheetBehavior mBehavior;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
View view = View.inflate(getContext(), R.layout.collections_layout, null);
LinearLayout linearLayout = view.findViewById(R.id.root);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) linearLayout.getLayoutParams();
params.height = getScreenHeight();
linearLayout.setLayoutParams(params);
dialog.setContentView(view);
mBehavior = BottomSheetBehavior.from((View) view.getParent());
return dialog;
}
@Override
public void onStart() {
super.onStart();
mBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
public static int getScreenHeight() {
return Resources.getSystem().getDisplayMetrics().heightPixels;
}
}
xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:fitsSystemWindows="true">
<LinearLayout
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/filter_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_cancel"
android:drawableLeft="@drawable/ic_cancel"
android:drawablePadding="30dp"
android:gravity="center_vertical"
android:padding="12dp"
android:text="Filters"
android:textColor="@color/black"
android:textSize="18sp" />
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:layout_marginRight="10dp"
android:padding="5dp"
android:text="Reset ALL"
android:textColor="#6f6f6f"
android:textSize="12sp" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#d8dbdb" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/sort_background"
android:drawableStart="@drawable/ic_star"
android:drawableLeft="@drawable/ic_star"
android:drawablePadding="15dp"
android:padding="15dp"
android:text="GUEST RATINGS"
android:textColor="#6f6f6f"
android:textSize="16sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/sort_background"
android:drawableStart="@drawable/ic_money"
android:drawableLeft="@drawable/ic_money"
android:drawablePadding="15dp"
android:padding="15dp"
android:text="PRICE RANGE"
android:textColor="#6f6f6f"
android:textSize="16sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/sort_background"
android:drawableStart="@drawable/ic_loan"
android:drawableLeft="@drawable/ic_star"
android:drawablePadding="15dp"
android:padding="15dp"
android:text="PAY AT HOTEL"
android:textColor="#6f6f6f"
android:textSize="16sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/sort_background"
android:drawableStart="@drawable/ic_folder"
android:drawableLeft="@drawable/ic_folder"
android:drawablePadding="15dp"
android:padding="15dp"
android:text="COLLECTIONS"
android:textColor="#6f6f6f"
android:textSize="16sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/sort_background"
android:drawableStart="@drawable/ic_perm_identity_black_24dp"
android:drawableLeft="@drawable/ic_perm_identity_black_24dp"
android:drawablePadding="15dp"
android:padding="15dp"
android:text="FACILITIES"
android:textColor="#6f6f6f"
android:textSize="16sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/sort_background"
android:drawableStart="@drawable/ic_apartment"
android:drawableLeft="@drawable/ic_apartment"
android:drawablePadding="15dp"
android:padding="15dp"
android:text="CATEGORIES"
android:textColor="#6f6f6f"
android:textSize="16sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/sort_background"
android:drawableStart="@drawable/ic_hotel_building"
android:drawableLeft="@drawable/ic_hotel_building"
android:drawablePadding="15dp"
android:padding="15dp"
android:text="ACCOMMODATION TYPE"
android:textColor="#6f6f6f"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>
我尝试了不同的方法,但没有一种技术是完美的。我尝试拦截 BottomSheetBehavior.BottomSheetCallback {}
中的事件并根据自定义逻辑调用 dismiss()
但它导致了一个问题。
所以,最后,在我的 BottomSheetDialogFragment
中,我添加了 bottomSheetBehavior.isDraggable = false
,这导致通过触摸拖动底部 sheet 而且,我我自己处理了对话的解雇。在空白区域对话框中无论如何都会被解雇。
请注意,底部 sheet 仍会随着动画展开。太棒了!
覆盖乐趣 onCreateDialog(savedInstanceState: Bundle?): Dialog { val dialog = super.onCreateDialog(savedInstanceState)
dialog.setOnShowListener {
val bottomSheetDialog = it as BottomSheetDialog
val bottomSheet =
bottomSheetDialog.findViewById<View>(com.google.android.material.R.id.design_bottom_sheet)
?: return@setOnShowListener
//Making background to transparent to avoid white background to given space margin.
bottomSheet.setBackgroundColor(ContextCompat.getColor(context!!, R.color.transparent))
val inflatedView = fragmentProfileDialogBinding.root
val parent = inflatedView.parent as View
val bottomSheetBehavior = BottomSheetBehavior.from(parent)
bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
bottomSheetBehavior.isDraggable = false
}
return dialog
}
我正在使用 material 库版本 1.1.0 并且 BottomSheetBehavior
class 有这个 属性 skipCollapsed
,如果你将它设置为 true
底部 sheet 将跳过 STATE_HALF_EXPANDED
.
这是我的代码:
class FilterBottomSheet : BottomSheetDialogFragment() {
private lateinit var behavior: BottomSheetBehavior<View>
override fun onStart() {
super.onStart()
behavior.state = BottomSheetBehavior.STATE_EXPANDED
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog
val view = View.inflate(requireContext(), R.layout.filter_bottom_sheet, null)
val params = view.root.layoutParams as LinearLayout.LayoutParams?
params?.height = getScreenHeight()
view.root.layoutParams = params
dialog.setContentView(view)
behavior = BottomSheetBehavior.from(view.parent as View)
behavior.skipCollapsed = true
return dialog
}
private fun getScreenHeight(): Int = Resources.getSystem().displayMetrics.heightPixels
}
根据其他答案,您可以通过在底部 sheet 上设置 app:behavior_skipCollapsed="true"
在 XML 中禁用此功能。例如,在我的用例中:
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/bottom_sheet"
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"
app:behavior_skipCollapsed="true"
app:behavior_hideable="true"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
android:background="@color/colorTransparent">
在 Kotlin 中,要禁用 STATE_HALF_EXPANDED
,您可以使用类似的解决方案,方法是访问 BottomSheetDialogFragment
的 BottomSheetBehavior
并设置 skipCollapsed = true
.
为此,您可以覆盖 onViewCreated
`BottomSheetDialogFragment 实现的方法并访问对话框的行为对象。
示例(代码在您的 BottomSheetDialogFragment
实现中):
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
dialog?.let {
val sheet = it as BottomSheetDialog
sheet.behavior.state = BottomSheetBehavior.STATE_EXPANDED
sheet.behavior.skipCollapsed = true
}
}