一、recycleView的使用场景
1、多种样式的列表
2、宫格和列表同时存在
3、分类列表比如通讯录城市列表等
二、基本使用
在布局文件中声明
在Activity中使用
Adapter的创建
添加单击事件
Item动画
更新数据
1、在布局文件中声明
<android.support.v7.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
2、在Activity中使用
复制代码
// 1,找到这个View
mRecyclerView = (RecyclerView)findViewById(R.id.my_recycler_view);
// 2,设置布局管理LayoutManager
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
// 3,(可选)如果可以确定每个item的高度是固定的,设置这个选项可以提高性能
mRecyclerView.setHasFixedSize(true);
// 4,设置Adapter
mRecyclerView.setAdapter(new MyAdapter());
复制代码
目前SDK中提供了三种自带的LayoutManager:
LinearLayoutManager
GridLayoutManager
StaggeredGridLayoutManager
LinearLayoutManager
mLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
GridLayoutManager
mLayoutManager = new GridLayoutManager(context,columNum);
mRecyclerView.setLayoutManager(mLayoutManager);
注:在Grid布局中也可以设置列表的Orientation属性,来实现横向和纵向的Grid布局。
StaggeredGridLayoutManager
瀑布流就使用StaggeredGridLayoutManager吧,具体使用方法见http://blog.csdn.net/duanymin/article/details/44979355
3、Adapter的创建
复制代码
1 public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
2 public String[] datas = null;
3 public MyAdapter(String[] datas) {
4 this.datas = datas;
5 }
6 //创建新View,被LayoutManager所调用
7 @Override
8 public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
9 View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item,viewGroup,false);
10 ViewHolder vh = new ViewHolder(view);
11 return vh;
12 }
13 //将数据与界面进行绑定的操作
14 @Override
15 public void onBindViewHolder(ViewHolder viewHolder, int position) {
16 viewHolder.mTextView.setText(datas[position]);
17 }
18 //获取数据的数量
19 @Override
20 public int getItemCount() {
21 return datas.length;
22 }
23 //自定义的ViewHolder,持有每个Item的的所有界面元素
24 public static class ViewHolder extends RecyclerView.ViewHolder {
25 public TextView mTextView;
26 public ViewHolder(View view){
27 super(view);
28 mTextView = (TextView) view.findViewById(R.id.text);
29 }
30 }
31 }
复制代码
4、添加单击事件
复制代码
// 1 定义接口
public static interface OnRecyclerViewItemClickListener {
void onItemClick(View view , DataModel data);
}
// 2 添加接口和设置接口的方法
private OnRecyclerViewItemClickListener mOnItemClickListener = null;
public void setOnItemClickListener(OnRecyclerViewItemClickListener listener) {
this.mOnItemClickListener = listener;
}
// 3 在Adapter实现OnClickListener方法
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements View.OnClickListener{
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, final int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
ViewHolder vh = new ViewHolder(view);
//将创建的View注册点击事件
view.setOnClickListener(this);
return vh;
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, final int i) {
viewHolder.mTextView.setText(datas.get(i).title);
//将数据保存在itemView的Tag中,以便点击时进行获取
viewHolder.itemView.setTag(datas.get(i));
}
...
@Override
public void onClick(View v) {
if (mOnItemClickListener != null) {
//注意这里使用getTag方法获取数据
}
...
}
复制代码
在Activity中
复制代码
mAdapter = new MyAdapter(getDummyDatas());
mRecyclerView.setAdapter(mAdapter);
mAdapter.setOnItemClickListener(new MyAdapter.OnRecyclerViewItemClickListener() {
@Override
public void onItemClick(View view, DataModel data) {
//DO your fucking bussiness here!
}
});
复制代码
5、Item动画
// 设置item动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
如果要自定义动画效果需要继承ItemAnimator
GitHub上的动画效果:RecyclerViewItemAnimators
6、更新数据
这里更新数据集不是用adapter.notifyDataSetChanged()而是 notifyItemInserted(position)与notifyItemRemoved(position) 否则没有动画效果。
为adapter中添加两个方法:
复制代码
public void addData(int position) {
mDatas.add(position, "Insert One");
notifyItemInserted(position);
}
public void removeData(int position) {
mDatas.remove(position);
notifyItemRemoved(position);
}
三、复杂布局的实现逻辑
1、RecycleView的关键成员
A、Type:类型 通过getItemViewType(position)获取
B、Holder(熟悉ListView的都知道)
1、holder在recycleView中保存view的单位
2、记录recycleview中的基本信息
C、RecycleView.Recycler(保存了一些缓存机制)
1、Recycleview中被缓存的holder
2、多个RecycleView共用一个RecycleredPool(缓存池)
3、配置缓存size
2、getItemViewType
a、ItemType保存在Holder中
B、Holder根据position被缓存在cache中
RecycleView之所以流畅,就是当我们需要复用的时候系统会在cache中拿holder,进而实现使用流畅。
C、遍历缓存中的holder,如果Type一致就返回。
3、多布局的实现
A、复写getItemViewType方法
B、需要处理getItemCount方法
C、按照获取的Type处理onCreateViewHolder和OnBinderViewHolder。
4、数据的处理
A、把多个数据类型都包装进一个Object(不利于查找)
B、封装RecycleView.Adapter,把一些不同的item当做header添加进来
5、多布局类型运行流程
滚动布局——》通过getItemViewType获取Type类型——》根据类型寻找holder——》如果holder为null执行adapter.createrHolder,否则执行adapter.bindViewHolder.
四、通过LinearLayoutManager实现多布局代码:
recyclerView = (RecyclerView) findViewById(R.id.recycleview);
recyclerView.setLayoutManager(new LinearLayoutManager(this,
LinearLayoutManager.VERTICAL,false));
adapter = new MyRecyclerViewAdapter(this);
recyclerView.setAdapter(adapter);
initData();
/**
* 模拟数据
/
private void initData(){
List<DataBean> dataBeanList = new ArrayList<>();
for(int i=0;i<20;i++){
int type = (int) ((Math.random()3)+1);
DataBean dataBean = new DataBean();
dataBean.titelColor = typeColors[type-1];
dataBean.type = type;
dataBean.contentColor = typeColors[(type+1)%3];
dataBean.content = "content"+i;
dataBean.name = "name"+i;
dataBeanList.add(dataBean);
}
adapter.addData(dataBeanList);
}
}
多布局就是不同的Viewholder加载渲染不同的布局,通过Type进行区分。
布局一和所对应的viewHolder、
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:gravity="center_vertical"
android:layout_height="60dp">
<ImageView
android:layout_marginLeft="20dp"
tools:src="@mipmap/ic_launcher"
android:id="@+id/title_image"
android:layout_width="45dp"
android:layout_height="45dp" />
<TextView
android:id="@+id/name_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="测试名字"
android:layout_marginLeft="10dp"
/>
</LinearLayout>
/**
* 布局一viewholder
* Created by zzj on 2017/2/16.
*/
public class TypeOneHolder extends TypeAbstractHolder {
private ImageView titel_image;
private TextView name_tv;
public TypeOneHolder(View itemView) {
super(itemView);
titel_image = (ImageView) itemView.findViewById(R.id.title_image);
name_tv = (TextView) itemView.findViewById(R.id.name_tv);
}
@Override
public void onBindData(DataBean dataBean) {
titel_image.setImageResource(dataBean.titelColor);
name_tv.setText(dataBean.name);
}
}
布局二、
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:gravity="center_vertical"
android:layout_height="60dp">
<ImageView
android:layout_marginLeft="20dp"
tools:src="@mipmap/ic_launcher"
android:id="@+id/title_image"
android:layout_width="45dp"
android:layout_height="45dp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:id="@+id/name_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="测试名字"
android:layout_marginLeft="10dp"
/>
<TextView
android:id="@+id/content_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="测试内容"
android:layout_marginTop="5dp"
android:layout_marginLeft="10dp"
/>
</LinearLayout>
</LinearLayout>
/**布局二viewholder
* Created by zzj on 2017/2/16.
*/
public class TypeTwoHolder extends TypeAbstractHolder {
private ImageView titel_image;
private TextView name_tv,content_tv;
public TypeTwoHolder(View itemView) {
super(itemView);
titel_image = (ImageView) itemView.findViewById(R.id.title_image);
name_tv = (TextView) itemView.findViewById(R.id.name_tv);
content_tv = (TextView) itemView.findViewById(R.id.content_tv);
}
@Override
public void onBindData(DataBean dataBean) {
titel_image.setImageResource(dataBean.titelColor);
name_tv.setText(dataBean.name);
content_tv.setText(dataBean.content);
}
}
布局三、
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:gravity="center_vertical"
android:layout_height="60dp">
<ImageView
android:layout_marginLeft="20dp"
tools:src="@mipmap/ic_launcher"
android:id="@+id/title_image"
android:layout_width="45dp"
android:layout_height="45dp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:id="@+id/name_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="测试名字"
android:layout_marginLeft="10dp"
/>
<TextView
android:id="@+id/content_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="测试内容"
android:layout_marginTop="5dp"
android:layout_marginLeft="10dp"
/>
</LinearLayout>
<ImageView
android:id="@+id/content_image"
tools:src="@mipmap/ic_launcher"
android:layout_width="100dp"
android:layout_height="40dp"
android:layout_marginLeft="60dp"
/>
</LinearLayout>
/**布局三viewholder
* Created by zzj on 2017/2/16.
*/
public class TypeThreeHolder extends TypeAbstractHolder {
private ImageView titel_image,content_image;
private TextView name_tv,content_tv;
public TypeThreeHolder(View itemView) {
super(itemView);
titel_image = (ImageView) itemView.findViewById(R.id.title_image);
name_tv = (TextView) itemView.findViewById(R.id.name_tv);
content_tv = (TextView) itemView.findViewById(R.id.content_tv);
content_image = (ImageView) itemView.findViewById(R.id.content_image);
}
@Override
public void onBindData(DataBean dataBean) {
titel_image.setImageResource(dataBean.titelColor);
name_tv.setText(dataBean.name);
content_tv.setText(dataBean.content);
content_image.setImageResource(dataBean.contentColor);
}
}
ViewHolder的父类
public abstract class TypeAbstractHolder extends RecyclerView.ViewHolder {
public TypeAbstractHolder(View itemView) {
super(itemView);
}
/**
* 绑定数据
* @param dataBean
*/
public abstract void onBindData(DataBean dataBean);
}
在Adapter中创建绑定ViewHolder
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType){
case DataBean.TYPE_ONE:
return new TypeOneHolder(inflater.inflate(R.layout.item_recycleview_linear_type_one,parent,false));
case DataBean.TYPE_TWO:
return new TypeTwoHolder(inflater.inflate(R.layout.item_recycleview_linear_type_two,parent,false));
case DataBean.TYPE_THREE:
return new TypeThreeHolder(inflater.inflate(R.layout.item_recycleview_linear_type_three,parent,false));
}
return null;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((TypeAbstractHolder)holder).onBindData(dataBeanList.get(position));
}
由上而下的多布局就基本创建完成。
网友评论