話不多說直接進入正題。
本文所有使用到的圖標資源下載地址:https://pan.baidu.com/s/1kWhs8mF
使用到的圖標、圖片都在裏面,按照文件夾名即可快速找到需要的資源。
新建項目MaterialDesignTest,一切默認。
一、標題欄Toolbar
要想使用Toolbar,就必須替換掉默認的ActionBar。替換步驟分兩步:
1、隱藏ActionBar
2、定義Toolbar
ActionBar根據指定的AppTheme主題來顯示的,找到主題的定義位置,修改主題即可達到隱藏ActionBar的目的。打開res/values/styles.xml。
<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>
將parent指定的主題修改來隱藏ActionBar,兩種修改方式:
Theme.AppCompat.NoActionBar //深色主題,即界面主體顏色深色,陪襯色爲淺色
Theme.AppCompat.Light.NoActionBar //淺色主題,即界面主體顏色淺色,陪襯色爲深色
這裏選擇淺色主題,即修改parent值爲:
parent="Theme.AppCompat.Light.NoActionBar"
接下來就是使用Toolbar,修改activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<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>
爲了兼容Android 5.0以前的系統,使用了xmlns:app命名空間,定義了高度爲actionBar高度,背景顏色爲colorPrimary,設置Toolbar的主題和彈出菜單的主題分別爲深色和淺色。
修改MainActivity中的代碼:
package com.my.materialdesigntest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
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);
}
}
運行程序:
它現在已經不是ActionBar了,而是Toolbar,接下來的任務就是豐富這個標題欄的內容。
1、爲標題欄修改標題
打開AndroidManifest.xml文件,找到application標籤,加入以下內容。
<application
...
<activity android:name=".MainActivity"
android:label="Fruits">
...
</activity>
</application>
這樣MainActivity的標題欄就被修改成了Fruits,不修改默認顯示應用程序名,當然也可以在資源文件夾下指定標題,方便日後維護。
2、爲標題欄添加按鈕
右擊res目錄→New→Directory,創建menu文件夾。右擊menu文件夾→New→Menu resource file,創建toolbar.xml文件夾。修改代碼,如下所示:
<?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>
app:showAsAction="always" //永遠顯示在Toolbar中,屏幕空間不夠則不顯示
app:showAsAction="ifRoom" //屏幕空間足夠顯示在Toolbar中,不夠顯示在菜單中
app:showAsAction="never" //永遠顯示在菜單中
上述代碼中的圖片可以在我給的圖片資源中找到。
另外注意:Toolbar中的action按鈕只會顯示圖片,菜單中的action按鈕只會顯示文字
3、修改MainActivity中的代碼:
public class MainActivity extends AppCompatActivity {
...
//加載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;
}
}
運行程序:
二、滑動菜單
1、使用DrawerLayout實現滑動菜單效果
DrawerLayout是一個佈局,在佈局中允許放入兩個直接子控件,第一個子控件是主屏幕中顯示的內容,第二個子控件是滑動菜單中顯示的內容。
修改activity_main.xml代碼:
<?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"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
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>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#FFF"
android:text="This is menu"
android:textSize="30sp" />
</android.support.v4.widget.DrawerLayout>
第二個子控件TextView中的android:layout_gravity="start"屬性一定要注意:這個屬性必須指定,意在指明滑動出來的菜單是在哪個位置。指定left是在左邊,指定right是在右邊,指定start是根據系統語言進行判斷,如果系統語言是從左往右的,比如英語、漢語,滑動菜單就在左邊,如果系統語言是從右往左的,比如阿拉伯語,滑動菜單就在右邊。
運行程序:
2、添加導航按鈕
在drawable目錄下放入準備好的ic_menu.png圖標(可以在我給的圖片資源中找到)。
修改MainActivity中的代碼:
public class MainActivity extends AppCompatActivity {
private DrawerLayout mDrawerLayout; //DrawerLayout佈局,用於實現滑動菜單
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBar actionBar = getSupportActionBar(); //獲取ActionBar實例,具體實現由Toolbar完成
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true); //顯示導航按鈕設置爲true
actionBar.setHomeAsUpIndicator(R.drawable.ic_menu); //設置導航按鈕
}
}
...
//爲按鈕設置點擊事件
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
...
case android.R.id.home:
//展示滑動菜單,與XML文件定義一致-> GravityCompat.START
mDrawerLayout.openDrawer(GravityCompat.START);
break;
default:
}
return true;
}
}
Toolbar最左側這個按鈕叫做HomeAsUp按鈕,它默認的圖標是一個返回的箭頭,含義是返回上一個活動。上述代碼對圖標和含義都進行了修改,並且要注意的是,HomeAsUp按鈕的id永遠都是android.R.id.home。運行程序:
3、使用NavigationView來優化滑動菜單頁面
NavigationView是Design Support庫中提供的控件,使用它必須將這個庫引用到項目中。
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'
compile 'com.android.support:design:25.3.1'
compile 'de.hdodenhof:circleimageview:2.2.0'
}
剛剛添加了兩個依賴關係:
compile 'com.android.support:design:25.3.1' //Design Support庫
compile 'de.hdodenhof:circleimageview:2.2.0' //CircleImageView開源項目,可以實現圖片圓形化
CircleImageView開源項目地址:https://github.com/hdodenhof/CircleImageView使用NavigationView還需要準備兩個東西:menu和headerLayout。
menu //用來在NavigationView中顯示具體的菜單項
headerLayout //用來在NavigationView中顯示頭部佈局
①、準備menu
將事先準備好的圖標放入drawable下(可以在我給的圖片資源中找到)。
右擊menu文件夾→New→Menu resource file,創建nav_menu.xml文件,並修改爲以下代碼:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="@+id/nav_call"
android:icon="@drawable/nav_call"
android:title="Call" />
<item
android:id="@+id/nav_friends"
android:icon="@drawable/nav_friends"
android:title="Friends" />
<item
android:id="@+id/nav_location"
android:icon="@drawable/nav_location"
android:title="Location" />
<item
android:id="@+id/nav_mail"
android:icon="@drawable/nav_mail"
android:title="Mail" />
<item
android:id="@+id/nav_task"
android:icon="@drawable/nav_task"
android:title="Tasks" />
</group>
</menu>
menu標籤中嵌套一個group標籤,代表一個組,並設置checkableBehavior屬性爲single,代表組中菜單項只能單選。
②準備headerLayout
headerLayout是一個可以隨意定製的佈局。我們可以在佈局中放置一個頭像,加上用戶名、郵箱地址信息。
將準備好的圖片nav_icon.png放到drawable下(可以在我給的圖片資源中找到).
右擊layout文件夾→New→Layout resource file,創建nav_header.xml文件。修改爲以下代碼:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="180dp"
android:background="?attr/colorPrimary"
android:padding="10dp">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/icon_image"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="@drawable/nav_icon" />
<TextView
android:id="@+id/username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="[email protected]"
android:textColor="#FFF"
android:textSize="14sp" />
<TextView
android:id="@+id/mail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/username"
android:text="Tony Green"
android:textColor="#FFF"
android:textSize="14sp" />
</RelativeLayout>
代碼含義很好理解。
準備完畢,開始使用NavigationView,修改activity_main.xml文件中的代碼,只需要將原來的TextView代碼塊換成以下代碼即可。
<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/nav_header"
app:menu="@menu/nav_menu" />
上述代碼的含義就是將剛剛準備的兩個文件引入到佈局中來最後修改MainActivity中的代碼:
public class MainActivity extends AppCompatActivity {
private DrawerLayout mDrawerLayout; //DrawerLayout佈局,用於實現滑動菜單
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
NavigationView navView = (NavigationView) findViewById(R.id.nav_view);//關聯Navigation控件
navView.setCheckedItem(R.id.nav_call); //設置默認選中項
//菜單項點擊事件
navView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
//關閉滑動菜單
mDrawerLayout.closeDrawers();
return true;
}
});
}
...
}
在點擊事件中可以爲每個菜單項分別設置點擊事件,這裏沒有寫,而是點擊任意菜單後關閉滑動菜單。
運行程序:
三、懸浮按鈕和可交互提示
1、懸浮按鈕FloatingActionButton
FloatingActionButton有Design Support庫提供,懸浮按鈕默認使用colorAccent作爲按鈕的顏色。也可以爲按鈕指定一個圖標來表明按鈕的作用。
將準備好的圖標ic_done.png放入drawable目錄中(圖標可以在我給的圖片資源中找到)。
修改activity_main.xml中的代碼:
<?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"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
...
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:src="@drawable/ic_done" />
</FrameLayout>
...
</android.support.v4.widget.DrawerLayout>
運行程序:
當然也可以爲這個懸浮按鈕設置懸浮高度。即:在懸浮按鈕定義標籤的最後加上:
app:elevation="8dp"
懸浮按鈕的點擊事件,修改MainActvity中的代碼:
public class MainActivity extends AppCompatActivity {
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
//懸浮按鈕的點擊事件
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this,"FAB clicked",Toast.LENGTH_LONG).show();
}
});
}
...
}
運行程序:
2、提示工具Snackbar
Snackbar由Design Support庫提供,作爲提示工具,他並不是Toast的替代品,Toast的作用是告訴用戶發生了什麼事情,Snackbar可以在提示的時候添加一個可交互按鈕。Snackbar的使用和Toast基本相似,只是多了一個按鈕的點擊事件。
修改MainActivity中的代碼,將懸浮按鈕的點擊事件的處理邏輯語句修改即可:
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Toast.makeText(MainActivity.this,"FAB clicked",Toast.LENGTH_LONG).show();
Snackbar.make(view, "是否刪除?", Snackbar.LENGTH_INDEFINITE)
.setAction("撤銷", new View.OnClickListener() { //設置按鈕的點擊事件
@Override
public void onClick(View view) {
//處理邏輯
Toast.makeText(MainActivity.this, "已撤銷刪除",
Toast.LENGTH_SHORT).show();
}
})
.show();
}
});
運行程序:
可以看到Snackbar給出了提示,並且可以讓用戶進行互動。但是彈出的提示把懸浮按鈕擋住了一部分,解決這個問題需要使用到CoordinatorLayout佈局。
3、CoordinatorLayout佈局
CoordinatorLayout佈局由Design Support庫提供。是加強版的FrameLayout,它可以監聽其所有子控件的事件,自動幫助我們做出最爲合理的響應。例如剛纔彈出的Snackbar將懸浮按鈕擋住了,使用CoordinatorLayout佈局就可以避免這種情況,它會自動監聽到Snackbar的彈出,然後把懸浮按鈕上移。
使用CoordinatorLayout佈局的方法非常簡單,只需要修改activity_main.xml代碼,將FrameLayout修改爲android.support.design.widget.CoordinatorLayout即可。即:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
...
</android.support.design.widget.CoordinatorLayout>
...
</android.support.v4.widget.DrawerLayout>
再次運行程序: