Android L最新支持包推出兩個UI控件RecycleView和CardView。RecyclerView是更先進,更靈活的ListView,這是一個很大的進步,由於ListView是UI組件中最經常使用的控件之一。此外,CardView控件是一個全新的組件。在這篇教程中將解釋如何使用這兩個控件以及如何混合使用它們,首先來來深刻了解一下RecyclerView。android
正如前面說RecyclerView是更加靈活的ListView,儘管它引進了一些複雜的東西。咱們都知道如何在app中使用ListView,而且若是想要提升ListView的性能,那麼可使用一種叫ViewHolder的模式。這個模式由一個簡單類組成,它持有ListView中每一行所包含的UI組件的引用。這種模式避免列表顯示的時候老是查找那些UI組件。儘管該模式引進了這點好處但咱們仍能夠不使用這種模式來實現ListView。而RecyclerView強制咱們使用ViewHolder模式來提升系統的性能。爲了說明如何使用RecyclerView,咱們能夠建立一個簡單的app來顯示通信錄卡片列表。第一件事就是建立主佈局文件,RecyclerView很像ListView,咱們能夠用相同的方式來使用它們。app
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MyActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/cardList"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
你應該注意到上面的layout了,RecycleView位於Android支持庫中,因此咱們要修改bulid.gradle文件來包含該依賴。ide
dependencies {
...
compile 'com.android.support:recyclerview-v7:21.0.0-rc1'
}
如今就能夠在onCreate
方法中咱們來獲取RecycleView的引用而且配置它。佈局
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
RecyclerView recList = (RecyclerView) findViewById(R.id.cardList);
recList.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(this);
llm.setOrientation(LinearLayoutManager.VERTICAL);
recList.setLayoutManager(llm);
}
你會注意到ReclerView與ListView的區別,RecycleView須要一個佈局管理器,這個組件把列表項視圖放到了行裏面,來決定何時去循環視圖。這個庫提供了一個默認的佈局管理器叫作LinearLayoutManager
。性能
CardView UI組件在卡片裏面顯示更多信息。能夠自定義它的圓角、陰影等效果。如今用這個組件來展現通信信息。卡片將做爲RecyclerView的行,稍後咱們能看到如何集成這兩個組件,如今來定義該卡片的佈局。gradle
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/card_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
card_view:cardCornerRadius="4dp"
android:layout_margin="5dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="20dp"
android:background="@color/bkg_card"
android:text="contact det"
android:gravity="center_vertical"
android:textColor="@android:color/white"
android:textSize="14dp"/>
<TextView
android:id="@+id/txtName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Name"
android:gravity="center_vertical"
android:textSize="10dp"
android:layout_below="@id/title"
android:layout_marginTop="10dp"
android:layout_marginLeft="5dp"/>
<TextView
android:id="@+id/txtSurname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Surname"
android:gravity="center_vertical"
android:textSize="10dp"
android:layout_below="@id/txtName"
android:layout_marginTop="10dp"
android:layout_marginLeft="5dp"/>
<TextView
android:id="@+id/txtEmail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Email"
android:textSize="10dp"
android:layout_marginTop="10dp"
android:layout_alignParentRight="true"
android:layout_marginRight="150dp"
android:layout_alignBaseline="@id/txtName"/>
</RelativeLayout>
正如你所看到的,CardView使用很是簡單,這個組件在另一個支持庫中,如今來添加依賴:this
dependencies {
compile 'com.android.support:cardview-v7:21.0.0-rc1'
compile 'com.android.support:recyclerview-v7:21.0.0-rc1'
}
適配器組件提供數據信息,UI組件渲染這些信息,換而言之,一個適配器告訴UI顯示哪些信息。所以若是咱們想顯示通信信息,咱們須要給RecyclerView一個適配器。該適配器必須繼承RecyclerView.Adapter
。傳遞MyHolder類實現ViewHolder模式。spa
public class MyAdapter extends RecyclerView.Adapter<MyHolder> { ..... }
如今咱們須要覆蓋兩個方法以致於能實現咱們的邏輯。onCreateViewHolder
會在新的ViewHolder實例建立的時候被調用,onBindViewHolder
在SO試圖綁定數據的時候調用,換句話說,數據顯示在UI中時調用。code
在這個案例中,適配器幫咱們把RecyclerView和CardView結合,以前咱們定義的卡片佈局將做爲RecyclerView的通信錄列表的行。在作這個以前,咱們須要定義好數據模型(例如:哪些信息須要顯示),爲了達到這個目的,咱們能夠定義一個簡單類:xml
public class ContactInfo {
protected String name;
protected String surname;
protected String email;
protected static final String NAME_PREFIX = "Name_";
protected static final String SURNAME_PREFIX = "Surname_";
protected static final String EMAIL_PREFIX = "email_";
}
最後,準備建立適配器,若是你還記得以前說過的ViewHolder模式的話,咱們須要編寫代碼來實現它。
public static class ContactViewHolder extends RecyclerView.ViewHolder {
protected TextView vName;
protected TextView vSurname;
protected TextView vEmail;
protected TextView vTitle;
public ContactViewHolder(View v) {
super(v);
vName = (TextView) v.findViewById(R.id.txtName);
vSurname = (TextView) v.findViewById(R.id.txtSurname);
vEmail = (TextView) v.findViewById(R.id.txtEmail);
vTitle = (TextView) v.findViewById(R.id.title);
}
}
從代碼中看出,在類的構造方法中,咱們獲取到了定義在卡片佈局的試圖的引用,如今編寫適配器代碼:
public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ContactViewHolder> {
private List<ContactInfo> contactList;
public ContactAdapter(List<ContactInfo> contactList) {
this.contactList = contactList;
}
@Override
public int getItemCount() {
return contactList.size();
}
@Override
public void onBindViewHolder(ContactViewHolder contactViewHolder, int i) {
ContactInfo ci = contactList.get(i);
contactViewHolder.vName.setText(ci.name);
contactViewHolder.vSurname.setText(ci.surname);
contactViewHolder.vEmail.setText(ci.email);
contactViewHolder.vTitle.setText(ci.name + " " + ci.surname);
}
@Override
public ContactViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.
from(viewGroup.getContext()).
inflate(R.layout.card_layout, viewGroup, false);
return new ContactViewHolder(itemView);
}
public static class ContactViewHolder extends RecyclerView.ViewHolder {
...
}
}
在代碼實現中,綁定數據給試圖的時候咱們覆蓋了onBindViewHolder
。注意咱們再沒有去查找UI組件只是簡單地引用存儲在CcontactViewHolder中的信息。在onCreateViewHolder返回了ContactViewHolder填充佈局的行(這個例子中的CardView)。
運行app,你會看到以下結果: