web-dev-qa-db-ja.com

ボトムシートのピークの高さを設定して、最初に特定のパーツのみを表示するにはどうすればよいですか?

私のボトムシートに次のようなウィジェットの行があるとしましょう。最初に最初の2行(つまり、最初の2つのLinearLayouts)のみを表示し、以下の残りのウィジェットは表示しない場合。私はそれらが最初に見られることを望まない。正しいピークの高さを設定するにはどうすればよいですか?ハードコーディングapp:behavior_peekHeightおそらく機能しないので、プログラムで設定する必要がありますが、高さを計算するにはどうすればよいですか?

または、同じ結果を得るためのより推奨される方法はありますか?つまり、Googleマップをテストすると、最初に場所を長押しすると、下部のシートとしてタイトル部分のみが表示されますが、下部のシートを上にスクロールしようとすると、タイトル部分のように感じられます(これは実際にはなかった可能性があります)ボトムシート)は、すべての要素を含む実際のボトムシートに置き換えられます。私の説明が十分でない場合は、Googleマップを自分で試してみてください。

<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>
4
Damn Vegetables

これを解決するには、_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です。ピークの高さを3番目のTextViewgetChildAt(2)によって取得)の上部に設定すると、折りたたまれている間、一番下のシートにちょうど2つのTextViewが表示されます。

enter image description hereenter image description here

11
Ben P.

peekHeightの参照としてビューIDをターゲットにするように、@ Ben P.の回答をカスタマイズし、関数を作成しました。

/**
 * 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
                    }
                })
    }
}

このユースケースでは、ビューのbottom部分をターゲットにする必要があったため、そのように設定しました。ユースケースに応じて調整できます。

2
AL.