RecyclerView使用、上拉加载、局部刷新、多种布局、点击事件和坑
2017-01-06 12:25
543 查看
一、Recycler的基础使用
先来了解一下它是干啥的:可以实现ListView的效果
可以实现GridView的效果
可以实现瀑布流的效果
主要是通过设置它的setLayoutManager来决定它长的啥样
//这里用线性显示 类似于listview mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); //这里用线性宫格显示 类似于grid view mRecyclerView.setLayoutManager(new GridLayoutManager(this, 2)); //这里用线性宫格显示 类似于瀑布流 mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, OrientationHelper.VERTICAL));
接下来就以线性布局的为例:
1、要使用RecyclerView要先在build.gradle中添加依赖(不要忘了同步哈)
compile 'com.android.support:design:25.0.0'
2、在XML中使用RecyclerView
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_list_view_demo" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.ws.myapplication.activitys.ListViewDemoActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/pullLoadMoreRecyclerView" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>
3、在Activity或者Fragment中找到控件,并设置数据(下面以Activity为例哈)
//找到控件 recyclerView = (RecyclerView) findViewById(R.id.pullLoadMoreRecyclerView); //设置想要的样式 linearLayoutManager = new LinearLayoutManager(ListViewDemoActivity.this); recyclerView.setLayoutManager(linearLayoutManager); //初始化Adapter mRecyclerViewAdapter = new RecyclerViewAdapter(); //像ListView一样给RecyclerView绑定Adapter recyclerView.setAdapter(mRecyclerViewAdapter);
4、关键就是RecyclerView的Adapter
首先RecyclerView的Adapter不是继承BaseAdapter而是继承RecyclerView.Adapter
RecyclerView的ViewHolder也是继承的RecyclerView.ViewHolder(public权限的)
//注意这里面的泛形,它是onCreateViewHolder返回的类型,也是onBindViewHolder的参数类型 public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> { public RecyclerViewAdapter() { } //创建每个Item @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //没个Item要显示的样子 View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_view_item, parent, false); return new ViewHolder(view); } //给每个Item设置数据 @Override public void onBindViewHolder(ViewHolder holder, int position) { holder.textView.setText(list.get(position)); } @Override public int getItemCount() { return list.size(); } public class ViewHolder extends RecyclerView.ViewHolder { TextView textView; public ViewHolder(View itemView) { super(itemView); textView = (TextView) itemView.findViewById(R.id.recycler_text); } } }
二、RecyclerView多种布局和上拉刷新
RecyclerView的多种布局与ListView有些相似也有不同,它不需要重写两个方法,只需要一个getItemViewType就可以了;而且它的默认值是0,它返回的是整数就可以,不需要连续。如果要实现RecyclerView的上拉刷新,可以给它加一个FooterView,来实现上拉加载的效果。
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private int load_more_status; //上拉加载更多 public static final int PULLUP_LOAD_MORE=0; //正在加载中 public static final int LOADING_MORE=1; public RecyclerViewAdapter() { } //viewType是getItemViewType返回的数据 @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //根据viewType来判断要创建哪个类型的view if(viewType == 0){ View view = LayoutInflater.from(ListViewDemoActivity.this).inflate(R.layout.footer_layout,parent,false); return new FooterHolder(view); }else { View view = LayoutInflater.from(ListViewDemoActivity.this).inflate(R.layout.recycler_view_item,parent,false); return new ViewHolder(view); } } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { //通过holder来确定显示的是哪个类型的View if(holder instanceof FooterHolder){ switch (load_more_status) { case PULLUP_LOAD_MORE: ((FooterHolder) holder).textView.setText("上拉加载更多"); break; case LOADING_MORE: ((FooterHolder) holder).textView.setText("正在加载更多"); break; } }else if(holder instanceof ViewHolder){ ((ViewHolder) holder).textView.setText(list.get(position)); holder.itemView.setTag(position); } } //因为要添加一个FooterView所以总体返回的数据应给+1 @Override public int getItemCount() { return list.size()+1; } //是最后一个的时候显示FooterView,否则正常显示 @Override public int getItemViewType(int position) { if(position+1==getItemCount()){ return 0; } return 1; } //正常布局的ViewHolder public class ViewHolder extends RecyclerView.ViewHolder { TextView textView; public ViewHolder(final View itemView) { super(itemView); textView = (TextView) itemView.findViewById(R.id.recycler_text); textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.e("-------------->","tag:"+itemView.getTag()); //在ViewHolder中通过getAdapterPosition方法获取在adapter中的位置,和设置tag效果相同 Log.e("---------->", "getAdapterPosition()" + getAdapterPosition()); } }); } } //FooterView布局的ViewHolder public class FooterHolder extends RecyclerView.ViewHolder{ TextView textView; public FooterHolder(View itemView) { super(itemView); textView = (TextView) itemView.findViewById(R.id.text); } } /** * //上拉加载更多 * PULLUP_LOAD_MORE=0; * //正在加载中 * LOADING_MORE=1; * //加载完成已经没有更多数据了 * NO_MORE_DATA=2; * @param status */ public void changeMoreStatus(int status){ load_more_status=status; } }
//上拉加载 recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); //设置加载的状态 mRecyclerViewAdapter.changeMoreStatus(RecyclerViewAdapter.LOADING_MORE); //判断到底部的条件 if (newState == RecyclerView.SCROLL_STATE_IDLE && linearLayoutManager.findLastVisibleItemPosition() + 1 == mRecyclerViewAdapter.getItemCount()) { Log.e("--------->", "到底"); //可以直接addAll for (int i = 0; i < 30; i++) { list.add("测试数据hhhhhhh:" + i); } //刷新数据 mRecyclerViewAdapter.notifyDataSetChanged(); mRecyclerViewAdapter.changeMoreStatus(RecyclerViewAdapter.PULLUP_LOAD_MORE); } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); } });
1、使用notifyDataSetChanged();会重新执行onBindViewHolder()。
2、在ViewHolder中使用getAdapterPosition()获取在adapter中的位置。
3、如过在ongBindViewHolder的点击事件中调用了notifyDataSetChanged()可能会报错Cannot call this method while RecyclerView is computing a layout orscrolling,这时可以把点击事件移到ViewHolder中
详细错误参考
(如果逻辑中真的恰巧要在onBindViewHolder 中去刷新,然后还报错,那么可以使用handler机制,通过发消息去解决。)
三、RecyclerView局部刷新
局部刷新分结构上的刷新和非结构上的,关于添加和移除是结构上的移除,所以分清情况使用哪种。// 更新列表position位置上的数据可以调用 notifyItemChanged(int position) //列表position位置添加一条数据时可以调用,伴有动画效果 notifyItemInserted(int position) //列表position位置移除一条数据时调用,伴有动画效果 notifyItemRemoved(int position) //列表fromPosition位置的数据移到toPosition位置时调用,伴有动画效果 notifyItemMoved(int fromPosition, int toPosition) //列表从positionStart位置到itemCount数量的列表项进行数据刷新 notifyItemRangeChanged(int positionStart, int itemCount) //列表从positionStart位置到itemCount数量的列表项批量添加数据时调用,伴有动画效果 notifyItemRangeInserted(int positionStart, int itemCount) //列表从positionStart位置到itemCount数量的列表项批量删除数据时调用,伴有动画效果 notifyItemRangeRemoved(int positionStart, int itemCount)
能用局部刷新就不要使用notifyDataSetChanged();
public class RecyclerViewDemoActivity extends AppCompatActivity { private List<String> list; private RecyclerView recyclerView; private MyApapter apapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_recycler_view_demo); recyclerView = (RecyclerView) findViewById(R.id.recycler); recyclerView.setLayoutManager(new LinearLayoutManager(RecyclerViewDemoActivity.this)); apapter = new MyApapter(); recyclerView.setAdapter(apapter); list = new ArrayList<>(); for (int i = 0; i < 30; i++) { list.add("数据" + i); } } //添加一条 public void addOne(View view) { list.add(3,"我是添加的一个"); apapter.notifyItemInserted(3); } //添加多条 public void addMore(View view) { for(int i = 5;i<9;i++){ list.add(i,"添加了一片哈哈"); } apapter.notifyItemRangeInserted(5,4); } //移除一条 public void removeOne(View view) { list.remove(1); apapter.notifyItemRemoved(1); } //移除多条 public void removeMore(View view) { for(int i = 20;i>15;i--){ list.remove(i); } apapter.notifyItemRangeRemoved(15,4); } //刷新一条 public void changeItem(View view) { list.set(2,"我就改了怎么的^_^"); apapter.notifyItemChanged(2); } private class MyApapter extends RecyclerView.Adapter<MyApapter.MyViewHolder> { @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(RecyclerViewDemoActivity.this).inflate(R.layout.recycler_view_item, parent, false); return new MyViewHolder(view); } @Override public void onBindViewHolder(MyViewHolder holder, int position) { holder.textView.setText(list.get(position)); } @Override public int getItemCount() { return list.size(); } public class MyViewHolder extends RecyclerView.ViewHolder { TextView textView; public MyViewHolder(View itemView) { super(itemView); textView = (TextView) itemView.findViewById(R.id.recycler_text); } } } }
四、RecyclerView点击事件
看另一片博客RecyclerView点击事件相关文章推荐
- RecyclerView使用详解一代替ListView(点击事件,添加头布局,上拉刷新下拉加载)
- RecyclerView使用(二)多种Item布局、添加点击事件
- RecyclerView支持下拉刷新上划加载,多种布局样式。RV集成框架使用(一)
- RecyclerView 模拟数据+长按点击事件+刷新加载
- RecyclerView点击事件、加载不同布局
- okhhtp + recyclerview + 上拉刷新下拉加载 + 点击事件
- PullRecyclerView上拉刷新下拉加载点击事件
- RecyclerView 条目点击事件 XRecyclerView刷新加载
- RecyclerView实现上拉刷新,下拉加载,item点击事件
- RecyclerView展示固定数据、上拉加载更多、下拉刷新、点击事件、长按点击事件、删除条目、刷新条目、添加条目、多条目加载
- RecyclerView的基本使用(优化图片加载、设置条目间距、设置Adapter、设置点击事件等)
- RecyclerView的使用以及下拉刷新自动加载(添加点击事件、头部)
- Android中Recyclerview使用7----条目中按钮点击事件,在activity中调用(接口回调)
- Android中Recyclerview使用3----添加条目得到点击事件和长按事件
- RecyclerView 使用总结(三):点击事件、GridView等、瀑布流、动态增删
- RecyclerView的使用(包含点击事件)
- RecyclerView加载不同item并实现其item点击事件,实现添加常用应用的功能
- RecyclerView的加载显示多种布局
- Android Studio 使用RecyclerView加载不同样式布局
- 关于recyclerview的横向布局的宽度以及item的点击事件的添加