Comment réinitialiser la position de la barre d'outils contrôlée par le CoordinatorLayout?
l'application sur laquelle je travaille se compose d'un tiroir de Navigation qui est implémenté dans une activité. La mise en page de l'activité est la suivante:
<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>
c'est un motif très courant, la seule chose qui change fréquemment est le Fragment à l'intérieur de la disposition du conteneur.
si un Fragment a un élément de défilement, lors du défilement, le CoordinatorLayout fera volontiers des translations de position, y compris la barre d'outils/AppBarLayout.
Le vrai problème est ici, lorsque le Fragment est remplacé, la position de la barre d'outils reste la même, c'est-à-dire que si la barre d'outils est cachée, elle le restera. ce qui n'est pas prévu.
Résultat:
Ceci:
coince:
Comment peut-on Réinitialiser la position de la barre d'outils pour ce cas?
EDIT: Un bug est probable, L'AppBarLayout offset change listener est appelé seulement lors de la relance de l'application (appuyez sur le bouton arrière et ouvrez l'application), et cesse d'être appelé à nouveau après une passade intense.
7 réponses
pour réinitialiser l'état de défilement, il suffit d'obtenir le AppBarLayout.Behavior
objet
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();
et appeler onNestedPreScroll
méthode manuellement:
int[] consumed = new int[2];
behavior.onNestedPreScroll(coordinator, appbar, null, 0, -1000, consumed);
Si vous souhaitez réinitialiser en douceur avec une animation, vous pouvez essayer d'appeler onNestedFling
au lieu de:
behavior.onNestedFling(coordinator, appbar, null, 0, -1000, true);
tout d'abord obtenir un refrence AppBarLayout dans votre MainActivity, puis dans l'état de pause du fragment qui est remplacé, utilisez la méthode ci-dessous pour étendre la barre d'outils :
MainActivity.appbar.setExpanded(true,true);
Et ou pour fermer la barre d'outils :
MainActivity.appbar.setExpanded(false,true);
Le deuxième paramètre est utilisé pour faire défiler la barre d'outils en douceur.
mise à Jour de votre soutien lib à v23 ensuite, vous pouvez utiliser:
appBarLayout.setExpanded(true/false);
public void setExpanded (boolean étendu)
détermine si cette Applbarlayout est étendue ou non, en animant si elle a déjà été mise en place.
comme pour le scrolling D'AppBarLayout, cette méthode repose sur le fait que cette mise en page est l'enfant direct d'un CoordinatorLayout.
étendu true si la mise en page doit être complètement développée, false si elle doit être totalement effondré
@razzledazzle L'AppBarLayout stocke des listeners onoffsetchanged en tant que faibles Références, ce qui signifie qu'ils sont des déchets ramassés en cas de besoin, par exemple quand vous faites un flirt intense. Voir la solution ici:
j'utilise ces codes avant les changements de fragments.
scrollingElement.startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);
scrollingElement.dispatchNestedPreScroll(0, -Integer.MAX_VALUE, null, null);
scrollingElement.stopNestedScroll();
remplacer ou envelopper le FrameLayout
dans le android.support.design.widget.CoordinatorLayout
avec un android.support.v4.widget.NestedScrollView
et cela fera le travail automatiquement sans avoir à d'autres hacks....ainsi, il ressemblerait à ceci:
<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>
document dit
AppBarLayout supporte
void setExpanded (booléen étendu, boolean animer);
Détermine si cette Applbarlayout est étendue ou non.
- étendu booléen: true si la mise en page doit être entièrement développé, false si elle doit être totalement effondré
- animer booléen: s'animer ou non vers le nouvel état
donc au début vous avez besoin
AppBarLayout appBarLayout = (AppBarLayout)findViewById(R.id.appBarLayout);
puis développez mise en page
appBarLayout.setExpanded(true, true); // with animation
appBarLayout.setExpanded(true, false); // without animation
et collapse mise en page
appBarLayout.setExpanded(false, true); // with animation
appBarLayout.setExpanded(false, false); // without animation