转载请标明出处:
http://blog.csdn.net/lmj623565791/article/details/45303349;
本文出自:【张鸿洋的博客】
随着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
md的主题有:
与之对应的Compat Theme:
我们可以根据我们的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>