ボトムシートが別のボトムシート内にネストされています(FrameLayouts
レイアウト動作を使用してBottomSheet
)
また、クリックリスナーがアタッチされた2つの「ピークビュー」(FrameLayouts
)もあり、クリックするとそれぞれ下部のシートを展開します。
したがって、アプリには基本的に3つのメイン画面があります。 「メインコンテナー」、次に最初の「ボトムシート」はフルスクリーンで展開でき、最初のボトムシートの一番下は2番目のボトムシートで、これもフルスクリーンで展開できます。
問題:
ネストしたボトムシートの「コンテナー」ビューにRecyclerView
を追加すると、2番目のピークビュー(シート2ピーク)でドラッグが機能しなくなります。ピークビューClickListener
またはを削除すると、RecyclerView
は問題なく動作するようです。
望ましい結果:
両方の下部シートはドラッグ可能なままで、ピークビューをクリックして親下部シートを展開できる必要があります。下のシートはネストされたスクロールに通常どおりに応答する必要があります。
ClickListener
を削除し、代わりにタッチジェスチャーを使用してみましたが、私が試したことは何も役に立たないようです。
設計サポートライブラリのv25.3.1
を使用しています。この問題は、4.4.4ストックを実行しているGalaxy S4、および7.1.2ストックを実行しているNexus 6Pで再現できます。 (他に利用可能なデバイスはありません)。
さらに詳しく見てみたい人のために、githubにテストプロジェクトを作成しました: https://github.com/timusus/bottomsheet-test
レイアウトを示すスクリーンショットをいくつか示します。
レイアウト構造は次のようになります(わかりやすくするために一部のコードは省略しています)。
<CoordinatorLayout>
<FrameLayout
Android:id="@+id/mainContainer"
Android:layout_height="match_parent"/>
<FrameLayout
Android:id="@+id/sheet1"
Android:layout_height="match_parent"
app:layout_behavior="CustomBottomSheetBehavior"
app:behavior_peekHeight="64dp">
<FrameLayout
Android:id="@+id/sheet1Container"
Android:layout_height="match_parent"/>
<CoordinatorLayout>
<FrameLayout
Android:id="@+id/sheet2
Android:layout_height="match_parent"
app:layout_behavior="CustomBottomSheetBehavior"
app:behavior_peekHeight="64dp">
<FrameLayout
Android:id="@+id/sheet2Container"
Android:layout_height="match_parent">
<!-- Problematic RecyclerView -->
<RecyclerView
Android:layout_height="match_parent"/>
</FrameLayout>
<!-- Problematic Click Listener on this view -->
<FrameLayout
Android:id="@+id/sheet2PeekView"
Android:layout_height=64dp"/>
</FrameLayout>
</CoordinatorLayout>
<FrameLayout
Android:id="@+id/sheet1PeekView"
Android:layout_height=64dp"/>
</FrameLayout>
</CoordinatorLayout/>
CustomBottomSheetBehavior
はBottomSheetBehavior
の単なるサブクラスであり、2番目のシートが展開またはドラッグされている場合、最初のシートがタッチイベントをインターセプトするのを防ぎます。これにより、最初のシートを折りたたむことなく、2番目のシートを「展開」から「折りたたみ」にドラッグできます。
public class CustomBottomSheetBehavior<V extends View> extends BottomSheetBehavior<V> {
private boolean allowDragging = true;
public void setAllowDragging(boolean allowDragging) {
this.allowDragging = allowDragging;
}
@Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
if (!allowDragging) {
return false;
}
return super.onInterceptTouchEvent(parent, child, event);
}
}
BottomSheetBehavior
のカスタマイズがこの問題に関連するとは思いませんが、完全を期すために、次のように使用しています。
FrameLayout sheet1 = (FrameLayout) findViewById(R.id.sheet1);
bottomSheetBehavior1 = (CustomBottomSheetBehavior) BottomSheetBehavior.from(sheet1);
FrameLayout sheet2 = (FrameLayout) findViewById(R.id.sheet2);
bottomSheetBehavior2 = (CustomBottomSheetBehavior) BottomSheetBehavior.from(sheet2);
bottomSheetBehavior2.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
//If the second sheet is expanded or dragging, don't allow the first sheet to respond to touch events.
if (newState == BottomSheetBehavior.STATE_EXPANDED || newState == BottomSheetBehavior.STATE_DRAGGING) {
bottomSheetBehavior1.setAllowDragging(false);
} else {
bottomSheetBehavior1.setAllowDragging(true);
}
}
これがonInterceptTouchEvent
のBottomSheet
、内部のRecyclerView
、View.ClickListener
盗むタッチのネストされたスクロール処理に関係するのかどうかわからないようですイベント、上記の組み合わせ、またはその他すべて。
どんな助けでも大歓迎です。
[〜#〜]固定[〜#〜]
これがBottomSheetのonInterceptTouchEvent、内部のRecyclerViewのネストされたスクロール処理、View.ClickListenerによるタッチイベントの盗用、上記の組み合わせ、または他の何かと完全に関連しているのかどうか、私にはわからないようです。
上記のCustomBottomSheetBehaviorとView.ClickListenerの組み合わせです。
問題はbottomSheetBehavior1がgetSheet2PeekViewをドラッグしているときにドラッグイベントを取っているため、タッチを検出しましたgetSheet2PeekViewのイベントとセットbottomSheetBehavior1ドラッグfalse
およびbottomSheetBehavior2true
このコードを入力すると、問題が解決します。
findViewById(getSheet2PeekViewResId()).setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.e(TAG, "onTouch: ");
bottomSheetBehavior1.setAllowDragging(false);
bottomSheetBehavior2.setAllowDragging(true);
return false;
}
});
Pull Requestも作成され、完全に機能する変更がリポジトリに作成されます。