Material Design 實(shí)戰(zhàn) 之第一彈——Toolbar詳解


本模塊共有六篇文章,參考郭神的《第一行代碼》俺叭,對(duì)Material Design的學(xué)習(xí)做一個(gè)詳細(xì)的筆記,大家可以一起交流一下:


??????寫(xiě)在文首,什么是Material Design铆隘?這里參考一下郭神的說(shuō)法:



文章提要與總結(jié)


1. 關(guān)于android:theme的詳細(xì)理解(附圖);
    (運(yùn)用:使用Toolbar代替ActionBar時(shí)南用,須將Theme.AppCompat.Light.DarkActionBar改成Theme.AppCompat.Light.NoActionBar)
2. 在activity_main.xml中使用Toolbar代替ActionBar膀钠;
        關(guān)于命名空間:android  app;
        關(guān)于Toolbar控件的屬性裹虫;
                尤其android:theme以及app:popupTheme的用法理解道伟;

3. 關(guān)于activity.android:label;

4. 通過(guò)Menu resource file菜單文件式(同時(shí)為xml格式)來(lái)為T(mén)oolbar添加action按鈕疆液;
        文件中:
        <item>標(biāo)簽來(lái)定義action按鈕车胡,
        android:id用于指定按鈕的id,
        android:icon用于指定按鈕的圖標(biāo)十酣,
        android:title用于指定按鈕的文字涩拙;
        使用app:showAsAction來(lái)指定按鈕的顯示位置际长,再次使用了app命名空間,同樣是為了能夠兼容低版本的系統(tǒng)兴泥;
         showAsAction的幾種選值:always   ifRoom   never
        注意工育,
                Toolbar中的action按鈕只會(huì)顯示圖標(biāo),
                菜單中的action按鈕只會(huì)顯示文字搓彻;

5. onCreateOptionsMenu()加載描述Toolbar的action按鈕的Menu resource file如绸;
    onOptionsItemSelected()方法中處理各個(gè)按鈕的點(diǎn)擊事件;

效果圖:



正文


關(guān)于Toolbar

Toolbar相關(guān)于ActionBar旭贬;
不過(guò)ActionBar由于其設(shè)計(jì)原因怔接,被限定只能位于活動(dòng)的頂部,從而不能實(shí)現(xiàn)一些Material Design的效果稀轨,因此官方現(xiàn)在已經(jīng)不建議使用ActionBar了扼脐。

首先要知道,任何一個(gè)新建的項(xiàng)目默認(rèn)都是會(huì)顯示ActionBar的奋刽。
ActionBar是根據(jù)項(xiàng)目中指定的主題來(lái)顯示瓦侮,
打開(kāi)AndroidManifest.xml文件:

可以看到這里用android:theme指定了一個(gè)AppTheme的主題。
打開(kāi)res/values/styles.xml文件可以查看其定義出處:

這里定義了一個(gè)叫AppTheme的主題并指定它的parent主題是Theme.AppCompat.Light.DarkActionBar佣谐。
DarkActionBar是一個(gè)深色的ActionBar主題肚吏,所有的新建項(xiàng)目中自帶的ActionBar就是因?yàn)橹付诉@個(gè)主題才出現(xiàn)的。

要使用TooIbar來(lái)替代ActionBar時(shí)需要指定一個(gè)不帶ActionBar的主題狭魂,
對(duì)應(yīng)的通常有Theme.AppCompat.NoActionBar和Theme.AppCompat.Light.NoActionBar這兩種主題可選罚攀;
其中:

  • Theme.AppCompat.NoActionBar表示深色主題,它會(huì)將界面的主體顏色設(shè)成深色雌澄,陪襯顏色設(shè)成淡色斋泄;
  • Theme.AppCompat.Light.NoActionBar表示淡色主題,它會(huì)將界面的主體顏色設(shè)成淡色掷伙,陪襯顏色設(shè)成深色是己。

具體可以根據(jù)情況去設(shè)置,這里主要選用淡色主題任柜,如下所示:

觀察代碼中AppTheme中的屬性重寫(xiě):
可見(jiàn)這里重寫(xiě)了colorPrimary卒废、colorPrimaryDark和colorAccent這3個(gè)屬性的顏色。
屬性指定顏色名稱對(duì)應(yīng)的位置宙地,如圖:

可見(jiàn)除了上述3個(gè)屬性之外摔认,我們還可以通過(guò)textColorPrimary、windowBackground和navigationBarCotor等屬性來(lái)控制更多位置的顏色宅粥。
不過(guò)colorAccent這個(gè)屬性比較特殊参袱,它不只是用來(lái)指定這樣一個(gè)按鈕的顏色,而是更多表達(dá)了一個(gè)強(qiáng)調(diào)的意思,比如一些控件的選中狀態(tài)也會(huì)使用colorAccent的顏色抹蚀。

至此已將ActionBar隱藏剿牺,接下來(lái)使用Toolbar來(lái)替代ActionBar。
修改activity_main.xml:

    <FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
    </FrameLayout>

下面解析一下這段代碼:

  1. 首先看一下第2行环壤,這里使用xmlns:app指定了一個(gè)新的命名空間晒来。
    正是由于每個(gè)布局文件都會(huì)使用xmlns:android來(lái)指定一個(gè)命名空間,因此我們才能一直使用android:id郑现、android:layoutwidth等寫(xiě)法湃崩,
    這里指定了xmlns:app,現(xiàn)在便可以使用app:attribute這樣的寫(xiě)法了接箫。

但是為什么這里要指定一個(gè)xmlns:app的命名空間呢攒读?
這是由于MaterialDesign是在Android5.0系統(tǒng)中才出現(xiàn)的,而很多的Material屬性在5.0之前的系統(tǒng)中并不存在辛友,那么為了能夠兼容之前的老系統(tǒng)薄扁,我們就不能使用android:attribute這樣的寫(xiě)法了,而是應(yīng)該使用app:attribute

  1. 接下來(lái)定義了一個(gè)Toolbar控件瞎领,這個(gè)控件是由appcompat-v7庫(kù)提供的泌辫。
    這里我們給Toolbar指定了一個(gè)id随夸,將它的
    寬度設(shè)置為matchparent九默,
    高度設(shè)置為actionBar的高度,
    背景色設(shè)置為colorPrimary宾毒。

  2. 接下來(lái)驼修,關(guān)于主題:
    由于我們剛才在styles.xml中將程序的主題指定成了淡色主題,因此Toolbar現(xiàn)在也是淡色主題(“藍(lán)底(黑字)”)诈铛,而TooIbar上面的各種元素就會(huì)自動(dòng)使用深色主題(“(黑底)X字”)乙各,這是為了和主體顏色區(qū)別開(kāi)(具體可以看文章開(kāi)頭對(duì)于深色淺色主題的解釋)。

    在styles.xml中將程序的主題指定成了淡色主題幢竹,Toolbar現(xiàn)在也是淡色主題耳峦,TooIbar上面的各種元素就會(huì)自動(dòng)使用深色主題

  1. 但是這個(gè)效果看起來(lái)就會(huì)很差之前使用ActionBar時(shí)文字都是白色的焕毫,現(xiàn)在變成黑色會(huì)很難看蹲坷。那么為了能讓Toolbar單獨(dú)(全局是用由APPTheme制定的淺色主題的,故相對(duì)而言這里用“單獨(dú)”)使用深色主題邑飒,這里我們使用android:theme屬性循签,將Toolbar的主題指定成了ThemeOverlay.AppCompat.Dark.ActionBar。

  2. 但是這樣指定完了之后又會(huì)出現(xiàn)新的問(wèn)題疙咸,如果Toolbar中有菜單按鈕县匠,那么彈出的菜單項(xiàng)也會(huì)變成深色主題,這樣就再次變得十分難看,于是這里使用了app:popupTheme屬性單獨(dú)將彈出的菜單項(xiàng)指定成了淡色主題乞旦。

  3. 之所以使用app:popupTheme贼穆,是因?yàn)閜opupTheme這個(gè)屬性是在Android5.0系統(tǒng)中新增的,我們使用app:popupTheme的話就可以兼容Android5.0以下的系統(tǒng)了兰粉。

