web-dev-qa-db-ja.com

CoordinatorLayoutによって制御されるツールバーの位置をリセットする方法は?

私が取り組んでいるアプリは、アクティビティに実装されているナビゲーションドロワーで構成されています。アクティビティのレイアウトは次のとおりです。

<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

<Android.support.v4.widget.DrawerLayout
    Android:id="@+id/drawer_layout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <Android.support.design.widget.CoordinatorLayout
        Android:id="@+id/coordinator"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent">

        <FrameLayout
            Android:id="@+id/container"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <include
            Android:id="@+id/appbar"
            layout="@layout/appbar" />

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

    <Android.support.design.widget.NavigationView
        Android:id="@+id/navigation_drawer"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:layout_gravity="start"
        app:headerLayout="@layout/header_drawer"
        app:menu="@menu/menu_nav">
    </Android.support.design.widget.NavigationView>

</Android.support.v4.widget.DrawerLayout>

</FrameLayout>

これは非常に一般的なパターンで、頻繁に変更されるのはコンテナレイアウト内のフラグメントのみです。

フラグメントのいずれかにスクロール要素がある場合、スクロール時にCoordinatorLayoutはツールバー/ AppBarLayoutを含む位置の変換を喜んで行います。

ここでの本当の問題は、フラグメントが置き換えられたとき、ツールバーの位置が同じままであることです。つまり、ツールバーが非表示の場合、意図しないままになります。

結果は次のとおりです。

この:

After scroll

動けなくなる:

Then change

この場合のツールバーの位置をリセットするにはどうすればよいですか?

編集:バグの可能性があります。AppBarLayoutのオフセット変更リスナーは、アプリを再起動するときにのみ呼び出され(戻るボタンを押してアプリを開く)、激しい放り込みの後に再び呼び出されるのを停止します。

49
razzledazzle

スクロール状態をリセットするには、AppBarLayout.Behaviorオブジェクト

CoordinatorLayout coordinator = (CoordinatorLayout) findViewById(R.id.coordinator);
AppBarLayout appbar = (AppBarLayout) findViewById(R.id.appbar);
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appbar.getLayoutParams();
AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();       

onNestedPreScrollメソッドを手動で呼び出します。

int[] consumed = new int[2];
behavior.onNestedPreScroll(coordinator, appbar, null, 0, -1000, consumed);

アニメーションでスムーズにリセットしたい場合は、代わりにonNestedFlingを呼び出してみてください:

behavior.onNestedFling(coordinator, appbar, null, 0, -1000, true);
46
MattSkala

まずMainActivityでAppBarLayoutの参照を取得し、次に置換されるフラグメントの一時停止状態で、以下のメソッドを使用してツールバーを展開します。

MainActivity.appbar.setExpanded(true,true);

または、ツールバーを閉じるには:

MainActivity.appbar.setExpanded(false,true);

2番目のパラメーターは、ツールバーをスムーズにスクロールするために使用されます。

32
Shayan Shafiee

サポートライブラリをv23に更新すると、次を使用できます。

appBarLayout.setExpanded(true/false);

public void setExpanded(boolean expanded

このAppBarLayoutが展開されているかどうかを設定し、既にレイアウトされている場合はアニメーション化します。

AppBarLayoutのスクロールと同様に、このメソッドはこのレイアウトがCoordinatorLayoutの直接の子であることに依存しています。

expandedレイアウトを完全に展開する必要がある場合はtrue、完全に折りたたむ必要がある場合はfalse

13
Context

@razzledazzle AppBarLayoutは、onOffsetChangedListenersをWeakReferencesとして保存します。これは、たとえば激しいフリングを行うときなど、必要なときにガベージコレクションされることを意味します。ここで解決策を参照してください:

https://code.google.com/p/Android/issues/detail?id=176328

3
freebiefalk

フラグメントが変更される前にこのコードを使用しています。

scrollingElement.startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);
scrollingElement.dispatchNestedPreScroll(0, -Integer.MAX_VALUE, null, null);
scrollingElement.stopNestedScroll();
2
weumj

ドキュメント のように

AppBarLayoutサポート
void setExpanded(ブール展開、ブールアニメーション);
このAppBarLayoutを展開するかどうかを設定します。

  • expandedboolean:レイアウトを完全に展開する必要がある場合はtrue、完全に折りたたむ必要がある場合はfalse
  • animateboolean:新しい状態にアニメートするかどうか

最初に、あなたが必要です

AppBarLayout appBarLayout = findViewById(R.id.appBarLayout);

次にexpandレイアウトに

appBarLayout.setExpanded(true, true); // with animation
appBarLayout.setExpanded(true, false); // without animation  

およびtocollapseレイアウト

appBarLayout.setExpanded(false, true); // with animation
appBarLayout.setExpanded(false, false); // without animation 
1

Android.support.design.widget.CoordinatorLayout内のFrameLayoutAndroid.support.v4.widget.NestedScrollViewで置換またはラップすると、他のハッキングなしで自動的にジョブが実行されます。次のようになります。

<Android.support.design.widget.CoordinatorLayout
    Android:id="@+id/coordinator"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <Android.support.v4.widget.NestedScrollView
        Android:id="@+id/container"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <include
        Android:id="@+id/appbar"
        layout="@layout/appbar" />

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