web-dev-qa-db-ja.com

Android Googleマップのようにボトムシートがスムーズに拡大

Googleマップアプリで提供されるボトムシートの動作を再現したい:

予想される動作へのリンク。

BottomSheetBehavior とumano AndroidSlidingUpPanelのような他のいくつかのサードパーティライブラリを使用してみましたが、回避できなかった問題は、すべてが状態間でボトムシートをスナップしていることです(折りたたまれて展開されています) )。

一番近い状態にスナップすることなく、上にスライドすることでスムーズに拡張できるボトムシートが欲しいのですが、代わりにユーザーがスライドで停止した場所にとどまります。

22
superhrvoje

これを実現するには、BottomSheetBehaviorをサブクラス化し、onTouchEventをオーバーライドして、ACTION_UPACTION_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);
    }
}
4
Tim Malseed