如何设置Bottom Sheet peek高度以便最初仅显示某些部件?

时间:2018-02-27 17:07:28

标签: android android-layout android-widget bottom-sheet

让我们说我的Bottom Sheet有如下所示的小部件。如果我想最初只显示前两行(即前两个LinearLayout),而不是下面的其他小部件。我不希望最初看到这些。如何设置正确的峰值高度?硬编码app:behavior_peekHeight可能不起作用,所以我需要以编程方式设置它,但是如何计算高度?

或者是否有更推荐的方法来获得相同的结果?我的意思是,如果我测试谷歌地图,长按一个位置首先只显示标题部分作为底部工作表,但当我尝试向上滚动底部工作表时,感觉好像标题部分(可能不是真实的底部表格由包含所有元素的真实底部表格替换。如果我的解释不够,请自行试用谷歌地图。

<android.support.v4.widget.NestedScrollView
    android:id="@+id/bottom_sheet"
    app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
    android:scrollbars="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <LinearLayout
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <TextView/>
            <android.support.v7.widget.AppCompatSpinner/>
        </LinearLayout>
        <LinearLayout
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <TextView/>
            <TextView/>
        </LinearLayout>
        <LinearLayout
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <TextView/>
            <TextView/>
        </LinearLayout>
        <android.support.v7.widget.RecyclerView/>
    </LinearLayout>
</android.support.v4.widget.NestedScrollView>

2 个答案:

答案 0 :(得分:4)

我会通过使用ViewTreeObserver.OnGlobalLayoutListener等待您的底页布局来解决此问题,然后使用您不希望看到的第一个视图的y坐标调用BottomSheetBehavior.setPeekHeight()

private BottomSheetBehavior<View> behavior;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    View bottomSheet = findViewById(R.id.bottomSheet);
    behavior = BottomSheetBehavior.from(bottomSheet);

    final LinearLayout inner = findViewById(R.id.inner);
    inner.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            inner.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            View hidden = inner.getChildAt(2);
            behavior.setPeekHeight(hidden.getTop());
        }
    });
}

在这种情况下,我的底部工作表是NestedScrollView,持有LinearLayout,其中包含许多TextView个。通过将窥视高度设置为第三个TextView的顶部(由getChildAt(2)获得),我的底部工作表最终会在折叠时显示两个TextView

enter image description here enter image description here

答案 1 :(得分:1)

自定义@Ben P.的答案,以将视图ID作为peekHeight的引用并创建函数:

/**
 * Gets the bottom part of the target view and sets it as the peek height of the specified @{BottomSheetBehavior}
 *
 * @param layout - layout of the bottom sheet.
 * @param targetViewId - id of the target view. Must be a view inside the 'layout' param.
 * @param behavior - bottom sheet behavior recipient.
 */
private fun <T : ViewGroup> getViewBottomHeight(layout: ViewGroup,
                                                targetViewId: Int,
                                                behavior: BottomSheetBehavior<T>) {
    layout.apply {
        viewTreeObserver.addOnGlobalLayoutListener(
                object : ViewTreeObserver.OnGlobalLayoutListener {
                    override fun onGlobalLayout() {
                        viewTreeObserver.removeOnGlobalLayoutListener(this)
                        behavior.peekHeight = findViewById<View>(targetViewId).bottom
                    }
                })
    }
}

在我们的用例中,我们需要定位视图的底部部分,因此我们以这种方式进行设置。可以根据用例进行调整。