小結(jié):

  1. 為了能夠兼容之前的老系統(tǒng)扮惦,使用app:attribute,而不是android:attribute;
  2. 在styles.xml中將程序的主題指定成了淡色主題;
  3. 使用android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"讓Toolbar單獨(dú)使用深色主題亲桦;
  4. 使用app:popupTheme="@style/ThemeOverlay.AppCompat.Light"單獨(dú)將彈出的菜單項(xiàng)指定成了淡色主題崖蜜;
  5. 之所以使用app:popupTheme,是因?yàn)閜opupTheme這個(gè)屬性是在Android5.0系統(tǒng)中新增的客峭,我們使用app:popupTheme的話就可以兼容Android5.0以下的系統(tǒng)了豫领。



接下來(lái)修改MainActivity:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    }

這里,
首先用findViewByid()得到Toolbar的實(shí)例舔琅,
然后調(diào)用setSupportActionBar()方法同時(shí)傳入Toolbar的實(shí)例等恐,
至此便實(shí)現(xiàn)了既使用Toolbar,又讓它的外觀與功能都同ActionBar一致备蚓。

現(xiàn)在運(yùn)行一下程序课蔬,效果如圖:


這個(gè)標(biāo)題欄雖然看上去和之前的沒(méi)什么兩樣,但其實(shí)它已經(jīng)是Toolbar而不是ActionBar了郊尝,它現(xiàn)在也具備了實(shí)現(xiàn)MaterialDesign效果的能力二跋。



接著實(shí)戰(zhàn)一些Toolbar比較常用的功能,比如修改標(biāo)題欄上顯示的文字內(nèi)容流昏,
這段文字是在AndroidManifest.xml中指定的扎即,如下所示:

這里給activity增加了一個(gè)android:label屬性,用于指定在Toolbar中顯示的文字內(nèi)容况凉,
如果沒(méi)有指定的話谚鄙,會(huì)默認(rèn)使用application中指定的label內(nèi)容,也就是我們的應(yīng)用名稱刁绒。

接下來(lái)再添加一些action按鈕來(lái)豐富Toolbar:
先準(zhǔn)備了幾張圖片來(lái)作為按鈕的圖標(biāo)闷营,將它們放在了drawable-xxhdpi目錄下;
右擊res目錄→New→Directory知市,創(chuàng)建一個(gè)menu文件夾傻盟;
右擊menu文件夾→New→Menuresourcefile,創(chuàng)建一個(gè)toolbar.xml文件并編寫(xiě):

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/backup"
        android:icon="@drawable/ic_backup"
        android:title="Backup"
        app:showAsAction="always"/>
    <item
        android:id="@+id/delete"
        android:icon="@drawable/ic_delete"
        android:title="Delete"
        app:showAsAction="ifRoom"/>
    <item
        android:id="@+id/settings"
        android:icon="@drawable/ic_settings"
        android:title="Settings"
        app:showAsAction="never"/>
</menu>
  • 可以看到初狰,我們通過(guò)
    <item>標(biāo)簽來(lái)定義action按鈕莫杈,
    android:id用于指定按鈕的id,
    android:icon用于指定按鈕的圖標(biāo)奢入,
    android:title用于指定按鈕的文字筝闹。

  • 接著使用app:showAsAction來(lái)指定按鈕的顯示位置媳叨,
    之所以這里再次使用了app命名空間,同樣是為了能夠兼容低版本的系統(tǒng)关顷。

  • showAsAction主要有以下幾種值可選:
    always表示永遠(yuǎn)顯示在Toolbar中糊秆,如果屏幕空間不夠則不顯示;
    ifRoom表示屏幕空間足夠的情況下顯示在Toolbar中议双,不夠的話就顯示在菜單當(dāng)中痘番;
    never則表示永遠(yuǎn)顯示在菜單當(dāng)中。

  • 注意平痰,
    Toolbar中的action按鈕只會(huì)顯示圖標(biāo)汞舱,
    菜單中的action按鈕只會(huì)顯示文字。

