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:
Klemmt:
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.
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);
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.
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
@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:
Ich verwende diese Codes vor Fragmentänderungen.
scrollingElement.startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);
scrollingElement.dispatchNestedPreScroll(0, -Integer.MAX_VALUE, null, null);
scrollingElement.stopNestedScroll();
Ersetzen oder wickeln Sie die FrameLayout
im Android.support.design.widget.CoordinatorLayout
mit einemAndroid.support.v4.widget.NestedScrollView
und 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>
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