在上一篇文章中我們詳細介紹了什麼是 Material Design,以及一些 MD 的風格,接下來我們就來進行實戰,而 ToolBar 將會是我們第一個來進行實戰的 Material 控件,雖然對 ToolBar 還不是那麼熟悉,但是相信另一個相關的控件我們是非常熟悉的,那就是 ActionBar,相信這個大家都是很熟悉了,沒錯,活動的頂部導航的那個標題欄其實就是 ActionBar,我們之前的應用開發中一定都有 ActionBar 的相關使用,不過 ActionBar 由於其設計原因,應用有一定的侷限性,比如被限定只能位於活動的頂部,從而不能實現一些 MD 風格,因此官方已經不建議使用 ActionBar 了,強力推薦使用 ToolBar,那麼 ToolBar 到底好在哪裏,ToolBar 的強大之處就在於,它不僅繼承了 ActionBar 的所用功能,而且靈活性很高,可以配合一些其他的控件來完成一些 MD 的效果,扯淡就到這裏,接下來開始演繹
新建一個 MaterialDesign 項目,我們馬上開始吧
一、項目的主題默認是在哪裏指定的?
首先我們要知道任何一個新建項目,默認都會顯示 ActionBar,那麼這個 ActionBar 到底是從哪裏來的,其實這是根據項目中指定的主題來顯示的,這裏我們不妨打開我們新建項目的清單文件 AndroidManifest.xml 文件來看一下,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.qiudengjiao.materialdesign">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
可以看到,這裏使用 android:theme 屬性指定了一個 AppTheme 的主題,那麼我們再具體去看看這 AppTheme 的主題是怎麼定義的,打開 AppTheme 定義如下:
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>
這裏定義了一個叫 AppTheme 的主題,然後指定它的 parent 主題是 Theme.AppCompat.Light.DarkAcionBar,這個 DarkActionBar 是一個深色的 ActionBar 主題,我們之前所有的項目中自帶的 ActionBar 就是因爲指定了這個主題纔出現的,顯示效果如下圖:
現在我們就要使用 ToolBar 來替代 ActionBar,因此需要指定一個不帶 ActionBar 的主題,通常有如下兩種主題可選:
- Theme.AppCompat.NoActionBar
- Theme.AppCompat.Light.NoActionBar
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
這裏重寫了 colorPrimary、colorPrimaryDark、colorAccent 這 3 個屬性的顏色,那麼這 3 個屬性的顏色分別代表着什麼位置的顏色呢?我們用語言太難描述清楚,直接上圖吧,這張圖大家也見過,來自 Google 官方網站,如下:
<style name="AppTheme.NoActionBar">
<!--狀態欄顏色-->
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<!--控制各個控件被選中時的顏色-->
<item name="colorAccent">@color/colorAccent</item>
<!--頁面背景色-->
<item name="android:windowBackground">@color/windowBackg</item>
<!--底部導航欄顏色-->
<item name="android:navigationBarColor">@color/navigationColor</item>
<!--Appbar背景色-->
<item name="android:colorPrimary">@color/colorPrimary</item>
<!--ToolBar上的Title顏色-->
<item name="android:textColorPrimary">@color/textColorPrimary</item>
<!--各個控制控件的默認顏色-->
<item name="android:colorControlNormal">@color/colorControlNormal</item>
</style>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
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="@color/colorPrimary"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
</RelativeLayout>
這段代碼不長,但裏面卻有不少技術點去仔細琢磨一下,首先看一下第三行,這裏使用 xmlns:app 指定了一個新的命名空間,思考一下,這是由於每個佈局文件都是用到 xmlns:android 來指定一個命名空間,因此我們才能一直使用 android:id、android:layout_width、android:layout_height 等寫法,那麼這裏指定了 xmlns:app,也就是說可以使用 xmlns:attribute 這樣的寫法了,但是這裏爲什麼要指定 xmlns:app 的命名空間呢,這是由於 Material Design 是在 Android 5.0 系統中才出現的,而很多的 Material 屬性在 5.0 之前系統中國並不存在,那麼爲了能夠兼容之前的老系統,我們就不能使用 android:attribute,而是使用 app:attribute
/**
* ToolBar 練習
*/
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
Toolbar toolbar = (Toolbar) findViewById(R.id.toolBar);
setSupportActionBar(toolbar);
}
}
這裏關鍵代碼只有兩句,主要就是通過調用 setSupportActionBar() 方法將 ToolBar 的實例傳入,這樣我們就做到了既使用 ToolBar,又讓它的外觀與功能和 ActionBar 一致了,運行一下程序,效果圖如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
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="@color/colorPrimary"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:titleTextColor="#f5f0f0" />
</RelativeLayout>
修改顯示文字,這裏給 Activity 增加了一個 android:label 屬性,用於指定 ToolBar 中顯示文字的內容,如果沒有指定的話,會默認顯示 application 中指定的 label 內容,也就是我們的應用名稱,代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.qiudengjiao.materialdesign">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="你好"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
<?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="@mipmap/ic_launcher"
android:title="Backup"
app:showAsAction="always" />
<item
android:id="@+id/delete"
android:icon="@mipmap/ic_launcher"
android:title="Delete"
app:showAsAction="ifRoom" />
<item
android:id="@+id/setting"
android:icon="@mipmap/ic_launcher"
android:title="Setting"
app:showAsAction="never" />
</menu>
可以看到,我們通過<item>標籤來定義 action 按鈕,這裏我們就是要注意一下 app:showAsAction 的用法,這個主要是用來指定按鈕顯示的位置,之所以這裏再次使用了 app 的命名空間,同樣是爲了能夠兼容低版本的系統,showAsAction 主要有三種值可選:
- always 表示永遠顯示在 ToolBar 中,如果屏膜空間不夠則不顯示
- ifRoom 表示屏膜空間足夠的情況下,顯示在 ToolBar 中,不夠的話就顯示在菜單當中,
- naver 則表示永遠顯示在菜單當中
/**
* ToolBar 練習
*/
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
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, "Click Backup", Toast.LENGTH_LONG).show();
break;
case R.id.delete:
Toast.makeText(this, "Click Delete", Toast.LENGTH_LONG).show();
break;
case R.id.setting:
Toast.makeText(this, "Click Setting", Toast.LENGTH_LONG).show();
break;
default:
}
return true;
}
}
<android.support.v7.widget.Toolbar
android:id="@+id/toolBar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary"
app:logo="@mipmap/ic_launcher"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:subtitle="@string/app_name"
app:subtitleTextColor="#c69aec"
app:titleTextColor="#f5f0f0" />
例如用 app:logo 來指定 app 的圖標,以及用 app:subtitle 來指定副標題,app:subtitleTextColor 來指定副標題的顏色等,效果如下: