Introduction
Last year, Google introduced Material Design and it became clear that motion and animation would be two of the most eye-catching features in modern Android applications. But Google didn't provide developers with an easy solution to integrate them in applications. As a result, many libraries were developed to solve the integration problem.
During this year's Google I/O, however, Google introduced the Android Design Support Library to make the adoption of Material Design easier. This lets developers focus on the features that make their applications unique.
1. Regions
In this tutorial, I'll show you how to implement the scrolling techniques shown in Google’s Material Design specification. Before we start, you should familiarize yourself with the available scrollable regions in an Android application. In the following image, you can see that there are four regions.
Status Bar
This is where notifications appear and the status of different features of the device are displayed.
Toolbar
The toolbar was formerly known as the action bar. It is now a more customizable view with the same functionalities.
Tab/Search Bar
This optional region is used to display the tabs that categorize the content of your application. You can read more about the usage of tabs and the different ways to display them in Google's Material Design specification. When suitable, you can also use it in Google’s lateral navigation.
Flexible Space
This is where you can display images or extended app bars.
With regards to scrolling techniques, it's the toolbar and the tab/search bar that respond when the content of your application is scrolling.
2. Project Setup
To follow along, you should be using the latest version of Android Studio. You can get it from the Android Developer website. To try these scrolling techniques, I recommend creating a new project (with a minimum API level of 15), because your application's layout will change significantly.
I've provided a starter project, which you can download from GitHub. You can use the starter project as a starting point and use the scrolling techniques in your own applications. Let's first add the following dependencies to your project's build.gradle file inside the app folder:
compile 'com.android.support:design:22.2.0' compile 'com.android.support:recyclerview-v7:22.2.0'
With the first dependency, you get the Android Design Support Library, which includes the new classes we need for this tutorial.
With the second dependency, you get the latest version of RecyclerView
. The version listed in the official article about creating lists won't be useful this time.
Next, you are going to need some dummy data to try these techniques and populate the RecyclerView
. You can implement them yourself or copy the implementation from the InitialActivity
class in the starter project.
3. Scrolling Technique 1
This technique hides the toolbar region when your application's content is being scrolled. You can see the technique in action in the following video.
For this layout design, you may think of something like this:
<RelativeLayout … > <Toolbar … /> <RecyclerView … /> </RelativeLayout>
The problem with this layout is that you have to manage the events yourself, but it will be painless if you take advantage of the new classes. Let's modify it as follows:
<android.support.design.widget.CoordinatorLayout 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" tools:context="co.herovitamin.androiddesignsupportlibraryapplication.CoordinatorLayoutAndAppBarActivity"> <android.support.design.widget.AppBarLayout android:id="@+id/my_appbar_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" > <android.support.v7.widget.Toolbar android:id="@+id/technique_one_toolbar" style="@style/TechniqueToolbar" app:layout_scrollFlags="scroll|enterAlways"> <!-- scroll enterAlways enterAlwaysCollapsed exitUntilCollapsed --> </android.support.v7.widget.Toolbar> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerView android:id="@+id/days_list" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"/> </android.support.design.widget.CoordinatorLayout>
In this new layout, you can see that:
- the
RelativeLayout
is replaced with aCoordinatorLayout
- the
Toolbar
is wrapped in aAppBarLayout
- the
Toolbar
andRecyclerView
received a few additional attributes
What are these new classes?
CoordinatorLayout
This layout is a new container and a supercharged FrameLayout
that provides an additional level of control over touch events between child views.
AppBarLayout
This layout is another new container, designed specifically to implement many of the features of the Material Design app bar concept. Keep in mind that if you use it within another ViewGroup
, most of its functionality won't work.
The key to this scrolling technique, and most other scrolling techniques that we'll discuss, is the CoordinatorLayout
class. This special class can receive events from and deliver events to its child views in order for them to respond appropriately. It is designed to be used as the root container view.
To enable this technique, the app:layout_behavior
attribute indicates which view will trigger the events in the Toolbar
. In this case, that's the RecyclerView
.
app:layout_behavior=“@string/appbar_scrolling_view_behavior"
The app:layout_scrollFlags
attribute of the Toolbar
indicates to the view how to respond.
app:layout_scrollFlags=“scroll|enterAlways"
The app:layout_scrollFlags
attribute can have four possible values, which can be combined to create the desired effect:
scroll
This flag should be set for all views that need to scroll off-screen. Views that don't use this flag remain pinned to the top of the screen.
enterAlways
This flag ensures that any downward scroll will cause this view to become visible, enabling the quick return pattern.
enterAlwaysCollapsed
When a view has declared a minHeight
and you use this flag, the view will only enter at its minimum height (collapsed), only expanding to its full height when the scrolling view has reached its top.
exitUntilCollapsed
This flag causes the view to scroll off-screen until it is collapsed (its minHeight
is reached) before exiting.
You can now run the project, or press Control+R, and see this technique in action.
4. Scrolling Technique 2
This technique scrolls the toolbar off-screen while the tab bar region stays anchored to the top. You can see this technique in action in the following video.
For this technique, I'm going to reuse the layout from the previous technique and add a TabLayout
view next to the Toolbar
, inside the AppBarLayout
.
<android.support.design.widget.CoordinatorLayout ... <android.support.design.widget.AppBarLayout ... <android.support.v7.widget.Toolbar ... app:layout_scrollFlags="scroll|enterAlways"/> <android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/primary" /> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerView ... app:layout_behavior="@string/appbar_scrolling_view_behavior"/> </android.support.design.widget.CoordinatorLayout>
The TabLayout
view provides a horizontal layout to display tabs. You can add any number of tabs using the newTab
method and set its behavior mode using the setTabMode
. Let's start by populating the tabs.
tab_layout = (TabLayout) findViewById(R.id.tabs); tab_layout.setTabMode(TabLayout.MODE_FIXED); tab_layout.addTab(tab_layout.newTab().setText("Tab 1")); tab_layout.addTab(tab_layout.newTab().setText("Tab 2")); tab_layout.addTab(tab_layout.newTab().setText("Tab 3"));
By changing the value of the app:layout_scrollFlags
attribute, and adding and removing it from the Toolbar
and TabLayout
, you can get animations like those used in:
- Google Play Store where the toolbar hides and the tab bar remains visible.
- Foursquare where the tab bar scrolls off-screen while the toolbar stays at the top.
- Play Music where both the toolbar and the tab bar scroll off-screen.
Take a look at the following videos for examples of this scrolling technique.
You can run your project and see this scrolling technique in action.
5. Scrolling Technique 3
For this scrolling technique, I'm going to make use of the flexible space region I mentioned in the beginning of this tutorial. I do this to shrink the initial height of the AppBarLayout
as the content is scrolling up. The height of the AppBarLayout
increases to its original height as the content is scrolled down. You can see this technique in action in the following video.
For this scrolling technique, I'm going to use the following layout:
<android.support.design.widget.CoordinatorLayout 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" tools:context="co.herovitamin.androiddesignsupportlibraryapplication.CoordinatorLayoutAndAppBarActivity"> <android.support.design.widget.AppBarLayout android:id="@+id/my_appbar_container" android:layout_width="match_parent" android:layout_height="192dp" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" android:background="@color/primary"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_container" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_scrollFlags="scroll|exitUntilCollapsed" app:contentScrim="@color/primary" app:expandedTitleMarginStart="48dp" app:expandedTitleMarginEnd="64dp"> <android.support.v7.widget.Toolbar android:id="@+id/technique_three_toolbar" android:layout_height="?attr/actionBarSize" android:layout_width="match_parent" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:layout_collapseMode="pin"/> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerView android:id="@+id/days_list_3" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"/> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="16dp" android:src="@drawable/plus" app:borderWidth="0dp" app:layout_anchor="@id/my_appbar_container" app:layout_anchorGravity="bottom|right|end" /> </android.support.design.widget.CoordinatorLayout>
It certainly looks like a lot of code, so let's break it down. In this layout, I made the following changes:
- The
Toolbar
is wrapped in aCollapsingToolBarLayout
and both elements are put in theAppBarLayout
. - The
app:layout_scrollFlags
attribute is moved from theToolbar
to theCollapsingToolBarLayout
, because this container is now in charge of responding to scroll events. - A new attribute,
app:layout_collapseMode
, was added to theToolbar
. This attribute ensures that theToolbar
remains pinned to the top of the screen. - The
AppBarLayout
has a fixed initial height of 192dp. - A
FloatingActionButton
was added to the layout, below theRecyclerView
.
What are these new classes for?
CollapsingToolBarLayout
This is a new view, designed specifically for wrapping the Toolbar
and implement a collapsing app bar. When using the CollapsingToolBarLayout
class, you must pay special attention to the following attributes:
app:contentScrim
This attribute specifies the color to display when it is fully collapsed.
app:expandedTitleMarginStart/app:expandedTitleMarginEnd
These attributes specify the margins of the expanded title. They are useful if you plan to use the setDisplayHomeAsUpEnabled
method in your activity and fill the new spaces created around the title.
FloatingActionButton
The floating action button is an important component of Material Design apps. You can now include floating action buttons in your layout with only a few lines of code. You can use the app:fabSize
attribute to choose from two different sizes, standard (56dp) and mini (40dp). Standard is the default size.
The disappearing effect is achieved automatically by anchoring the floating action button to the AppBarLayout
using the app:layout_anchor
attribute. You can also specify the position relative to this anchor by using the app:layout_anchorGravity
attribute.
Before running the project, we need to specify in the activity that the CollapsingToolBarLayout
is going to display the title instead of the Toolbar
. Take a look at the following code snippet for clarification.
collapsing_container = (CollapsingToolbarLayout) findViewById(R.id.collapsing_container); collapsing_container.setTitle(getResources().getString(R.string.title_activity_technique3));
Run the project to see the third scrolling technique in action.
6. Scrolling Technique 4
This scrolling technique uses the extended AppBarLayout
, shown in the previous technique, to display an image. You can see this technique in the following video.
For this technique, I'm going to reuse the previous layout and modify it slightly:
<android.support.design.widget.CoordinatorLayout ...> <android.support.design.widget.AppBarLayout android:id="@+id/my_appbar_container" android:layout_width="match_parent" android:layout_height="192dp" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" > <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_container" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_scrollFlags="scroll|exitUntilCollapsed" app:contentScrim="@color/primary"> <ImageView android:id="@+id/imgToolbar" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" android:src="@drawable/image" app:layout_collapseMode="parallax" /> <android.support.v7.widget.Toolbar ...> </android.support.v7.widget.Toolbar> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerView .../> <android.support.design.widget.FloatingActionButton ... /> </android.support.design.widget.CoordinatorLayout>
In this layout, I made the following modifications:
- The
android:background
attribute was removed from theAppBarLayout
. Because theImageView
is going to fill this space, there's no need to have a background color. - The
app:expandedTitleMarginStart
andapp:expandedTitleMarginEnd
attributes were removed, because we're not using thesetDisplayHomeAsUpEnabled
method in the activity.
- An
ImageView
was added before theToolbar
. This is important to avoid that theAppBarLayout
shows a part of the image instead of the primary color when it is collapsed.
You may also have noticed that the ImageView
has the app:layout_collapseMode
attribute. The value of the attribute is set to parallax
to implement parallax scrolling. In addition, you could also add the app:layout_collapseParallaxMultiplier
attribute to set a multiplier.
These are all the changes you have to do to get this scrolling technique running smoothly in your app. Run the project to see this scrolling technique in action.
7. Scrolling Technique 5
For this scrolling technique, the flexible space is overlapped by the content of the app and is scrolled off-screen when the content is scrolled. You can see this technique in action in the following video.
For this technique, you can reuse the layout from the previous technique, with a few little modifications.
<android.support.design.widget.CoordinatorLayout 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" tools:context="co.herovitamin.androiddesignsupportlibraryapplication.CoordinatorLayoutAndAppBarActivity"> <android.support.design.widget.AppBarLayout android:id="@+id/my_appbar_container" android:layout_width="match_parent" android:layout_height="192dp" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_container" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_scrollFlags="scroll|exitUntilCollapsed" android:background="@color/primary"> <android.support.v7.widget.Toolbar android:id="@+id/technique_five_toolbar" android:layout_height="?attr/actionBarSize" android:layout_width="match_parent" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:layout_collapseMode="pin" android:background="@color/primary" /> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerView android:id="@+id/days_list_5" 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>
For this layout:
- The
ImageView
and theFloatingActionButton
inside theCollapsingToolbarLayout
were removed. This technique does not require an image. - In the
CollapsingToolbarLayout
, theapp:contentScrim
attribute was replaced with theandroid:background
attribute. We do this, because the background color needs to match theToolbar
background color nicely when disappearing. - The
android:background
attribute was added to theToolbar
. - The
app:behavior_overlapTop
attribute was added to theRecyclerView
. This is the most important attribute for this scrolling technique as this attribute specifies the amount of overlap the view should have with theAppBarLayout
. For this attribute to have effect, it should be added to the same view that has theapp:layout_behavior
attribute.
If you try to use this scrolling technique with these modifications, then the resulting layout won't have a title in the Toolbar
. To solve this, you could create a TextView
and add it to the Toolbar
programmatically.
TextView text = new TextView(this); text.setText(R.string.title_activity_technique5); text.setTextAppearance(this, android.R.style.TextAppearance_Material_Widget_ActionBar_Title_Inverse); toolbar.addView(text);
Conclusion
Note that you don't need to implement every one of these techniques in your app. Some will be more useful to your design than others. Now that you know how to implement each one, you can choose and experiment with them.
I hope you found this tutorial useful. Don't forget to share it if you liked it. You can leave any comments and questions below.
Comments