盒子
盒子
Posts List
  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

支持一下
赞赏是一门艺术