RecyclerView简单使用
1. 在build.gradle(Module)的dependency(dependencies)添加引用:
compile 'com.android.support:recyclerview-v7:25.3.1
2. 在布局中添加recyclerview
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/darker_gray"
android:visibility="gone"
android:fadeScrollbars="true"
android:scrollbars="vertical">
</android.support.v7.widget.RecyclerView>
3. 创建recyclerView的Adapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private ArrayList<String> mData;
public MyAdapter(ArrayList<String> data) {
this.mData = data;
}
public void addNewItem() {
if(mData == null) {
mData = new ArrayList<>();
}
int size=mData.size();
mData.add(size, size+" Item");
notifyItemInserted(size);
}
public void deleteItem() {
if(mData == null || mData.isEmpty()) {
return;
}
int size=mData.size();
mData.remove(size-1);
notifyItemRemoved(size-1);
}
public void updateData(ArrayList<String> data) {
this.mData = data;
notifyDataSetChanged();
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// 实例化展示的view
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_rv_item, parent, false);
// 实例化viewholder
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
// 绑定数据
holder.mTv.setText(mData.get(position));
}
@Override
public int getItemCount() {
return mData == null ? 0 : mData.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView mTv;
public ViewHolder(View itemView) {
super(itemView);
mTv = (TextView) itemView.findViewById(R.id.item_tv);
}
}
}
public class MyStaggeredRvAdapter extends RecyclerView.Adapter<MyStaggeredRvAdapter.ViewHolder> {
/**
* 展示数据
*/
private ArrayList<String> mData;
public MyStaggeredRvAdapter(ArrayList<String> data) {
this.mData = data;
}
public void updateData(ArrayList<String> data) {
this.mData = data;
notifyDataSetChanged();
}
@Override
public int getItemViewType(int position) {
// 瀑布流样式外部设置spanCount为3,在这列设置三个不同的item type,以区分不同的布局
return position % 3;
}
@Override
public MyStaggeredRvAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// 实例化展示的view
View v;
if(viewType == 1) {
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_rv_staggered_item, parent, false);
} else if (viewType==2){
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_rv_staggered_item_three, parent, false);
}else {
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_rv_staggered_item_two, parent, false);
}
// 实例化viewholder
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
}
@Override
public void onBindViewHolder(MyStaggeredRvAdapter.ViewHolder holder, int position) {
// 绑定数据
holder.mTv.setText(mData.get(position));
}
@Override
public int getItemCount() {
return mData == null ? 0 : mData.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView mTv;
public ViewHolder(View itemView) {
super(itemView);
mTv = (TextView) itemView.findViewById(R.id.item_tv);
}
}
}
4. RecyclerView的item直接的间隔设置(自己定义)
// 线性recyclerview 的分组装饰(间隔)
public class MyDividerItemDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{
android.R.attr.listDivider
};
public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
/**
* 用于绘制间隔样式
*/
private Drawable mDivider;
/**
* 列表的方向,水平/竖直
*/
private int mOrientation;
private int mGroupHeight=40,mLeftMargin=10;
private Paint mGroutPaint,mTextPaint;
private MainActivity.GroupListener groupListener;
public void setGroupListener(MainActivity.GroupListener groupListener) {
this.groupListener = groupListener;
}
private boolean isFirstInGroup(int position){
if (position==0){
return true;
}else {
String prevGroupId = groupListener.getGroupName(position - 1);
String groupId = groupListener.getGroupName(position);
return !TextUtils.equals(prevGroupId,groupId);
}
}
public MyDividerItemDecoration(Context context, int orientation) {
// 获取默认主题的属性
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
setOrientation(orientation);
mGroutPaint=new Paint();
mGroutPaint.setColor(0xFF41C2F9);
mGroutPaint.setStyle(Paint.Style.FILL);
mTextPaint=new Paint();
mTextPaint.setStyle(Paint.Style.FILL);
mTextPaint.setColor(0xffffffff);
mTextPaint.setTextSize(20.0f);
mTextPaint.setStrokeWidth(5);
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
// 绘制间隔
// if (mOrientation == VERTICAL_LIST) {
// drawVertical(c, parent);
// } else {
// drawHorizontal(c, parent);
// }
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
// if (mOrientation == VERTICAL_LIST) {
// outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
// } else {
// outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
// }
int pos = parent.getChildAdapterPosition(view);
String groupId = groupListener.getGroupName(pos);
if (groupId == null) return;
//只有是同一组的第一个才显示悬浮栏
if (pos == 0 || isFirstInGroup(pos)) {
outRect.top = mGroupHeight;
}
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
final int itemCount = state.getItemCount();
final int childCount = parent.getChildCount();
final int left = parent.getLeft() + parent.getPaddingLeft();
final int right = parent.getRight() - parent.getPaddingRight();
String preGroupName; //标记上一个item对应的Group
String currentGroupName = null; //当前item对应的Group
for (int i = 0; i < childCount; i++) {
View view = parent.getChildAt(i);
int position = parent.getChildAdapterPosition(view);
preGroupName = currentGroupName;
currentGroupName = groupListener.getGroupName(position);
if (currentGroupName == null || TextUtils.equals(currentGroupName, preGroupName))
continue;
int viewBottom = view.getBottom();
float top = Math.max(mGroupHeight, view.getTop());//top 决定当前顶部第一个悬浮Group的位置
if (position + 1 < itemCount) {
//获取下个GroupName
String nextGroupName = groupListener.getGroupName(position + 1);
//下一组的第一个View接近头部
if (!currentGroupName.equals(nextGroupName) && viewBottom < top) {
top = viewBottom;
}
}
//根据top绘制group
c.drawRect(left, top - mGroupHeight, right, top, mGroutPaint);
Paint.FontMetrics fm = mTextPaint.getFontMetrics();
//文字竖直居中显示
float baseLine = top - (mGroupHeight - (fm.bottom - fm.top)) / 2 - fm.bottom;
c.drawText(currentGroupName, left + mLeftMargin, baseLine, mTextPaint);
}
}
private void setOrientation(int orientation) {
if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
throw new IllegalArgumentException("invalid orientation");
}
mOrientation = orientation;
}
/**
* 绘制间隔
*/
private void drawVertical(Canvas c, RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getBottom() + params.bottomMargin +
Math.round(ViewCompat.getTranslationY(child));
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
/**
* 绘制间隔
*/
private void drawHorizontal(Canvas c, RecyclerView parent) {
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int left = child.getRight() + params.rightMargin +
Math.round(ViewCompat.getTranslationX(child));
final int right = left + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
}
//表格类型的Recyclerview的间隔线装饰
public class MyGridRvDividerDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
/**
* 用于绘制间隔样式
*/
private Drawable mDivider;
public MyGridRvDividerDecoration(Context context) {
// 获取默认主题的属性
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
// 绘制间隔,每一个item,绘制右边和下方间隔样式
int childCount = parent.getChildCount();
int spanCount = ((GridLayoutManager)parent.getLayoutManager()).getSpanCount();
int orientation = ((GridLayoutManager)parent.getLayoutManager()).getOrientation();
boolean isDrawHorizontalDivider = true;
boolean isDrawVerticalDivider = true;
int extra = childCount % spanCount;
extra = extra == 0 ? spanCount : extra;
for(int i = 0; i < childCount; i++) {
isDrawVerticalDivider = true;
isDrawHorizontalDivider = true;
// 如果是竖直方向,最右边一列不绘制竖直方向的间隔
if(orientation == OrientationHelper.VERTICAL && (i + 1) % spanCount == 0) {
isDrawVerticalDivider = false;
}
// 如果是竖直方向,最后一行不绘制水平方向间隔
if(orientation == OrientationHelper.VERTICAL && i >= childCount - extra) {
isDrawHorizontalDivider = false;
}
// 如果是水平方向,最下面一行不绘制水平方向的间隔
if(orientation == OrientationHelper.HORIZONTAL && (i + 1) % spanCount == 0) {
isDrawHorizontalDivider = false;
}
// 如果是水平方向,最后一列不绘制竖直方向间隔
if(orientation == OrientationHelper.HORIZONTAL && i >= childCount - extra) {
isDrawVerticalDivider = false;
}
if(isDrawHorizontalDivider) {
drawHorizontalDivider(c, parent, i);
}
if(isDrawVerticalDivider) {
drawVerticalDivider(c, parent, i);
}
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int spanCount = ((GridLayoutManager) parent.getLayoutManager()).getSpanCount();
int orientation = ((GridLayoutManager)parent.getLayoutManager()).getOrientation();
int position = parent.getChildLayoutPosition(view);
if(orientation == OrientationHelper.VERTICAL && (position + 1) % spanCount == 0) {
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
return;
}
if(orientation == OrientationHelper.HORIZONTAL && (position + 1) % spanCount == 0) {
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
return;
}
outRect.set(0, 0, mDivider.getIntrinsicWidth(), mDivider.getIntrinsicHeight());
}
/**
* 绘制竖直间隔线
*
* @param canvas
* @param parent 父布局,RecyclerView
* @param position item在父布局中所在的位置
*/
private void drawVerticalDivider(Canvas canvas, RecyclerView parent, int position) {
final View child = parent.getChildAt(position);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getTop() - params.topMargin;
final int bottom = child.getBottom() + params.bottomMargin + mDivider.getIntrinsicHeight();
final int left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicWidth();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(canvas);
}
/**
* 绘制水平间隔线
*
* @param canvas
* @param parent
* 父布局,RecyclerView
* @param position
* item在父布局中所在的位置
*/
private void drawHorizontalDivider(Canvas canvas, RecyclerView parent, int position) {
final View child = parent.getChildAt(position);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
final int left = child.getLeft() - params.leftMargin;
final int right = child.getRight() + params.rightMargin + mDivider.getIntrinsicWidth();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(canvas);
}
}
// 瀑布流的Recyclerview的间隔线装饰
public class MyStaggeredRvDividerDecotation extends RecyclerView.ItemDecoration{
private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
/**
* 用于绘制间隔样式
*/
private Drawable mDivider;
public MyStaggeredRvDividerDecotation(Context context) {
// 获取默认主题的属性
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
// 绘制间隔,每一个item,绘制右边和下方间隔样式
int childCount = parent.getChildCount();
int spanCount = ((StaggeredGridLayoutManager)parent.getLayoutManager()).getSpanCount();
int orientation = ((StaggeredGridLayoutManager)parent.getLayoutManager()).getOrientation();
boolean isDrawHorizontalDivider = true;
boolean isDrawVerticalDivider = true;
int extra = childCount % spanCount;
extra = extra == 0 ? spanCount : extra;
for(int i = 0; i < childCount; i++) {
isDrawVerticalDivider = true;
isDrawHorizontalDivider = true;
// 如果是竖直方向,最右边一列不绘制竖直方向的间隔
if(orientation == OrientationHelper.VERTICAL && (i + 1) % spanCount == 0) {
isDrawVerticalDivider = false;
}
// 如果是竖直方向,最后一行不绘制水平方向间隔
if(orientation == OrientationHelper.VERTICAL && i >= childCount - extra) {
isDrawHorizontalDivider = false;
}
// 如果是水平方向,最下面一行不绘制水平方向的间隔
if(orientation == OrientationHelper.HORIZONTAL && (i + 1) % spanCount == 0) {
isDrawHorizontalDivider = false;
}
// 如果是水平方向,最后一列不绘制竖直方向间隔
if(orientation == OrientationHelper.HORIZONTAL && i >= childCount - extra) {
isDrawVerticalDivider = false;
}
if(isDrawHorizontalDivider) {
drawHorizontalDivider(c, parent, i);
}
if(isDrawVerticalDivider) {
drawVerticalDivider(c, parent, i);
}
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int spanCount = ((StaggeredGridLayoutManager) parent.getLayoutManager()).getSpanCount();
int orientation = ((StaggeredGridLayoutManager)parent.getLayoutManager()).getOrientation();
int position = parent.getChildLayoutPosition(view);
if(orientation == OrientationHelper.VERTICAL && (position + 1) % spanCount == 0) {
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
return;
}
if(orientation == OrientationHelper.HORIZONTAL && (position + 1) % spanCount == 0) {
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
return;
}
outRect.set(0, 0, mDivider.getIntrinsicWidth(), mDivider.getIntrinsicHeight());
}
/**
* 绘制竖直间隔线
*
* @param canvas
* @param parent 父布局,RecyclerView
* @param position item在父布局中所在的位置
*/
private void drawVerticalDivider(Canvas canvas, RecyclerView parent, int position) {
final View child = parent.getChildAt(position);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getTop() - params.topMargin;
final int bottom = child.getBottom() + params.bottomMargin + mDivider.getIntrinsicHeight();
final int left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicWidth();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(canvas);
}
/**
* 绘制水平间隔线
*
* @param canvas
* @param parent
* 父布局,RecyclerView
* @param position
* item在父布局中所在的位置
*/
private void drawHorizontalDivider(Canvas canvas, RecyclerView parent, int position) {
final View child = parent.getChildAt(position);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
final int left = child.getLeft() - params.leftMargin;
final int right = child.getRight() + params.rightMargin + mDivider.getIntrinsicWidth();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(canvas);
}
}
5. 开始使用RecyclerView
private RecyclerView recyclerView;
private RecyclerView.LayoutManager layoutManager;
private MyAdapter adapter;
// private MyStaggeredRvAdapter adapter;
@TargetApi(Build.VERSION_CODES.M)
private void init() {
adapter=new MyAdapter(getData());
// adapter=new MyStaggeredRvAdapter(getData()); // 瀑布流时使用的Adapter
layoutManager=new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false); //线性类型的LayoutManager 显示ListView类似
// layoutManager=new GridLayoutManager(this,3, OrientationHelper.VERTICAL,false); //表格类型的LayoutManager 显示GridView类似
// layoutManager=new StaggeredGridLayoutManager(3, OrientationHelper.VERTICAL); // 显示瀑布流效果
recyclerView= (RecyclerView) findViewById(R.id.recyclerview);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
MyDividerItemDecoration itemDecoration=new MyDividerItemDecoration(this,LinearLayoutManager.VERTICAL); // 每一个RecyclerView的item之间的装饰(间隔,可设置自己想要的效果,如:间隔线、分组等)
itemDecoration.setGroupListener(groupListener);
recyclerView.addItemDecoration(itemDecoration); //给recycler view添加item之间的间隔装饰
// recyclerView.addItemDecoration(new MyGridRvDividerDecoration(this));
// recyclerView.addItemDecoration(new MyStaggeredRvDividerDecotation(this));
}