路要走,生活还得继续。

Hardworking Now

Android Material Design之Toolbar实践

浪了这么多天,是时候要静下心好好的学习一波了。两个星期没有碰Android,感觉好多东西都忘记了,下午在看到了一篇关于Marterial Design的报道,其实Marterial Design一直是我个人比较喜欢的风格的。下面我们来一起看看这个吊炸天的Marterial Design:

前言

我们都知道Marterial Design是Google推出的全新UI设计规范,如果对其不太了解的可以看下:Material design非官方中文指导手册 ,或者我的前面几篇Material Design的译文,相比之前Google在Android Holo风格上平平淡淡的表现不同,Material Design现在是被Google所比较重视的。在推出这门全新设计语言后,Android上自家的应用很快就使用Material Design全新设计了,如Play商店,Google Map,Google+,比较新的Inbox等;Web上的视觉体验也是很Material的,最有帮助的当属这个了Material Design的官方介绍(自备梯子)了;iOS方面的Google应用也在慢慢推进中。所以作为一个Android开发者怎么能不紧跟Google的步伐呢,下面就来通过Toolbar和Palette这两个在API21后推出的东西,当然Google已经把它们放到到v7库里了,使用Material Design来设计App当然不仅限于这两个方面了,前面的Material Design的译文已经清楚知道怎么去全面设计。除了Toolbar和Palette这篇文章还会介绍在Toolbar下使用Drawer。

Toolbar

Toolbar是什么?大概说一下它的官方介绍。Toolbar是应用的内容的标准工具栏,可以说是Actionbar的升级版,两者不是独立关系,要使用Toolbar还是得跟ActionBar扯上关系的。相比Actionbar Toolbar最明显的一点就是变得很自由,可随处放置,因为它是作为一个ViewGroup来定义使用的,所以单纯使用ActionBar已经稍显过时了,它的一些方法已被标注过时。

那么它怎么使用呢,首先我们一样要用到v7的支持包,然后定义程序的主题样式,在style里得先把Actionbar去掉,有点像欲想练功,必先自宫的感觉啊。如下:

/res/values/styles.xml

    <resources xmlns:android="http://schemas.android.com/apk/res/android">  
      
        <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cstyle%20name%3D%22AppBaseTheme%22%20parent%3D%22Theme.AppCompat.Light.NoActionBar%22%3E%20%20%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C!--%20toolbar%EF%BC%88actionbar%EF%BC%89%E9%A2%9C%E8%89%B2%20--%3E%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Citem%20name%3D%22colorPrimary%22%3E%234876FF%3C%2Fitem%3E%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C!--%20%E7%8A%B6%E6%80%81%E6%A0%8F%E9%A2%9C%E8%89%B2%20--%3E%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Citem%20name%3D%22colorPrimaryDark%22%3E%233A5FCD%3C%2Fitem%3E%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C!--%20%E7%AA%97%E5%8F%A3%E7%9A%84%E8%83%8C%E6%99%AF%E9%A2%9C%E8%89%B2%20--%3E%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Citem%20name%3D%22android%3AwindowBackground%22%3E%40android%3Acolor%2Fwhite%3C%2Fitem%3E%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C!--%20SearchView%20--%3E%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Citem%20name%3D%22searchViewStyle%22%3E%40style%2FMySearchViewStyle%3C%2Fitem%3E%20%20%0A%20%20%20%20%20%20%20%20%3C%2Fstyle%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<style>" title="<style>" />  
      
        <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cstyle%20name%3D%22AppTheme%22%20parent%3D%22%40style%2FAppBaseTheme%22%3E%3C%2Fstyle%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<style>" title="<style>" />  
      
        <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cstyle%20name%3D%22MySearchViewStyle%22%20parent%3D%22Widget.AppCompat.SearchView%22%3E%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C!--%20%20%0A%20%20%20%20%20%20%20%20Background%20for%20the%20search%20query%20section%20(e.g.%20EditText)%20%20%0A%20%20%20%20%20%20%20%20%3Citem%20name%3D%22queryBackground%22%3E...%3C%2Fitem%3E%20%20%0A%20%20%20%20%20%20%20%20Background%20for%20the%20actions%20section%20(e.g.%20voice%2C%20submit)%20%20%0A%20%20%20%20%20%20%20%20%3Citem%20name%3D%22submitBackground%22%3E...%3C%2Fitem%3E%20%20%0A%20%20%20%20%20%20%20%20Close%20button%20icon%20%20%0A%20%20%20%20%20%20%20%20%3Citem%20name%3D%22closeIcon%22%3E...%3C%2Fitem%3E%20%20%0A%20%20%20%20%20%20%20%20Search%20button%20icon%20%20%0A%20%20%20%20%20%20%20%20%3Citem%20name%3D%22searchIcon%22%3E...%3C%2Fitem%3E%20%20%0A%20%20%20%20%20%20%20%20Go%2Fcommit%20button%20icon%20%20%0A%20%20%20%20%20%20%20%20%3Citem%20name%3D%22goIcon%22%3E...%3C%2Fitem%3E%20%20%0A%20%20%20%20%20%20%20%20Voice%20search%20button%20icon%20%20%0A%20%20%20%20%20%20%20%20%3Citem%20name%3D%22voiceIcon%22%3E...%3C%2Fitem%3E%20%20%0A%20%20%20%20%20%20%20%20Commit%20icon%20shown%20in%20the%20query%20suggestion%20row%20%20%0A%20%20%20%20%20%20%20%20%3Citem%20name%3D%22commitIcon%22%3E...%3C%2Fitem%3E%20%20%0A%20%20%20%20%20%20%20%20Layout%20for%20query%20suggestion%20rows%20%20%0A%20%20%20%20%20%20%20%20%3Citem%20name%3D%22suggestionRowLayout%22%3E...%3C%2Fitem%3E%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20--%3E%20%20%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%3C%2Fstyle%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<style>" title="<style>" />  
      
    </resources>

