Besoin de désactiver l'expansion sur CollapsingToolbarLayout pour certains fragments

J'ai une AppCompatActivity qui contrôle le remplacement de nombreux fragments. Voici ma mise en page.

Activity_main.xml

  • Comment puis-je informer une activité en cours d'exécution d'un récepteur de diffusion?
  • Pourquoi NotificationManagerCompat :: cancelAll () reçoit SecurityException?
  • WebViewClient onReceivedError déconseillé, la nouvelle version ne détecte pas toutes les erreurs
  • Comment créer une variable globale dans Android?
  • Comment définir le texte de la boîte de dialogue google api dans la langue par défaut de l'application
  • Qu'est-ce que le fichier boot.img dans Android?
  • <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/drawer_layout" android:layout_height="match_parent" android:layout_width="match_parent" android:fitsSystemWindows="true"> <include layout="@layout/activity_main_frame"/> <android.support.design.widget.NavigationView android:id="@+id/navigation_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" android:fitsSystemWindows="true" android:background="@color/white" app:headerLayout="@layout/drawer_header" app:menu="@menu/drawer"/> </android.support.v4.widget.DrawerLayout> 

    Activity_main_frame.xml

     <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/main_content" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <android.support.design.widget.AppBarLayout android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" android:fitsSystemWindows="true"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_scrollFlags="scroll|exitUntilCollapsed" android:fitsSystemWindows="true" app:contentScrim="?attr/colorPrimary" app:expandedTitleMarginStart="48dp" app:expandedTitleMarginEnd="64dp"> <ImageView android:id="@+id/backdrop" android:layout_width="match_parent" android:layout_height="256dp" android:scaleType="centerCrop" android:fitsSystemWindows="true" app:layout_collapseMode="parallax" /> <include layout="@layout/activity_main_items"/> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:layout_collapseMode="pin"/> <android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" android:visibility="gone" android:layout_gravity="bottom"/> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <FrameLayout android:id="@+id/content_frame" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" > </FrameLayout> <android.support.design.widget.FloatingActionButton android:id="@+id/fab1" android:layout_height="wrap_content" android:layout_width="wrap_content" app:layout_anchor="@id/appbar" app:layout_anchorGravity="bottom|right|end" app:borderWidth="0dp" android:src="@drawable/app_ic_slide_wallpaper_dark" android:layout_margin="@dimen/big_padding" android:clickable="true"/> </android.support.design.widget.CoordinatorLayout> 

    Mon fragment de maison est défini initialement et c'est là que je souhaite que la barre d'outils s'effondre et que cela fonctionne bien. Cependant, lorsque je change de fragments du tiroir latéral, je désire désactiver la barre d'outils en expansion.

    J'ai compris comment l'effondrer lorsqu'un élément de tiroir est sélectionné, mais je dois aussi m'assurer qu'il ne se développe pas à moins que le fragment de la maison ne soit affiché. Est-ce possible?

     public void collapseToolbar(){ CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appbar.getLayoutParams(); behavior = (AppBarLayout.Behavior) params.getBehavior(); if(behavior!=null) { behavior.onNestedFling(coordinator, appbar, null, 0, 10000, true); } } 

  • Android CheckBox - Restauration de l'état après la rotation de l'écran
  • Créer une application Android qui agit comme un raccourci vers notre site mobile
  • Lire les données du périphérique bluetooth dans Android
  • Android AppCompat 21 Elevation
  • Exception Android: java.io.IOException: open failed: EACCES (Autorisation refusée)
  • Gradle ne peut pas trouver de dépendance (bibliothèque de support Android)
  • 9 Solutions collect form web for “Besoin de désactiver l'expansion sur CollapsingToolbarLayout pour certains fragments”

    Maintenant, dans la bibliothèque support v23, vous pouvez facilement contrôler la visibilité de votre application.

    Il suffit d'obtenir une référence à votre AppBarLayout et de le cacher / afficher en fonction du fragment que vous souhaitez charger:

     private AppBarLayout appBarLayout; @Override protected void onCreate(Bundle savedInstanceState) { [...] appBarLayout = (AppBarLayout) findViewById(R.id.appbar); [...] } public void switchToFragment(Fragment fragment, String tag, boolean expandToolbar){ FragmentManager fragmentManager = getSupportFragmentManager(); Fragment currentFragment = fragmentManager.findFragmentByTag(currentFragmentTag); if(currentFragment == null || !TextUtils.equals(tag, currentFragmentTag) ){ currentFragmentTag = tag; fragmentManager .beginTransaction() .replace(R.id.flContent, fragment, currentFragmentTag) .commit(); if(expandToolbar){ appBarLayout.setExpanded(true,true); }else{ appBarLayout.setExpanded(false,true); } } } 

    PS n'oubliez pas d'ajouter les dépendances requises dans votre build.gradle:

     dependencies { compile 'com.android.support:design:23.2.1' compile 'com.android.support:appcompat-v7:23.2.1' compile 'com.android.support:recyclerview-v7:23.2.1' } 

    EDIT: Si vous souhaitez également verrouiller votre barre d'outils dans certains fragments (à part l'effondrement), vous devez recourir à des solutions de contournement car cette fonctionnalité n'est pas fournie par CollapsingToolbarLayout jusqu'à maintenant (v23.2.1 de la conception de support). Ici, vous pouvez trouver ma solution de contournement proposée.

    Désactivez le défilement imbriqué sur le contenu du fragment de défilement:

     recyclerView.setNestedScrollingEnabled(false); 

    Utilisez ceci si vous utilisez la bibliothèque de support:

     ViewCompat.setNestedScrollingEnabled(recyclerView, false); 

    Cette classe vous permettra de désactiver / réactiver le comportement d'extension.

     public class DisableableAppBarLayoutBehavior extends AppBarLayout.Behavior { private boolean mEnabled; public DisableableAppBarLayoutBehavior() { super(); } public DisableableAppBarLayoutBehavior(Context context, AttributeSet attrs) { super(context, attrs); } public void setEnabled(boolean enabled) { mEnabled = enabled; } @Override public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes) { return mEnabled && super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes); } public boolean isEnabled() { return mEnabled; } } 

    Utilisez-le dans votre mise en page de la manière suivante:

     <android.support.design.widget.AppBarLayout ... other attributes ... app:layout_behavior="com.yourpackage.DisableableAppBarLayoutBehavior" > <!-- your app bar contents --> </android.support.design.widget.AppBarLayout> 

    Ensuite, lorsque vous souhaitez désactiver le comportement:

     AppBarLayout myAppBar = ....; CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) myAppBar.getLayoutParams(); ((DisableableAppBarLayoutBehavior) layoutParams.getBehavior()).setEnabled(false); 

    Tout ce que vous avez à faire est de remplacer CoordinatorLayout par la mise en œuvre personnalisée de CoordinatorLayout qui trichera que le défilement imbriqué a été traité.

    MyCoordinatorLayout mise en œuvre:

     public class MyCoordinatorLayout extends CoordinatorLayout { private boolean allowForScroll = false; public MyCoordinatorLayout(Context context) { super(context); } public MyCoordinatorLayout(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) { return allowForScroll && super.onStartNestedScroll(child, target, nestedScrollAxes); } public boolean isAllowForScroll() { return allowForScroll; } public void setAllowForScroll(boolean allowForScroll) { this.allowForScroll = allowForScroll; } } 

    Vue d'activité xml:

     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <android.support.v4.widget.DrawerLayout android:id="@+id/drawerLayout" android:layout_width="match_parent" android:layout_height="match_parent" > <!--CONTENT--> <com.example.views.MyCoordinatorLayout android:id="@+id/coordinator" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" > <com.example.views.ControllableAppBarLayout android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="192dp" android:fitsSystemWindows="true" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" app:contentScrim="?attr/colorPrimary" app:expandedTitleMarginBottom="32dp" app:expandedTitleMarginEnd="64dp" app:expandedTitleMarginStart="48dp" app:layout_scrollFlags="scroll|exitUntilCollapsed"> <ImageView android:id="@+id/header" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/primary" android:fitsSystemWindows="true" android:scaleType="centerCrop" app:layout_collapseMode="parallax" /> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_collapseMode="pin" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /> </android.support.design.widget.CollapsingToolbarLayout> </com.example.views.ControllableAppBarLayout> <FrameLayout android:id="@+id/flContent" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> </com.example.views.MyCoordinatorLayout> <!-- DRAWER --> <fragment android:id="@+id/fDrawer" android:name="com.example.fragment.DrawerFragment" android:layout_width="@dimen/drawer_width" android:layout_height="match_parent" android:layout_gravity="left|start" android:fitsSystemWindows="true" android:clickable="true" /> </android.support.v4.widget.DrawerLayout> </LinearLayout> 

    Je vous encourage à utiliser une implémentation AppBarLayout personnalisée avec des méthodes d'aide pour réduire / développer la barre d'outils. Sur cette règle, vous en trouverez une.

    Ok, il est maintenant temps de configurer notre barre d'outils en activité.

     public class ToolbarAppcompatActivity extends AppCompatActivity implements AppBarLayout.OnOffsetChangedListener { protected Toolbar toolbar; protected MyCoordinatorLayout coordinator; protected ControllableAppBarLayout appbar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); configureToolbar(); switchFragment(new FooFragment(), "FOO", true); } protected void configureToolbar() { toolbar = (Toolbar) findViewById(R.id.toolbar); coordinator = (MyCoordinatorLayout) findViewById(R.id.coordinator); appbar = (ControllableAppBarLayout) findViewById(R.id.appbar); appbar.addOnOffsetChangedListener(this); getDelegate().setSupportActionBar(toolbar); } public void switchToFragment(Fragment fragment, String tag, boolean expandToolbar){ FragmentManager fragmentManager = getSupportFragmentManager(); Fragment currentFragment = fragmentManager.findFragmentByTag(currentFragmentTag); if(currentFragment == null || !TextUtils.equals(tag, currentFragmentTag) ){ currentFragmentTag = tag; fragmentManager .beginTransaction() .replace(R.id.flContent, fragment, currentFragmentTag) .commit(); if(expandToolbar){ expandToolbar(); }else{ collapseToolbar(); } } } protected void addFragment(Fragment fragment, String tag, boolean expandToolbar) { FragmentManager fragmentManager = getSupportFragmentManager(); currentFragmentTag = tag; fragmentManager .beginTransaction() .add(R.id.flContent, fragment, currentFragmentTag) .addToBackStack(tag) .commit(); if(expandToolbar){ expandToolbar(); }else{ collapseToolbar(); } } protected void collapseToolbar(){ appbar.collapseToolbar(); coordinator.setAllowForScroll(false); } public void expandToolbar(){ appbar.expandToolbar(); coordinator.setAllowForScroll(true); } } 

    Chaque fois que vous souhaitez changer la barre d'outils de fragment et d'effondrement / expansion, appelez simplement method switchFragment / addFragment avec un paramètre booléen approprié.

    Juste une dernière note. Assurez-vous d'utiliser les dernières bibliothèques de support.

     dependencies { // android support compile 'com.android.support:appcompat-v7:22.2.1' compile 'com.android.support:recyclerview-v7:22.2.1' compile 'com.android.support:design:22.2.1' } 

    N'utilisez pas include tag dans AppBarLayout. Ça ne marche pas

    Avec Android Design Library v23.1.1, la méthode décrite par @LucyFair ne fonctionne pas. J'ai réussi à le faire fonctionner en configurant l' app:layout_scrollFlags à enterAlwaysCollapsed uniquement, et la barre d'application reste "verrouillée".

    J'espère que cela t'aides. 🙂

    J'ai trouvé une solution de contournement qui fonctionne avec des activités et divers fragments. Vous implémentez CollapsingToolbarLayout avec AppBar, etc. dans votre activité, puis chaque fois que vous appelez un nouveau fragment, vous pouvez appeler ces 2 fonctions.

    • Lorsque je souhaite que mon appbar continuera à s'effondrer:

       public void lockAppBarClosed() { mAppBarLayout.setExpanded(false, false); mAppBarLayout.setActivated(false); CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)mAppBarLayout.getLayoutParams(); lp.height = (int) getResources().getDimension(R.dimen.toolbar_height); } 
    • Quand je souhaite que mon application soit étendue et défilable à nouveau

       public void unlockAppBarOpen() { mAppBarLayout.setExpanded(true, false); mAppBarLayout.setActivated(true); CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)mAppBarLayout.getLayoutParams(); lp.height = (int) getResources().getDimension(R.dimen.toolbar_expand_height); } 

    Vous pouvez appeler ces fonctions à partir de vos fragments en implémentant une interface. Voici un exemple rapide pour votre cas (la barre d'outils se développe uniquement dans homeFragment)

     public interface CustomListener() { void unlockAppBarOpen(); void lockAppBarClosed() } public class MainActivity extends BaseActivity implements CustomListener { @Override public void unlockAppBarOpen() { mAppBarLayout.setExpanded(true, false); mAppBarLayout.setActivated(true); CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)mAppBarLayout.getLayoutParams(); lp.height = (int) getResources().getDimension(R.dimen.toolbar_expand_height); } @Override public void lockAppBarClosed() { mAppBarLayout.setExpanded(false, false); mAppBarLayout.setActivated(false); CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)mAppBarLayout.getLayoutParams(); lp.height = (int) getResources().getDimension(R.dimen.toolbar_height); } } public class MainFragment extends BaseFragment { @Override public void onResume() { super.onPause(); ((MainActivity) getContext()).unlockAppBarOpen(); } } public class SecondFragment extends BaseFragment { @Override public void onResume() { super.onPause(); ((MainActivity) getContext()).lockAppBarClosed(); } } 

    Avec cet exemple:

    • Chaque fois que le MainFragment sera affiché -> il étendra la barre d'outils et la rendra collable et extensible

    • Chaque fois que le SecondFragment est affiché -> il va effondrer la barre d'outils sur une taille standard et l'empêcher de se développer à nouveau

    J'espère que cela vous aidera!

    J'ai trouvé une solution simple pour activer / désactiver l'effondrement dans CollapsingToolbarLayout:

      private void setExpandEnabled(boolean enabled) { mAppBarLayout.setExpanded(enabled, false); mAppBarLayout.setActivated(enabled); final AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams(); if (enabled) params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED); else params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED); collapsingToolbarLayout.setLayoutParams(params); } 

    J'ai utilisé la solution de DragCallback et ajouté DragCallback à la classe de comportement pour éviter de toucher et de glisser CollapsingToolbarLayout pour l'étendre

     private void setDragCallback() { setDragCallback(new DragCallback() { @Override public boolean canDrag(@NonNull AppBarLayout appBarLayout) { return mEnabled; } }); } 

    Aucune des solutions fournies n'a fonctionné pour moi, sauf celle-ci. Avec cette solution, je peux facilement gérer l'état de la barre d'outils en panne. Cela empêchera l'expansion de la barre d'outils en panne et la définition du titre pour elle.

     public void lockAppBar(boolean locked,String title) { if(locked){ appBarLayout.setExpanded(false, true); int px = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 80, getResources().getDisplayMetrics()); CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)appBarLayout.getLayoutParams(); lp.height = px; appBarLayout.setLayoutParams(lp); collapsingToolbarLayout.setTitleEnabled(false); toolbar.setTitle(title); }else{ appBarLayout.setExpanded(true, false); appBarLayout.setActivated(true); CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams(); lp.height = (int) getResources().getDimension(R.dimen.toolbarExpandHeight); collapsingToolbarLayout.setTitleEnabled(true); collapsingToolbarLayout.setTitle(title); } } 
    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.