一、recycleView的使用場(chǎng)景
1、多種樣式的列表
2撩嚼、宮格和列表同時(shí)存在
3、分類列表比如通訊錄城市列表等
二挖帘、基本使用
在布局文件中聲明
在Activity中使用
Adapter的創(chuàng)建
添加單擊事件
Item動(dòng)畫(huà)
更新數(shù)據(jù)
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中使用
復(fù)制代碼
// 1,找到這個(gè)View
mRecyclerView = (RecyclerView)findViewById(R.id.my_recycler_view);
// 2,設(shè)置布局管理LayoutManager
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
// 3拇舀,(可選)如果可以確定每個(gè)item的高度是固定的逻族,設(shè)置這個(gè)選項(xiàng)可以提高性能
mRecyclerView.setHasFixedSize(true);
// 4,設(shè)置Adapter
mRecyclerView.setAdapter(new MyAdapter());
復(fù)制代碼
目前SDK中提供了三種自帶的LayoutManager:
LinearLayoutManager
GridLayoutManager
StaggeredGridLayoutManager
LinearLayoutManager
mLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
GridLayoutManager
mLayoutManager = new GridLayoutManager(context,columNum);
mRecyclerView.setLayoutManager(mLayoutManager);
注:在Grid布局中也可以設(shè)置列表的Orientation屬性骄崩,來(lái)實(shí)現(xiàn)橫向和縱向的Grid布局聘鳞。
StaggeredGridLayoutManager
瀑布流就使用StaggeredGridLayoutManager吧薄辅,具體使用方法見(jiàn)http://blog.csdn.net/duanymin/article/details/44979355
3、Adapter的創(chuàng)建
復(fù)制代碼
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 //創(chuàng)建新View搁痛,被LayoutManager所調(diào)用
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 //將數(shù)據(jù)與界面進(jìn)行綁定的操作
14 @Override
15 public void onBindViewHolder(ViewHolder viewHolder, int position) {
16 viewHolder.mTextView.setText(datas[position]);
17 }
18 //獲取數(shù)據(jù)的數(shù)量
19 @Override
20 public int getItemCount() {
21 return datas.length;
22 }
23 //自定義的ViewHolder长搀,持有每個(gè)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 }
復(fù)制代碼
4、添加單擊事件
復(fù)制代碼
// 1 定義接口
public static interface OnRecyclerViewItemClickListener {
void onItemClick(View view , DataModel data);
}
// 2 添加接口和設(shè)置接口的方法
private OnRecyclerViewItemClickListener mOnItemClickListener = null;
public void setOnItemClickListener(OnRecyclerViewItemClickListener listener) {
this.mOnItemClickListener = listener;
}
// 3 在Adapter實(shí)現(xiàn)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);
//將創(chuàng)建的View注冊(cè)點(diǎn)擊事件
view.setOnClickListener(this);
return vh;
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, final int i) {
viewHolder.mTextView.setText(datas.get(i).title);
//將數(shù)據(jù)保存在itemView的Tag中鸡典,以便點(diǎn)擊時(shí)進(jìn)行獲取
viewHolder.itemView.setTag(datas.get(i));
}
...
@Override
public void onClick(View v) {
if (mOnItemClickListener != null) {
//注意這里使用getTag方法獲取數(shù)據(jù)
}
...
}
復(fù)制代碼
在Activity中
復(fù)制代碼
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!
}
});
復(fù)制代碼
5源请、Item動(dòng)畫(huà)
// 設(shè)置item動(dòng)畫(huà)
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
如果要自定義動(dòng)畫(huà)效果需要繼承ItemAnimator
GitHub上的動(dòng)畫(huà)效果:RecyclerViewItemAnimators
6、更新數(shù)據(jù)
這里更新數(shù)據(jù)集不是用adapter.notifyDataSetChanged()而是 notifyItemInserted(position)與notifyItemRemoved(position) 否則沒(méi)有動(dòng)畫(huà)效果彻况。
為adapter中添加兩個(gè)方法:
復(fù)制代碼
public void addData(int position) {
mDatas.add(position, "Insert One");
notifyItemInserted(position);
}
public void removeData(int position) {
mDatas.remove(position);
notifyItemRemoved(position);
}
三谁尸、復(fù)雜布局的實(shí)現(xiàn)邏輯
1、RecycleView的關(guān)鍵成員
A纽甘、Type:類型 通過(guò)getItemViewType(position)獲取
B良蛮、Holder(熟悉ListView的都知道)
1、holder在recycleView中保存view的單位
2悍赢、記錄recycleview中的基本信息
C决瞳、RecycleView.Recycler(保存了一些緩存機(jī)制)
1、Recycleview中被緩存的holder
2左权、多個(gè)RecycleView共用一個(gè)RecycleredPool(緩存池)
3皮胡、配置緩存size
2、getItemViewType
a赏迟、ItemType保存在Holder中
B屡贺、Holder根據(jù)position被緩存在cache中
RecycleView之所以流暢,就是當(dāng)我們需要復(fù)用的時(shí)候系統(tǒng)會(huì)在cache中拿holder锌杀,進(jìn)而實(shí)現(xiàn)使用流暢甩栈。
C、遍歷緩存中的holder糕再,如果Type一致就返回量没。
3、多布局的實(shí)現(xiàn)
A突想、復(fù)寫(xiě)getItemViewType方法
B殴蹄、需要處理getItemCount方法
C、按照獲取的Type處理onCreateViewHolder和OnBinderViewHolder蒿柳。
4饶套、數(shù)據(jù)的處理
A漩蟆、把多個(gè)數(shù)據(jù)類型都包裝進(jìn)一個(gè)Object(不利于查找)
B垒探、封裝RecycleView.Adapter,把一些不同的item當(dāng)做header添加進(jìn)來(lái)
5怠李、多布局類型運(yùn)行流程
滾動(dòng)布局——》通過(guò)getItemViewType獲取Type類型——》根據(jù)類型尋找holder——》如果holder為null執(zhí)行adapter.createrHolder圾叼,否則執(zhí)行adapter.bindViewHolder.
四蛤克、通過(guò)LinearLayoutManager實(shí)現(xiàn)多布局代碼:
recyclerView = (RecyclerView) findViewById(R.id.recycleview);
recyclerView.setLayoutManager(new LinearLayoutManager(this,
LinearLayoutManager.VERTICAL,false));
adapter = new MyRecyclerViewAdapter(this);
recyclerView.setAdapter(adapter);
initData();
/**
* 模擬數(shù)據(jù)
/
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加載渲染不同的布局,通過(guò)Type進(jìn)行區(qū)分夷蚊。
布局一和所對(duì)應(yīng)的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="測(cè)試名字"
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="測(cè)試名字"
android:layout_marginLeft="10dp"
/>
<TextView
android:id="@+id/content_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="測(cè)試內(nèi)容"
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="測(cè)試名字"
android:layout_marginLeft="10dp"
/>
<TextView
android:id="@+id/content_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="測(cè)試內(nèi)容"
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);
}
/**
* 綁定數(shù)據(jù)
* @param dataBean
*/
public abstract void onBindData(DataBean dataBean);
}
在Adapter中創(chuàng)建綁定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));
}
由上而下的多布局就基本創(chuàng)建完成筋现。