studio example error custom coordinatorlayout collapsing android android-support-library android-toolbar coordinator-layout

android - example - Necesita deshabilitar expandir en CollapsingToolbarLayout para ciertos fragmentos



toolbar android material design (13)

Ahora, en la v23 de la biblioteca de soporte, puede controlar fácilmente la visibilidad de su barra de aplicaciones.

Solo obtén una referencia a tu AppBarLayout y escóndela / muéstrala según el fragmento que quieras cargar:

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

PD: no olvide agregar las dependencias requeridas en su 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'' }

EDITAR: si también desea bloquear su barra de herramientas en ciertos fragmentos (aparte del colapso), debe recurrir a soluciones alternativas ya que esta característica no ha sido proporcionada por CollapsingToolbarLayout hasta ahora (v23.2.1 del diseño de soporte). Here puede encontrar mi solución propuesta.

Tengo una AppCompatActivity que controla la sustitución de muchos fragmentos. Aquí está mi diseño para ello.

activity_main.xml

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

Inicialmente, mi fragmento de inicio está configurado y ahí es donde quiero que se expanda la barra de herramientas de colapso y eso funciona bien. Sin embargo, cuando cambio fragmentos del cajón lateral, quiero deshabilitar la barra de herramientas desplegable.

He descubierto cómo contraerlo cuando se selecciona un elemento del cajón, pero también necesito asegurarme de que no se expanda a menos que se muestre el fragmento de inicio. ¿es posible?

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


Con Android Design Library v23.1.1, el método descrito por @LucyFair no funciona. app:layout_scrollFlags que funcionara configurando la app:layout_scrollFlags para enterAlwaysCollapsed solamente, y la barra de aplicaciones permanece "bloqueada".

Espero que esto ayude. :)


Deshabilite el desplazamiento anidado en el contenido del fragmento de desplazamiento:

recyclerView.setNestedScrollingEnabled(false);

Use esto si está usando la biblioteca de soporte:

ViewCompat.setNestedScrollingEnabled(recyclerView, false);


El siguiente código logra 3 objetivos:

Deshabilite CollapsingToolbarLayout expandir o contraer por el usuario, pero aún permita AppBarLayout.setExpanded .

Evite que el desplazamiento de RecyclerView o NestedScrollView expanda o contraiga CollapsingToolbarLayout.

// scrollView can be RecyclerView or NestedScrollView ViewCompat.setNestedScrollingEnabled(scrollView, false)

Evite que el usuario expanda o contraiga CollapsingToolbarLayout moviendo la barra de aplicaciones.

val params = appBar.layoutParams as CoordinatorLayout.LayoutParams if (params.behavior == null) params.behavior = AppBarLayout.Behavior() val behaviour = params.behavior as AppBarLayout.Behavior behaviour.setDragCallback(object : AppBarLayout.Behavior.DragCallback() { override fun canDrag(appBarLayout: AppBarLayout): Boolean { return false } })

https://code.luasoftware.com/tutorials/android/how-to-disable-or-lock-collapsingtoolbarlayout-collapse-or-expand/


Encontré una solución simple para habilitar / deshabilitar el colapso en 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); }


Esta clase le permitirá deshabilitar / volver a habilitar el comportamiento de expansión.

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

Úselo en su diseño así:

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

Luego, cuando desee deshabilitar el comportamiento:

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


He encontrado una solución alternativa que funciona con actividad y varios fragmentos. Implemente CollapsingToolbarLayout con AppBar, etc. en su actividad y luego, cada vez que llame a un nuevo fragmento, puede llamar a estas 2 funciones.

  • Cuando quiero que mi barra de aplicaciones se mantenga colapsada:

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

  • Cuando quiero que mi barra de aplicaciones se expanda y se pueda volver a desplazar

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

Puede llamar a estas funciones desde sus fragmentos mediante la implementación de una interfaz. Aquí hay un ejemplo rápido, para su caso (la barra de herramientas se expande solo en 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(); } }

Con este ejemplo:

  • cada vez que se muestre el MainFragment -> extenderá la barra de herramientas y la hará plegable y expandible

  • cada vez que se muestra el SecondFragment -> il colapsará la barra de herramientas a un tamaño estándar y evitará que se expanda nuevamente

Espero que te ayude !


Ninguna de las soluciones proporcionadas funcionó para mí, excepto esta. Con esta solución, puedo administrar fácilmente el estado de la barra de herramientas contraída. Esto evitará la expansión de la barra de herramientas contraída y establecerá el título para ello.

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


No puedo comentar, así que publicaré mis adiciones a JasonWyatt''s solución JasonWyatt''s JasonWyatt como respuesta independiente.

public class DisableableAppBarLayoutBehavior extends AppBarLayout.Behavior { private boolean mEnabled = true; // enabled by default 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, int type) { return mEnabled && super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes, type); } @Override public void onNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) { if (!isEnabled()) return; super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type); } @Override public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed, int type) { if (!isEnabled()) return; super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type); } public boolean isEnabled() { return mEnabled; } }

Además de onStartNestedScroll, también bloquee onNestedPreScroll y onNestedScroll para evitar un comportamiento inesperado. Por ejemplo, en mi caso, llamar a setExpanded (falso, verdadero) en mi barra de aplicaciones estaba frenando el comportamiento esperado y todavía se estaba expandiendo con retrasos. Ahora funciona:

LayoutParams layoutParams = (LayoutParams) context.appBarLayout.getLayoutParams(); ((DisableableAppBarLayoutBehavior)layoutParams.getBehavior()).setEnabled(false); context.appBarLayout.setLayoutParams(layoutParams); context.appBarLayout.setExpanded(false, true); // collapse app bar


Puede bloquear la expansión de la barra de herramientas restableciendo la altura de la barra de herramientas contraída a la altura de la barra de herramientas

toolbarHeight = toolbar.getLayoutParams().height; if (expand) { collapsingToolbar.getLayoutParams().height = getResources().getDimensionPixelOffset(R.dimen.collapsingToolbarDefaultHeight); appBarLayout.setExpanded(true, true); } else { //collapse //** it is important you do this before resetting ** appBarLayout.setExpanded(false, true); appBarLayout.postDelayed(new Runnable() { @Override public void run() { collapsingToolbar.getLayoutParams().height = toolbarHeight; } }, 700/* 600 is default animation time to collapse */); }


Todo lo que tiene que hacer es reemplazar CoordinatorLayout con una implementación personalizada de CoordinatorLayout que engañará a que se haya manejado el desplazamiento anidado.

Implementación MyCoordinatorLayout:

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

vista de actividad 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>

Le recomiendo que use la implementación personalizada de AppBarLayout con métodos auxiliares para contraer / expandir la barra de herramientas. En esta gist puedes encontrar uno.

Ok, ahora es el momento de configurar nuestra barra de herramientas en actividad.

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

Cada vez que desee cambiar la barra de herramientas fragmentar y contraer / expandir simplemente llame al método switchFragment / addFragment con el parámetro booleano adecuado.

Solo una última nota. Asegúrese de utilizar las últimas bibliotecas de soporte.

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

No utilice la etiqueta de inclusión en AppBarLayout. No funciona


Encuentra el ID de AppBarLayout como este.

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

Desactivar expandir en CollapsingToolbarLayout para ciertos fragmentos

appBarLayout.setExpanded(true,true);

Habilitar expandir en CollapsingToolbarLayout para ciertos fragmentos

appBarLayout.setExpanded(false,true);

Espero que te ayude !!


Utilicé la solución de DragCallback y agregué DragCallback a la clase de comportamiento para evitar tocar y arrastrar CollapsingToolbarLayout para expandirlo.

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