recyclerview的使用

来源:互联网 发布:软件免责条款 编辑:程序博客网 时间:2024/05/06 17:11

一、recyclerview简介:


RecyclerView是support-v7包中的新组件,是一个强大的滑动组件,与经典的ListView相比,同样拥有item回收复用的功能,但是直接把viewholder的实现封装起来,用户只要实现自己的viewholder就可以了,该组件会自动帮你回收复用每一个item 
它不但变得更精简,也变得更加容易使用,而且更容易组合设计出自己需要的滑动布局。


api文档中对recyclerview的介绍:
RecyclerView is a more advanced and flexible version of ListView. This widget is a container for large sets of views that can be recycled and scrolled very efficiently. Use the RecyclerView widget when you have lists with elements that change dynamically.
简单说,它是ListView的进化,为了当你需要动态展示一组数据的时候就会需要它。


recyclerview相比listview的优点:
简介中提到的它封装了viewholder的回收复用。
RecyclerView使用布局管理器管理子view的位置,也就是说你再不用拘泥于ListView的线性展示方式,能够使用复杂的布局来展示一个动态组件。
可以设置加载和移除时的动画,方便做出各种动态浏览的效果
缺点:
  1.不能加头部,尾部
   2.


二、recyclerview可以实现的效果
 技术分享


技术分享







三、使用recyclerview的前期准备
RecyclerView 是 android-support-v7-21 版本中新增的一个 Widgets,除了需要导入v7包之外,还需要导入recyclerview的jar包
gradle里加入:
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:recyclerview-v7:23.1.1'


四、recyclerview的基本使用
基本的使用分为3个步骤


1.创建布局管理器,为recylerview设置布局管理器:调用Recylerview的setLayoutManager方法
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
//可以设置方向
linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(linearLayoutManager);


2.初始化要展示的数据集合
List<String> listData = new ArrayList<String>();
for (int i = 0; i < 100; i++) {
    listData.add(String.valueOf(i));
}




3.创建adapter,并为recylerview设置adapter,在adapter里定义并设置view holder
首先定义一个adapter类
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {


    List<String> mListDatas;
    Context mContext;


    MyAdapter(List<String> listDatas,Context context){
        mListDatas = listDatas;
        this.mContext = context;
    }


    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        ViewHolder holder = null;//new ViewHolder()


        View itemView = LayoutInflater.from(mContext).inflate(android.R.layout.simple_list_item_1,null);
        holder = new ViewHolder(itemView);


        return holder;
    }


    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.mTextView.setText(mListDatas.get(position));


    }


    @Override
    public int getItemCount() {
        return mListDatas.size();
    }


    public static class ViewHolder extends RecyclerView.ViewHolder {
       public TextView mTextView;


        public ViewHolder(View itemView) {
            super(itemView);


            mTextView = (TextView) itemView;
        }
    }
}


然后设置recylerview的adapter
recyclerView.setAdapter(new MyAdapter(listData,this));


五、recyclerview的其他功能点:




1.GridLayoutManager:网状布局的recylerview
GridLayoutManager layoutManager = new GridLayoutManager(this,2);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
如果方向为纵向,则第二个参数表示多少列,否则表示多少行


每个item的布局:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="180dp"
    android:background="@drawable/shape_item"
    android:gravity="center"
    android:textSize="50sp"
    android:layout_margin="5dp"
    android:id="@+id/tvitem">


</TextView>
shape为每个item设置背景:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
    <stroke android:color="@color/colorAccent" android:width=“0.1dp"/>
    <corners android:radius="5dp"/>


</shape>
设置跨列:
layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
    @Override
    public int getSpanSize(int position) {
        if (position == 2){
            return 2;
        }
        else {
            return 1;
        }
    }
});


2.实现瀑布流:
item的布局(一定要设置adjustviewbounds为true):
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:adjustViewBounds="true"
    android:id="@+id/ivitem"
    >


</ImageView>
实现代码:
public class WaterfallActivity extends AppCompatActivity {


