Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hiding AppBarLayout and giving its space to the remaining view

Tags:

I have a pretty standard layout using the new design libraries:

<AppBarLayout>     <CollapsingToolbarLayout>         <ImageView/>         <Toolbar/>     </CollapsingToolbarLayout> </AppBarLayout>  <android.support.v4.widget.NestedScrollView/> <!-- content here --> 

What I'm trying to do is to completely hide the whole AppBarLayout programmatically, to temporarily get rid of the Toolbar and its collapsing feature.

So I'm calling this:

private void disableCollapsing() {     AppBarLayout.LayoutParams p = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams();     p.setScrollFlags(0);     collapsingToolbarLayout.setLayoutParams(p); } 

to disable the collapsing behavior (works well), and finally this:

@Override public void hide() {     final AppBarLayout layout = (AppBarLayout) findViewById(R.id.appbar);      layout.animate().translationY(-layout.getHeight())             .setListener(new AnimatorListenerAdapter() {                 @Override                 public void onAnimationEnd(Animator animation) {                     super.onAnimationEnd(animation);                     layout.setVisibility(View.GONE);                 }             }).start(); } 

I make the AppBarLayout translate to the top (works smoothly), and at the end of the animation set is visibility to View.GONE.

Issue

At the end of the animation, no matter I also set the visibility to GONE, I can't get the space that was previously occupied by the AppBarLayout. My NestedScrollView remains confined in the lower half of the screen, as if the AppBarLayout was still there (which is not). How can I fix it?

Before hiding:

Before

After hiding (AppBar translated to the top):

After

As you can see, the top space is empty and unreachable. The scroll view scrolls inside the margins it had before, as if the visibility change was not measured by the CoordinatorLayout.

  • I have tried calling coordinator.requestLayout(), with no success.

  • I also tried setting the AppBarLayout as an app:anchor for my NestedScrollView, but that screws things up - scroll view ends up taking the whole screen even before hiding.

  • I was thinking of a custom Behavior to be set on the scroll view when entering this hidden-AppBar mode, but I can't get started on that.

like image 476
natario Avatar asked Jun 16 '15 18:06

natario


People also ask

How do you make AppBarLayout transparent?

Simply use app:elevation="0dp" inside "AppBarLayout" to remove the shadow.

What is the use of AppBarLayout in Android?

AppBarLayout is a vertical LinearLayout which implements many of the features of material designs app bar concept, namely scrolling gestures. Children should provide their desired scrolling behavior through AppBarLayout.

What is the difference between AppBarLayout and ToolBar?

AppBarLayout is a parent layout of ToolBar and ToolBar is custom ActionBar. if you want scroll action on the ToolBar so you should write ToolBar into the AppBarLayout,before you will write code for scroll the ToolBar, you must know the NestedScrollBar,it is used to scroll the ToolBar.


2 Answers

Yes this looks like a bug, I solved this issue for my application setting the appbar height to 0:

android.support.design.widget.AppBarLayout appbar = (android.support.design.widget.AppBarLayout) findViewById(R.id.appbar);  CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)appbar.getLayoutParams();  lp.height = 0;  appbar.setLayoutParams(lp); 
like image 70
Alberto Polo Avatar answered Sep 22 '22 14:09

Alberto Polo


As mentioned above, setting the Coordinator.LayoutParams#height fixes the issue.

However, I wanted to express how/when this occurs (not necessarily why):

The CollaspingToolbarLayout will exhibit this behavior only when its app:layout_scrollFlags property is set to exitUntilCollapsed and its nested ToolBar also has defines app:layout_collapseMode="pin". With this combination of flags, the Toolbar will pin itself to the top of the screen, and this is intentional and sometimes desirable.

(snipped for brevity)

<androidx.coordinatorlayout.widget.CoordinatorLayout     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">      <com.google.android.material.appbar.AppBarLayout         android:id="@+id/appbar"         android:layout_width="match_parent"         android:layout_height="wrap_content">          <com.google.android.material.appbar.CollapsingToolbarLayout             android:id="@+id/collapsingToolbar"             android:layout_width="match_parent"             android:layout_height="wrap_content"             app:layout_scrollFlags="scroll|exitUntilCollapsed">              <!-- some other component here, i.e ImageView -->              <androidx.appcompat.widget.Toolbar                 android:id="@+id/toolbar"                 android:layout_width="match_parent"                 android:layout_height="?attr/actionBarSize"                 android:gravity="top"                 app:layout_collapseMode="pin" />          </com.google.android.material.appbar.CollapsingToolbarLayout>      </com.google.android.material.appbar.AppBarLayout>      <!-- some scrolling view/layout -->  </androidx.coordinatorlayout.widget.CoordinatorLayout> 

In the Fragment/Activity after the view is created, in Kotlin + ViewBinding:

binding.appbar.updateLayoutParams<CoordinatorLayout.LayoutParams> {     height = 0 } 

For me, I had to capture the height of the AppBarLayout before hiding it to restore it to its original height when I wanted to show it.

private var appbarLayoutHeight = 0 private fun hideAppBar() {     appbarLayoutHeight = binding.appbar.measuredHeight     binding.appbar.updateLayoutParams<CoordinatorLayout.LayoutParams> {         height = 0     } } private fun showAppBar() {     binding.appbar.updateLayoutParams<CoordinatorLayout.LayoutParams> {         height = appbarLayoutHeight     } } 

Disclaimer: ViewBinding is not necessary to achieve this, nor is using Kotlin, and it's just what I use to acquire the AppBarLayoout and make this as terse/sugary as possible.

like image 43
matteo Avatar answered Sep 21 '22 14:09

matteo