私のボトムシートに次のようなウィジェットの行があるとしましょう。最初に最初の2行(つまり、最初の2つのLinearLayout
s)のみを表示し、以下の残りのウィジェットは表示しない場合。私はそれらが最初に見られることを望まない。正しいピークの高さを設定するにはどうすればよいですか?ハードコーディング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>
これを解決するには、_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番目のTextView
(getChildAt(2)
によって取得)の上部に設定すると、折りたたまれている間、一番下のシートにちょうど2つのTextView
が表示されます。
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部分をターゲットにする必要があったため、そのように設定しました。ユースケースに応じて調整できます。