    RecyclerView recyclerView;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_waterfall);


        recyclerView = (RecyclerView) findViewById(R.id.recyclerview_waterfall);


        StaggeredGridLayoutManager manager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(manager);


        //初始化数据集合
        List<Integer> listItems = new ArrayList<Integer>();
        for (int i = 0; i < 10; i++) {
            if(i%2 == 0){
                listItems.add(R.drawable.aaa);
            }
            else{
                listItems.add(R.drawable.ddd);
            }
        }


        //没有动画的adapter
        MyRecyclerAdapter adapter = new MyRecyclerAdapter(listItems,this);


        recyclerView.setAdapter(adapter);




    }


    class MyRecyclerAdapter extends RecyclerView.Adapter<MyViewHolder>{
        List<Integer> mListDatas;
        Context mContext;


        public MyRecyclerAdapter(List<Integer> listData,Context context){


            mListDatas = listData;
            mContext = context;
        }




        @Override
        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(mContext).inflate(R.layout.layout_waterfallitem,null);
            MyViewHolder viewHolder = new MyViewHolder(view);


            return viewHolder;
        }


        @Override
        public void onBindViewHolder(MyViewHolder holder, int position) {
            holder.im.setImageResource(mListDatas.get(position));
        }


        @Override
        public int getItemCount() {
            return mListDatas.size();
        }
    }


    private class MyViewHolder extends RecyclerView.ViewHolder {
        ImageView im;


        public MyViewHolder(View itemView) {
            super(itemView);
            im = (ImageView) itemView;
        }
    }
}


3.设置间距:
首先需要定义一个类继承ItemDecoration
class MyDecoration extends RecyclerView.ItemDecoration{
    int miSpace;
    public MyDecoration(int iSpace){
        miSpace = iSpace;
    }


    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {


        super.getItemOffsets(outRect, view, parent, state);
        outRect.bottom = miSpace;
        outRect.left = miSpace;




    }
}
然后通过这个类的对象设置间距
//设置间距
SpaceItemDecoration space = new SpaceItemDecoration(12);
recyclerView.addItemDecoration(space);


4.添加、删除item:
先删除adapter里list中对应位置的数据,然后调用notify方法,注意notify要指定删除数据的位置,用这种方式有动画
也可以用notifydatasetchanged方式,但是不会有动画
listData.remove(0);
mListDatas.notifyItemRemoved(0);


添加的时候,要调用方法让recyclerview跳到第一个位置,否则如果在第一个位置加item,要手动上拉才能看到:
mListDatas.add(0,R.drawable.bbb);
adapter.notifyItemInserted(0);
recyclerView.scrollToPosition(0);


5.item点击事件的响应
recyclerview并没有方法直接响应item的点击,但是可以在adapter里的ViewHolder里面是可以获取到每个item的根view的,而且viewholder里面有getLayoutPosition能获取当前点击的位置
所以可以在viewholder里对根view设置点击事件的响应
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener{
    ImageView mIvData;
    View mItemView;
    public MyViewHolder(View itemView) {
        super(itemView);
        mItemView = itemView;
        itemView.setOnLongClickListener(this);






        mIvData = (ImageView) itemView.findViewById(R.id.ivItem);
    }


    @Override
    public boolean onLongClick(View v) {
        int lPos = getLayoutPosition();
        removeData(lPos);


        return false;
    }
}
6.设置分割线:
导入分割线库:
https://github.com/yqritc/RecyclerView-FlexibleDivider
代码实现:
recyclerView.addItemDecoration(
        new VerticalDividerItemDecoration.Builder(this)
                .color(Color.RED)
                .size(10)
                .margin(20, 20)
                .build());
7.下拉刷新,上拉加载:
导入第三方库:
https://github.com/WuXiaolong/PullLoadMoreRecyclerView


gradle里导入库
dependencies {
  compile 'com.wuxiaolong.pullloadmorerecyclerview:library:1.0.4'
}


布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <com.wuxiaolong.pullloadmorerecyclerview.PullLoadMoreRecyclerView
        android:id="@+id/recyclerview_waterfall"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>


</RelativeLayout>
设置布局管理器:
refreshrecyclerView = (PullLoadMoreRecyclerView) findViewById(R.id.recyclerview_waterfall);
refreshrecyclerView.setStaggeredGridLayout(2);
设置刷新和加载监听