接下來(lái)就是創(chuàng)建菜單的套路了宗雇,修改MainActivity中的代碼昂芜,如下所示:

package com.example.materialtest;

import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.toolbar,menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case R.id.backup:
                Toast.makeText(this,"You clicked Backup" , Toast.LENGTH_SHORT).show();
                break;
            case R.id.delete:
                Toast.makeText(this,"You clicked Delete" , Toast.LENGTH_SHORT).show();
                break;
            case R.id.settings:
                Toast.makeText(this,"You clicked Settings" , Toast.LENGTH_SHORT).show();
                break;
            default:
        }
        return true;
    }

}

上述代碼:
在onCreate0ptionsMenu()中加載toolbar.xml這個(gè)菜單文件,
在onOptionsItemSelected()中處理各個(gè)按鈕的點(diǎn)擊事件赔蒲。
重新運(yùn)行一下程序泌神,效果如圖:

可見(jiàn)Toolbar上面現(xiàn)在顯示了兩個(gè)action按鈕,這是因?yàn)?br> Backup按鈕指定的顯示位置是alway舞虱,
Delete按鈕指定的顯示位置是ifRoom欢际,而現(xiàn)在屏幕空間充足。因此兩個(gè)按鈕都會(huì)顯示在Toolbar中矾兜。
Settings按鈕則由于指定的顯示位置是never损趋,所以顯示在菜單中(點(diǎn)擊最右邊的三個(gè)小點(diǎn)即知)。

同時(shí)注意這些action按鈕都是可以響應(yīng)點(diǎn)擊事件的焕刮!


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末舶沿,一起剝皮案震驚了整個(gè)濱河市墙杯,隨后出現(xiàn)的幾起案子配并,更是在濱河造成了極大的恐慌,老刑警劉巖高镐,帶你破解...
    沈念sama閱讀 212,599評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件溉旋,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡嫉髓,警方通過(guò)查閱死者的電腦和手機(jī)观腊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)算行,“玉大人梧油,你說(shuō)我怎么就攤上這事≈菪希” “怎么了儡陨?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,084評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我骗村,道長(zhǎng)嫌褪,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,708評(píng)論 1 284
  • 正文 為了忘掉前任胚股,我火速辦了婚禮笼痛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘琅拌。我一直安慰自己缨伊,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布进宝。 她就那樣靜靜地躺著倘核,像睡著了一般。 火紅的嫁衣襯著肌膚如雪即彪。 梳的紋絲不亂的頭發(fā)上紧唱,一...
    開(kāi)封第一講書(shū)人閱讀 50,021評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音隶校,去河邊找鬼漏益。 笑死,一個(gè)胖子當(dāng)著我的面吹牛深胳,可吹牛的內(nèi)容都是我干的绰疤。 我是一名探鬼主播,決...
    沈念sama閱讀 39,120評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼舞终,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼轻庆!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起敛劝,我...
    開(kāi)封第一講書(shū)人閱讀 37,866評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤余爆,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后夸盟,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蛾方,經(jīng)...
    沈念sama閱讀 44,308評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評(píng)論 2 327
  • 正文 我和宋清朗相戀三年上陕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了桩砰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,768評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡释簿,死狀恐怖亚隅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情庶溶,我是刑警寧澤煮纵,帶...
    沈念sama閱讀 34,461評(píng)論 4 333
  • 正文 年R本政府宣布沉删,位于F島的核電站,受9級(jí)特大地震影響醉途,放射性物質(zhì)發(fā)生泄漏矾瑰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評(píng)論 3 317
  • 文/蒙蒙 一隘擎、第九天 我趴在偏房一處隱蔽的房頂上張望殴穴。 院中可真熱鬧,春花似錦货葬、人聲如沸采幌。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,850評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)休傍。三九已至,卻和暖如春蹲姐,著一層夾襖步出監(jiān)牢的瞬間磨取,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,082評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工柴墩, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留忙厌,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,571評(píng)論 2 362
  • 正文 我出身青樓江咳,卻偏偏與公主長(zhǎng)得像逢净,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子歼指,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評(píng)論 2 350