Codelab for Android Design Support Library

Posted Android 从零单排

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codelab for Android Design Support Library相关的知识,希望对你有一定的参考价值。

extends:http://inthecheesefactory.com/blog/android-design-support-library-codelab

 

At the moment I believe that there is no any Android Developer who doesn‘t know about Material Design anymore since it officially becomes a design philosophy by shaking the world of design in passed year.

Surprisingly that it was not easy to implement Material Design in android application because those Material Design‘s UI Component like Floating Action Button (FAB) wasn‘t available in Android pre-Lollipop. Only choice we had was to use 3rd party library published by indie android developer out there.

Here comes a good news. Last week during Google I/O 2015 event, Google announced the most excited support library within year named Android Design Support Library providing a bunch of useful Material Design UI Components in a single library. Let me use this chance to describe to you one by one how to use each of them through this article.

Please check the video below as the final of result of this tutorial.

And this is the starting point. A blank Activity with DrawerLayout equipped.

Activity is also already adjusted the theme in Material Design‘s way.

1
2
3
<item name="colorPrimary">#2196F3</item>
<item name="colorPrimaryDark">#1565C0</item>
<item name="colorAccent">#E91E63</item>

OK, let‘s start !

Step 1: Clone Source Code from Github

I have prepared source code for this codelab. You could simply clone it from GitHub. MainActivity is the final result shown above. Please do your codelab in CodeLabActivity prepared in the same project.

First task that you have to do it yourself is ... to successfully run it which it supposes to be done by simply clicking on Run button.

Step 2: Add Android Design Support Library Dependency

First thing to do to include Android Design Support Library in our project is to add a line of dependency code in app‘s build.gradle file.

1
compile ‘com.android.support:design:22.2.1‘

Please note that Design Support Library depends on Support v4 and AppCompat v7. Once you include this library in your project, you will also gain an access to those libraries‘ components.

By the way, source code cloned from Github has already been added above line of code. But if you create your own project, you need to add it by yourself.

Step 3: Add FAB

Floating Action Button (FAB) is simply a circle button with some drop shadow that unbelieveably could change the world of design. No surprise why it becomes a signature of Material Design. So let‘s start with this thing. Add FAB in layout file with FloatingActionButton and wrap it with FrameLayout since it needs some parent to make it aligned at bottom right position of the screen. Place those things as DrawerLayout‘s content by replacing an existed TextViewin activity_code_lab.xml file like below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<android.support.v4.widget.DrawerLayout ...
    xmlns:app="http://schemas.android.com/apk/res-auto"
    ....>
 
    <FrameLayout
        android:id="@+id/rootLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
 
        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fabBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|right"
            android:src="@drawable/ic_plus"
            app:fabSize="normal" />
 
    </FrameLayout>
 
    ...
 
</android.support.v4.widget.DrawerLayout>

android:src is used to define a Resource ID of icon you want (40dp transparent png file is recommended) while app:fabSize="normal" is used to define FAB‘s size. normal means the standard 56dp button used in most of the case but in case you want to use the smaller one, mini is an another choice that will change its width to 40dp.

That‘s all. FAB is now ready to use! Here is the result when we run the code on Android 4.4.

技术分享

But when we run on Android 5.0, the result turn into this ...

技术分享

There is nothing fancy but just a bug. Fortunate that design library‘s developer team has already known the issue and will release a fixed version in the near future. But if you want to use it now, we could do some workaround by setting FAB‘s margin right and margin bottom to 16dp for API Level 21+ and to 0dp for Android pre-Lollipop. Thanks Configuration Qualifier that allows us to do it extremely easy.

res/values/dimens.xml

1
2
<dimen name="codelab_fab_margin_right">0dp</dimen>
<dimen name="codelab_fab_margin_bottom">0dp</dimen>

res/values-v21/dimens.xml

1
2
<dimen name="codelab_fab_margin_right">16dp</dimen>
<dimen name="codelab_fab_margin_bottom">16dp</dimen>

res/layout/activity_code_lab.xml

1
2
3
4
5
<android.support.design.widget.FloatingActionButton
    ...
    android:layout_marginBottom="@dimen/codelab_fab_margin_bottom"
    android:layout_marginRight="@dimen/codelab_fab_margin_right"
    .../>

Hola !

技术分享

The shadow depth is automatically set to the best practices one, 6dp at idle state and 12dp at pressed state. Anyway you are allowed to override these values by defining app:elevation for idle state‘s shadow depth andapp:pressedTranslationZ for press state‘s.

Regard to button‘s color, basically FAB uses the accent color but you could override withapp:backgroundTint attribute.

Just like a traditional Button, you could handle click with setOnClickListener(). Add the following line of codes in initInstances in CodeLabActivity.java file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
FloatingActionButton fabBtn;
 
...
 
