本文原創(chuàng),轉(zhuǎn)載請(qǐng)注明出處。
歡迎關(guān)注我的 簡(jiǎn)書(shū) ,關(guān)注我的專題 Android Class 我會(huì)長(zhǎng)期堅(jiān)持為大家收錄簡(jiǎn)書(shū)上高質(zhì)量的Android相關(guān)博文。
寫(xiě)在前面:
因?yàn)閯倓偖厴I(yè)不久,面對(duì)編程世界中快速的知識(shí)更迭、龐大的知識(shí)體系,總覺(jué)得有心無(wú)力。想學(xué)的東西很多,想實(shí)踐的技術(shù)很多,但是感覺(jué)始終處在追追趕趕的狀態(tài)中。終于到了周末,拿出來(lái)這非常難得的大塊時(shí)間,做一次知識(shí)總結(jié)和技術(shù)實(shí)踐。
最近公司在重構(gòu)代碼,包括UI布局這塊也是,打算采用 DrawerLayout + Toolbar + Statusbar 這種形式展示出來(lái)。說(shuō)來(lái)慚愧,其實(shí)這三個(gè)組件出來(lái)很久了,也看過(guò)一些資料,不過(guò)忘記是從哪里看到過(guò)一句話,那就是“沒(méi)有敲過(guò)的代碼永遠(yuǎn)不屬于自己,并且也不要指望能找到一行都不需要修改的代碼”,我非常認(rèn)同這句話,所以今天要一步一步的實(shí)現(xiàn)上述界面及功能。
新建項(xiàng)目
我們來(lái)在最新版的 Android Studio 中,新建一個(gè) module ,項(xiàng)目類型選第一個(gè),帶默認(rèn) FloatingActionButton 的這個(gè)。
來(lái)看看默認(rèn)的 xml 布局的樣子:
布局文件的名字仍然是讓人熟悉的 activity_main ,不過(guò)港真...里面這些組件的名字也許有的是你第一次才見(jiàn)到,不過(guò)沒(méi)關(guān)系,我們一會(huì)來(lái)一個(gè)個(gè)的學(xué)習(xí)下它們,在此之前呢,來(lái)看看通過(guò) include 引入的這個(gè)布局 content_main 。
這個(gè)就好眼熟了對(duì)吧,以前我們創(chuàng)建一個(gè) empty activity 時(shí),這個(gè)布局就是 activity_main,現(xiàn)在它作為子布局,被 include 進(jìn)入了現(xiàn)在的 MainActivity 的布局中,這里想提一下,其實(shí) include 標(biāo)簽是可以作為布局優(yōu)化的一種方式,能讓你的代碼更整潔,便于管理。
現(xiàn)在運(yùn)行一下項(xiàng)目,看看整體的樣子如何:
如果你的公司項(xiàng)目上面的標(biāo)題欄部分還在手工寫(xiě),那未免也太跟不上時(shí)代了,原生的如此美觀,體驗(yàn)也如巧克力入口一般絲滑,所以趕緊換成原生的吧~
組件介紹
回過(guò)頭來(lái)看看新建項(xiàng)目中的我們可能還不認(rèn)識(shí)的組件,我來(lái)給大家做一個(gè)簡(jiǎn)略的介紹。
CoordinatorLayout
CoordinatorLayout 是一個(gè)頂層布局,繼承自 ViewGroup ,并且它可以通過(guò) Behavior 來(lái)控制子 View 的各種狀態(tài),來(lái)實(shí)現(xiàn)炫酷的效果,如果未來(lái)你想用 MD 的風(fēng)格來(lái)設(shè)計(jì)你的 app ,CoordinatorLayout 是你必須要接觸的。
CoordinatorLayout介紹及使用--張興業(yè)
AppBarLayout
AppBarLayout 是 MD 設(shè)計(jì)中,作為頂頭 Bar 的父布局出現(xiàn)的,它的存在可以實(shí)現(xiàn)多種炫酷的效果,這里不再詳細(xì)描述,需要使用自行查詢。
Toolbar
Toolbar 本身是代替 ActionBar 出現(xiàn)的控件,具有更靈活,可定制性更強(qiáng)的屬性,如果你的 app 需要一個(gè)導(dǎo)航欄,那目前 Toolbar 就是不二之選,Toolbar 也是我們今天的主角之一。
搭建 Toolbar
千里之行,始于足下,我們最先來(lái)搭建 Toolbar 好了。
在此之前一定要記住,如果想使用這些組件并且向下兼容它們,要在 gradle 文件中引入兩個(gè)必要的庫(kù):
compile 'com.android.support:appcompat-v7:24.2.0'
compile 'com.android.support:design:24.2.0'
效果很簡(jiǎn)單,來(lái)看看gif圖:
首先我們?cè)?layout 文件夾下 新建一個(gè) xml 文件,名字叫:common_toolbar
代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:toolbar="http://schemas.android.com/apk/res-auto"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
toolbar:title="@string/author_name"
toolbar:navigationIcon="@mipmap/ic_toolbar_navigation"
app:popupTheme="@style/AppTheme.PopupOverlay">
</android.support.v7.widget.Toolbar>
接下來(lái)解釋一下屬性
為了防止我們?cè)O(shè)置 toolbar 的屬性無(wú)效,需要加上自定義的命名控件:
xmlns:toolbar="http://schemas.android.com/apk/res-auto"
這樣在 xml 中設(shè)置 toolbar:title
toolbar:navigationIcon
等才會(huì)生效(這是一個(gè)無(wú)愛(ài)的 bug)
toolbar:title
是上面的 Melo 字樣,代表 Toolbar 的標(biāo)題
toolbar:navigationIcon
是 Melo 左側(cè)的抽屜按鈕,一會(huì)我們通過(guò)它來(lái)點(diǎn)開(kāi)抽屜
接下來(lái)配置 Toolbar 右側(cè)三個(gè)點(diǎn)的菜單
在 menu 文件夾下 創(chuàng)建 menu_main.xml,代碼如下:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.melo.blog.wigetdemo.MainActivity">
<item
android:id="@+id/action_settings"
android:orderInCategory="1"
android:title="@string/action_settings"
app:showAsAction="never" />
<item
android:id="@+id/action_about"
android:orderInCategory="2"
android:title="@string/action_about"
app:showAsAction="never" />
<item
android:id="@+id/action_share"
android:orderInCategory="3"
android:title="@string/action_share"
app:showAsAction="never" />
<item
android:id="@+id/action_like"
android:orderInCategory="4"
android:title="@string/action_like"
app:showAsAction="never" />
<item
android:id="@+id/action_collect"
android:orderInCategory="5"
android:title="@string/action_collect"
app:showAsAction="never" />
</menu>
這個(gè)沒(méi)什么太多介紹的,不懂的屬性自行查詢一下就可以解了。
將 Toolbar include 進(jìn) activity_main 的布局中:
接著 MainActivity 中尋找 Toolbar ,并且為右上方菜單設(shè)置點(diǎn)擊事件:
package com.melo.blog.wigetdemo;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements Toolbar.OnMenuItemClickListener {
private Toolbar toolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initView();
initListener();
}
private void initView() {
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.inflateMenu(R.menu.menu_main);
}
private void initListener() {
toolbar.setOnMenuItemClickListener(this);
}
@Override
public boolean onMenuItemClick(MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.action_settings:
Toast.makeText(this, getResources().getString(R.string.action_settings), Toast.LENGTH_SHORT).show();
break;
case R.id.action_about:
Toast.makeText(this, getResources().getString(R.string.action_about), Toast.LENGTH_SHORT).show();
break;
case R.id.action_collect:
Toast.makeText(this, getResources().getString(R.string.action_collect), Toast.LENGTH_SHORT).show();
break;
case R.id.action_like:
Toast.makeText(this, getResources().getString(R.string.action_like), Toast.LENGTH_SHORT).show();
break;
case R.id.action_share:
Toast.makeText(this, getResources().getString(R.string.action_share), Toast.LENGTH_SHORT).show();
break;
}
return false;
}
}
是不是很簡(jiǎn)單清晰呢?我們關(guān)于 Toolbar 來(lái)總結(jié)幾點(diǎn)需要注意的地方:
- 自定義
xmlns:toolbar
否則在 xml 設(shè)置屬性會(huì)失效。 - 菜單項(xiàng)的條目背景和顏色,均可以在
app:popupTheme="@style/AppTheme.PopupOverlay"
style中設(shè)置:
菜單配置 - MainActivity 的主題應(yīng)該為
AppTheme.NoActionBar
,或者在代碼中動(dòng)態(tài)地調(diào)用supportRequestWindowFeature(Window.FEATURE_NO_TITLE)
- 關(guān)于 Toolbar 的屬性還有很多,并且都可定制化(顏色或者大小),如果有需要你甚至可以在上面添加你的自定義 View ,如有需要,請(qǐng)留言或者查閱文檔。
搭建 DrawerLayout
DrawerLayout 是 Google 推出的官方組件,用來(lái)實(shí)現(xiàn)側(cè)滑欄抽屜的效果:
相信非常多的人已經(jīng)熟悉 DrawerLayout 的使用了,我們應(yīng)該注意以下兩點(diǎn):
1.DrawerLayout 的第一個(gè)子 View 必須是當(dāng)抽屜沒(méi)有打開(kāi)時(shí)候的默認(rèn)布局。
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawerlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.melo.blog.wigetdemo.MainActivity">
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<include layout="@layout/common_toolbar" />
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main" />
</android.support.design.widget.CoordinatorLayout>
<include layout="@layout/common_drawer" />
</android.support.v4.widget.DrawerLayout>
在我的 Demo 中,CoordinatorLayout 是 DrawerLayout 的第一個(gè)字 View ,來(lái)作為默認(rèn)的沒(méi)有拉開(kāi)抽屜時(shí)候的默認(rèn)布局。假設(shè)我用 DrawerLayout 來(lái)嵌套 content_main 時(shí),content_main 就作為了 DrawerLayout 未拉開(kāi)的默認(rèn)布局,此時(shí)抽屜應(yīng)該是在 Toolbar 之下拉出的。
2.第二點(diǎn)需要注意就是 抽屜的拉出方向,是由 DrawerLayout 本身的頂層布局的 layout_gravity 屬性設(shè)置的,start就是左側(cè)拉出,end就是右側(cè)拉出,這個(gè)布局我起名為 common_drawer ,代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/navigation_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#ffffff"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="256dp"
android:background="@mipmap/drawer_header">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_margin="@dimen/fab_margin"
android:text="DrawerHeader"
android:textColor="@color/author_text_color"
android:textSize="@dimen/author_text_size" />
</FrameLayout>
</LinearLayout>
最后我將這個(gè)布局在 activity_main 中 include 引入。
當(dāng)然,我們是比較關(guān)心 DrawerLayout 和 Toolbar 設(shè)置的 navigation 按鈕 icon 是如何建立關(guān)聯(lián)的,其實(shí)很簡(jiǎn)單,在 代碼中調(diào)用這行代碼:
ActionBarDrawerToggle mToggle = new ActionBarDrawerToggle(this,drawerlayout,toolbar, R.string.open,R.string.close);
然后在 onPostCreate 方法中 調(diào)用 mToggle.syncState()
來(lái)同步滑動(dòng)狀態(tài)。
另外想多提一句,NavigationDrawer 是 google 規(guī)范的 抽屜內(nèi)容的布局,不過(guò)定制性比較差,并不建議你項(xiàng)目中使用它。
當(dāng)然有關(guān) DrawerLayout 還有很多屬性可以配置,有其他需要就去查查官方文檔吧~
我準(zhǔn)備再開(kāi)一個(gè)坑,就是爭(zhēng)取慢慢熟悉所有 MD 風(fēng)格的組件,每一個(gè)都能寫(xiě) Demo 來(lái)練練手,喜歡就關(guān)注下好了。項(xiàng)目的 Github 地址如下: