RecyclerView基础介绍
android.support.v7.widget.RecyclerView
android.support.v7.widget.LinearLayoutManager
android.support.v7.widget.GridLayoutManager
android.support.v7.widget.StaggeeredGridLayoutManager
android.support.v7.widget.RecyclerView.Adapter
android.support.v7.widget.RecyclerView.ViewHolder
android.support.v7.widget.RecyclerView.LayoutManager
android.support.v7.widget.RecyclerView.ItemDecoration
android.support.v7.widget.RecyclerView.ItemAnimator
RecyclerView和以前的ListView、GridView相比起来,性能上更好,耦合性更低,然而使用起来相对来说复杂度有所增加,在开发中能够使用这个
控件的地方尽量使用。
基本介绍
下面介绍和RecyclerView紧密相关的几个类型:
1、LayoutManager,这是控制RecyclerView布局方式的管理类,这是一个抽象类,默认提供的实现有LinearLayoutManager和GridLayoutManager和StaggeeredGridLayoutManager,主要对应于线性布局和网格布局方式。效果图如:
GridLayoutManager:
LinearLayoutManager:
2、ItemDecoration,主要用于RecyclerView的分割线,如果需要在RecyclerView中使用分割线就需要继承这个类去自定义。RecyclerView没有提供默认的分割线。 3、ItemAnimator,主要用于Item的添加、删除时的动画,需要使用的时候需要继承自这个类去自定义。 4、Adapter,这是RecyclerView的一个内部类,作用和平时我们使用的Adapter一样,主要用于RecyclerView的Adapter设置,在往RecyclerView中添加数据时需要继承这个Adapter去实现自己的内容。 5、ViewHolder,类似于平时我们使用的Adapter中定义的ViewHolder,在使用RecyclerView的Adapter的时候必须使用该类。
基本用法
1、布局属性
1、mst:reverseLayout,取值为true和false。表示布局后Item是否是逆向布局,正常情况下是从上到下,从左到右,设置这个属性后会逆向布局,也就是从下到上,从右到左。 2、mst:spanCount,取值为整数。网格布局时网格的列数,该属性只在GridLayoutManager和StaggeeredGridLayoutManager中使用到。 3、android:orientation,取值为horizontal或者vertical。表示RecyclerView的布局是横向还是纵向排列,如果是在网格布局中将该属性设置为那么spanCount就表示网格行数。 4、mst:layoutManager,通过LayoutManage的完整类名给RecyclerView设置LayoutManager,这样就不用在代码里面设置了。2、使用方式之初始化
1、布局:
1
2
3
|
</android.support.v7.widget.recyclerview>
|
Adapter的定义:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
class
MyAdapter
extends
RecyclerView.Adapter<myadapter.myviewholder> {
private
ArrayList<string> mData =
new
ArrayList<string>();
@Override
public
MyViewHolder onCreateViewHolder(ViewGroup parent,
int
viewType){
MyViewHolder holder =
new
MyViewHolder(LayoutInflater.from(
mContext).inflate(R.layout.recyclerview_item, parent,
false
));
return
holder;
}
@Override
public
void
onBindViewHolder(MyViewHolder holder,
int
position){
holder.bindData(mData,position);
}
@Override
public
int
getItemCount() {
return
mDatas.size();
}
@Override
public
int
getItemViewType(
int
position){
return
super
.getItemViewType(position);
}
static
class
MyViewHolder
extends
ViewHolder {
TextView text;
public
MyViewHolder(View view) {
super
(view);
text = (TextView) view.findViewById(android.R.id.text1);
}
public
void
bindData(ArrayList<string> datas,
int
position){
text.setText(datas.get(position));
}
}
}
</string></string></string></myadapter.myviewholder>
|
RecyclerView的初始化:
1
2
3
|
RecyclerView mList = (RecyclerView)mContentView.findViewById(R.id.recycler_view);
mList.setLayoutManager(
new
LinearLayoutManager(mContext,LinearLayoutManager.VERTICAL,
false
));
mList.setAdapter(
new
MyAdapter());
|
3、使用方法之Adapter
Adapter常用方法,RecyclerView的Adapter和以前我们常用的Adapter区别还是挺大的,下面介绍一些常用方法
给Item创建一个ViewHolder,其中第一个参数parent是当前RecyclerView,第二个参数是Item的View的类型,可以重写 public int getItemViewType(int position) 方法,然后在 onCreateViewHolder 中通过返回值去让不同的Item加载不同的View。
1
|
public
ViewHolder onCreateViewHolder(ViewGroup parent,
int
itemViewType)
|
1
|
public
void
onBindViewHolder(ViewHolder holder,
int
position)
|
1
|
public
int
getItemViewType(
int
position)
|
1
|
public
final
void
notifyDataSetChanged()
|
1
|
public
final
void
notifyItemChanged(
int
position)
|
更新从第2条开始的5条Item,可以这样调用这个方法notifyItemRangeChanged(2,5);
1
|
public
final
void
notifyItemRangeChanged(
int
positionStart,
int
itemCount)
|
1
|
public
final
void
notifyItemInserted(
int
position)
|
1
|
public
final
void
notifyItemRangeInserted(
int
positionStart,
int
itemCount)
|
1
|
public
final
void
notifyItemRemoved(
int
position)
|
1
|
public
final
void
notifyItemRangeRemoved(
int
positionStart,
int
itemCount)
|
4、使用方法之ViewHolder
在使用RecyclerView时需要对Item设置ViewHolder,然后在ViewHolder中进行数据绑定和Item的初始化,这样将数据处理和Adapter进行
解耦:
1
2
3
4
5
6
7
8
9
10
11
12
|
static
class
MyViewHolder
extends
ViewHolder {
TextView text;
public
MyViewHolder(View view) {
super
(view);
text = (TextView) view.findViewById(android.R.id.text1);
}
public
void
bindData(ArrayList<string> datas,
int
position){
text.setText(datas.get(position));
}
}</string>
|
ViewHolder常用方法:
构造函数,构造函数的参数就是Item的View,一般在这里初始化Item中的View。
1
|
public
ViewHolder(View itemView)
|
item经过一些变换后所处的真正位置。
1
|
public
final
int
getLayoutPosition()
|
1
|
public
final
int
getAdapterPosition()
|
1
|
public
final
int
getItemViewType()
|
1
|
public
final
void
setIsRecyclable(
boolean
recyclable)
|
1
|
public
final
boolean
isRecyclable()
|
4、使用方法之LayoutManager
LayoutManager主要控制RecyclerView中Item的布局方式,默认提供了如下几个LayoutManager
LinearLayoutManager
LinearLayoutManager使得RecyclerView的布局是线性的,要么垂直布局,要么水平布局。
LinearLayoutManager的常用属性:
如果设置LinearLayoutManager的布局方向为水平的话,RecyclerView的布局就是线性的水平方向上的布局 LinearLayoutManager.VERTICAL
如果设置LinearLayoutManager的布局方向为垂直的话,RecyclerView的布局就是线性的垂直方向上的布局
构造函数:
默认是垂直布局
1
|
public
LinearLayoutManager(Context context)
|
1
|
public
LinearLayoutManager(Context context,
int
orientation,
boolean
reverseLayout)
|
1
|
public
LinearLayoutManager(Context context, AttributeSet attrs,
int
defStyleAttr,
int
defStyleRes)
|
常用方法:
当LayoutManager不起作用时是否会回收Item
1
|
public
boolean
getRecycleChildrenOnDetach()
|
1
|
public
void
setRecycleChildrenOnDetach(
boolean
recycleChildrenOnDetach)
|
1
2
|
public
void
setOrientation(
int
orientation) ;
public
int
getOrientation();
|
1
2
|
public
void
setReverseLayout(
boolean
reverseLayout) ;
public
boolean
getReverseLayout()
|
常用方法先介绍这些,其他方法请参考Android官方文档https://developer.android.com/reference/android/support/v7/widget/RecyclerView.html
GridLayoutManager
GridLayoutManager是网格布局。
构造函数:
1
|
public
GridLayoutManager(Context context,
int
spanCount);
|
1
2
|
public
GridLayoutManager(Context context,
int
spanCount,
int
orientation,
boolean
reverseLayout)
|
1
2
|
public
GridLayoutManager(Context context, AttributeSet attrs,
int
defStyleAttr,
int
defStyleRes)
|
常用方法:
设置每一个Item的跨度,通过这个方法可以设置Item的跨度,默认Item跨度为1,数值越大,跨度越大,例如默认情况:这种情况下spanCount为2,跨度为1
设置了自定义SpanSizeLookup:spanCount同样为2,但是图中的SpanSizeLookup是3, 2, 1, 3, 2, 1,3,2,1….这样排列
的,可以看到显示效果的不同。
1
|
public
void
setSpanSizeLookup(SpanSizeLookup spanSizeLookup)
|
其中第一个参数SpanSizeLookup是GridLayoutManager的一个内部抽象类,如果要使用的话需要去继承这个类,并
实现public int getSpanSize(int position),在这里返回SpanSizeLookup的数值。例如:
1
2
3
4
5
6
7
8
|
public
static
final
class
MySpanSizeLookup
extends
SpanSizeLookup {
@Override
public
int
getSpanSize(
int
position) {
return
2
;
}
}
|
1
2
|
public
void
setSpanCount(
int
spanCount) ;
public
int
getSpanCount();
|
StaggeredGridLayoutManager
StaggeredGridLayoutManager可以实现瀑布流形式的布局,如下图是一个列数为2的垂直方向上的瀑布流:
构造函数:
1
|
public
StaggeredGridLayoutManager(
int
spanCount,
int
orientation);
|
1
2
|
public
StaggeredGridLayoutManager(Context context, AttributeSet attrs,
int
defStyleAttr,
int
defStyleRes)
|
常用方法:
设置列数
1
|
public
void
setSpanCount(
int
spanCount)
|
1
|
public
void
setOrientation(
int
orientation)
|
1
|
public
void
setReverseLayout(
boolean
reverseLayout)
|
检查Item的布局边缘从而更新视图,这样会导致Item位置发生变化,为了解决这个问题,可以使用边缘策略方法
1
|
public
void
setGapStrategy(
int
gapStrategy);
|
取值为:StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS
和StaggeredGridLayoutManager.GAP_HANDLING_NONE
1
|
public
int
[] findFirstVisibleItemPositions(
int
[] into)
|