android开发之recycleView的使用

一、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));
    }

由上而下的多布局就基本创建完成。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,076评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,658评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,732评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,493评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,591评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,598评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,601评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,348评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,797评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,114评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,278评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,953评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,585评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,202评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,180评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,139评论 2 352

推荐阅读更多精彩内容

  • RecycleView多种布局显示 1.前言 我们知道ListView多种布局显示用到两个方法一个getItemV...
    TheTwo阅读 7,920评论 15 56
  • Android四大组件: activity: activity的生命周期:activity是context的子类,...
    梧桐树biu阅读 639评论 0 2
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,014评论 25 707
  • 3件事: 1. 早上的手忙脚乱及急躁。 2. 环境带来的倦怠。 3. 处理claim的效率及协助。 10点开会,超...
    冰羯阅读 208评论 0 0
  • 不能再挥霍钱财了,你所说的把最后的这几年过得精彩,是以父母的逐渐衰老为代价的。不要只顾着奋斗,只顾着享受而忽略了父...
    奋斗的小柯基阅读 77评论 0 0