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,你会看到以下结果: