在 BottomSheetDialog Fragment 中将视图固定到屏幕底部

Posted

技术标签:

【中文标题】在 BottomSheetDialog Fragment 中将视图固定到屏幕底部【英文标题】:Pin a view to bottom of screen in BottomSheetDialog Fragment 【发布时间】:2019-01-25 17:09:11 【问题描述】:

我在我的项目中使用了 BottomSheetDialogFragment,我将其设计如下:

目标:我要将 BottomSheetDialog 的底部菜单粘贴到屏幕底部,无论是折叠还是展开模式。

所以在BottomSheetDialog布局中,我使用RelativeLayout作为父级,“layout_alignParentBottom”作为菜单容器,如下:

<RelativeLayout 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/bottomSheetContainer"
android:layout_
android:layout_
android:layout_gravity="center_horizontal"
app:behavior_hideable="true"
app:behavior_peekHeight="0dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
tools:context=".MyBottomSheetDialogFragment">

<RelativeLayout
    android:id="@+id/topSection"
    android:layout_
    android:layout_
    android:layout_alignParentTop="true">
    ....
</RelativeLayout>

<android.support.v4.widget.NestedScrollView
    android:id="@+id/descriptionContainer"
    android:layout_
    android:layout_
    android:layout_below="@id/topSection">
    ....
</android.support.v4.widget.NestedScrollView>

<HorizontalScrollView
    android:id="@+id/iconsContainer"
    android:layout_
    android:layout_
    android:layout_alignParentBottom="true">
    ....
</HorizontalScrollView>
</RelativeLayout>

但对话如下:

如你所见,底部菜单一开始是不可见的。

谁能帮我解决这个问题?

【问题讨论】:

如何将gravity 设置为bottom?你还没试过吗?此外,如我所见,您在彼此下方的视图很少,RelativeLayout 可能是布局顶部的LinearLayout-FrameLayout,您可以轻松管理其他下面的布局。你可能想看看:***.com/a/4099076/4409113 @ʍѳђઽ૯ท 我做到了,但实际上问题是,我要在 BottomSheetDialog 中做到这一点!看看这张图你就知道这是什么原因了:photobox.co.uk/my/… 【参考方案1】:

为了解决这个问题,我尝试了几件事,但我没有成功。

但这最终通过这种方式为我解决了:

对于折叠模式,我将 bottomSheetBehavior 的 peekHeight 设置为屏幕的 1/3(使用以下代码):

    View bottomSheetContainer = dialog.findViewById(R.id.bottomSheetContainer);
    View parent = (View) bottomSheetContainer.getParent();
    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) parent.getLayoutParams();
    BottomSheetBehavior bottomSheetBehavior = (BottomSheetBehavior) params.getBehavior();
    View inflatedView = View.inflate(getContext(), R.layout.word_details_bottom_sheet, null);
    inflatedView.measure(0, 0);
    int screenHeight = getActivity().getResources().getDisplayMetrics().heightPixels;

    if (bottomSheetBehavior != null) 
        bottomSheetBehavior.setPeekHeight(screenHeight /3);
    

所以我决定这样做:

1- 折叠模式:bottomSheet 容器的高度 = bottomSheetBehavior 的 peekHeight

2- 对于展开模式:bottomSheet 容器的高度 = 全屏高度

于是我写了如下代码(完整代码):

WordDetailsBottomSheet.java

public class WordDetailsBottomSheet extends BottomSheetDialogFragment 

public WordDetailsBottomSheet()  // Required empty public constructor 

@NotNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) 
    BottomSheetDialog dialog = new BottomSheetDialog(getActivity(), 0);
    dialog.setContentView(R.layout.word_details_bottom_sheet);

    View bottomSheetContainer = dialog.findViewById(R.id.bottomSheetContainer);
    View parent = (View) bottomSheetContainer.getParent();
    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) parent.getLayoutParams();
    BottomSheetBehavior bottomSheetBehavior = (BottomSheetBehavior) params.getBehavior();
    View inflatedView = View.inflate(getContext(), R.layout.word_details_bottom_sheet, null);
    inflatedView.measure(0, 0);
    int screenHeight = getActivity().getResources().getDisplayMetrics().heightPixels;
    int statusBarHeight = getStatusBarHeight();

    if (bottomSheetBehavior != null) 
        bottomSheetBehavior.setPeekHeight(screenHeight / BOTTOM_SHEET_PEEK_HEIGHT_PERCENT);
        bottomSheetContainer.getLayoutParams().height = bottomSheetBehavior.getPeekHeight();
    

    bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() 
        @Override
        public void onStateChanged(@NonNull View view, int newState) 
            switch (newState) 
                case BottomSheetBehavior.STATE_EXPANDED:
                    bottomSheetContainer.getLayoutParams().height = screenHeight-statusBarHeight;
                    break;
                case BottomSheetBehavior.STATE_COLLAPSED:
                    bottomSheetContainer.getLayoutParams().height = bottomSheetBehavior.getPeekHeight();
                    break;
                case BottomSheetBehavior.STATE_HIDDEN:
                    dismiss();
                    break;
                default:
                    break;
            
        

        @Override
        public void onSlide(@NonNull View view, float slideOffset) 
        
    );

    return dialog;


public int getStatusBarHeight() 
    int result = 0;
    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0) 
        result = getResources().getDimensionPixelSize(resourceId);
    
    return result;
    

word_details_bottom_sheet.xml

<RelativeLayout 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/bottomSheetContainer"
android:layout_
android:layout_
android:layout_gravity="center_horizontal"
app:behavior_hideable="true"
app:behavior_peekHeight="0dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
tools:context=".MyBottomSheetDialogFragment">

<RelativeLayout
android:id="@+id/topSection"
android:layout_
android:layout_
android:layout_alignParentTop="true">
....
</RelativeLayout>

<android.support.v4.widget.NestedScrollView
android:id="@+id/descriptionContainer"
android:layout_
android:layout_
android:layout_below="@id/topSection">
....
</android.support.v4.widget.NestedScrollView>

<HorizontalScrollView
android:id="@+id/iconsContainer"
android:layout_
android:layout_
android:layout_alignParentBottom="true">
....
</HorizontalScrollView>
</RelativeLayout>

在xml文件中,重要的是:

1- 父 id (android:id="@+id/bottomSheetContainer")

2-iconsContainer 对齐 (android:layout_alignParentBottom="true")

【讨论】:

这更像是 一个自定义 BottomSheetDialogFragment,而不是我在回答中提到的 BottomSheetDialog 的问题。【参考方案2】:

如你所见,底部菜单一开始是不可见的。

谁能帮我解决这个问题

我猜这种行为运行良好,因为您设置了layout_height of NestedScrollView (中心内容)wrap_content,这意味着它将被被里面的内容包裹

同时;

android:layout_alignParentBottom="true"

To HorizontalScrollView (低于layout表示它将在另一个layouts下它目前是!

所以,如果你想看看它是否工作正常,设置100dp-50dp(或者当BottomSheetDialog出现时你可以看到的特定尺寸)而不是wrap_contentNestedScrollView 那么你可能会看到下面的layout 和其他layouts 将是可见的。

无论如何,此布局中的所有内容看起来都正确无误。有图有真相。

【讨论】:

以上是关于在 BottomSheetDialog Fragment 中将视图固定到屏幕底部的主要内容,如果未能解决你的问题,请参考以下文章

膨胀BottomSheetDialog时替换片段

在 Android 中,BottomSheetDialog 未正确舍入顶角

如何在 BottomSheetDialog 中获取 ViewModel

如何在BottomSheetDialog android的顶部中心添加关闭按钮?

在 BottomSheetDialog Fragment 中将视图固定到屏幕底部

Android BottomSheetDialog设置背景透明无效?(解决)