Googleマップアプリで提供されるボトムシートの動作を再現したい:
予想される動作へのリンク。
BottomSheetBehavior とumano AndroidSlidingUpPanelのような他のいくつかのサードパーティライブラリを使用してみましたが、回避できなかった問題は、すべてが状態間でボトムシートをスナップしていることです(折りたたまれて展開されています) )。
一番近い状態にスナップすることなく、上にスライドすることでスムーズに拡張できるボトムシートが欲しいのですが、代わりにユーザーがスライドで停止した場所にとどまります。
これを実現するには、BottomSheetBehavior
をサブクラス化し、onTouchEvent
をオーバーライドして、ACTION_UP
とACTION_CANCEL
の早い段階で戻ります。
public class CustomBottomSheetBehavior<V extends View> extends BottomSheetBehavior<V> {
public CustomBottomSheetBehavior() {
super();
}
public CustomBottomSheetBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
return true;
}
return super.onTouchEvent(parent, child, event);
}
}
これにより、BottomSheetBehavior
クラスがこれらのイベントを処理し、「expand」または「collapse」呼び出しをトリガーするのを防ぎます。
CustomBottomSheetBehavior
をxmlに適用するには:app:layout_behavior="com.yourpackage.CustomBottomSheetBehavior"
シートが完全に展開または折りたたまれたときにデフォルトの機能をBottomSheetBehavior
に戻すには、スライドオフセットが特定の値に達したときに設定されるフラグを追加します。次の例では、下部のシートACTION_UP
およびACTION_CANCEL
イベントは、スライドオフセットが0.1〜0.9の場合にのみ無視されます。
public class CustomBottomSheetBehavior<V extends View> extends BottomSheetBehavior<V> {
private boolean isExpandedOrCollapsed;
public CustomBottomSheetBehavior() {
super();
listenForSlideEvents();
}
public CustomBottomSheetBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
listenForSlideEvents();
}
void listenForSlideEvents() {
setBottomSheetCallback(new BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
isExpandedOrCollapsed = slideOffset < 0.1f || slideOffset > 0.9f;
}
});
}
@Override
public boolean onTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
if (!isExpandedOrCollapsed) {
int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
return true;
}
}
return super.onTouchEvent(parent, child, event);
}
}