RecyclerView 的使用详解

什么是 RecyclerView? 请度娘。。。本文只介绍RecyclerView 的常规使用,基本问题都已经解决。

xml文件
.support.v7.widget.RecyclerView
    android:id="@+id/recyler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
设置LayoutManager
  • 所有的RecyclerView 在使用之前必须设置LayoutManager

  • LayoutManager 分为三种:LinearLayoutManager、GridLayoutManager、StaggeredGridLayoutManager

  • LinearLayoutManager 线性布局,类似于横向竖向的lsitview 设置方法见下面代码,最后一个boolean类型的入参,是指顺序还是倒序。如在聊天页面,就应该将数据倒序显示并且最开始选中最后一行。

  • GridLayoutManager 类似于GridView, 入参可确定一行显示多少条数据。

  • StaggeredGridLayoutManager 瀑布模型布局,麻麻再也不用担心我要去自己写瀑布布局了。。。

mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, true);
mRecyclerView.setLayoutManager(mLayoutManager);
Adapter的设计之ViewHolder
  • 所有RecyclerView设置的adapter 必须继承RecyclerView.Adapter< ViewHolder >

  • ViewHolder 与 之前在listview中自定义的ViewHolder类似,只是RecyclerView将ViewHolder封装了一下,看代码

public class MyViewHolder extends ViewHolder{

    public TextView mTextViewName;
    public TextView mTextViewAge;

    public MyViewHolder(View itemView) {
        super(itemView);
        mTextViewName= (TextView) itemView.findViewById(R.id.view_item_text);
        mTextViewAge= (TextView) itemView.findViewById(R.id.view_item_text_2);
    }
}
  • ViewHolder 的itemView将在 Adapter 中传入
Adapter的设计之Adapter
  • Adapter 继承自RecyclerView.Adapter< ViewHolder >,主要实现一下三个方法:onCreateViewHolder、onBindViewHolder、getItemCount

  • 在页面展示的时候,会先调用 onCreateViewHolder, 页面上展示多少个,就会create多少次

  • 在之后的页面上,就只调用onBindViewHolder(有特殊情况,下面分析)

  • getItemCount() 返回需要展示的条目数

public class MyRecyclerAdapter extends RecyclerView.Adapter<ViewHolder> {
    public MyRecyclerAdapter(Activity act, List list) {
        this.activity = act;
        this.list = list;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(activity).inflate(R.layout.view_item,
                    parent, false);
        MyViewHolder holder = new MyViewHolder(v);
        return holder;
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, final int position) {
        final MyViewHolder myholder = (MyViewHolder) holder;
        Student item = list.get(position);
        myholder.mTextViewName.setText(item.getName());
        myholder.mTextViewAge.setText(String.valueOf(item.getAge()));
    }

    @Override
    public int getItemCount() {
        return list.size();
    }
}
代码设置Adapter, 没什么好说的….
    mAdapter = new MyRecyclerAdapter(this, mDatas);
    mRecycleView.setAdapter(mAdapter);
一些问题

listview 可以设置headerview、 footerView以解决scrollview 嵌套 listview 的尴尬,recyclerView 如何实现设置”HeaderView” 呢?

RecyclerView 如何设置item的点击事件?

RecyclerView 的数据更新?

如何监听RecyclerView滑到最底部?

一些问题的解答

