盒子
盒子
文章目录
  1. 前言
    1. 添加依赖
    2. Adapter变化
      1. onCreateViewHolder
      2. onBindViewHolder
      3. setLayoutManager
    3. ListView与GridView嵌套效果
    4. RecyclerView动画
    5. RecyclerView的CursorAdapter
      1. CursorFilter
      2. RecyclerBaseCursorAdapter
  2. 效果图
  3. 结语

RecyclerView深入浅出

前言

RecyclerView已经出来好一段时间了,对于新接触Android的学员来说大多数使用的是ListViewGridView,对于RecyclerView的使用可能都不是很熟悉,相信这片文章能很好的带你进去RecyclerView的大门,快速了解与掌握新技术。

添加依赖

大家使用ListViewGridView只要在xml中引用就可以了,没错RecyclerView也是一样,但在引用前要先添加依赖,在项目的app目录下的build.gradl的dependencies中添加:

1
compile 'com.android.support:recyclerview-v7:23.2.0'

完了之后别忘了Sync Now

Adapter变化

既然要有ListViewGridView的效果自然不能少了adapter,而RecyclerViewadapter主要有两个重大的变化,原来adapter中的getView()方法取消了,替换成了onCreateViewHolder()onBindViewHolder()。其实就是分成了两部分,一部分创建视图另一部分绑定数据,是不是感觉层次更清晰了呢,下面主要介绍之两大方法的使用。

onCreateViewHolder

说白了这个方法就是创建视图,在创建之前要创建个ViewHolder相信在原来的adapter中应该有使用过吧.这里继承RecyclerView.ViewHolder

1
2
3
4
5
6
7
8
public static class NormalViewHolder extends RecyclerView.ViewHolder {
@Bind(R.id.item_tv)
TextView itemTv;
public NormalViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}

然后在onCreateViewHolder中调用:

1
2
3
4
@Override
public NormalViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new NormalViewHolder(mLayoutInflater.inflate(R.layout.item_text, parent, false));
}

onBindViewHolder

视图创建完毕就是简单的绑定了,使用holder对控件进行绑定设置数据:

1
2
3
4
@Override
public void onBindViewHolder(NormalViewHolder holder, int position) {
holder.itemTv.setText((CharSequence) mListData.get(position));
}

OK了,是不是感觉很简单呢?是的就是这么简单,至于设置adapter就不说了相信之后的步骤大家都会了。

setLayoutManager

你是不是想说如何设置显示的方式是ListViewGridView,这个其实更加简单只需一句代码,setLayoutManager()即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
switch (type) {
case App.LINEAR_LAYOUT:
//ListView
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
break;
case App.GRID_LAYOUT:
//GridView
gridLayoutManager = new GridLayoutManager(getActivity(),3);
recyclerView.setLayoutManager(gridLayoutManager);
break;
case App.STAGGERED_GRID_LAYOUT:
//Can customize the waterfall flow
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, OrientationHelper.VERTICAL));
break;
default:
break;
}

设置了显示的方式后再setAdapter()即可,效果图还是放到最后一起显示吧

ListView与GridView嵌套效果

如果要实现首尾是ListView布局效果,中间的GridView效果,我们可以使用RecyclerView.Adapter提供的getItemViewType(int position)方法,注意这里与ListViewadapter不同只有这一个方法,没有getViewTypeCount() 方法,我们可以通过首尾要显示的行数来控制显示的布局

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
public int getItemViewType(int position) {
mHeadCount = getHeadCount();
mContentCount = getContentCount();
mBottomCount = mHeadCount + mContentCount;
if (mHeadCount > position) {
return App.LINEAR_LAYOUT;//ListView
} else if (mBottomCount <= position) {
return App.STAGGERED_GRID_LAYOUT;//Can customize the waterfall flow
} else {
return App.GRID_LAYOUT;//GridView
}
}

根据不同的viewtype返回不同的布局

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case App.LINEAR_LAYOUT:
return onCreateHeadViewHolder(parent);
case App.GRID_LAYOUT:
return onCreateContentViewHolder(parent);
case App.STAGGERED_GRID_LAYOUT:
return onCreateBottomViewHolder(parent);
default:
return null;
}
}

RecyclerView动画

RecyclerViewadapter提供了一些简单的动画实现,下面是一部分:

  • notifyItemRemoved(int position)
  • notifyItemInserted(int position)
  • notifyItemChanged(int position)
  • notifyItemRangeChanged(int positionStart,int itemCount)

只要在数据改变时通过adapter调用就行:

1
2
3
4
5
6
7
8
9
10
@OnClick(R.id.item_tv)
public void onClick() {
if (getLayoutPosition() != 1) {
animationAdapter.mListData.add("add"+getLayoutPosition());
animationAdapter.notifyItemInserted(getLayoutPosition());
} else {
animationAdapter.mListData.remove(getLayoutPosition());
animationAdapter.notifyItemRemoved(getLayoutPosition());
}
}

使用recyclerViewsetItemAnimator()可以设置动画:

1
recyclerView.setItemAnimator(new DefaultItemAnimator());

当然你也可以实现自己的动画,只要extends ItemAnimator重写几个方法,这里就不展开了,读者可以自己去试试。

RecyclerView的CursorAdapter

讲到这里了你可以能会认为CursorAdapter也是跟原来的差不多,但我要说的是RecyclerView并没有提供有关与CursorAdapter的操作。所以当我们要使用CursorAdapter时要怎么办呢?我们只能自己实现一个CursorAdapter的抽象类,是不是感觉头痛,这一点看起来确实有点麻烦,但是我告诉你们实现也是很简单的一件事,为什么这么说呢,因为我们只要仿造ListViewCursorAdapter就可以了。

CursorFilter

这个是Cursor的过滤器,我们无需做什么,找到ListViewCursorFilter复制就可以了。代码没什么贴的,都是源码,自己可以去查看.

RecyclerBaseCursorAdapter

这个抽象类大部分都是与ListViewCursorAdapter相同,只是有几个地方需要特别提醒下

  • 原来的有notifyDataSetInvalidated()方法,但RecyclerView没有提供该方法,我们可以使用notifyDataSetChanged()替代
  • 原来的hasStableIds() 方法也没用,我们也可以使用setHasStableIds(true)设置为ture来实现相同的效果
  • 原来的getView()方法要替换成onBindViewHolder()方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void init(Context context, Cursor c, int flags) {
boolean cursorPresent = c != null;
mCursor = c;
mDataValid = cursorPresent;
mContext = context;
mRowIDColumn = cursorPresent ? c.getColumnIndexOrThrow("_id") : -1;
if ((flags & FLAG_REGISTER_CONTENT_OBSERVER) == FLAG_REGISTER_CONTENT_OBSERVER) {
mChangeObserver = new ChangeObserver();
mDataSetObserver = new MyDataSetObserver();
} else {
mChangeObserver = null;
mDataSetObserver = null;
}

if (cursorPresent) {
if (mChangeObserver != null) c.registerContentObserver(mChangeObserver);
if (mDataSetObserver != null) c.registerDataSetObserver(mDataSetObserver);
}
//should set true to init
setHasStableIds(true);
}
1
2
3
4
5
6
7
@Override
public void onInvalidated() {
mDataValid = false;
// notifyDataSetInvalidated();
//there is no notifyDataSetInvalidated method we should use notifyDataSetChanged method;
notifyDataSetChanged();
}

基本上主要的就是这些了,更多详情可以查看后面的Demo链接,最后使用都相同的套路,继承该抽象类,相信应该没有问题。

效果图

效果图

结语

源码地址链接:https://github.com/idisfkj/RecyclerView
最后感谢大家的阅读,有不足的地方欢迎指出。

转载请指明出处 idisfkj博客:https://idisfkj.github.io

支持一下
赞赏是一门艺术