簡體   English   中英

如何設置 Bottom Sheet peek height 最初只顯示某些部分?

[英]How to set Bottom Sheet peek height to show only certain parts initially?

假設我的 Bottom Sheet 有幾行小部件,如下所示。 如果我最初只想顯示前兩行(即前兩行LinearLayout ),而不是下面的其余小部件。 我不希望最初看到這些。 如何設置正確的窺視高度? 硬編碼app:behavior_peekHeight可能行不通,所以我需要以編程方式設置它,但如何計算高度?

還是有更推薦的方法來獲得相同的結果? 我的意思是,如果我測試谷歌地圖,長按一個位置首先只顯示標題部分作為底部工作表,但是當我嘗試向上滾動底部工作表時,感覺標題部分(可能不是真實的) bottom sheet) 被包含所有元素的真正的 bottom sheet 所取代。 如果我的解釋還不夠,請自行嘗試谷歌地圖。

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

我將通過使用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 ,它包含一個包含許多TextViewLinearLayout 通過將峰值高度設置為第三個TextView的頂部(由getChildAt(2) ),我的底部頁面在折疊時最終顯示兩個TextView

在此輸入圖像描述 在此輸入圖像描述

定制@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
                    }
                })
    }
}

在我們的用例中,我們需要定位視圖的底部 ,因此我們將其設置為這樣。 它可以根據用例進行調整。

真聰明! 我的問題是在錯誤的時間嘗試getTop()getHeight() ,如果視圖未准備好,它返回0

是的,使用viewTreeObserver來避免這種情況。

這實際上與@Ben P. 之前的回答沒有什么不同,只是一個 kotlin 版本:


class MyBottomSheetDialog() : BottomSheetDialogFragment(){

    private val binding by viewBinding(SomeLayoutViewBinding::bind)
    ...

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        (this.dialog as BottomSheetDialog).behavior.let { behavior ->
            /* Set "pivotView" as interested target and make it the pivot of peek */
            binding.pivotView.viewTreeObserver.addOnGlobalLayoutListener(object :
                OnGlobalLayoutListener {
                override fun onGlobalLayout() {
                    binding.pivotView.viewTreeObserver.removeOnGlobalLayoutListener(this)
                    behavior.peekHeight = binding.pivotView.top
                }
            })
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM