— 从入门到放弃,我想说的是,我不是那样的人,这个逼,我要装下去!
listView的相关认知,学习,我们也讲了不少了,要学习的可以 点这里 接下来,我想接着走完RecyclerView,让我们在对比实践中学习吧,毕竟它们相似相杀;
- 首先,我们来看看他们运用上最大的区别:
熟悉RecyclerView的人早已经理解了,不熟悉的也早就听说了,RecyclerView相对于listView的最明显的好处就是
- 横向滚动的ListView,RecyclerView天生自带;
- 横向滚动的GridView,RecyclerView天生自带;
- 瀑布流的效果,RecyclerView天生自带;
以上这些效果listview也都能实现,像我这样的懒货,还是喜欢用人家的现成的!说的我好像真的会一样,哈哈。
- 其次,来对比下api的使用吧
- listView的先不说了 点这里 看完懂
- RecyclerView需要继承重写 RecyclerView.Adapter 和 RecyclerView.ViewHolder
- RecyclerView需要设置布局管理器,控制布局效果
这里是示例代码:
//adapter的大概写法
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private ArrayList<String> mData;
private List<Boolean> boolList;
private View v;
private MyAdapter.OnItemClickListener onItemClickListener;
public MyAdapter(ArrayList<String> data, List<Boolean> boolList) {
this.mData = data;
this.boolList = boolList;
}
//item的点击事件需要自定义
public interface OnItemClickListener {
void onItemClick(View view, int position);
void onItemLongClick(View view, int position);
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == 2) {
// 实例化展示的view
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.iten_view, parent, false);
// 实例化viewholder
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
} else {
// 实例化展示的view
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_teo, parent, false);
// 实例化viewholder
ViewHolder viewHolderTwo = new ViewHolder(v);
return viewHolderTwo;
}
}
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
// 绑定数据
holder.mTv.setText(mData.get(position));
holder.cbChange.setChecked(boolList.get(position));
holder.cbChange.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//此处处理checkbox在RecyclerView中状态复用的问题
MainActivity.changeCheckty(position, boolList);
}
});
}
@Override
public int getItemCount() {
return mData == null ? 0 : mData.size();
}
@Override
public int getItemViewType(int position) {
if (position == 3 || position == 10) {
return 1;
}
return 2;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
CheckBox cbChange;
TextView mTv;
public ViewHolder(View itemView) {
super(itemView);
mTv = (TextView) itemView.findViewById(R.id.tv_coments);
cbChange = (CheckBox) itemView.findViewById(R.id.cb_my);
}
}
}
~~~
//以下是在MainActiviy中的代码:
private void initView() {
mRecyclerView = (RecyclerView) findViewById(R.id.rv_list);
// 设置布局管理器
mRecyclerView.setLayoutManager(mLayoutManager);
// 设置adapter
mRecyclerView.setAdapter(mAdapter);
// 设置Item添加和移除的动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
// 设置Item之间间隔样式
mRecyclerView.addItemDecoration(new DividerItemDecoration(MainActivity.this, LinearLayoutManager.VERTICAL));
}
private void initData() {
//设置布局管理器,控制布局效果
mLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
mAdapter = new MyAdapter(getData(),boolist);
}
以上代码就是我们在之前介绍listview的项目中不同的地方,是实现同样的效果的,可以看下图(同样解决了内部复用是,选中状态失去的问题)
public static abstract class LayoutManager {
嘛的,说了一大堆,其实就是:
LayoutManager 只是一个抽象类而已,系统已经为我们提供了三个相关的实现类 LinearLayoutManager(线性布局效果)、GridLayoutManager(网格布局效果)、StaggeredGridLayoutManager(瀑布流布局效果)。如果你想用 RecyclerView 来实现自己的一种效果,则应该去继承实现自己的 LayoutManager,并重写相应的方法。
void addView(View child, int index)
//根据索引在RecyclerView中添加子View。
void addView(View child)
//添加子View。
int computeHorizontalScrollExtent(RecyclerView.State state)
int computeHorizontalScrollOffset(RecyclerView.State state)
int computeHorizontalScrollRange(RecyclerView.State state)
int computeVerticalScrollExtent(RecyclerView.State state)
int computeVerticalScrollOffset(RecyclerView.State state)
int computeVerticalScrollRange(RecyclerView.State state)
//官方API文档已经说的很清楚了,如果要实现scroll bar可能就需要复写以上的六个方法中的某一些。
//View findViewByPosition(int position)
根据Adapter的位置查找RecyclerView的子View。
View getChildAt(int index)
//根据索引获取子View。
int getChildCount()
//获取RecyclerView的子View的个数。
int getHeight()
int getWidth()
//获取RecyclerView的高度和宽度的两个函数
int getItemCount()
//获取Adapter中子项的个数
int getItemViewType(View view)
//获取Adapter 中定义的子项的ViewType(子项View的类型),在RecyclerView中并没有ListView的head和footer的实现方法,这个方法也提供了head和footer的实现思路,在初始位置返回的ViewType为head,末尾位置返回的ViewType为footer,根据返回的ViewType的不同,我们可以去创建不同的子项的View和绑定不同的ViewHolder。
void moveView(int fromIndex, int toIndex)
//移动一个View的位置到另一个View。
Parcelable onSaveInstanceState()
//当需要保存LayoutManager的状态时调用。
void onScrollStateChanged(int state)
//当滑动状态改变时RecyclerView调用这个方法去通知LayoutManager。
void removeAllViews()
Remove all views from the currently attached RecyclerView.
//移除当前依附在RecyclerView上的所有View。
void removeView(View child)
//移除当前依附在RecyclerView上的一个子View。
void removeViewAt(int index)
//根据索引移除当前依附在RecyclerView上的一个子View。
listView和RecyclerView的api不同的对比:
- listView直接自带setEmptyView()属性,当界面列表没有数据的时候,可以直接设置
- RecyclerView没有自带的,当然你可以自定义一个;这里有个大神已经做过,他是这样实现的
————*———–
- listView直接自带addFooterView() 和 addFooterView() 的api
- RecyclerView中,我们在上面讲LayoutManager 的getItemViewType(View view)时候可以做出判断,绑定不同的布局,当然这样实现会有一些问题,有更好的实现方案,没得说,一定是这篇了: http://blog.csdn.net/lmj623565791/article/details/51854533
————*———–
- lsitview的刷新相关 notifyDataSetChanged() ,调用简单,但是并不是每个item都需要重新绘制,造成了一定的资源浪费;
- RecyclerView的刷新相关,方法更多,notifyItemChanged(int position)可以只针对某个item刷新;
————*———–
- listView的item加动画,我们只能自己通过属性动画来操作 Item 的视图,可以找别人封装的开源库,相对麻烦一些;
- RecyclerView的动画:系统也为我们提供了两个默认的动画实现:SimpleItemAnimator 和 DefaultItemAnimator。上面写到的mRecyclerView.setItemAnimator(new DefaultItemAnimator()),当然有特殊要求的可以找别人封装的开源库;
————*———–
- 还有就是listView的点击事件值得一提,adapter的内部外部都可以设置点击事件,但是RecyclerView的点击事件是需要我们自己定义的,可这完全不是问题,我们在最上面的代码中已经贴出了代码,不再重复了;
————*———–
- 另外重要的一点就是如果有的时候你需要配合AppBarLayout 、 CollapsingToolbarLayout 这种需要嵌套滚动的机制才能达到效果的控件,那么就选择 RecyclerView ,因为 ListView 内部吃掉了,不支持滚动机制NestedScrollingChild 。
**以上就是简单的RecyclerView的讲解,当然我们不是没有追求的人,我们怎么可以忍受代码这么乱,最基本的封装都没有,那就看这里:http://www.jianshu.com/p/2f2996ef2c75
我只想说,收下我的膝盖!**
- ### 综上所述,在分析项目需求的时候,根据不同的需求选择不同的列表,适当的扩展,合适就好
有兴趣的可以继续学习之前的系列篇:ListView系列详解
我的简书:http://www.jianshu.com/p/e8e61d6b0329