Scrolling techniques

From Google Material Design documentation:

When designing scrolling behavior, app bars contain four main regions (referred to as blocks) that comprise the scrolling structure:

  • Status bar
  • Tool bar
  • Tab bar/search bar
  • Flexible space: space to accommodate a desired aspect ratio for images or extended app bars

How to add?

I. In your build.gradle file add the latest design library.

dependencies {  
    compile 'com.android.support:design:X.X.X'
    // X.X.X especifica la versiĆ³n
}

II. Make your Activity extend android.support.v7.app.AppCompatActivity.

public class MainActivity extends AppCompatActivity {  

III. Add the Toolbar inside an AppBarLayout, and this one inside a CoordinatorLayout.

<android.support.design.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"
    android:orientation="vertical">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary"
        android:elevation="@dimen/toolbar_elevation">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            style="@style/AppTheme.Widget.Toolbar"/>

    </android.support.design.widget.AppBarLayout>

    ...

</android.support.design.widget.CoordinatorLayout>  

From that point, the configuration depends on some flags described below.

Standard app bar: disappears when scrolling

The Toolbar needs to specify the following flags by using app:layout_scrollFlags:

  • scroll - it will be shown and hidden when the specified view is scrolled.
  • enterAlways - when we scroll up, the view appears immediately, instead of waiting until the scroll finishes.
  • snap - if the view remains semi-visible when scroll stops, it will be animated until it's completely shown or hidden.
<android.support.v7.widget.Toolbar  
    ...
    app:layout_scrollFlags="scroll|enterAlways|snap"/>

You also need to specify which view you want to observe the scroll from. It can be a NestedScrollView, a RecyclerView or any other view that implements NestedScrollingChild. It is done by using app:layout_behavior:

<android.support.v4.widget.NestedScrollView  
    ...
    app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

Tabs

Tabs usually stay pinned at the top when app bar hides. Add the tabs to the AppBarLayout. Previous configuration will be enough to get the expected behaviour:

<android.support.design.widget.AppBarLayout  
    ...
>

    <android.support.v7.widget.Toolbar
        ...
    />

    <android.support.design.widget.TabLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.DarkOverlay"/>

</android.support.design.widget.AppBarLayout>  

Flexible space

To generate app bars with flexible size, you'll need a CollapsingToolbarLayout, used inside a CoordinatorLayout.

<android.support.design.widget.AppBarLayout  
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:theme="@style/AppTheme.DarkOverlay">

    <android.support.design.widget.CollapsingToolbarLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:contentScrim="?attr/colorPrimary"
        app:layout_scrollFlags="scroll|exitUntilCollapsed">

        <android.support.v7.widget.Toolbar
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            tools:src="@mipmap/ic_launcher"/>

    </android.support.design.widget.CollapsingToolbarLayout>

</android.support.design.widget.AppBarLayout>  

Flexible space with image

Very similar to the previous one, but adds an ImageView to the CollapsingToolbarLayout.

<android.support.design.widget.AppBarLayout  
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppTheme.DarkOverlay">

    <android.support.design.widget.CollapsingToolbarLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:contentScrim="?attr/colorPrimary"
        app:layout_scrollFlags="scroll|exitUntilCollapsed">

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="200dp"
            app:layout_collapseMode="parallax"/>

        <android.support.v7.widget.Toolbar
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"/>

    </android.support.design.widget.CollapsingToolbarLayout>

</android.support.design.widget.AppBarLayout>  

Flexible space with overlapping content

The app bar is initially behind the content, and during scroll it shrinks until it gets its collapsed size. From that point, content moves behind it. app:behaviour_overlapTop will do the work.

<android.support.design.widget.CoordinatorLayout  
    ... >

    <android.support.design.widget.AppBarLayout
        android:id="@+id/toolbar_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.design.widget.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="172dp"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:titleEnabled="false">

        <android.support.v7.widget.Toolbar
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:theme="@style/AppTheme.DarkOverlay"
            android:background="@null"
            app:layout_collapseMode="pin"/>

        </android.support.design.widget.CollapsingToolbarLayout>

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        app:behavior_overlapTop="64dp"/>

</android.support.design.widget.CoordinatorLayout>