Android學習筆記之Material Design實戰
Material Design是在2014年Google I/O大會上重磅推出的一套全新的介面設計語言,是由谷歌的設計工程師們基於傳統優秀的設計原則,結合豐富的創意和科學技術所發明的一套全新的介面設計語言,包含了視覺、運動、互動效果等特性。
為支援Material Design UI設計風格,谷歌在2015年的Google I/O大會上推出了一個Design Support庫,這個庫將Material Design中最具代表性的一些控制元件和效果進行了封裝,使得開發者在即使不瞭解Material Design的情況下也能非常輕鬆地將自己地應用Material化。
一、Toolbar
Toolbar將會是我們接觸地第一個Material控制元件,雖說對於Toolbar你暫時應該還是比較陌生地,但是對於它地另一個相關控制元件ActionBar,你應該有點熟悉。每個活動最頂部地那個標題欄其實就i是ActionBar,不過ActionBar由於其設計地原因,被限定只能位於活動地頂部,從而不能實現一些Material Design的效果,因此官方現在已經不再建議使用ActionBar了。
Toolbar的強大之處在於,它不僅繼承了ActionBar的所有功能,而且靈活性很高,可以配合其他控制元件來完成一些Material Design的效果。
首先你要知道,任何一個新建的專案,預設都是會顯示ActionBar的,那麼這個ActionBar到底是哪裡來的呢?其實這是根據專案中指定的主題來顯示的,AndroidManifest.xml中如下所示:
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportRtl="true"
android:theme=‘@style/AppTheme"
>
...
</application>
可以看到,這裡使用android:theme屬性指定了一個AppTheme的主題,那麼這個AppTheme又是再哪裡定義的呢?開啟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>
</resources>
這裡定義了一個叫AppTheme的主題,然後指定它的parent主題是Theme.AppCompat.Light.DarkActionBar。這個DarkActionBar是一個深色的ActionBar主題,我們之前所有的專案中自帶的ActionBar就是因為指定了這個主題才出現的。
而現在我們準備使用Toolbar來替代ActionBar,因此需要指定一個不帶ActionBar的主題,通常Theme.AppCompat.NoActionBar和ThemeAppCompat.Light.NoActionBar這兩種主題可選,其中Theme.AppCompat.NoActionBar表示深色主題,它會將介面的主體顏色設成深色,陪襯顏色設成淡色。而Theme.AppCompat.Light.NoActionBar表示淡色主題,他會將介面的主體顏色設成淡色,陪襯顏色設成深色。具體效果你可以試一試,這裡由於我們之前的程式一直都是以淡色為主的,那麼我就選用淡色主題了了,如下所示:
<resources>
<!--Base application theme -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- 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中的屬性重寫,這裡重寫了colorPrimary、colorPrimaryDark和colorAccent這3個屬性的顏色。除上述3個屬性之外,我們還可以通過textColorPrimary、windowBackground和navigationBarColor等屬性來控制更多位置的顏色。不過唯獨colorAccent這個屬性比較難理解,它不只是用來指定這樣一個按鈕的顏色,而是更多表達了一個強調的意思,比如一些控制元件的選中狀態也會使用這個顏色。
現在我們已經將ActionBar隱藏起來了,那麼接下來看一看如何使用Toolbar來替代ActionBar。修改activity_material_design_test.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>
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="@android:drawable/ic_menu_close_clear_cancel" android:title="Backup" app:showAsAction="always" /> <item android:id="@+id/delete" android:icon="@android:drawable/ic_menu_delete" android:title="Delete" app:showAsAction="ifRoom" /> <item android:id="@+id/settings" android:icon="@android:drawable/ic_menu_more" android:title="Settings" app:showAsAction="never" /> </menu>
使用app:showAsAction來指定按鈕的顯示位置,之所以這裡再次使用了app名稱空間,同樣是為了能夠相容低版本的系統。showAsAction主要有以下幾種值可選:always表示永遠顯示在Toolbar中,如果螢幕控制元件不夠則不顯示;ifRoom表示螢幕控制元件足夠的情況下顯示在Toolbar中,不夠的化就顯示在選單當中;never則表示永遠顯示在選單當中。注意,Toolbar中的action按鈕只會顯示圖示,選單中的action按鈕只會顯示文字。
主程式碼如下:
public class MaterialDesignTestActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_material_design_test); initUI(); } public void initUI(){ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); ActionBar actionBar = getSupportActionBar(); if(actionBar!=null){ actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeAsUpIndicator(R.mipmap.ic_launcher); }} public boolean onCreateOptionsMenu(Menu menu){ getMenuInflater().inflate(R.menu.toolbar,menu); return true; } 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; } }
二、滑動選單
滑動選單可以說是Material Design中最常見的效果之一了。所謂的滑動選單就是將一些選單選項隱藏起來,而不是放置在主螢幕上,然後通過滑動的方式將選單顯示出來。這種方式既節省了螢幕空間,又實現了非常好的動畫效果,是Material Design中推薦的做法。
1.DrawerLayout
activity_material_design_test.xml中程式碼如下:
<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:text="This is menu"
android:textSize="30sp"
android:background="#FFF"
/>
</android.support.v4.widget.DrawerLayout>
可以看到,這裡最外層的控制元件使用了DrawerLayout,這個控制元件是由support-v4庫提供的。DrawerLayout中放置了兩個直接子控制元件,第一個子空間是FrameLayout,用於作為主螢幕顯示的內容;第二個子控制元件這裡使用了一個TextView,用於作為滑動選單中顯示的內容,起始使用什麼都可以,DrawerLayout並沒有限制只能使用固定的控制元件。
但是關於第二個子控制元件有一點需要注意,layout_gravity這個屬性是必須指定的,因為我們需要告訴DrawerLayout滑動選單是在螢幕的左邊還是右邊,指定left表示滑動選單在左邊,指定right滑動選單在右邊,這裡指定start,表示會根據系統語言進行判斷。
public class MaterialDesignTestActivity extends AppCompatActivity { private DrawerLayout mDrawerLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_material_design_test); initUI(); } public void initUI(){ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawaer_layout); ActionBar actionBar = getSupportActionBar(); if(actionBar!=null){ actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeAsUpIndicator(R.mipmap.ic_launcher); } /*findViewById(R.id.tv_menu).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mDrawerLayout.closeDrawers(); } });*/ } public boolean onCreateOptionsMenu(Menu menu){ getMenuInflater().inflate(R.menu.toolbar,menu); return true; } public boolean onOptionsItemSelected(MenuItem item){ switch(item.getItemId()){ case android.R.id.home: mDrawerLayout.openDrawer(GravityCompat.START); break; 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; } }
2.NavigationView
NavigationView是Design Support庫中提供的一個控制元件,它不僅是嚴格按照MaterialDesign的要求來進行設計的,而且還可以將滑動選單頁面的實現變得非常簡單。
首先,這個控制元件是Design Support庫中提供的,俺麼我們就需要將這個庫引入到專案中才行。開啟app/build.gradle檔案,再dependencies閉包中新增如下內容:
dependencies{
compile fileTree(dir:'libs',include:['*.jar'])
compile 'com.android.support.appcompat-v7:24.2.1'
testCompile 'junit:junit:4.12'
compile 'com.android.support;design;24.2.1'
compile 'de.hdodenhof:circleimageview:2.1.0'
}
這裡添加了兩行依賴關係,第一行就是Design Support庫,第二行是一個開源專案CircleImageView,它可以用來輕鬆實現圖片圖形化的功能,我們待會就會用到它。CircleImageView的專案主頁地址是:https://github.com/hdodenhof/CircleImageView。
在開始使用之前,我們還需要提前準備好兩個東西:menu和headerLayout。menu是用來在NavigationView中顯示具體的選單項的,headerLayout則是用來在NavigationView中顯示頭部佈局的。
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="@android:drawable/ic_menu_call" android:title="Call" /> <item android:id="@+id/nav_friends" android:icon="@android:drawable/ic_menu_agenda" android:title="Friends" /> <item android:id="@+id/nav_location" android:icon="@android:drawable/ic_menu_mylocation" android:title="Location" /> <item android:id="@+id/nav_mail" android:icon="@android:drawable/ic_menu_report_image" android:title="Mail" /> <item android:id="@+id/nav_task" android:icon="@android:drawable/ic_menu_recent_history" android:title="Tasks" /> </group> </menu>
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:padding="10dp" android:background="?attr/colorPrimary" > <de.hdodenhof.circleimageview.CircleImageView android:id="@+id/icon_iamge" android:layout_width="70dp" android:layout_height="70dp" android:src="@mipmap/ic_launcher" android:layout_centerInParent="true" /> <TextView android:id="@+id/mail" 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/username" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@id/mail" android:text="Tony Green" android:textColor="#FFF" android:textSize="14sp" /> </RelativeLayout>
修改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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/drawaer_layout" > <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:id="@+id/tv_menu" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="start" android:text="This is menu" android:textSize="30sp" android:background="#FFF" />--> <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:menu="@menu/nav_menu" app:headerLayout="@layout/nav_header" /> </android.support.v4.widget.DrawerLayout>
這裡通過app:menu和app:headerLayout屬性將我們剛才準備好的menu和headerLayout設定了進去,這樣NavigationView就定義完成了。
public class MaterialDesignTestActivity extends AppCompatActivity { private DrawerLayout mDrawerLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_material_design_test); initUI(); } public void initUI(){ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawaer_layout); NavigationView navView = (NavigationView) findViewById(R.id.nav_view); ActionBar actionBar = getSupportActionBar(); if(actionBar!=null){ actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeAsUpIndicator(R.mipmap.ic_launcher); } navView.setCheckedItem(R.id.nav_call); navView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener(){ @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { mDrawerLayout.closeDrawers(); return true; } }); /*findViewById(R.id.tv_menu).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mDrawerLayout.closeDrawers(); } });*/ } public boolean onCreateOptionsMenu(Menu menu){ getMenuInflater().inflate(R.menu.toolbar,menu); return true; } public boolean onOptionsItemSelected(MenuItem item){ switch(item.getItemId()){ case android.R.id.home: mDrawerLayout.openDrawer(GravityCompat.START); break; 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.FloatingActionButton
FloatingActionButton是Design Support庫中提供的一個控制元件,這個控制元件可以幫助我們比較輕鬆地實現懸浮按鈕地效果。
佈局程式碼如下所示:
<?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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/drawaer_layout" > <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" /> <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="@android:drawable/ic_menu_share" app:elevation="8dp" /> </FrameLayout> </android.support.v4.widget.DrawerLayout>
這裡使用app:elevation屬性來給FloatingActionButton指定一個高度值,高度值越大,投影範圍也越大,但是投影效果越淡,高度值越小,投影範圍也越小,但是投影效果越濃。
程式碼中FloatingActionButton點選事件處理如下:
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View view) { Toast.makeText(MaterialDesignTestActivity.this,"FAB clicked",Toast.LENGTH_SHORT).show(); } });
2.Snackbar
提示工具Snackbar並不是Toast的替代品,它們兩者之間有著不同的應用場景。Toast的作用是告訴使用者現在發生了什麼事情,但同時使用者只能被動接收這個事情,因為沒有什麼辦法讓使用者進行選擇。而Snackbar則在這方面進行了擴充套件,它允許在提示當中加入一個可互動按鈕,當用戶點選按鈕的時候可以執行一些額外的邏輯操作。打個比方,如果我們在執行刪除操作的時候只彈出一個Toast提示,那麼使用者要是誤刪了後果很嚴重,但是如果我們增加一個Undo按鈕,就相當於給使用者提供了一種彌補措施,從而大大降低了事故發生的概率,提升了使用者體驗。
Snackbar的用法也非常簡單,它和Toast是基本相似的,只不過可以額外增加一個按鈕的點選事件。
程式碼中實現如下所示:
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View view) { Snackbar.make(view,"Data delete", Snackbar.LENGTH_SHORT). setAction("Undo",new View.OnClickListener(){ @Override public void onClick(View view) { Toast.makeText(MaterialDesignTestActivity.this,"Data restored",Toast.LENGTH_SHORT).show(); } }).show(); } });
Snackbar的make()方法來建立一個Snackbar物件,make()方法的第一個引數需要傳入一個View,只要是當前姐買你佈局的任意一個View都可以,Snackbar會使用這個View來自動查詢最外層的佈局,用於展示Snackbar。第二個引數就是Snackbar中顯示的內容,第三個引數是Snackbar顯示的時長。接著又呼叫了一個setAction()方法來設定一個動作,從而讓Snackbar不僅僅是一個提示,而是可以和使用者進行互動的。最後呼叫show()方法讓Snackbar顯示出來。
不管是出現還是消失,Snackbar都是帶有動畫小夥的,因此視覺體驗也會比較好。
不過你有沒有發現一個bug,這個Snackbar竟然將我們的懸浮按鈕給遮擋住了。雖然說也不是什麼重大問題,因為Snackbar過一會兒就會自動消失,但這種使用者體驗總歸是不友好的。有沒有什麼辦法能解決一下呢?當然有,只需要藉助CoordinatorLayout就可以輕鬆解決。
3.CoordinatorLayout
CoordinatorLayout可以說是一個加強版的FrameLayout,這個庫也是由Design Support庫提供的。它在普通情況下的作用和FrameLayout基本一致。事實上,CoordinatorLayout可以監聽其所有子控制元件的各種事件,然後自動幫助我們做出最為合理的響應。
舉個簡單的例子,剛才彈出的Snackbar提示將懸浮按鈕遮擋住了,而如果我們能讓CoordinatorLayout監聽到Snackbar的彈出事件,那麼它會自動將內部的FloatingActionButton向上偏移,從而確保不會被Snackbar遮擋到。
將原佈局中的FrameLayout替換成CoordinatorLayout,程式碼如下:
<?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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/drawaer_layout" > <android.support.design.widget.CoordinatorLayout 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" /> <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="@android:drawable/ic_menu_share" app:elevation="8dp" /> </android.support.design.widget.CoordinatorLayout> <!--<TextView android:id="@+id/tv_menu" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="start" android:text="This is menu" android:textSize="30sp" android:background="#FFF" />--> <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:menu="@menu/nav_menu" app:headerLayout="@layout/nav_header" /> </android.support.v4.widget.DrawerLayout>
由於CoordinatorLayout本身就是一個加強版的FrameLayout,因此這種替換不會有任何的副作用。
可以看到,懸浮按鈕自動向上偏移了Snackbar的同等高度,從而確保不會被遮擋住,當Snackbar消失的時候,懸浮按鈕會自動向下偏移回到原來位置。
另外懸浮按鈕的向上和向下偏移也是伴隨著動畫效果的,且和Snackbar完全同步,整體效果看上去特別賞心悅目。
不過我們回過頭來再思考一下,剛才說的是CoordinatorLayout可以監聽其所有子控制元件的各種事件,但是Snackbar好像並不是CoordiantorLayout的子控制元件吧,為什麼它卻可以被監聽到呢?
其實道理很簡單,還記得我們再Snackbar的make()方法中傳入的第一個引數嗎?這個引數就是用來指定Snackbar是基於哪個View來出發的,剛才我們傳入的是FloatingActionButton本身,而其是CoordinatorLayout中的子控制元件,因此這個事件就理所應當能被監聽到了。你可以做個試驗,如果給Snackbar的make()方法出入一個DrawerLayout,那麼Snackbar就會再次遮擋住懸浮按鈕,因為DrawerLayout不是CoordinatorLayout的子控制元件,CoordinatorLayout也就無法監聽到Snackbar的彈出和隱藏事件了。
四、卡片式佈局
卡片式佈局也是Materials Design中提出的一個新概念,它可以讓頁面中的元素看起來就像是再卡片中一樣,並且還鞥你擁有圓角和投影。
1.CardView
CardView是用於實現卡片式佈局效果的重要控制元件,由appcompat-v7庫提供。實際上,CardView也是一個FrameLayout,只是額外提供了圓角和陰影等效果,看上去會有立體的感覺。
eg.
<android.support.v7.widget.CardView
android:layout_width=’match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius=”4dp“
app:elevation="5dp"
>
<TextView
android:id="@+id.info_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</android.support.v7.widget.CardView>
這裡定義了一個CardView佈局,我們可以通過app;cardCornerRadius屬性指定卡片圓角的弧度,數值遠大,圓角的弧度也越大。另外還可以通過app:elevation屬性指定卡片的高度,高度值越大,投影範圍也越大,但是投影效果越淡,高度值越小,投影範圍也越小,但是投影效果越濃。
新增波紋點選效果
預設情況,CardView是不可點選的,並且沒有任何的觸控反饋效果。觸控反饋動畫在使用者點選CardView時可以給使用者以視覺上的反饋。為了實現這種行為,你必須提供一下屬性:
<android.support.v7.widget.CardView
...
android:clickable="true"
android:foreground="?android:attr/selectableItemBackground">
...
</android.support.v7.widget.CardView>
使用android:foreground=”?android:attr/selectableItemBackground”可以使CardView點選產生波紋的效果,有觸控點向外擴散。
常見屬性
cardBackgroundColor -----》 設定cardview背景顏色
cardCornerRadius -----》設定cardview 圓角的半徑
cardElevation----》設定cardview的陰影
contentPadding-----》設定cardview的內間距
5.x上面可以設定點選水波紋效果
android:foreground="?attr/selectableItemBackground"
cardPreventCornerOverlap ------》防止api20之前圓角與內容重疊 ,在21以後不會重疊
cardUseCompatPadding ----》設定為true 可以為不同L版提供內間距相容 ,預設為false
eg.實現圖片列表
依賴庫:
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' testCompile 'junit:junit:4.12' compile 'com.android.support:design:25.3.1'compile 'com.github.bumptech.glide:glide:3.7.0' compile 'com.android.support:recyclerview-v7:25.3.1' compile 'de.hdodenhof:circleimageview:2.1.0' compile 'com.android.support:cardview-v7:25.3.1' }這裡添加了一個Glide庫的依賴。Glide是一個超級強大的圖片載入庫,它不僅可以用於載入本地圖片,還可以載入網路圖片、GIF圖片、甚至是本地視訊。最重要的是,Glide的用法非常簡單,只需一行程式碼就能輕鬆實現複雜的圖片載入功能。Glide的專案主頁地址是:https://github.com/bumptech.glide。主佈局程式碼:
<?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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/drawaer_layout" > <android.support.design.widget.CoordinatorLayout 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" /> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" /> <android.support.design.widget.FloatingActionButton android:id