デザインサポートライブラリ_v. 23.2
_はBottomSheetBehavior
を導入しました。これにより、コーディネーターの子がボトムシート(画面の下部からドラッグ可能なビュー)として機能できます。
私がやりたいのは、ボトムシートビューとして、次のビュー(典型的なコーディネーター+崩壊するもの)を持つことです:
_<CoordinatorLayout
app:layout_behavior=“@string/bottom_sheet_behavior”>
<AppBarLayout>
<CollapsingToolbarLayout>
<ImageView />
</CollapsingToolbarLayout>
</AppBarLayout>
<NestedScrollView>
<LinearLayout>
< Content ... />
</LinearLayout>
</NestedScrollView>
</CoordinatorLayout>
_
残念ながら、ボトムシートビューはネストされたスクロールを実装する必要があります。そうしないと、スクロールイベントが発生しません。メインアクティビティを試してからこのビューをボトムシートとして読み込むと、スクロールイベントは紙の「シート」に対してのみ作用し、読み続けると奇妙な動作をすることがわかります。
これはCoordinatorLayout
をサブクラス化することで、またはBottomSheetBehavior
をサブクラス化することでさらに良くなると確信しています。ヒントはありますか?
いくつかの条件で親からイベントを盗むために、requestDisallowInterceptTouchEvent()
を使用する必要があります。
AppBarLayout
オフセットが> 0の場合AppBarLayout
オフセットが== 0であるが、上にスクロールしている場合(少し考えてみればわかります)最初の条件は、OnOffsetChanged
を内部アプリバーに設定することで取得できます。
2番目は、たとえば次のようなイベント処理を必要とします。
_switch (MotionEventCompat.getActionMasked(event)) {
case MotionEvent.ACTION_DOWN:
startY = event.getY();
lastY = startY;
userIsScrollingUp = false;
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
userIsScrollingUp = false;
break;
case MotionEvent.ACTION_MOVE:
lastY = event.getY();
float yDeltaTotal = startY - lastY;
if (yDeltaTotal > touchSlop) { // Moving the finger up.
userIsScrollingUp = true;
}
break;
}
_
言うまでもなく、私は今この仕事をすることはできません。条件が満たされたときにイベントをキャッチできず、他のケースではそれらをキャッチできません。以下の画像では、標準のCoordinatorLayoutで何が起こるかを確認できます。
アプリバーを下にスクロールするとシートは閉じられますが、ネストされたコンテンツを下にスクロールするとシートは閉じられません。ネストされたスクロールイベントは、コーディネーターの動作に伝達されないようです。
内側のアプリバーにも問題があります:ネストされたスクロールコンテンツは、折りたたまれているときにアプリバーに追従しません。
これらの問題を示す githubのサンプルプロジェクト をセットアップしました。
シート内のアプリバー/スクロールビューの正しい動作。
シートが展開されると、下にスクロールすると折りたたまれますが、内部のアプリバーも完全に展開されている場合のみです。現時点では、アプリバーの状態に関係なく、アプリバーをドラッグした場合にのみ折りたたみます。
シートが折りたたまれると、上にスクロールするジェスチャーで展開されます(内側のアプリバーには影響しません)。
連絡先アプリの例(おそらくBottomSheetBehaviorを使用しませんが、これは私が望むものです):
私はついに実装をリリースしました。それを見つける Githubで またはjcenterから直接:
compile 'com.otaliastudios:bottomsheetcoordinatorlayout:1.0.0’
必要なことは、BottomSheetCoordinatorLayout
をボトムシートのルートビューとして使用することだけです。自動的に動作動作を膨らませるので、心配する必要はありません。
私はこれを長い間使用していますが、スクロールの問題が発生したり、ABLでのドラッグがサポートされたりすることはありません。
上記の質問の方法に従って、さらに説明が必要なソリューションを考え出しました。サンプルコードに従って、xmlに追加部分を統合して、BottomSheeetの動作のように動作させてください。
<CoordinatorLayout>
<AppBarLayout>
<Toolbar
app:layout_collapseMode="pin">
</Toolbar>
</AppBarLayout>
<NestedScrollView
app:layout_behavior=“@string/bottom_sheet_behavior” >
<include layout="@layout/items" />
</NestedScrollView>
<!-- Bottom Sheet -->
<BottomSheetCoordinatorLayout>
<AppBarLayout
<CollapsingToolbarLayout">
<ImageView />
<Toolbar />
</CollapsingToolbarLayout>
</AppBarLayout>
<NestedScrollView">
<include layout="@layout/items" />
</NestedScrollView>
</BottomSheetCoordinatorLayout>
</CoordinatorLayout>
注:あなたの質問の最後のコメントですでに説明した解決策
より良い移植:https://github.com/laenger/BottomSheetCoordinatorLayout
NestedScrollView
でLinearLayout
を使用しないようにしてください。これは私のアプリでも問題を引き起こしています。代わりにLinearLayout
のみを使用してください、私にとってはうまくいきます。
次を試してください:
<CoordinatorLayout
app:layout_behavior=“@string/bottom_sheet_behavior”>
<AppBarLayout>
<CollapsingToolbarLayout>
<ImageView />
</CollapsingToolbarLayout>
</AppBarLayout>
<LinearLayout>
<!--don't forget to addd this line-->
app:layout_behavior="@string/appbar_scrolling_view_behavior">
< Content ... />
</LinearLayout>
この問題に関して、laengerの最初のgithubテストプロジェクトをフォローしました。アプリでもこの動作が必要だったので、彼の問題のいくつかの解決策を共有できてうれしいです。
これは彼の問題の解決策です:❌ツールバーが時々早く崩壊する
これを防ぐには、カスタムAppBarLayout.Behavior
を作成する必要があります。それは、AppBarLayout.behavior
がスクロールモーションを取得するのはドラッグ中に上にスクロールするときだからです。 STATE_DRAGGINGにあるかどうかを検出し、ツールバーを早めに非表示/折りたたみにしないように戻る必要があります。
public class CustomAppBarLayoutBehavior extends AppBarLayout.Behavior {
private CoordinatorLayoutBottomSheetBehavior behavior;
public CustomAppBarLayoutBehavior() {
}
public CustomAppBarLayoutBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes) {
behavior = CoordinatorLayoutBottomSheetBehavior.from(parent);
return super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes);
}
@Override
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed) {
if(behavior.getState() == CoordinatorLayoutBottomSheetBehavior.STATE_DRAGGING){
return;
}else {
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);
}
}
@Override
public void setDragCallback(@Nullable DragCallback callback) {
super.setDragCallback(callback);
}
}
これは、他の問題をどのように解決するかについての良い出発点かもしれません。
dragツールバーはドラッグで折りたたむことはできません
❌メインコーディネーターのレイアウトはスクロールを消費します
私は実際には良いUI /アニメーションの人ではありませんが、実装するための適切なコールバック/オーバーライド関数を見つけて、時々コードを理解することは大変です。
これをappbarlayoutの動作として設定します
<Android.support.design.widget.AppBarLayout
Android:id="@+id/bottom_sheet_appbar"
style="@style/BottomSheetAppBarStyle"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
app:layout_behavior="your.package.CustomAppBarLayoutBehavior">
最初の子がnestedscroll
の場合、他の問題が発生します。この解決策は私の問題を解決し、あなたも解決することを願っています。
<CoordinatorLayout
app:layout_behavior=“@string/bottom_sheet_behavior”>
<AppBarLayout>
<CollapsingToolbarLayout>
<ImageView />
</CollapsingToolbarLayout>
</AppBarLayout>
</LinearLayout>
<NestedScrollView>
<LinearLayout>
< Content ... />
</LinearLayout>
</NestedScrollView>
</LinearLayout>
</CoordinatorLayout>