final MyRecyclerAdapter adapter = new MyRecyclerAdapter(listItems, this);


refreshrecyclerView.setAdapter(adapter);


refreshrecyclerView.setOnPullLoadMoreListener(new PullLoadMoreRecyclerView.PullLoadMoreListener() {
    @Override
    public void onRefresh() {
        listItems.add(0, R.drawable.aaa);
        adapter.notifyDataSetChanged();
        refreshrecyclerView.setPullLoadMoreCompleted();
    }


    @Override
    public void onLoadMore() {


        //2s后加载一张图片,只会不再提供加载功能
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                listItems.add(R.drawable.ddd);
                adapter.notifyDataSetChanged();
                refreshrecyclerView.setPullLoadMoreCompleted();
                refreshrecyclerView.setPushRefreshEnable(false);
            }
        }, 2000);


    }
});
PullLoadMoreRecyclerView得到recyclerview:
refreshrecyclerView.getRecyclerView()
比如要设置间隔:
refreshrecyclerView.getRecyclerView().addItemDecoration(new MyDecoration(10));




六、动画


第三方动画库:https://github.com/wasabeef/recyclerview-animators
注意:模拟器sdk版本需要5.0以上






七、多布局


adapter:
package com.example.zhouyi.recyclerviewtest;


import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;


import java.util.List;


/**
 * Created by zhouyi on 16/7/5.
 */
public class MyMutilAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private List<MyInfo> mlstDatas;
    private Context mContext;


    public MyMutilAdapter(List<MyInfo> lstDatas,Context context){
        mlstDatas = lstDatas;
        mContext = context;
    }


    @Override
    public int getItemViewType(int position) {
        //return super.getItemViewType(position);
        return mlstDatas.get(position).miType;
    }


    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {


        if (viewType == 0){
            View view = LayoutInflater.from(mContext).inflate(R.layout.layout_textitem,parent,false);
            MyTextViewHolder textViewHolder = new MyTextViewHolder(view);
            return textViewHolder;


        }else {
            View view = LayoutInflater.from(mContext).inflate(R.layout.layout_imageitem,parent,false);
            MyPicViewHolder picViewHolder = new MyPicViewHolder(view);
            return picViewHolder;
        }


        //return null;
    }


    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        int iType = getItemViewType(position);
        if (iType == 0){
            ((MyTextViewHolder)holder).mtvItem.setText(mlstDatas.get(position).mstrMsg);
        }else{
            ((MyPicViewHolder)holder).mivItem.setImageResource(mlstDatas.get(position).miResId);
        }
    }


    @Override
    public int getItemCount() {
        return mlstDatas.size();
    }


    class MyTextViewHolder extends RecyclerView.ViewHolder{
        TextView mtvItem;


        public MyTextViewHolder(View itemView) {
            super(itemView);
            mtvItem = (TextView) itemView;
        }
    }


    class MyPicViewHolder extends RecyclerView.ViewHolder{
        ImageView mivItem;


        public MyPicViewHolder(View itemView) {
            super(itemView);


            mivItem = (ImageView) itemView;
        }
    }


}
MyInfo类:
public class MyInfo {
    public int miType;//表示当前条目的类型,0代表文字(TextView),1代表图片资源(ImageView)
    public String mstrMsg;//如果类型为0,就取这个文字的内容展示到textview上
    public int miResId;//如果类型为1,就取这个图片资源id,展示到imageview上
}


使用:
List<MyInfo> lstDatas = new ArrayList<>();
for (int i = 0; i < 20; i++) {
    MyInfo info = new MyInfo();
    if (i%2 == 0){
        info.miType = 0;
        info.mstrMsg = "test";
    }else {
        info.miType = 1;
        info.miResId = R.mipmap.aaa;
    }
    lstDatas.add(info);
}


MyMutilAdapter adapter = new MyMutilAdapter(lstDatas,this);
mrcvTest.setAdapter(adapter);




作业:72g手游助手的赚钱页面,使用recyclerview替换































1 0