web-dev-qa-db-ja.com

AppBarLayoutを使用してCoordinatorLayoutでスクロール時にBottomNavigationViewを表示/非表示

AppBarLayoutBottomNavigationLayoutの両方を1つのCoordinatorLayoutで使用しようとしていますが、 材料ガイドライン の要件に従って、BottomNavigationLayoutを非表示にできません。

私はこのようなものを意味します:

<Android.support.design.widget.CoordinatorLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:orientation="vertical"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:fitsSystemWindows="false">

    <Android.support.design.widget.AppBarLayout
        Android:id="@+id/app_bar"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        app:layout_insetEdge="top"
        Android:theme="@style/AppTheme.AppBarOverlay">

        <Android.support.v7.widget.Toolbar
            Android:id="@+id/toolbar"
            Android:layout_width="match_parent"
            Android:layout_height="?attr/actionBarSize"
            app:popupTheme="@style/AppTheme.PopupOverlay"
            app:layout_scrollFlags="scroll|enterAlways"/>
    </Android.support.design.widget.AppBarLayout>


    <Android.support.design.widget.BottomNavigationView
        Android:id="@+id/bottom_nav"
        Android:layout_width="match_parent"
        Android:layout_height="56dp"
        Android:layout_gravity="bottom"
        app:menu="@menu/menu_bottom_navigation"/>

    <FrameLayout
        Android:id="@+id/content_container"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_gravity="top"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

</Android.support.design.widget.CoordinatorLayout>

ご覧のとおり、実際のコンテンツにフラグメントを含めるために使用されるFrameLayoutもあります。現在、BottomNavigationViewのデフォルト/組み込みの動作はありません-ビュー自体にも、その兄弟にもありません。既存の appbar_scrolling_view_behaviorはappbarと連携してコンテンツビューを処理しますが、他の兄弟は無視します。

Appbarとスクロール時に下部ナビゲーションビューの両方を非表示および表示するソリューションを探しています。

10
stan0

1〜2日検索した後、Behaviorに添付されたカスタム BottomNavigationView で解決しました。その主なアイデアは、BottomNavigationViewの兄弟がスクロールされたときにそれを検出して、BottomNavigationViewを非表示にできるようにすることです。このようなもの:

public class BottomNavigationBehavior extends CoordinatorLayout.Behavior<BottomNavigationView> {

    public BottomNavigationBehavior() {
        super();
    }

    public BottomNavigationBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, BottomNavigationView child, View dependency) {
        boolean dependsOn = dependency instanceof FrameLayout;
        return dependsOn;
    }

    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, BottomNavigationView child, View directTargetChild, View target, int nestedScrollAxes) {
        return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
    }

    @Override
    public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, BottomNavigationView child, View target, int dx, int dy, int[] consumed) {
        if(dy < 0) {
            showBottomNavigationView(child);
        }
        else if(dy > 0) {
            hideBottomNavigationView(child);
        }
    }

    private void hideBottomNavigationView(BottomNavigationView view) {
        view.animate().translationY(view.getHeight());
    }

    private void showBottomNavigationView(BottomNavigationView view) {
        view.animate().translationY(0);
    }
}

ご覧のとおり、私は子ビューの ViewPropertyAnimator メソッドを使用して取得した単純な animate を使用しています。これにより、AppBarLayoutの動作と実際には一致しない単純なアニメーションが生成されますが、見栄えがよく、実装も簡単です。

AndroidチームがBottomNavigationViewのデフォルトの動作をサポートライブラリに追加することを期待しているため、AppBarLayoutの動作を正確に複製するために多くの時間を費やすことは妥当ではないと思います。

edit(2018年4月):onStartNestedScrollonNestedPreScrollとそれらの新しいバージョンに関する簡単な説明については、コメントセクションを参照してください。

21
stan0

HideBottomViewOnScrollBehavior を使用することもできます。この動作は基本的に同じ方法で機能しますが、パフォーマンスを向上させるために実行中の既存のアニメーションのキャンセルも処理します。

3
Cameron Ketcham