private void initInstances() {
    ...
 
    fabBtn = (FloatingActionButton) findViewById(R.id.fabBtn);
    fabBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
 
        }
    });
}

Done !

Step 4: Play with Snackbar

Snackbar, a tiny black bar showing a brief message at the bottom of the screen, is also available in this library. Snackbar shares the same concept as Toast but unlike Toast, it shows as a part of UI instead of overlaying on screen.

技术分享

Not just a concept but also coding style that it is inspired from Toast. You could summon Snackbar by the code below.

1
2
3
4
5
6
7
8
Snackbar.make(someView, "Hello. I am Snackbar!", Snackbar.LENGTH_SHORT)
        .setAction("Undo", new View.OnClickListener() {
            @Override
            public void onClick(View v) {
 
            }
        })
        .show();

The first parameter of make() is a View or Layout that you want to show a Snackbar at it‘s bottom position. In this example, a FrameLayout that wrapped a FAB is the one. setAction() method is used to set the action displayed on the right of Snackbar with a listener corresponded. This method is not required and could be removed.

Now let‘s give a try by adding the following code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
FrameLayout rootLayout;
 
...
 
private void initInstances() {
    ...
 
    rootLayout = (FrameLayout) findViewById(R.id.rootLayout);
 
    fabBtn = (FloatingActionButton) findViewById(R.id.fabBtn);
    fabBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Snackbar.make(rootLayout, "Hello. I am Snackbar!", Snackbar.LENGTH_SHORT)
                    .setAction("Undo", new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
 
                        }
                    })
                    .show();
        }
    });
}

Click at FAB and see the result.

技术分享

It works ! but ... not perfectly yet. It is appeared that Snackbar is placed on top of FAB which is totally bad in term of UX. Anyway the behavior is already correct since there is no any relation between Snackbar and FAB defined.

A special Layout is invented for this purpose especially, make child Views work coordinated. No surprise why its name is CoordinatorLayout

Step 5: Make them collaborated with CoordinatorLayout

CoordinatorLayout is a Layout let child Views work coordinated. Anyway there is no magic. Each View inside must be designed and implemented to work with CoordinatorLayout as well. FAB and Snackbar are two of those.

So ... let‘s change FrameLayout wrapped a FAB to CoordinatorLayout now.

res/layout/activity_code_lab.xml

1
2
3
4
5
6
7
8
<android.support.design.widget.CoordinatorLayout
    android:id="@+id/rootLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <android.support.design.widget.FloatingActionButton
        ... />
</android.support.design.widget.CoordinatorLayout>

And don‘t forget to change rootLayout‘s variable type in CodeLabActivity.java to CoordinatorLayout as well or it will crash.

1
2
3
4
5
//FrameLayout rootLayout;
CoordinatorLayout rootLayout;
 
//rootLayout = (FrameLayout) findViewById(R.id.rootLayout);
rootLayout = (CoordinatorLayout) findViewById(R.id.rootLayout);

Another bug is here. On Android 4.4, FAB‘s margin has surprisingly been dropped to the zero which let its position moved to bottom-right as a result.

技术分享

This bug just happens on Android Design Support Library 22.2.1 so let‘s wait for the official fix but for now in case you want to use FloatingActionButton inside CoordinatorLayout, please manually adjust FAB‘s margin right and margin bottom to 16dp.

res/values/dimens.xml

1
2
<dimen name="codelab_fab_margin_right">16dp</dimen>
<dimen name="codelab_fab_margin_bottom">16dp</dimen>

Done

技术分享

Result: FAB now moves along with Snackbar‘s appearance and disappearance. Some feature is also added. Snackbar is now able to Swipe-to-dismiss ! Here is the result.

Please note that FAB had ever moved back to the proper position with smoother animation on v22.2.0 but it turns to be worse in v22.2.1

From now on, if you plan to use Android Design Support Library. Please think about CoordinatorLayout first since it is something like a core of this library.

Step 6: Goodbye ActionBar, Hail Toolbar

Toolbar is not part of Android Design Support Library but is needed to be used together with the rest of components in this library.

Toolbar is a replacement of traditional Action Bar with far more flexible behavior. I encourage you guys to hiding an Action Bar and switch to Toolbar from now on since new libraries with wonderful features are all designed to work together with Toolbar not Action Bar including components in this Design Support Library.

It is easy to switch to Toolbar. Just start with hiding an Action Bar from an Activity by defining these attributes in AppTheme‘s style.

1
2
3
4
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
</style>

Then place a Toolbar component inside CoordinatorLayout right before where FAB is.

1
2
3
4
5
6
7
8
9
10
11
12
13
<android.support.design.widget.CoordinatorLayout
    ...>
    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
    <android.support.design.widget.FloatingActionButton
        ...>
    </android.support.design.widget.FloatingActionButton>
</android.support.design.widget.CoordinatorLayout>

Now write a code to tell system that we will use Toolbar as an Action Bar replacement with Java Code below.