去除Actionbar最简单的方法就是直接继承NoActionBar的主题了。颜色的属性说明,还是下面这张图最清楚了:

另外,SearchView在AppCompat中提供了更强的可定制性和更多的样式可供设置,不过一般我们用默认的就行。

还有我们可以在values-v21给API21的系统版本设置默认的底部导航栏默认的颜色:

/res/values-v21/styles.xml

    <resources xmlns:android="http://schemas.android.com/apk/res/android">  
      
        <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cstyle%20name%3D%22AppTheme%22%20parent%3D%22%40style%2FAppBaseTheme%22%3E%20%20%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C!--%20%E5%BA%95%E9%83%A8%E5%AF%BC%E8%88%AA%E6%A0%8F%E9%A2%9C%E8%89%B2%20--%3E%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Citem%20name%3D%22android%3AnavigationBarColor%22%3E%234876FF%3C%2Fitem%3E%20%20%0A%20%20%20%20%20%20%20%20%3C%2Fstyle%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<style>" title="<style>" />  
      
    </resources>

设置好主题的下一步工作:
在xml的layout中定义一个Toolbar:

/layout/toolbar.xml

    <?xml version="1.0" encoding="utf-8"?>  
    <android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"  
        xmlns:app="http://schemas.android.com/apk/res/com.example.toolbar"  
        android:id="@+id/toolbar"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:background="?attr/colorPrimary"  
        android:minHeight="?attr/actionBarSize"  
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"  
        app:theme="@style/ThemeOverlay.AppCompat.ActionBar" >  
      
    </android.support.v7.widget.Toolbar>

我们把toolbar作为一个独立的布局xml,方便在其他布局里include进去。可以看到我们在这里是可以设置Toolbar的属性的,初上面的外还有以下的属性,都是见名知意的就不一一说明了。

然后在activity的布局里把它include进去就行了,当然一般把它放到最上面了,有需要你是可以把它放到中间、底部或其它位置的,可见它的自由度是很高的。在下一步呢就到代码了,在onCreate中:

    mToolbar = (Toolbar) findViewById(R.id.toolbar);  
    // toolbar.setLogo(R.drawable.ic_launcher);  
    mToolbar.setTitle("Rocko");// 标题的文字需在setSupportActionBar之前,不然会无效  
    // toolbar.setSubtitle("副标题");  
    setSupportActionBar(mToolbar);  
    /* 这些通过ActionBar来设置也是一样的,注意要在setSupportActionBar(toolbar);之后,不然就报错了 */  
    // getSupportActionBar().setTitle("标题");  
    // getSupportActionBar().setSubtitle("副标题");  
    // getSupportActionBar().setLogo(R.drawable.ic_launcher);  
      
    /* 菜单的监听可以在toolbar里设置,也可以像ActionBar那样,通过Activity的onOptionsItemSelected回调方法来处理 */  
    mToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {  
        @Override  
        public boolean onMenuItemClick(MenuItem item) {  
            switch (item.getItemId()) {  
            case R.id.action_settings:  
                Toast.makeText(MainActivity.this, "action_settings", 0).show();  
                break;  
            case R.id.action_share:  
                Toast.makeText(MainActivity.this, "action_share", 0).show();  
                break;  
            default:  
                break;  
            }  
            return true;  
        }  
    });

上面关键的一点就是setSupportActionBar(mToolbar);把Toolbar当做ActionBar给设置了。menu还是可以像ActionBar一样用和处理的:

res/menu/main.xml

这一步时候程序的样子:

 PS.  Genymotion可以用5.0的模拟器了

可以感觉到这样是不是和ActionBar没什么区别呢。诶,左边的菜单图标怎么出来的呢,其实上面还没处理到,他就是Navigation drawer了,使用新版本的v4、v7库的drawer明显的一点是它带了一个酷酷的交互动画(请看最后的gif图)。那么使用Toolbar之后又怎么去在Toolbar中使用drawer呢。下面当然也是跟着代码来.

/layout/activity_main.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
        xmlns:tools="http://schemas.android.com/tools"  
        android:layout_width="match_parent"  
        android:layout_height="match_parent"  
        android:orientation="vertical"  
        tools:context="com.example.toolbar.MainActivity" >  
      
        <include layout="@layout/toolbar" />  
      
        <android.support.v4.widget.DrawerLayout  
            android:id="@+id/drawer"  
            android:layout_width="match_parent"  
            android:layout_height="match_parent" >  
      
            <!-- 内容界面 -->  
      
            <LinearLayout  
                android:layout_width="match_parent"  
                android:layout_height="match_parent"  
                android:orientation="vertical" >  
      
                <com.example.toolbar.widget.PagerSlidingTabStrip  
                    android:id="@+id/tabs"  
                    android:layout_width="match_parent"  
                    android:layout_height="48dip" >  
                </com.example.toolbar.widget.PagerSlidingTabStrip>  
      
                <android.support.v4.view.ViewPager  
                    android:id="@+id/pager"  
                    android:layout_width="match_parent"  
                    android:layout_height="match_parent" >  
                </android.support.v4.view.ViewPager>  
            </LinearLayout>  
      
            <!-- 侧滑菜单内容 -->  
      
            <LinearLayout  
                android:id="@+id/drawer_view"  
                android:layout_width="match_parent"  
                android:layout_height="match_parent"  
                android:layout_gravity="start"  
                android:background="@drawable/drawer"  
                android:orientation="vertical"  
                android:padding="8dp" >  
      
                <TextView  
                    android:layout_width="match_parent"  
                    android:layout_height="match_parent" />  
            </LinearLayout>  
        </android.support.v4.widget.DrawerLayout>  
      
    </LinearLayout>

Pager的东西可以先忽略,后面会说到。侧滑菜单的内容为简单起见直接先用图片来演示了。可以看到布局的设置大同小异,不同点在代码中:

    getSupportActionBar().setDisplayHomeAsUpEnabled(true);  
    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer);  
    mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, mToolbar, R.string.drawer_open,  
            R.string.drawer_close);  
    mDrawerToggle.syncState();  
    mDrawerLayout.setDrawerListener(mDrawerToggle);

要是需要把drawer覆盖toolbar怎么办呢?需要稍微调整一下界面的布局位置就行了,效果就不贴上来了(脑补,或者改下源码的setContentView运行):

    <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"  
        xmlns:tools="http://schemas.android.com/tools"  
        android:id="@+id/drawer"  
        android:layout_width="match_parent"  
        android:layout_height="match_parent"  
        android:fitsSystemWindows="true" >  
      
        <LinearLayout  
            android:layout_width="match_parent"  
            android:layout_height="match_parent"  
            android:orientation="vertical"  
            tools:context="com.example.toolbar.MainActivity" >  
      
            <include layout="@layout/toolbar" />  
            <!-- 内容界面 -->  
      
            <LinearLayout  
                android:layout_width="match_parent"  
                android:layout_height="match_parent"  
                android:background="@drawable/content"  
                android:orientation="vertical" >  
      
                <com.example.toolbar.widget.PagerSlidingTabStrip  
                    android:id="@+id/tabs"  
                    android:layout_width="match_parent"  
                    android:layout_height="48dip"  
                    android:visibility="invisible" >  
                </com.example.toolbar.widget.PagerSlidingTabStrip>  
      
                <android.support.v4.view.ViewPager  
                    android:id="@+id/pager"  
                    android:layout_width="match_parent"  
                    android:layout_height="match_parent"  
                    android:visibility="invisible" >  
                </android.support.v4.view.ViewPager>  
            </LinearLayout>  
        </LinearLayout>  
        <!-- 侧滑菜单内容 -->  
      
        <LinearLayout  
            android:id="@+id/drawer_view"  
            android:layout_width="match_parent"  
            android:layout_height="match_parent"  
            android:layout_gravity="start"  
            android:background="@drawable/drawer"  
            android:orientation="vertical"  
            android:clickable="true"  
            android:padding="8dp" >  
      
            <TextView  
                android:layout_width="match_parent"  
                android:layout_height="match_parent" />  
        </LinearLayout>  
      
    </android.support.v4.widget.DrawerLayout>

做这里时发现拉出菜单后还是可以点击Toggle按钮的,解决方法时把侧滑的布局设置为clickable=”true”。关于侧滑菜单需不需要的覆盖Toolbar的问题好像从Google提供的例子来看两者都有。我想既然它做出这个Toggle按钮的动画来的话如果覆盖了不就没有意义了?或者还有其它考虑?暂时我们看着Google Play来就行,新版Play的是没有覆盖上去的。

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注