web-dev-qa-db-de.com

Wie setzt man die vom CoordinatorLayout gesteuerte Toolbar-Position zurück

Die App, an der ich gerade arbeite, besteht aus einer Navigationsleiste, die in einer Aktivität implementiert ist. Das Aktivitätslayout sieht wie folgt aus:

<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>

Dies ist ein sehr verbreitetes Muster. Das Fragment, das sich häufig im Container-Layout befindet, ändert sich häufig.

Wenn eines der Fragmente ein Bildlaufelement enthält, erstellt das CoordinatorLayout beim Scrollen gerne Positionsübersetzungen, einschließlich der Toolbar/AppBarLayout.

Das eigentliche Problem hierbei ist, dass, wenn das Fragment ersetzt wird, die Position für die Symbolleiste gleich bleibt, d. H. Wenn die Symbolleiste ausgeblendet ist, bleibt es so, was nicht beabsichtigt ist. 

Ergebnis ist folgendes:

Diese:

After scroll

Klemmt:

Then change

Wie kann man die Toolbar-Position für diesen Fall zurücksetzen?

EDIT: Ein Fehler ist wahrscheinlich, der AppBarLayout-Listener wird nur beim Neustart der App aufgerufen (Schaltfläche "Zurück" drücken und App öffnen) und nach einem intensiven Fling nicht mehr aufgerufen.

47
razzledazzle

Um den Bildlaufzustand zurückzusetzen, rufen Sie einfach das AppBarLayout.Behavior-Objekt ab

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();       

und rufen Sie die onNestedPreScroll-Methode manuell auf:

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

Wenn Sie mit einer Animation problemlos zurücksetzen möchten, können Sie stattdessen onNestedFling aufrufen:

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

Rufen Sie zunächst eine AppBarLayout-Anweisung in Ihrer MainActivity auf, dann verwenden Sie im Pause-Zustand des zu ersetzenden Fragments die folgende Methode, um die Symbolleiste zu erweitern:

MainActivity.appbar.setExpanded(true,true);

Und oder um die Symbolleiste zu schließen:

MainActivity.appbar.setExpanded(false,true);

Mit dem zweiten Parameter können Sie die Symbolleiste reibungslos durchlaufen.

31
Shayan Shafiee

Aktualisieren Sie Ihre Support-Bibliothek auf Version 23, dann können Sie Folgendes verwenden:

appBarLayout.setExpanded(true/false);

public void setExpanded (boolean erweitert )

Legt fest, ob dieses AppBarLayout erweitert wird oder nicht, und wird animiert, wenn es bereits angelegt wurde.

Wie beim Scrollen von AppBarLayout beruht diese Methode darauf, dass dieses Layout ein direktes untergeordnetes Element eines CoordinatorLayout ist.

expand true, wenn das Layout vollständig erweitert werden soll, false, wenn es vollständig reduziert werden soll

12
Context

@razzledazzle Das AppBarLayout speichert onOffsetChangedListeners als WeakReferences. Dies bedeutet, dass sie bei Bedarf Abfälle gesammelt werden, zum Beispiel, wenn Sie eine intensive Aktion ausführen. Siehe Lösung hier:

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

3
freebiefalk

Ich verwende diese Codes vor Fragmentänderungen.

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

Ersetzen oder wickeln Sie die FrameLayout im Android.support.design.widget.CoordinatorLayout mit einemAndroid.support.v4.widget.NestedScrollViewund das erledigt den Job automatisch, ohne dass Sie andere Hacks benötigen .... so würde es so aussehen:

<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

Wie Dokument sagte 

AppBarLayout unterstützt
void setExpanded (boolean erweitert, boolean animiert);
Legt fest, ob dieses AppBarLayout erweitert wird oder nicht.

  • extended boolean: true, wenn das Layout vollständig erweitert werden soll, false, wenn es vollständig reduziert werden soll 
  • animate boolean: Gibt an, ob der neue Zustand aktiviert werden soll 

Also zuerst brauchst du 

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

dann zu expand layout 

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

und zum collapse Layout 

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