Material Design拢操,中文名:材料設(shè)計(jì)語(yǔ)言锦亦,是由Google推出的全新的設(shè)計(jì)語(yǔ)言,谷歌表示令境,這種設(shè)計(jì)語(yǔ)言旨在為手機(jī)杠园、平板電腦、臺(tái)式機(jī)和“其他平臺(tái)”提供更一致舔庶、更廣泛的“外觀和感覺(jué)”抛蚁。然而,Material Design卻是UI設(shè)計(jì)者和Android開(kāi)發(fā)者同時(shí)應(yīng)該注意和學(xué)習(xí)的事惕橙。為什么呢瞧甩,美工是設(shè)計(jì)者,程序員是實(shí)現(xiàn)者弥鹦。程序員要知道怎么快速地去實(shí)現(xiàn)美工根據(jù)Material Design設(shè)計(jì)的UI肚逸,當(dāng)然,谷歌也考慮到了這一點(diǎn)彬坏,于是也有了Material Design Library朦促。
Material Design Library,可以說(shuō)是頗受開(kāi)發(fā)者矚目的一個(gè)控件效果庫(kù)栓始,能夠讓開(kāi)發(fā)者在Android 2.2系統(tǒng)上使用Android 5.0才支持的控件效果务冕,比如扁平、矩形幻赚、浮動(dòng)按鈕禀忆,復(fù)選框以及各式各樣的進(jìn)度指示器等臊旭。
那么,對(duì)于Material Design的風(fēng)格油湖,開(kāi)發(fā)者要怎么實(shí)現(xiàn)呢巍扛?
1. ToolBar
實(shí)現(xiàn):android.support.v7.widget.Toolbar
- app_bar_main.xml : 標(biāo)題欄布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:background="@color/colorPrimary"
android:layout_height="56dp"
app:contentInsetStart="0.0dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/fl_title_left"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackgroundBorderless"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:visibility="gone">
<ImageView
android:id="@+id/iv_title_left"
android:layout_width="23dp"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</FrameLayout>
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:textColor="#fff"
android:textSize="18sp"
android:gravity="center_horizontal"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
android:lines="1"
android:layout_centerVertical="true"/>
<FrameLayout
android:id="@+id/fl_title_right"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackgroundBorderless"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:layout_alignParentRight="true"
android:visibility="gone">
<ImageView
android:id="@+id/iv_title_right"
android:layout_width="23dp"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
</FrameLayout>
</RelativeLayout>
</android.support.v7.widget.Toolbar>
</LinearLayout>
- ToolBarUtil.java : ToolBar幫助類
public class ToolBarUtil {
private Toolbar toolbar;
private FrameLayout fl_title_left;
private ImageView iv_title_left;
private TextView tv_title;
private FrameLayout fl_title_right;
private ImageView iv_title_right;
public ToolBarUtil(Toolbar toolbar){
this.toolbar = toolbar;
this.fl_title_left = (FrameLayout) toolbar.findViewById(R.id.fl_title_left);
this.iv_title_left = (ImageView) toolbar.findViewById(R.id.iv_title_left);
this.tv_title = (TextView) toolbar.findViewById(R.id.tv_title);
this.fl_title_right = (FrameLayout) toolbar.findViewById(R.id.fl_title_right);
this.iv_title_right = (ImageView) toolbar.findViewById(R.id.iv_title_right);
}
// 設(shè)置標(biāo)題位置
public void setTitleGravity(int gravity){
this.tv_title.setGravity(gravity);
}
// 設(shè)置左邊按鈕圖標(biāo)以及點(diǎn)擊事件
public void setLeftButton(int icon, View.OnClickListener listener){
this.iv_title_left.setImageResource(icon);
this.fl_title_left.setVisibility(View.VISIBLE);
this.fl_title_left.setOnClickListener(listener);
}
// 設(shè)置右邊按鈕圖標(biāo)以及點(diǎn)擊事件
public void setRightButton(int icon, View.OnClickListener listener){
this.iv_title_right.setImageResource(icon);
this.fl_title_right.setVisibility(View.VISIBLE);
this.fl_title_right.setOnClickListener(listener);
}
- MainActivity.java : 設(shè)置ToolBar標(biāo)題及其左右Button的圖標(biāo)和點(diǎn)擊事件
@Override
public void initToolBar() {
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
ToolBarUtil toolBarUtil = new ToolBarUtil(toolbar);
toolBarUtil.setTitleGravity(Gravity.LEFT);
toolBarUtil.setLeftButton(R.drawable.titlebar_menu, new View.OnClickListener() {
@Override
public void onClick(View view) {
// 菜單鍵
}
});
toolBarUtil.setRightButton(R.drawable.titlebar_search, new View.OnClickListener() {
@Override
public void onClick(View view) {
// 搜索鍵
}
});
}
另外,為了實(shí)現(xiàn)這種標(biāo)題欄的效果乏德,還需要設(shè)置app的主題(去掉默認(rèn)標(biāo)題欄,將狀態(tài)欄顏色設(shè)置為colorPrimaryDark)
<style name="AppTheme02" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
</style>
2. TabLayout
實(shí)現(xiàn):android.support.design.widget.TabLayout
常用屬性:
屬性名 | 作用 |
---|---|
app:tabTextColor="" | 標(biāo)簽顏色 |
app:tabSelectedTextColor="" | 標(biāo)簽選中時(shí)顏色 |
app:tabIndicatorColor="" | 標(biāo)簽下標(biāo)指示器顏色 |
app:tabIndicatorHeight="" | 標(biāo)簽下標(biāo)指示器高度 |
app:tabMode="" | 標(biāo)簽?zāi)芊襁M(jìn)行橫向滑動(dòng) |
- build.gradle(Module:app) : 導(dǎo)入Material Design Library
dependencies {
...
compile 'com.android.support:design:25.0.1'
}
- activity_main.xml : TabLayout布局
<android.support.design.widget.TabLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="45dp"
app:tabTextColor="#666"
app:tabSelectedTextColor="@color/colorPrimary"
app:tabIndicatorColor="@color/colorPrimary"/>
- MainActivity.java : 設(shè)置Tab標(biāo)題和ViewPager
public void initTabs(){
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.addTab(tabLayout.newTab().setText("design01"));
tabLayout.addTab(tabLayout.newTab().setText("design02"));
tabLayout.addTab(tabLayout.newTab().setText("design03"));
tabLayout.setupWithViewPager(viewPager);
}
- activity_main.xml : TabLayout布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#ddd"
android:layout_above="@+id/tabLayout"/>
<android.support.design.widget.TabLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="60dp"
app:tabTextColor="#666"
app:tabSelectedTextColor="@color/colorPrimary"
app:tabIndicatorHeight="0dp"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
- MainActivity.java : 設(shè)置Tab標(biāo)題和ViewPager,以及選中圖標(biāo)改變事件
public void initTabs(){
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.addTab(tabLayout.newTab().setText("design01").setIcon(R.drawable.tab_design_selected));
tabLayout.addTab(tabLayout.newTab().setText("design02").setIcon(R.drawable.tab_design_unselected));
tabLayout.addTab(tabLayout.newTab().setText("design03").setIcon(R.drawable.tab_design_unselected));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
tabLayout.getTabAt(0).setIcon(R.drawable.tab_design_unselected);
tabLayout.getTabAt(1).setIcon(R.drawable.tab_design_unselected);
tabLayout.getTabAt(2).setIcon(R.drawable.tab_design_unselected);
if (tab == tabLayout.getTabAt(0)) {
tab.setIcon(R.drawable.tab_design_selected);
}
else if (tab == tabLayout.getTabAt(1)) {
tab.setIcon(R.drawable.tab_design_selected);
}
else if (tab == tabLayout.getTabAt(2)) {
tab.setIcon(R.drawable.tab_design_selected);
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
3. DrawerLayout + NavigationView
實(shí)現(xiàn):android.support.v4.widget.DrawerLayout + android.support.design.widget.NavigationView
NavigationView 常用屬性:
屬性名 | 作用 |
---|---|
app:headerLayout="" | 頭布局 |
app:menu="" | 菜單布局 |
android:layout_gravity="left" | 在父視圖中的布局 |
android:fitSystemWindows="true" | 適應(yīng)系統(tǒng) |
- build.gradle(Module:app) : 導(dǎo)入Material Design Library
dependencies {
...
compile 'com.android.support:design:25.0.1'
compile 'com.jaeger.statusbaruitl:library:1.2.7'
}
- activity_main.xml : DrawerLayout和NavigationView布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<!--你的布局-->
<android.support.design.widget.NavigationView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/nv_main"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/navigation_header"
app:menu="@menu/drawer_view"
android:clickable="true"
android:fitsSystemWindows="true" />
</android.support.v4.widget.DrawerLayout>
</RelativeLayout>
- navigation_view.xml : 側(cè)滑菜單頭布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="163dp"
android:background="@drawable/navigation_header"
android:orientation="vertical"
android:theme="@style/ThemeOverlay.AppCompat.Dark">
</LinearLayout>
- drawer_view.xml : 側(cè)滑菜單選項(xiàng)
<?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_home"
android:icon="@drawable/tab_design_selected"
android:title="Design01"/>
<item
android:id="@+id/nav_messages"
android:icon="@drawable/tab_design_selected"
android:title="Design02"/>
<item
android:id="@+id/nav_friends"
android:icon="@drawable/tab_design_selected"
android:title="Design03"/>
<item
android:id="@+id/nav_discussion"
android:icon="@drawable/tab_design_selected"
android:title="Design04"/>
</group>
<item android:title="More">
<menu>
<item
android:icon="@drawable/tab_design_selected"
android:title="Design05"/>
<item
android:icon="@drawable/tab_design_selected"
android:title="Design06"/>
</menu>
</item>
</menu>
- MainActivity.java : 設(shè)置側(cè)滑菜單選項(xiàng)點(diǎn)擊事件
public void initDrawer(){
drawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
StatusBarUtil.setColorNoTranslucentForDrawerLayout(MainActivity.this,
drawerLayout, getResources().getColor(R.color.colorPrimaryDark));
navigationView = (NavigationView) findViewById(R.id.navigationView);
navigationView.setNavigationItemSelectedListener(
new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
drawerLayout.closeDrawers();
if (menuItem.getTitle().equals("Design01")){
// 選擇Design01
}
else if (menuItem.getTitle().equals("Design02")){
// 選擇Design02
}
else if (menuItem.getTitle().equals("Design03")){
// 選擇Design03
}
else if (menuItem.getTitle().equals("Design04")){
// 選擇Design04
}
else if (menuItem.getTitle().equals("Design05")){
// 選擇Design05
}
else if (menuItem.getTitle().equals("Design06")){
// 選擇Design06
}
return false;
}
});
}
4. FloatingActionButton
實(shí)現(xiàn):android.support.design.widget.FloatingActionButton
常用屬性:
屬性名 | 作用 |
---|---|
app:backgroundTint="" | 背景色 |
app:fabSize="" | 包裹圖片類型 |
app:elevation="" | Z軸,用來(lái)控制控件陰影效果 |
app:rippleColor="" | 按鈕點(diǎn)擊時(shí)顏色效果 |
app:layout_anchor="" | 顯示位置的錨點(diǎn) |
app:layout_anchorGravity="" | 按鈕在錨點(diǎn)處的位置 |
- build.gradle(Module:app) : 導(dǎo)入Material Design Library
dependencies {
...
compile 'com.android.support:design:25.0.1'
}
- activity_main.xml : 懸浮按鈕的布局
<android.support.design.widget.FloatingActionButton
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/titlebar_search"
android:clickable="true"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="130dp"
android:layout_marginRight="30dp"/>
5. TextInputLayout
實(shí)現(xiàn):android.support.design.widget.TextInputLayout
- build.gradle(Module:app) : 導(dǎo)入Material Design Library
dependencies {
...
compile 'com.android.support:design:25.0.1'
}
- activity_main.xml : 輸入框的布局
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:orientation="vertical">
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:hint="Phone"
android:inputType="phone"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:hint="Password"
android:inputType="textPassword"/>
</android.support.design.widget.TextInputLayout>
</LinearLayout>
6.Snackbar
實(shí)現(xiàn):android.support.design.widget.Snackbar
- build.gradle(Module:app) : 導(dǎo)入Material Design Library
dependencies {
...
compile 'com.android.support:design:25.0.1'
}
- MainActivity.java : 點(diǎn)擊彈出Snackbar
Snackbar.make(view, "Snackbar comes out", Snackbar.LENGTH_LONG)
.setAction("Action", new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,
"Toast comes out",
Toast.LENGTH_SHORT).show();
}
}).show();
7.CoordinatorLayout
實(shí)現(xiàn):android.support.design.widget.CoordinatorLayout
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Your Scrollable View -->
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<android.support.design.widget.AppBarLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:background="@color/colorPrimary"
android:layout_height="56dp"
app:contentInsetStart="0.0dp"
app:layout_scrollFlags="scroll|enterAlways">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:textColor="#fff"
android:textSize="16sp"
android:gravity="center_horizontal"/>
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="45dp"
app:tabTextColor="#666"
app:tabSelectedTextColor="@color/colorPrimary" />
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
其中河劝,一個(gè)可以滾動(dòng)的組件法焰,例如RecyclerView、ListView(這里需要注意的是怠李,貌似只支持RecyclerView、ListView,如果你用一個(gè)ScrollView蘑拯,是沒(méi)有效果的)。如果:
1兜粘、給這個(gè)可滾動(dòng)組件設(shè)置了layout_behavior
2申窘、給另一個(gè)控件設(shè)置了layout_scrollFlags
那么,當(dāng)設(shè)置了layout_behavior的控件滑動(dòng)時(shí)孔轴,就會(huì)觸發(fā)設(shè)置了layout_scrollFlags的控件發(fā)生狀態(tài)的改變剃法。
設(shè)置的layout_scrollFlags的選項(xiàng):
- scroll - 想滾動(dòng)就必須設(shè)置這個(gè)。
- enterAlways - 實(shí)現(xiàn)quick return效果, 當(dāng)向下移動(dòng)時(shí)路鹰,立即顯示View(比如Toolbar)贷洲。
- exitUntilCollapsed - 向上滾動(dòng)時(shí)收縮View,但可以固定Toolbar一直在上面晋柱。
- enterAlwaysCollapsed - 當(dāng)你的View已經(jīng)設(shè)置minHeight屬性又使用此標(biāo)志時(shí)优构,你的View只能以最小高度進(jìn)入,只有當(dāng)滾動(dòng)視圖到達(dá)頂部時(shí)才擴(kuò)大到完整高度雁竞。
PS : 所有使用scroll flag的view都必須定義在沒(méi)有使用scroll flag的view的前面钦椭,這樣才能確保所有的view從頂部退出,留下固定的元素浓领。
8.CollapsingToolbarLayout
實(shí)現(xiàn):android.support.design.widget.CollapsingToolbarLayout
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Your Scrollable View -->
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<android.support.design.widget.AppBarLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsingToolbarLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="@color/colorPrimary"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="32dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="@+id/backdrop"
android:layout_width="match_parent"
android:layout_height="200dp"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
android:src="@drawable/navigation_header"
app:layout_collapseMode="parallax"/>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
我們?cè)贑ollapsingToolbarLayout中設(shè)置了一個(gè)ImageView和一個(gè)Toolbar玉凯。并把這個(gè)CollapsingToolbarLayout放到AppBarLayout中作為一個(gè)整體。
1联贩、在CollapsingToolbarLayout中:
- 設(shè)置了layout_scrollFlags的值(詳細(xì)見(jiàn)上)漫仆,其中還設(shè)置了一些屬性,簡(jiǎn)要說(shuō)明一下:
- contentScrim - 設(shè)置當(dāng)完全CollapsingToolbarLayout折疊(收縮)后的背景顏色泪幌。
- expandedTitleMarginStart - 設(shè)置擴(kuò)張時(shí)候(還沒(méi)有收縮時(shí))title向左填充的距離盲厌。
2署照、在ImageView中:
- 設(shè)置了layout_collapseMode (折疊模式) - 有兩個(gè)值:
- pin - 設(shè)置為這個(gè)模式時(shí),當(dāng)CollapsingToolbarLayout完全收縮后吗浩,Toolbar還可以保留在屏幕上建芙。
- parallax - 設(shè)置為這個(gè)模式時(shí),在內(nèi)容滾動(dòng)時(shí)懂扼,CollapsingToolbarLayout中的View(比如ImageView)也可以同時(shí)滾動(dòng)禁荸,實(shí)現(xiàn)視差滾動(dòng)效果,通常和layout_collapseParallaxMultiplier(設(shè)置視差因子)搭配使用阀湿。
- layout_collapseParallaxMultiplier(視差因子) - 設(shè)置視差滾動(dòng)因子赶熟,值為:0~1。
3陷嘴、在Toolbar中:
- 設(shè)置了layout_collapseMode(折疊模式):為pin映砖。
綜上分析:當(dāng)設(shè)置了layout_behavior的控件響應(yīng)起了CollapsingToolbarLayout中的layout_scrollFlags事件時(shí),ImageView會(huì)有視差效果的向上滾動(dòng)移除屏幕灾挨,當(dāng)開(kāi)始折疊時(shí)CollapsingToolbarLayout的背景色(也就是Toolbar的背景色)就會(huì)變?yōu)槲覀冊(cè)O(shè)置好的背景色邑退,Toolbar也一直會(huì)固定在最頂端。
PS:使用CollapsingToolbarLayout時(shí)必須把title設(shè)置到CollapsingToolbarLayout上劳澄,設(shè)置到Toolbar上不會(huì)顯示地技。即:
- 設(shè)置標(biāo)題:mCollapsingToolbarLayout.setTitle(" ");
- 設(shè)置擴(kuò)張時(shí)候的title顏色:mCollapsingToolbarLayout.setExpandedTitleColor();
- 設(shè)置收縮后在Toolbar上顯示時(shí)的title的顏色:mCollapsingToolbarLayout.setCollapsedTitleTextColor();