IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    [原]Android 5.x Theme 与 ToolBar 实战

    lmj623565791发表于 2015-04-27 09:50:39
    love 0

    转载请标明出处:
    http://blog.csdn.net/lmj623565791/article/details/45303349;
    本文出自:【张鸿洋的博客】

    1、概述

    随着Material Design的逐渐的普及,业内也有很多具有分享精神的伙伴翻译了material design specification ,中文翻译地址:Material Design 中文版。So,我们也开始Android 5.x相关的blog,那么首先了解的当然是其主题的风格以及app bar。

    当然,5.x普及可能还需要一段时间,所以我们还是尽可能的去使用兼容包支持低版本的设备。

    ps:本博客使用:

    • compileSdkVersion 22
    • buildToolsVersion “22.0.1”
    • compile ‘com.android.support:appcompat-v7:22.1.1’
    • 忽然发现ActionBarActivity被弃用了,推荐使用AppCompatActivity,相关blog地址:Android Support Library 22.1

    2、Material Design的Theme

    md的主题有:

    • @android:style/Theme.Material (dark version)
    • @android:style/Theme.Material.Light (light version)
    • @android:style/Theme.Material.Light.DarkActionBar

    与之对应的Compat Theme:

    • Theme.AppCompat
    • Theme.AppCompat.Light
    • Theme.AppCompat.Light.DarkActionBar

    (1)个性化 Color Palette

    我们可以根据我们的app的风格,去定制Color Palette(调色板),重点有以下几个属性:

    <resources>
        
        <style name="AppBaseTheme" parent="Theme.AppCompat">
    
            <!<span class="hljs-tag">--</span> <span class="hljs-tag">customize</span> <span class="hljs-tag">the</span> <span class="hljs-tag">color</span> <span class="hljs-tag">palette</span> <span class="hljs-tag">--</span>>
            <<span class="hljs-tag">item</span> <span class="hljs-tag">name</span>="<span class="hljs-tag">colorPrimary</span>"><span class="hljs-at_rule">@<span class="hljs-keyword">color/material_blue_500</item></span>
            <item name=<span class="hljs-string">"colorPrimaryDark"</span>>@color/material_blue_700</item>
            <item name=<span class="hljs-string">"colorAccent"</span>>@color/material_green_A200</item>
        </span></span><span class="hljs-tag"></<span class="hljs-title">style</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">resources</span>></span>
    </code></pre>
    
    <ul>
    <li>colorPrimary 对应ActionBar的颜色。</li>
    <li>colorPrimaryDark对应状态栏的颜色</li>
    <li>colorAccent 对应EditText编辑时、RadioButton选中、CheckBox等选中时的颜色。</li>
    </ul>
    
    <p>与之对应的图:</p>
    
    <p><img src="http://img.blog.csdn.net/20150427034747930" width="320px"  /></p>
    
    <blockquote>
      <p>metarial design的theme允许我们去设置status bar的颜色,如果你项目的最小支持版本为5.0,那么你可以使用<code>android:Theme.Material</code>,设置<code>android:statusBarColor</code>。当然了这种情况目前来说比较少,所以我们多数使用的是<code>Theme.AppCompat</code>,通过设置<code>android:colorPrimaryDark.</code>来设置status bar颜色。(ps:默认情况下,<code>android:statusBarColor</code>的值继承自<code>android:colorPrimaryDark</code>).</p>
    </blockquote>
    
    <p>对于5.0以下的设备,目前<code>colorPrimaryDark</code>无法去个性化状态栏的颜色;底部的navagationBar可能也不一样,更别说设置颜色了。</p>
    
    <p>下面写个简单的Demo去测试下。</p>
    
    <h4 id="2测试效果">(2)测试效果</h4>
    
    <p>values/styles.xml</p>
    
    
    
    <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">resources</span>></span>
        <span class="hljs-comment"><!-- Base application theme. --></span>
    
        <span class="hljs-tag"><<span class="hljs-title">style</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"AppTheme"</span> <span class="hljs-attribute">parent</span>=<span class="hljs-value">"AppBaseTheme"</span>></span><span class="css">
    
    
        </span><span class="hljs-tag"></<span class="hljs-title">style</span>></span>
    
        <span class="hljs-tag"><<span class="hljs-title">style</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"AppBaseTheme"</span> <span class="hljs-attribute">parent</span>=<span class="hljs-value">"Theme.AppCompat.Light"</span>></span><span class="css">
    
            <!<span class="hljs-tag">--</span> <span class="hljs-tag">customize</span> <span class="hljs-tag">the</span> <span class="hljs-tag">color</span> <span class="hljs-tag">palette</span> <span class="hljs-tag">--</span>>
            <<span class="hljs-tag">item</span> <span class="hljs-tag">name</span>="<span class="hljs-tag">colorPrimary</span>"><span class="hljs-at_rule">@<span class="hljs-keyword">color/material_blue_500</item></span>
            <item name=<span class="hljs-string">"colorPrimaryDark"</span>>@color/material_blue_700</item>
            <item name=<span class="hljs-string">"colorAccent"</span>>@color/material_green_A200</item>
    
        </span></span><span class="hljs-tag"></<span class="hljs-title">style</span>></span>
    
    
    <span class="hljs-tag"></<span class="hljs-title">resources</span>></span>
    
    </code></pre>
    
    <p>values-v21/styles.xml</p>
    
    
    
    <pre class="prettyprint"><code class=" hljs xml"><span class="hljs-tag"><<span class="hljs-title">resources</span>></span>
    
        <span class="hljs-tag"><<span class="hljs-title">style</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"AppTheme"</span> <span class="hljs-attribute">parent</span>=<span class="hljs-value">"AppBaseTheme"</span>></span><span class="css">
            <<span class="hljs-tag">item</span> <span class="hljs-tag">name</span>="<span class="hljs-tag">android</span><span class="hljs-pseudo">:statusBarColor"</span>><span class="hljs-at_rule">@<span class="hljs-keyword">color/material_blue_700</item></span>
        </span></span><span class="hljs-tag"></<span class="hljs-title">style</span>></span>
    
    
    <span class="hljs-tag"></<span class="hljs-title">resources</span>></span>
    </code></pre>
    
    <p>values/colors.xml</p>
    
    
    
    <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-pi"><?xml version="1.0" encoding="utf-8"?></span>
    <span class="hljs-tag"><<span class="hljs-title">resources</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">color</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"material_blue_500"</span>></span>#009688<span class="hljs-tag"></<span class="hljs-title">color</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">color</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"material_blue_700"</span>></span>#00796B<span class="hljs-tag"></<span class="hljs-title">color</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">color</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"material_green_A200"</span>></span>#FD87A9<span class="hljs-tag"></<span class="hljs-title">color</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">resources</span>></span>
    </code></pre>
    
    <p><img src="http://img.blog.csdn.net/20150427034817149" width="320px"  /></p>
    
    <p>可以看到:colorAccent也就是图中的粉色,EditText正在输入时,RadioButton选中时的颜色。ps:5.0以下设备,状态栏颜色不会变化。</p>
    
    
    
    <h3 id="3toolbar的使用">3、ToolBar的使用</h3>
    
    <p>众所周知,在使用ActionBar的时候,一堆的问题:这个文字能不能定制,位置能不能改变,图标的间距怎么控制神马的,由此暴露出了ActionBar设计的不灵活。为此官方提供了ToolBar,并且提供了supprot library用于向下兼容。Toolbar之所以灵活,是因为它其实就是一个ViewGroup,我们在使用的时候和普通的组件一样,在布局文件中声明。</p>
    
    
    
    <h4 id="1toolbar的引入">(1)ToolBar的引入</h4>
    
    <p>既然准备用ToolBar,首先看看如何将其引入到app中。</p>
    
    
    
    <h5 id="1隐藏原本的actionbar">1)隐藏原本的ActionBar</h5>
    
    <p>隐藏可以通过修改我们继承的主题为:<code>Theme.AppCompat.Light.NoActionBar</code>,当然也可以通过设置以下属性完成:</p>
    
    
    
    <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">item</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"windowActionBar"</span>></span>false<span class="hljs-tag"></<span class="hljs-title">item</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">item</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"android:windowNoTitle"</span>></span>true<span class="hljs-tag"></<span class="hljs-title">item</span>></span></code></pre>
    
    <p>我们这里选择前者:</p>
    
    
    
    <pre class="prettyprint"><code class="language-xml hljs ">    <span class="hljs-tag"><<span class="hljs-title">style</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"AppBaseTheme"</span> <span class="hljs-attribute">parent</span>=<span class="hljs-value">"Theme.AppCompat.Light.NoActionBar"</span>></span><span class="css">
    
            <!<span class="hljs-tag">--</span> <span class="hljs-tag">customize</span> <span class="hljs-tag">the</span> <span class="hljs-tag">color</span> <span class="hljs-tag">palette</span> <span class="hljs-tag">--</span>>
            <<span class="hljs-tag">item</span> <span class="hljs-tag">name</span>="<span class="hljs-tag">colorPrimary</span>"><span class="hljs-at_rule">@<span class="hljs-keyword">color/material_blue_500</item></span>
            <item name=<span class="hljs-string">"colorPrimaryDark"</span>>@color/material_blue_700</item>
            <item name=<span class="hljs-string">"colorAccent"</span>>@color/material_green_A200</item>
    
        </span></span><span class="hljs-tag"></<span class="hljs-title">style</span>></span></code></pre>
    
    
    
    <h5 id="2在布局文件中声明">2)在布局文件中声明</h5>
    
    
    
    <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">LinearLayout</span> <span class="hljs-attribute">xmlns:android</span>=<span class="hljs-value">"http://schemas.android.com/apk/res/android"</span>
        <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span>
        <span class="hljs-attribute">android:orientation</span>=<span class="hljs-value">"vertical"</span>
        <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"match_parent"</span>
        <span class="hljs-attribute">xmlns:app</span>=<span class="hljs-value">"http://schemas.android.com/apk/res-auto"</span>></span>
    
        <span class="hljs-tag"><<span class="hljs-title">android.support.v7.widget.Toolbar
    </span>        <span class="hljs-attribute">android:id</span>=<span class="hljs-value">"@+id/id_toolbar"</span>
            <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"wrap_content"</span>
            <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span> /></span>
    
        <span class="hljs-tag"><<span class="hljs-title">android.support.v7.widget.GridLayout
    </span>        <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"wrap_content"</span>
            <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"wrap_content"</span>
            <span class="hljs-attribute">android:layout_gravity</span>=<span class="hljs-value">"center_horizontal"</span>
    
            <span class="hljs-attribute">app:useDefaultMargins</span>=<span class="hljs-value">"true"</span>
            <span class="hljs-attribute">app:columnCount</span>=<span class="hljs-value">"3"</span>></span>
    
    
            <span class="hljs-tag"><<span class="hljs-title">TextView
    </span>            <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"First Name:"</span>
                <span class="hljs-attribute">app:layout_gravity</span>=<span class="hljs-value">"right"</span> /></span>
    
            <span class="hljs-tag"><<span class="hljs-title">EditText
    </span>            <span class="hljs-attribute">android:ems</span>=<span class="hljs-value">"10"</span>
                <span class="hljs-attribute">app:layout_columnSpan</span>=<span class="hljs-value">"2"</span> /></span>
    
            <span class="hljs-tag"><<span class="hljs-title">TextView
    </span>            <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"Last Name:"</span>
    
                <span class="hljs-attribute">app:layout_column</span>=<span class="hljs-value">"0"</span>
                <span class="hljs-attribute">app:layout_gravity</span>=<span class="hljs-value">"right"</span> /></span>
    
            <span class="hljs-tag"><<span class="hljs-title">EditText
    </span>            <span class="hljs-attribute">android:ems</span>=<span class="hljs-value">"10"</span>
                <span class="hljs-attribute">app:layout_columnSpan</span>=<span class="hljs-value">"2"</span> /></span>
    
    
            <span class="hljs-tag"><<span class="hljs-title">TextView
    </span>            <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"Visit Type:"</span>
    
                <span class="hljs-attribute">app:layout_column</span>=<span class="hljs-value">"0"</span>
                <span class="hljs-attribute">app:layout_gravity</span>=<span class="hljs-value">"right"</span> /></span>
    
            <span class="hljs-tag"><<span class="hljs-title">RadioGroup</span> <span class="hljs-attribute">app:layout_columnSpan</span>=<span class="hljs-value">"2"</span>></span>
    
                <span class="hljs-tag"><<span class="hljs-title">RadioButton
    </span>                <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"wrap_content"</span>
                    <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"wrap_content"</span>
                    <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"Business"</span> /></span>
    
    
                <span class="hljs-tag"><<span class="hljs-title">RadioButton
    </span>                <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"wrap_content"</span>
                    <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"wrap_content"</span>
                    <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"Social"</span> /></span>
    
            <span class="hljs-tag"></<span class="hljs-title">RadioGroup</span>></span>
    
            <span class="hljs-tag"><<span class="hljs-title">Button
    </span>            <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"Ok"</span>
                <span class="hljs-attribute">app:layout_column</span>=<span class="hljs-value">"1"</span> /></span>
    
            <span class="hljs-tag"><<span class="hljs-title">Button
    </span>            <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"Cancel"</span>
                <span class="hljs-attribute">app:layout_column</span>=<span class="hljs-value">"2"</span> /></span>
    
        <span class="hljs-tag"></<span class="hljs-title">android.support.v7.widget.GridLayout</span>></span>
    
    <span class="hljs-tag"></<span class="hljs-title">LinearLayout</span>></span>
    </code></pre>
    
    <p>ok,这里我们也贴出来上面图片的效果的xml,使用GridLayout实现的,有兴趣的可以研究下。可以看到我们在布局文件中定义了ToolBar。</p>
    
    
    
    <h5 id="3代码中设定">3)代码中设定</h5>
    
    
    
    <pre class="prettyprint"><code class="language-java hljs "><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AppCompatActivity</span> {</span>
    
        <span class="hljs-annotation">@Override</span>
        <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span>(Bundle savedInstanceState) {
            <span class="hljs-keyword">super</span>.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            Toolbar toolbar = (Toolbar) findViewById(R.id.id_toolbar);
            setSupportActionBar(toolbar);
        }</code></pre>
    
    <p>ok,基本就是先隐藏ActionBar,然后在布局文件中声明,最后代码中设定一下。现在看一下效果图:</p>
    
    <p><img src="http://img.blog.csdn.net/20150427034731419" width="320px"  /></p>
    
    <p>可以看到我们的ToolBar显示出来了,默认的Title为ToolBar,但是这个样式实在是不敢恭维,下面看我们如何定制它。</p>
    
    
    
    <h4 id="2定制toolbar">(2)定制ToolBar</h4>
    
    <p>首先给它一个nice的背景色,还记得前面的colorPrimary么,用于控制ActionBar的背景色的。当然这里我们的ToolBar就是一个普通的ViewGroup在布局中,所以我们直接使用background就好,值可以为:<code>?attr/colorPrimary</code>使用主题中定义的值。</p>
    
    <p>ToolBar中包含Nav Icon , Logo , Title , Sub Title , Menu Items 。</p>
    
    <p>我们可以通过代码设置上述ToolBar中的控件:</p>
    
    
    
    <pre class="prettyprint"><code class="language-java hljs "><span class="hljs-annotation">@Override</span>
        <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span>(Bundle savedInstanceState) {
            <span class="hljs-keyword">super</span>.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            Toolbar toolbar = (Toolbar) findViewById(R.id.id_toolbar);
    
            <span class="hljs-comment">// App Logo</span>
            toolbar.setLogo(R.mipmap.ic_launcher);
            <span class="hljs-comment">// Title</span>
            toolbar.setTitle(<span class="hljs-string">"App Title"</span>);
            <span class="hljs-comment">// Sub Title</span>
            toolbar.setSubtitle(<span class="hljs-string">"Sub title"</span>);
    
            setSupportActionBar(toolbar);
            <span class="hljs-comment">//Navigation Icon</span>
            toolbar.setNavigationIcon(R.drawable.ic_toc_white_24dp);
        }
    </code></pre>
    
    <p><code>可选方案</code>当然如果你喜欢,也可以在布局文件中去设置部分属性:</p>
    
    
    
    <pre class="prettyprint"><code class="language-xml hljs "> <span class="hljs-tag"><<span class="hljs-title">android.support.v7.widget.Toolbar
    </span>        <span class="hljs-attribute">android:id</span>=<span class="hljs-value">"@+id/id_toolbar"</span>
            <span class="hljs-attribute">app:title</span>=<span class="hljs-value">"App Title"</span>
            <span class="hljs-attribute">app:subtitle</span>=<span class="hljs-value">"Sub Title"</span>
            <span class="hljs-attribute">app:navigationIcon</span>=<span class="hljs-value">"@drawable/ic_toc_white_24dp"</span>
            <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"wrap_content"</span>
            <span class="hljs-attribute">android:minHeight</span>=<span class="hljs-value">"?attr/actionBarSize"</span>
            <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span>
            <span class="hljs-attribute">android:background</span>=<span class="hljs-value">"?attr/colorPrimary"</span>/></span></code></pre>
    
    <p>至于Menu Item,依然支持在menu/menu_main.xml去声明,然后复写<code>onCreateOptionsMenu</code>和<code>onOptionsItemSelected</code>即可。</p>
    
    <p><code>可选方案</code>也可以通过<code>toolbar.setOnMenuItemClickListener</code>实现点击MenuItem的回调。</p>
    
    
    
    <pre class="prettyprint"><code class="language-java hljs ">  toolbar.setOnMenuItemClickListener(<span class="hljs-keyword">new</span> Toolbar.OnMenuItemClickListener() {
                <span class="hljs-annotation">@Override</span>
                <span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">onMenuItemClick</span>(MenuItem item) {
                    <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
                }
            });</code></pre>
    
    <p>效果图:</p>
    
    <p><img src="http://img.blog.csdn.net/20150427034759686" width="320px"  /></p>
    
    <p>关于字体的样式,可以在布局文件设置属性<code>app:titleTextAppearance</code>、<code>app:subtitleTextAppearance</code>或者代码<code>setTitleTextAppearance</code>、<code>setSubTitleTextAppearance</code>设置。</p>
    
    
    
    <h3 id="4实战">4、实战</h3>
    
    <p>简单介绍了Toolbar以后呢,我们决定做点有意思的事,整合ToolBar,DrawerLayout,ActionBarDrawerToggle写个实用的例子,效果图如下:</p>
    
    <p><img src="http://img.blog.csdn.net/20150427034930126" width="320px"  /></p>
    
    <p>ok,简单处理了下横纵屏幕的切换。接下来看代码实现。</p>
    
    <ul>
    <li>大致思路</li>
    </ul>
    
    <p>整体实现还是比较容易的,首先需要引入DrawerLayout(如果你对DrawerLayout不了解,可以参考  <br  />
    <a href="http://blog.csdn.net/lmj623565791/article/details/41531475">Android DrawerLayout 高仿QQ5.2双向侧滑菜单</a>),然后去初始化<code>mActionBarDrawerToggle</code>,mActionBarDrawerToggle实际上是个<code>DrawerListener</code>,设置<code>mDrawerLayout.setDrawerListener(mActionBarDrawerToggle);</code>就已经能够实现上面点击Nav Icon切换效果了。当然了细节还是挺多的。</p>
    
    <p>我们的效果图,左侧菜单为Fragment,内容区域为Fragment,点击左侧菜单切换内容区域的Fragment即可。关于Fragment的知识,可以查看:<a href="http://blog.csdn.net/lmj623565791/article/details/42628537">Android Fragment 你应该知道的一切</a></p>
    
    <ul>
    <li>布局文件 <br  />
    activity_main.xml</li>
    </ul>
    
    
    
    <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">LinearLayout</span> <span class="hljs-attribute">xmlns:android</span>=<span class="hljs-value">"http://schemas.android.com/apk/res/android"</span>
        <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span>
        <span class="hljs-attribute">android:orientation</span>=<span class="hljs-value">"vertical"</span>
        <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"match_parent"</span>
        <span class="hljs-attribute">android:background</span>=<span class="hljs-value">"#ffffffff"</span>
        <span class="hljs-attribute">xmlns:app</span>=<span class="hljs-value">"http://schemas.android.com/apk/res-auto"</span>></span>
    
        <span class="hljs-comment"><!--app:subtitle="Sub Title"--></span>
        <span class="hljs-tag"><<span class="hljs-title">android.support.v7.widget.Toolbar
    </span>        <span class="hljs-attribute">android:id</span>=<span class="hljs-value">"@+id/id_toolbar"</span>
            <span class="hljs-attribute">app:title</span>=<span class="hljs-value">"App Title"</span>
            <span class="hljs-attribute">app:navigationIcon</span>=<span class="hljs-value">"@drawable/ic_toc_white_24dp"</span>
            <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"wrap_content"</span>
            <span class="hljs-attribute">android:minHeight</span>=<span class="hljs-value">"?attr/actionBarSize"</span>
            <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span>
            <span class="hljs-attribute">android:background</span>=<span class="hljs-value">"?attr/colorPrimary"</span> /></span>
    
        <span class="hljs-tag"><<span class="hljs-title">android.support.v4.widget.DrawerLayout
    </span>        <span class="hljs-attribute">android:id</span>=<span class="hljs-value">"@+id/id_drawerlayout"</span>
            <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span>
            <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"match_parent"</span>></span>
    
            <span class="hljs-tag"><<span class="hljs-title">FrameLayout
    </span>            <span class="hljs-attribute">android:id</span>=<span class="hljs-value">"@+id/id_content_container"</span>
                <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span>
                <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"match_parent"</span>></span><span class="hljs-tag"></<span class="hljs-title">FrameLayout</span>></span>
    
            <span class="hljs-tag"><<span class="hljs-title">FrameLayout
    </span>            <span class="hljs-attribute">android:id</span>=<span class="hljs-value">"@+id/id_left_menu_container"</span>
                <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span>
                <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"match_parent"</span>
                <span class="hljs-attribute">android:layout_gravity</span>=<span class="hljs-value">"left"</span>
                <span class="hljs-attribute">android:background</span>=<span class="hljs-value">"#ffffffff"</span>></span><span class="hljs-tag"></<span class="hljs-title">FrameLayout</span>></span>
    
    
        <span class="hljs-tag"></<span class="hljs-title">android.support.v4.widget.DrawerLayout</span>></span>
    
    
    <span class="hljs-tag"></<span class="hljs-title">LinearLayout</span>></span>
    
    </code></pre>
    
    <p>DrawerLayout中包含两个FrameLayout,分别放内容区域和左侧菜单的Fragment。</p>
    
    <ul>
    <li>LeftMenuFragment</li>
    </ul>
    
    
    
    <pre class="prettyprint"><code class="language-java hljs "><span class="hljs-keyword">package</span> com.zhy.toolbar;
    
    <span class="hljs-keyword">import</span> android.os.Bundle;
    <span class="hljs-keyword">import</span> android.support.annotation.Nullable;
    <span class="hljs-keyword">import</span> android.support.v4.app.ListFragment;
    <span class="hljs-keyword">import</span> android.view.LayoutInflater;
    <span class="hljs-keyword">import</span> android.view.View;
    <span class="hljs-keyword">import</span> android.view.ViewGroup;
    <span class="hljs-keyword">import</span> android.widget.ListView;
    
    <span class="hljs-javadoc">/**
     * Created by zhy on 15/4/26.
     */</span>
    <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LeftMenuFragment</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ListFragment</span> {</span>
    
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> SIZE_MENU_ITEM = <span class="hljs-number">3</span>;
    
        <span class="hljs-keyword">private</span> MenuItem[] mItems = <span class="hljs-keyword">new</span> MenuItem[SIZE_MENU_ITEM];
    
        <span class="hljs-keyword">private</span> LeftMenuAdapter mAdapter;
    
        <span class="hljs-keyword">private</span> LayoutInflater mInflater;
    
        <span class="hljs-annotation">@Override</span>
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span>(@Nullable Bundle savedInstanceState) {
            <span class="hljs-keyword">super</span>.onCreate(savedInstanceState);
    
            mInflater = LayoutInflater.from(getActivity());
    
            MenuItem menuItem = <span class="hljs-keyword">null</span>;
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < SIZE_MENU_ITEM; i++) {
                menuItem = <span class="hljs-keyword">new</span> MenuItem(getResources().getStringArray(R.array.array_left_menu)[i], <span class="hljs-keyword">false</span>, R.drawable.music_36px, R.drawable.music_36px_light);
                mItems[i] = menuItem;
            }
        }
    
        <span class="hljs-annotation">@Override</span>
        <span class="hljs-keyword">public</span> View <span class="hljs-title">onCreateView</span>(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.onCreateView(inflater, container, savedInstanceState);
        }
    
        <span class="hljs-annotation">@Override</span>
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onViewCreated</span>(View view, @Nullable Bundle savedInstanceState) {
            <span class="hljs-keyword">super</span>.onViewCreated(view, savedInstanceState);
    
            setListAdapter(mAdapter = <span class="hljs-keyword">new</span> LeftMenuAdapter(getActivity(), mItems));
    
        }
    
        <span class="hljs-annotation">@Override</span>
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onListItemClick</span>(ListView l, View v, <span class="hljs-keyword">int</span> position, <span class="hljs-keyword">long</span> id) {
            <span class="hljs-keyword">super</span>.onListItemClick(l, v, position, id);
    
            <span class="hljs-keyword">if</span> (mMenuItemSelectedListener != <span class="hljs-keyword">null</span>) {
                mMenuItemSelectedListener.menuItemSelected(((MenuItem) getListAdapter().getItem(position)).text);
            }
    
            mAdapter.setSelected(position);
    
        }
    
    
        <span class="hljs-comment">//选择回调的接口</span>
        <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">OnMenuItemSelectedListener</span> {</span>
            <span class="hljs-keyword">void</span> menuItemSelected(String title);
        }
        <span class="hljs-keyword">private</span> OnMenuItemSelectedListener mMenuItemSelectedListener;
    
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setOnMenuItemSelectedListener</span>(OnMenuItemSelectedListener menuItemSelectedListener) {
            <span class="hljs-keyword">this</span>.mMenuItemSelectedListener = menuItemSelectedListener;
        }
    
    
    
    }
    </code></pre>
    
    <p>继承自ListFragment,主要用于展示各个Item,提供了一个选择Item的回调,这个需要在Activity中去注册处理。</p>
    
    <ul>
    <li>LeftMenuAdapter</li>
    </ul>
    
    
    
    <pre class="prettyprint"><code class="language-java hljs "><span class="hljs-keyword">package</span> com.zhy.toolbar;
    
    <span class="hljs-keyword">import</span> android.content.Context;
    <span class="hljs-keyword">import</span> android.graphics.Color;
    <span class="hljs-keyword">import</span> android.view.LayoutInflater;
    <span class="hljs-keyword">import</span> android.view.View;
    <span class="hljs-keyword">import</span> android.view.ViewGroup;
    <span class="hljs-keyword">import</span> android.widget.ArrayAdapter;
    <span class="hljs-keyword">import</span> android.widget.ImageView;
    <span class="hljs-keyword">import</span> android.widget.TextView;
    
    <span class="hljs-javadoc">/**
     * Created by zhy on 15/4/26.
     */</span>
    <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LeftMenuAdapter</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ArrayAdapter</span><<span class="hljs-title">MenuItem</span>> {</span>
    
    
        <span class="hljs-keyword">private</span> LayoutInflater mInflater;
    
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> mSelected;
    
    
        <span class="hljs-keyword">public</span> <span class="hljs-title">LeftMenuAdapter</span>(Context context, MenuItem[] objects) {
            <span class="hljs-keyword">super</span>(context, -<span class="hljs-number">1</span>, objects);
    
            mInflater = LayoutInflater.from(context);
    
        }
    
        <span class="hljs-annotation">@Override</span>
        <span class="hljs-keyword">public</span> View <span class="hljs-title">getView</span>(<span class="hljs-keyword">int</span> position, View convertView, ViewGroup parent) {
    
    
            <span class="hljs-keyword">if</span> (convertView == <span class="hljs-keyword">null</span>) {
                convertView = mInflater.inflate(R.layout.item_left_menu, parent, <span class="hljs-keyword">false</span>);
            }
    
            ImageView iv = (ImageView) convertView.findViewById(R.id.id_item_icon);
            TextView title = (TextView) convertView.findViewById(R.id.id_item_title);
            title.setText(getItem(position).text);
            iv.setImageResource(getItem(position).icon);
            convertView.setBackgroundColor(Color.TRANSPARENT);
    
            <span class="hljs-keyword">if</span> (position == mSelected) {
                iv.setImageResource(getItem(position).iconSelected);
                convertView.setBackgroundColor(getContext().getResources().getColor(R.color.state_menu_item_selected));
            }
    
            <span class="hljs-keyword">return</span> convertView;
        }
    
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setSelected</span>(<span class="hljs-keyword">int</span> position) {
            <span class="hljs-keyword">this</span>.mSelected = position;
            notifyDataSetChanged();
        }
    
    
    }
    
    
    <span class="hljs-keyword">package</span> com.zhy.toolbar;
    
    <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MenuItem</span> {</span>
    
        <span class="hljs-keyword">public</span> <span class="hljs-title">MenuItem</span>(String text, <span class="hljs-keyword">boolean</span> isSelected, <span class="hljs-keyword">int</span> icon, <span class="hljs-keyword">int</span> iconSelected) {
            <span class="hljs-keyword">this</span>.text = text;
            <span class="hljs-keyword">this</span>.isSelected = isSelected;
            <span class="hljs-keyword">this</span>.icon = icon;
            <span class="hljs-keyword">this</span>.iconSelected = iconSelected;
        }
    
        <span class="hljs-keyword">boolean</span> isSelected;
        String text;
        <span class="hljs-keyword">int</span> icon;
        <span class="hljs-keyword">int</span> iconSelected;
    }
    </code></pre>
    
    <p>Adapter没撒说的~~提供了一个setSection方法用于设置选中Item的样式什么的。 <br  />
    接下来看ContentFragment,仅仅只是一个TextView而已,所以代码也比较easy。</p>
    
    
    
    <pre class="prettyprint"><code class="language-java hljs "><span class="hljs-keyword">package</span> com.zhy.toolbar;
    
    <span class="hljs-keyword">import</span> android.os.Bundle;
    <span class="hljs-keyword">import</span> android.support.annotation.Nullable;
    <span class="hljs-keyword">import</span> android.support.v4.app.Fragment;
    <span class="hljs-keyword">import</span> android.text.TextUtils;
    <span class="hljs-keyword">import</span> android.view.Gravity;
    <span class="hljs-keyword">import</span> android.view.LayoutInflater;
    <span class="hljs-keyword">import</span> android.view.View;
    <span class="hljs-keyword">import</span> android.view.ViewGroup;
    <span class="hljs-keyword">import</span> android.widget.TextView;
    
    <span class="hljs-javadoc">/**
     * Created by zhy on 15/4/26.
     */</span>
    <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ContentFragment</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Fragment</span> {</span>
    
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String KEY_TITLE = <span class="hljs-string">"key_title"</span>;
        <span class="hljs-keyword">private</span> String mTitle;
    
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> ContentFragment <span class="hljs-title">newInstance</span>(String title) {
            ContentFragment fragment = <span class="hljs-keyword">new</span> ContentFragment();
            Bundle bundle = <span class="hljs-keyword">new</span> Bundle();
            bundle.putString(KEY_TITLE, title);
            fragment.setArguments(bundle);
            <span class="hljs-keyword">return</span> fragment;
        }
    
        <span class="hljs-annotation">@Nullable</span>
        <span class="hljs-annotation">@Override</span>
        <span class="hljs-keyword">public</span> View <span class="hljs-title">onCreateView</span>(LayoutInflater inflater, @Nullable ViewGroup container,
                                 @Nullable Bundle savedInstanceState) {
    
            TextView tv = <span class="hljs-keyword">new</span> TextView(getActivity());
            String title = (String) getArguments().get(KEY_TITLE);
            <span class="hljs-keyword">if</span> (!TextUtils.isEmpty(title))
            {
                tv.setGravity(Gravity.CENTER);
                tv.setTextSize(<span class="hljs-number">40</span>);
                tv.setText(title);
            }
    
            <span class="hljs-keyword">return</span> tv;
        }
    }
    </code></pre>
    
    <p>提供newInstance接收一个title参数去实例化它。</p>
    
    <p>最后就是我们的MainActivity了,负责管理各种Fragment。</p>
    
    <ul>
    <li>MainActivity</li>
    </ul>
    
    
    
    <pre class="prettyprint"><code class="language-java hljs "><span class="hljs-keyword">package</span> com.zhy.toolbar;
    
    <span class="hljs-keyword">import</span> android.os.Bundle;
    <span class="hljs-keyword">import</span> android.support.v4.app.Fragment;
    <span class="hljs-keyword">import</span> android.support.v4.app.FragmentManager;
    <span class="hljs-keyword">import</span> android.support.v4.app.FragmentTransaction;
    <span class="hljs-keyword">import</span> android.support.v4.widget.DrawerLayout;
    <span class="hljs-keyword">import</span> android.support.v7.app.ActionBarDrawerToggle;
    <span class="hljs-keyword">import</span> android.support.v7.app.AppCompatActivity;
    <span class="hljs-keyword">import</span> android.support.v7.widget.Toolbar;
    <span class="hljs-keyword">import</span> android.text.TextUtils;
    <span class="hljs-keyword">import</span> android.view.Gravity;
    
    <span class="hljs-keyword">import</span> java.util.List;
    
    
    <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AppCompatActivity</span> {</span>
    
        <span class="hljs-keyword">private</span> ActionBarDrawerToggle mActionBarDrawerToggle;
    
        <span class="hljs-keyword">private</span> DrawerLayout mDrawerLayout;
    
        <span class="hljs-keyword">private</span> Toolbar mToolbar;
    
        <span class="hljs-keyword">private</span> LeftMenuFragment mLeftMenuFragment;
        <span class="hljs-keyword">private</span> ContentFragment mCurrentFragment;
    
        <span class="hljs-keyword">private</span> String mTitle;
    
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String TAG = <span class="hljs-string">"com.zhy.toolbar"</span>;
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String KEY_TITLLE = <span class="hljs-string">"key_title"</span>;
    
        <span class="hljs-annotation">@Override</span>
        <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span>(Bundle savedInstanceState) {
            <span class="hljs-keyword">super</span>.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            initToolBar();
            initViews();
    
            <span class="hljs-comment">//恢复title</span>
            restoreTitle(savedInstanceState);
    
            FragmentManager fm = getSupportFragmentManager();
            <span class="hljs-comment">//查找当前显示的Fragment</span>
            mCurrentFragment = (ContentFragment) fm.findFragmentByTag(mTitle);
    
            <span class="hljs-keyword">if</span> (mCurrentFragment == <span class="hljs-keyword">null</span>) {
                mCurrentFragment = ContentFragment.newInstance(mTitle);
                fm.beginTransaction().add(R.id.id_content_container, mCurrentFragment, mTitle).commit();
            }
    
            mLeftMenuFragment = (LeftMenuFragment) fm.findFragmentById(R.id.id_left_menu_container);
            <span class="hljs-keyword">if</span> (mLeftMenuFragment == <span class="hljs-keyword">null</span>) {
                mLeftMenuFragment = <span class="hljs-keyword">new</span> LeftMenuFragment();
                fm.beginTransaction().add(R.id.id_left_menu_container, mLeftMenuFragment).commit();
            }
    
            <span class="hljs-comment">//隐藏别的Fragment,如果存在的话</span>
            List<Fragment> fragments = fm.getFragments();
            <span class="hljs-keyword">if</span> (fragments != <span class="hljs-keyword">null</span>)
    
                <span class="hljs-keyword">for</span> (Fragment fragment : fragments) {
                    <span class="hljs-keyword">if</span> (fragment == mCurrentFragment || fragment == mLeftMenuFragment) <span class="hljs-keyword">continue</span>;
                    fm.beginTransaction().hide(fragment).commit();
                }
    
            <span class="hljs-comment">//设置MenuItem的选择回调</span>
            mLeftMenuFragment.setOnMenuItemSelectedListener(<span class="hljs-keyword">new</span> LeftMenuFragment.OnMenuItemSelectedListener() {
                <span class="hljs-annotation">@Override</span>
                <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">menuItemSelected</span>(String title) {
    
                    FragmentManager fm = getSupportFragmentManager();
                    ContentFragment fragment = (ContentFragment) getSupportFragmentManager().findFragmentByTag(title);
                    <span class="hljs-keyword">if</span> (fragment == mCurrentFragment) {
                        mDrawerLayout.closeDrawer(Gravity.LEFT);
                        <span class="hljs-keyword">return</span>;
                    }
    
                    FragmentTransaction transaction = fm.beginTransaction();
                    transaction.hide(mCurrentFragment);
    
                    <span class="hljs-keyword">if</span> (fragment == <span class="hljs-keyword">null</span>) {
                        fragment = ContentFragment.newInstance(title);
                        transaction.add(R.id.id_content_container, fragment, title);
                    } <span class="hljs-keyword">else</span> {
                        transaction.show(fragment);
                    }
                    transaction.commit();
    
                    mCurrentFragment = fragment;
                    mTitle = title;
                    mToolbar.setTitle(mTitle);
                    mDrawerLayout.closeDrawer(Gravity.LEFT);
    
    
                }
            });
    
        }
    
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">restoreTitle</span>(Bundle savedInstanceState) {
            <span class="hljs-keyword">if</span> (savedInstanceState != <span class="hljs-keyword">null</span>)
                mTitle = savedInstanceState.getString(KEY_TITLLE);
    
            <span class="hljs-keyword">if</span> (TextUtils.isEmpty(mTitle)) {
                mTitle = getResources().getStringArray(
                        R.array.array_left_menu)[<span class="hljs-number">0</span>];
            }
    
            mToolbar.setTitle(mTitle);
        }
    
    
        <span class="hljs-annotation">@Override</span>
        <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onSaveInstanceState</span>(Bundle outState) {
            <span class="hljs-keyword">super</span>.onSaveInstanceState(outState);
            outState.putString(KEY_TITLLE, mTitle);
        }
    
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">initToolBar</span>() {
    
            Toolbar toolbar = mToolbar = (Toolbar) findViewById(R.id.id_toolbar);
            <span class="hljs-comment">// App Logo</span>
            <span class="hljs-comment">// toolbar.setLogo(R.mipmap.ic_launcher);</span>
            <span class="hljs-comment">// Title</span>
            toolbar.setTitle(getResources().getStringArray(R.array.array_left_menu)[<span class="hljs-number">0</span>]);
            <span class="hljs-comment">// Sub Title</span>
            <span class="hljs-comment">// toolbar.setSubtitle("Sub title");</span>
    
    <span class="hljs-comment">//        toolbar.setTitleTextAppearance();</span>
    
    
            setSupportActionBar(toolbar);
    
    
            <span class="hljs-comment">//Navigation Icon</span>
            toolbar.setNavigationIcon(R.drawable.ic_toc_white_24dp);
            <span class="hljs-comment">/*
            toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem item) {
                    return false;
                }
            });*/</span>
    
        }
    
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">initViews</span>() {
    
            mDrawerLayout = (DrawerLayout) findViewById(R.id.id_drawerlayout);
    
            mActionBarDrawerToggle = <span class="hljs-keyword">new</span> ActionBarDrawerToggle(<span class="hljs-keyword">this</span>,
                    mDrawerLayout, mToolbar, R.string.open, R.string.close);
            mActionBarDrawerToggle.syncState();
            mDrawerLayout.setDrawerListener(mActionBarDrawerToggle);
    
    
        }
    }
    </code></pre>
    
    <p>内容区域的切换是通过Fragment hide和show实现的,毕竟如果用replace,如果Fragment的view结构比较复杂,可能会有卡顿。当然了,注意每个Fragment占据的内存情况,如果内存不足,可能需要改变实现方式。 <br  />
    对于旋转屏幕或者应用长时间置于后台,Activity重建的问题,做了简单的处理。</p>
    
    <p>对了,写布局的时候,可以尽可能的去考虑 Material design 的规范。</p>
    
    
    
    <h3 id="5参考资料">5、参考资料</h3>
    
    <ul>
    <li><a href="https://developer.android.com/training/material/theme.html">Using the Material Theme</a></li>
    <li><a href="http://android-developers.blogspot.ca/2015/04/android-support-library-221.html">Android Support Library 22.1</a></li>
    <li><a href="http://www.google.com/design/spec/layout/metrics-keylines.html#">Material design</a></li>
    </ul>
    
    <blockquote>
      <p><a href="https://github.com/hongyangAndroid/Android_Blog_Demos/tree/master/toolbar_2015_04_26">源码下载</a> <br  />
      群号: 264950424 <br  />
      微信公众号:hongyangAndroid <br  />
      (欢迎关注,第一时间推送博文信息) <br  />
      <img src="http://img.my.csdn.net/uploads/201501/30/1422600516_2905.jpg" width="200px"  /></p>
    </blockquote>
                <div>
                    作者:lmj623565791 发表于2015/4/27 9:50:39 <a href="http://blog.csdn.net/lmj623565791/article/details/45303349">原文链接</a>
                </div>
                <div>
                阅读:8560 评论:40 <a href="http://blog.csdn.net/lmj623565791/article/details/45303349#comments" target="_blank">查看评论</a>
                </div>


沪ICP备19023445号-2号
友情链接