listview 可以设置headerview、 footerView以解决scrollview 嵌套 listview 的尴尬,recyclerView 如何实现设置”HeaderView” 呢?

  • 细心的人会注意到 onCreateViewHolder 的参数有两个,一个ViewHolder, 一个不知名的int,在上面的代码中,我 已经将其更名为viewType。 这个viewType 就是设置不同的 Item 的关键。

  • 第一条提到的ViewType 与 adapter 中的 getItemViewType(int position) 是相对应的,我们可以设置不同的viewType。 看下面代码

  • 除了设置headerview, 也可以通过这个方法去设置每一行的特殊,如偶数行显示白色,单数行显示灰色等等。

  • 看起来有些繁琐,但是效果不错。 我们不用担心 如果不同的 type 的 item 不会在一开始就被展示出来而无法调用到onCreateViewHolder,log 告诉我,在不同的type 的时候 如果该 type 所对应的 viewHolder 还没被初始化的时候,会重新调用 onCreateViewHolder 的, 而其他的还是会只调用 onBindViewHolder。

    private static final int HEADER_VIEW_TYPE = 0;
    private static final int ITEM_VIEW_TYPE = 1;

    @Override
    public int getItemViewType(int position) {
        if (position == 0) //当第一行的时候,viewType设置为 HeaderView
            return HEADER_VIEW_TYPE;
        else
            return ITEM_VIEW_TYPE;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == HEADER_VIEW_TYPE) {
            View v = LayoutInflater.from(activity).inflate(R.layout.view_item_header,
                    parent, false);
            SecondViewHolder holder = new SecondViewHolder(v);
            return holder;
        } else {
            View v = LayoutInflater.from(activity).inflate(R.layout.view_item,
                    parent, false);
            MyViewHolder holder = new MyViewHolder(v);
            return holder;
        }
    }

        @Override
    public void onBindViewHolder(final ViewHolder holder, final int position) {
        if (position == 0) {
            // 在onBindViewHolder 的时候根据position强转
            final SecondViewHolder headerHolder = (SecondViewHolder) holder;
        } else {
            final MyViewHolder myholder = (MyViewHolder) holder;
        }

RecyclerView 如何设置item的点击事件?

  • listview 或者 gridview 中很简单,但是 recyclerview 却没有提供该方法,所以只好我们自己去写 listener 了。看代码。
    public interface OnRecylerViewItemClickListener {
        public void onClick(int position);
    }

    public class MyViewHolder extends ViewHolder{

    public TextView mTextViewName;
    public TextView mTextViewAge;

    public MyViewHolder(View itemView, final OnRecylerViewItemClickListener listener) {
        super(itemView);
        mTextViewName= (TextView) itemView.findViewById(R.id.view_item_text);
        mTextViewAge= (TextView) itemView.findViewById(R.id.view_item_text_2);
        itemView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View arg0) {
                listener.onClick(getPosition());
            }
        });
    }
}

RecyclerView 的数据更新?

  • 一样的,调用 mAdapter.notifyDataSetChanged();

  • 当插入单条数据及删除单条数据的时候,可以调用 mAdapter.notifyItemInserted(position); mAdapter.notifyItemRemoved(position); 等等,会有自带的动画效果,还不错,如果你想自己写动画,也是可以的。这个木有研究。

如何监听RecyclerView滑到最底部?

        mRecycleView.setOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                int lastVisibleItem = ((LinearLayoutManager) mLayoutManager)
                        .findLastVisibleItemPosition();
                int totalItemCount = mLayoutManager.getItemCount();
                if (lastVisibleItem >= totalItemCount - 1 && dy > 0) {
                    //加载更多
                    for (int i = 0; i < 20; i++) {
                        mDatas.add(String.valueOf(i));
                    }
                    mAdapter.notifyDataSetChanged();
                }
            }
        });
  • RecyclerView添加间隔
//recyclerView.addItemDecoration(new DividerItemDecoration(getActivity().getResources().getDrawable(R.drawable.tab_line),false,false));

recyclerView.addItemDecoration(new DividerItemDecoration(10));

public class SpaceItemDecoration extends RecyclerView.ItemDecoration{

        private int space;

        public SpaceItemDecoration(int space) {
            this.space = space;
        }

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

            //设置左右的间隔如果想设置的话自行设置,我这用不到就注释掉了
/*          outRect.left = space;
            outRect.right = space;*/

            if(parent.getChildPosition(view) != 0)
                outRect.top = space;
        }
    }
  • 上面的代码是有点点问题的,比如网络加载的时候,如果每次到达底部都去加载的话,可能会加载多次,所以自己控制一下吧!

结束

你可能感兴趣的:(实用工具)