如何让 BottomSheetDialogFragment 的高度始终保持 match_parent?

How can I keep a BottomSheetDialogFragment height to always match_parent?

我遇到了 BottomSheetDialogFragment 几天前我在一个项目中实现的问题。
发生的情况是我有一个 BottomSheet,其中包含一个 SearchView 和一个 Recyclerview。对话框片段显示正确,一切都很好。
当我使用 SearchView 过滤 Recyclerview 的结果时,问题就开始了,因为当有 5 个或更少的结果时,键盘会与现在较小的 Recyclerview.
重叠 我想知道是否可以将 BottomSheet 高度保持为 match_parent 或填充 window 或保持 Recyclerview 足够大以避免键盘 "messing up" 与结果。我使用以下方法使片段在打开时展开:

private fun expandBottomSheet() {
    view?.viewTreeObserver?.addOnGlobalLayoutListener {
        val dialog = dialog as BottomSheetDialog

        val bottomSheet = dialog.findViewById<View>(com.google.android.material.R.id.design_bottom_sheet)

        val behavior = BottomSheetBehavior.from<View>(bottomSheet)

        behavior.state = BottomSheetBehavior.STATE_EXPANDED
    }

}

我的 XML sheet 是这样的:

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    app:layout_behavior="@string/bottom_sheet_behavior">

    <View
        android:layout_width="52dp"
        android:layout_height="7dp"
        android:layout_gravity="center"
        android:layout_marginTop="@dimen/size_small_4"
        android:layout_marginBottom="@dimen/size_small_4"
        android:background="@drawable/border_top_swipe_indicator" />

    <androidx.appcompat.widget.SearchView
        android:id="@+id/searchView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:iconifiedByDefault="false"
        app:queryHint="@string/text_type_your_query" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/border_top_white"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        tools:listitem="@layout/list_item" />

</LinearLayout>

在此先感谢您的帮助!

编辑:
包含 Recyclerview 和内容的底部 sheet 是子片段(从另一个片段实例化的片段。)

在 manifest.xml 文件中,您已为您的应用程序声明了您的活动。在托管此底部 sheet 的 <activity> 块内,您可以声明一个 window 软输入模式,这样键盘就不会与视图重叠 - 而是将其向上推。

<activity
   ...
   android:windowSoftInputMode="adjustResize|stateVisible"> ... </activity>

状态可见:"The soft keyboard is visible when that's normally appropriate (when the user is navigating forward to the activity's main window)."

调整调整大小:"The activity's main window is always resized to make room for the soft keyboard on screen."

Docs

这应该适合你。根据您的观点,这可能会导致 UI 和用户体验不佳。如果是这样,您可以在搜索视图上设置一个焦点侦听器,当它获得焦点时,以编程方式将底部 sheet 的状态设置为展开。见答案

尽管我对我提出的修复不满意,但我不得不说它工作顺利。
基本上我用 ViewPager 包装了我的 bottomsheet 并且它没有调整大小。
我承认这是一个 hack,我希望有人能对此提供更体面的答案。同时,ViewPager 和单个 bottomsheet 是要走的路。

您可以在 Activity 创建时使用以下代码设置高度

view?.viewTreeObserver?.addOnGlobalLayoutListener {
            val rect = Rect()
            view?.getWindowVisibleDisplayFrame(rect)
            val screenHeight = view?.rootView?.height
            val keyPadHeight = screenHeight?.minus(rect.bottom)

            if (screenHeight != null) {
                if (keyPadHeight != 0) {
                    if (view?.paddingBottom != keyPadHeight) {
                        view?.setPadding(0, 0, 0, keyPadHeight!!)
                    }
                } else {
                    if (view?.paddingBottom != 0) {
                        view?.setPadding(0, 0, 0, 0)
                    }
                }

希望这对你有用。

对于正在搜索此问题的任何人,如果您想强制 BottomSheetDialogFragment 具有全屏高度,只需将底部 sheet 内容布局包裹在此自定义 FrameLayout 中:

public class MatchParentFrameLayout extends FrameLayout {
    public MatchParentFrameLayout(@NonNull Context context) {
        super(context);
    }

    public MatchParentFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MatchParentFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public MatchParentFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY);
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}