本模塊共有六篇文章,參考郭神的《第一行代碼》俺叭,對(duì)Material Design的學(xué)習(xí)做一個(gè)詳細(xì)的筆記,大家可以一起交流一下:
Material Design 實(shí)戰(zhàn) 之第二彈——滑動(dòng)菜單詳解&實(shí)戰(zhàn)
Material Design 實(shí)戰(zhàn) 之第三彈—— 懸浮按鈕和可交互提示(FloatingActionButton & Snackbar & CoordinatorLayout)
Material Design 實(shí)戰(zhàn) 之第四彈 —— 卡片布局以及靈動(dòng)的標(biāo)題欄(CardView & AppBarLayout)
Material Design 實(shí)戰(zhàn) 之第五彈 —— 下拉刷新(SwipeRefreshLayout)
-
最終預(yù)覽圖
??????寫(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>
下面解析一下這段代碼:
- 首先看一下第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
接下來(lái)
定義了一個(gè)Toolbar控件
瞎领,這個(gè)控件是由appcompat-v7庫(kù)提供的泌辫。
這里我們給Toolbar指定了一個(gè)id随夸,將它的
寬度設(shè)置為matchparent九默,
高度設(shè)置為actionBar的高度,
背景色設(shè)置為colorPrimary宾毒。-
接下來(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)使用深色主題
但是這個(gè)效果看起來(lái)就會(huì)很差
,之前
使用ActionBar時(shí)文字都是白色
的焕毫,現(xiàn)在變成黑色
的會(huì)很難看
蹲坷。那么為了能讓Toolbar單獨(dú)(全局是用由APPTheme制定的淺色主題的,故相對(duì)而言這里用“單獨(dú)”)使用深色主題
邑飒,這里我們使用android:theme
屬性循签,將Toolbar的主題指定成了ThemeOverlay.AppCompat.Dark.ActionBar。
但是這樣指定完了之后又會(huì)出現(xiàn)新的問(wèn)題疙咸,如果Toolbar中有菜單按鈕县匠,那么彈出的菜單項(xiàng)也會(huì)變成深色主題,這樣就
再次變得十分難看
,于是這里使用了app:popupTheme屬性單獨(dú)將彈出的菜單項(xiàng)指定成了淡色主題乞旦。
之所以使用app:popupTheme贼穆,是因?yàn)閜opupTheme這個(gè)屬性是在Android5.0系統(tǒng)中新增的,我們使用app:popupTheme的話就可以兼容Android5.0以下的系統(tǒng)了兰粉。
小結(jié):
- 為了能夠兼容之前的老系統(tǒng)扮惦,使用
app:attribute
,而不是android:attribute
;- 在styles.xml中將程序的主題指定成了淡色主題;
- 使用
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
讓Toolbar單獨(dú)使用深色主題亲桦;- 使用
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
單獨(dú)將彈出的菜單項(xiàng)指定成了淡色主題崖蜜;- 之所以使用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)擊事件的焕刮!