1
2
3
4
5
6
7
Toolbar toolbar;
 
private void initInstances() {
    toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    ...
}

Although it could run fine by now but from I said previously. Things placed inside CoordinatorLayout must be designed and implemented to work with it or it will not coordinate with any other sibling views. But well ... Toolbar is not designed for that. Don‘t worry, there is no any new special Toolbar here, just an component that is prepared to make Toolbar works perfectly with CoordinatorLayout. An easy task, just simply wrap Toolbar with AppBarLayout. That‘s all !

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<android.support.design.widget.CoordinatorLayout
    ...>
 
    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
       <android.support.v7.widget.Toolbar
           .../>
    </android.support.design.widget.AppBarLayout>
 
    <android.support.design.widget.FloatingActionButton
        ...>
    </android.support.design.widget.FloatingActionButton>
</android.support.design.widget.CoordinatorLayout>

Now run and test. If you do it all right, you will see that Drawer Menu will overlay on top of the App Bar area.

This step is now done. From now on I suggest you to always wrap ToolBar element with AppBarLayout regards to making it works perfectly with CoordinatorLayout.

Step 7: Place something in content area

We got FAB, we got Toolbar. Now it‘s time to place something in content area of an Activity.

Umm. How about two simple buttons? Well, let‘s place them between AppBarLayout and FAB.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    ...
</android.support.design.widget.AppBarLayout>
 
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Yo Yo"
        />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Yo Yo"
        />
</LinearLayout>
 
<android.support.design.widget.FloatingActionButton
    ...>

Here is the result ...

技术分享

It is appeared that those buttons are unexpectedly placed under Toolbar. Guess why...

Yah, same old reason, LinearLayout is not designed to work with CoordinatorLayout. In this case, there is no any layout to wrap it like Toolbar‘s case. It is for more easy, you just need to add an attribute to the LinearLayout telling its scroll behavior like below.

1
2
3
4
5
<LinearLayout
    ...
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    ...
    >

And now they are at the right place. Yah !

技术分享

Done =)

Step 8: Play with TabLayout

Tab is a part of UX best practices in Android Application. Previously if we want to use new Material Design Tab, we need to download source code of SlidingTabLayout and SlidingTabStrip to our project ourselves. Right now we could just use TabLayout provided in this library, also with some more tweak options.

Where should we place this TabLayout? According to Android Application UX Guideline, Tab should be placed on top of the screen not the bottom. And well, it should be above the drop shadow part. So we will place it inside AppBarLayout along with Toolbar. It could be done like this becauseAppBarLayout is inherited from a vertical LinearLayout.

1
2
3
4
5
6
7
8
9
10
<android.support.design.widget.AppBarLayout ...>
 
    <android.support.v7.widget.Toolbar ... />
 
    <android.support.design.widget.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
 
</android.support.design.widget.AppBarLayout>

Add some tabs with Java Code.

1
2
3
4
5
6
7
8
9
10
TabLayout tabLayout;
 
private void initInstances() {
    tabLayout = (TabLayout) findViewById(R.id.tabLayout);
    tabLayout.addTab(tabLayout.newTab().setText("Tab 1"));
    tabLayout.addTab(tabLayout.newTab().setText("Tab 2"));
    tabLayout.addTab(tabLayout.newTab().setText("Tab 3"));
 
    ...
}

Here is the result.

技术分享

Background color is automatically set to primary color while the indicator line‘s color is the accent one. But you will notice that Tab‘s font is still black but we expect it to be white. This happens because we didn‘t provide it any theme yet. Simply define TabLayout a theme like this.

1
2
3
<android.support.design.widget.TabLayout
    ...
    app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />

They are white now.

技术分享

You have a choice to manually control TabLayout like above or let it work with ViewPager automatically by calling setupWithViewPager(...). I believe that it will be used quite frequent for this case.

There are two attributes we could adjust the display in TabLayout.

app:tabMode - set it as fixed if you want to display every single tab on the screen. Good for a small number of tabs but totally a bad choice if there are so many tabs. In the case you are not sure that all of them could be displayed nicely at a time, you could set this attribute asscrollable to let user scroll through tabs instead just like Google Play Store‘s.

app:tabGravity - set it as fill if you want distribute all available space to each tab or set it as center if you want to place all of the tabs at the center of the screen. Please note that this attribute will be ignored if tabMode is set to scrollable.

Here is what it looks like in each mode.

技术分享

Done with TabLayout =)

Step 9: Make AppBarLayout exit the screen along with content when scroll

One nice Android UX Guideline announced is the App Bar could be scrolled out of the screen along with content to get some more additional space to display content and it is already proved that this UX is good. Previously there were some application that was already implemented this behavior but developer had to do it by themselves. Right now it could be done easily with just a line of code.

First of all, we need to make the content scrollable first by adding some amount of Buttons to LinearLayout. How about 20?