RecycleView和ListView一样,都是做列表显示View子项的控件,它比ListView更高效和自由。
解析RecycleView,Recycle View意思就是该控件只管回收和显示View子项,而对于如何显示,显示什么,它是不关心的,这给开发过程带来了极大的便利,比如ListView只能作为单列的列表显示,GridView将一个界面表格化,通常情况下GridView通过强制View子项的宽度来显示,在横竖屏切换时的效果很差。
而RecycleView可以实现:
ListView的功能
GridView的功能
横向ListView的功能
横向ScrollView的功能
瀑布流的功能
添加和删除View子项
这些功能,非常强大,可以看出,它几乎可以替代所有的动态布局控件。
这么强大的动态布局控件,得益于它的高度解耦,同样,众所周知,高度解耦,就意味着复杂度提升,相较于ListView、GridView等控件,RecycleView才实现过程是相对较复杂的。
RecyclerView的适配器需要继承自RecyclerView.Adapter,在该适配器将要面向ViewHolder,也就是说,它内部已经实现了缓存复用。
实现GridView功能
已经实现了ListView,对于一个高度解耦的RecyclerView来说,再实现GridView的功能就非常简单了。
新建RecyclerViewDemo2工程。Adapter可以直接拷贝RecyclerViewDemo1中的内容。暂时不考虑分隔线的情况下,只需要将实现ListView时使用的LinnerLayoutManager换成GridLayoutManager即可,只需要改动两行代码。
Java Code
GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 4);
recyclerView.setLayoutManager(gridLayoutManager);
非常的方便,那么,在一个界面中通过判断屏幕方向,使用不同的显示方式,也就顺理成章了。
其他的东西都是不变的,除了布局管理器的改变之外,另一个需要注意的就是分隔线,需要重新绘制。
Java Code
package com.hqyj.dev.recyclerviewdemo2;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.Log;
import android.view.View;
/**
* Created by jiyangkang on 2016/7/16 0016.
*/
public class GridItemDecoration extends
RecyclerView.ItemDecoration {
private Drawable mDivider;
private static final int[] ATTRS = new int[]{
android.R.attr.listDivider
};
public GridItemDecoration(Context context) {
final TypedArray t = context.obtainStyledAttributes(ATTRS);
mDivider = t.getDrawable(0);
t.recycle();
}
@Override
public void onDraw(Canvas c,
RecyclerView parent,
RecyclerView.State state) {
super.onDraw(c, parent, state);
drawHorizontal(c, parent);
drawVertical(c, parent);
}
//获取列数
private int getSpanCount(RecyclerView parent) {
int spandCount = -1;
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
spandCount = ((GridLayoutManager) layoutManager).getSpanCount();
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
spandCount = (
(StaggeredGridLayoutManager) layoutManager).getSpanCount();
}
return spandCount;
}
private void drawVertical(Canvas c, RecyclerView parent) {
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
Log.d("Draw_v", "drawVertical: " + i);
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (
RecyclerView.LayoutParams) child.getLayoutParams();
final int top = child.getTop() - params.topMargin;
final int bottom = child.getBottom() + params.bottomMargin;
final int left = child.getRight();
final int right = left + mDivider.getIntrinsicWidth();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
private void drawHorizontal(Canvas c, RecyclerView parent) {
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
Log.d("Draw_h", "drawVertical: " + i);
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (
RecyclerView.LayoutParams) child.getLayoutParams();
final int left = child.getLeft() - params.leftMargin;
final int right = child.getRight() + params.rightMargin
+ mDivider.getIntrinsicWidth();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
@Override
public void getItemOffsets(Rect outRect,
View view,
RecyclerView parent,
RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
outRect.set(0,0,mDivider.getIntrinsicWidth(), mDivider.getIntrinsicHeight());
}
}
对View子项的操作和仿制ListView的时候是一致的。