封装通用RecycleAdapter
package com.example.selfview.adapter;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public abstract class MyRecycleViewAdapter<T> extends RecyclerView.Adapter<MyRecycleViewAdapter.MyViewHolder>{
List<T> list;
int ItemViewId=-1;
View convertView;
public MyRecycleViewAdapter(List<T> list,@IdRes int ItemViewId){
this.list=list;
this.ItemViewId=ItemViewId;
}
public MyRecycleViewAdapter(List<T> list,View itemView){
this.list=list;
this.convertView=itemView;
}
@NonNull
@Override
public MyRecycleViewAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// convertView = ItemViewId==-1 ? convertView : View.inflate(parent.getContext(),ItemViewId,null);
//推荐使用layoutInflater,防止holder中view获取不到LayoutParam问题,使用上面的方法需要xml布局中childView必须有父类ViewGroup
convertView = ItemViewId==-1 ? convertView : LayoutInflater.from(parent.getContext()).inflate(ItemViewId,parent,false);
return new MyViewHolder(convertView);
}
@Override
public void onBindViewHolder(@NonNull MyRecycleViewAdapter.MyViewHolder holder, int position) {
convert(holder, position);
}
@Override
public int getItemCount() {
return list.size();
}
/**
* viewholder
*/
public class MyViewHolder extends RecyclerView.ViewHolder{
private SparseArray<View> mViews;
private View mConvertView;
public MyViewHolder(View v){
super(v);
mConvertView = itemView;
mViews = new SparseArray<View>();
}
public <T extends View> T getView(int viewId){
View view = mViews.get(viewId);
if (view == null){
view = mConvertView.findViewById(viewId);
mViews.put(viewId, view);
}
return (T) view;
}
}
//**************************** out method *********************************
/**
* bind data to view
* @param holder
* @param pos
*/
public abstract void convert(MyViewHolder holder, int pos);
/**
* addData and refresh
* @param pos
* @param t
*/
public void addData(int pos,T t){
list.add(pos,t);
notifyItemInserted(pos);
}
/**
* removeData and refresh
* @param pos
*/
public void removeData(int pos){
list.remove(pos);
notifyItemRemoved(pos);
}
}
封装Divider
1. listView使用的div
package com.example.selfview.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.View;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.ItemDecoration;
public class RecycleViewDivider extends ItemDecoration {
private Paint mPaint;
private Drawable mDivider;
private int mDividerHeight = 2;//分割线高度,默认为1px
private int mOrientation;//列表的方向:LinearLayoutManager.VERTICAL或LinearLayoutManager.HORIZONTAL
private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
/**
* 默认分割线:高度为2px,颜色为灰色
*
* @param context
* @param orientation 列表方向
*/
public RecycleViewDivider(Context context, int orientation) {
if (orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL) {
throw new IllegalArgumentException("use 0 or 1 means HORIZONTAL or VERTICAL");
}
mOrientation = orientation;
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
}
/**
* 自定义分割线
*
* @param context
* @param orientation 列表方向
* @param drawableId 分割线图片
*/
public RecycleViewDivider(Context context, int orientation, int drawableId) {
this(context, orientation);
mDivider = ContextCompat.getDrawable(context, drawableId);
mDividerHeight = mDivider.getIntrinsicHeight();
}
/**
* 自定义分割线
*
* @param context
* @param orientation 列表方向
* @param dividerHeight 分割线高度
* @param dividerColor 分割线颜色
*/
public RecycleViewDivider(Context context, int orientation, int dividerHeight, int dividerColor) {
this(context, orientation);
mDividerHeight = dividerHeight;
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(dividerColor);
mPaint.setStyle(Paint.Style.FILL);
}
//获取分割线尺寸
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
outRect.set(0, 0, 0, mDividerHeight);
}
//绘制分割线
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
if (mOrientation == LinearLayoutManager.VERTICAL) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
}
//绘制横向 item 分割线
private void drawHorizontal(Canvas canvas, RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getMeasuredWidth() - parent.getPaddingRight();
final int childSize = parent.getChildCount();
for (int i = 0; i < childSize; i++) {
final View child = parent.getChildAt(i);
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
final int top = child.getBottom() + layoutParams.bottomMargin;
final int bottom = top + mDividerHeight;
if (mDivider != null) {
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(canvas);
}
if (mPaint != null) {
canvas.drawRect(left, top, right, bottom, mPaint);
}
}
}
//绘制纵向 item 分割线
private void drawVertical(Canvas canvas, RecyclerView parent) {
final int top = parent.getPaddingTop();
final int bottom = parent.getMeasuredHeight() - parent.getPaddingBottom();
final int childSize = parent.getChildCount();
for (int i = 0; i < childSize; i++) {
final View child = parent.getChildAt(i);
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
final int left = child.getRight() + layoutParams.rightMargin;
final int right = left + mDividerHeight;
if (mDivider != null) {
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(canvas);
}
if (mPaint != null) {
canvas.drawRect(left, top, right, bottom, mPaint);
}
}
}
}
2. GridView使用的div
package com.example.selfview.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.View;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import static androidx.recyclerview.widget.GridLayoutManager.LayoutParams;
import static androidx.recyclerview.widget.RecyclerView.*;
/**
*
* @author laoniu
*
*/
public class DividerGridItemDecoration extends ItemDecoration
{
private static final int[] ATTRS = new int[] { android.R.attr.listDivider };
private Drawable mDivider;
public DividerGridItemDecoration(Context context)
{
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
}
@Override
public void onDraw(Canvas c, RecyclerView parent, State state)
{
drawHorizontal(c, parent);
drawVertical(c, parent);
}
private int getSpanCount(RecyclerView parent)
{
// 列数
int spanCount = -1;
LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager)
{
spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
} else if (layoutManager instanceof StaggeredGridLayoutManager)
{
spanCount = ((StaggeredGridLayoutManager) layoutManager)
.getSpanCount();
}
return spanCount;
}
public void drawHorizontal(Canvas c, RecyclerView parent)
{
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++)
{
final View child = parent.getChildAt(i);
final LayoutParams params = (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);
}
}
public void drawVertical(Canvas c, RecyclerView parent)
{
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++)
{
final View child = parent.getChildAt(i);
final LayoutParams params = (LayoutParams) child
.getLayoutParams();
final int top = child.getTop() - params.topMargin;
final int bottom = child.getBottom() + params.bottomMargin;
final int left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicWidth();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
private boolean isLastColum(RecyclerView parent, int pos, int spanCount,
int childCount)
{
LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager)
{
if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
{
return true;
}
} else if (layoutManager instanceof StaggeredGridLayoutManager)
{
int orientation = ((StaggeredGridLayoutManager) layoutManager)
.getOrientation();
if (orientation == StaggeredGridLayoutManager.VERTICAL)
{
if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
{
return true;
}
} else
{
childCount = childCount - childCount % spanCount;
if (pos >= childCount)// 如果是最后一列,则不需要绘制右边
return true;
}
}
return false;
}
private boolean isLastRaw(RecyclerView parent, int pos, int spanCount,
int childCount)
{
LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager)
{
childCount = childCount - childCount % spanCount;
if (pos >= childCount)// 如果是最后一行,则不需要绘制底部
return true;
} else if (layoutManager instanceof StaggeredGridLayoutManager)
{
int orientation = ((StaggeredGridLayoutManager) layoutManager)
.getOrientation();
// StaggeredGridLayoutManager 且纵向滚动
if (orientation == StaggeredGridLayoutManager.VERTICAL)
{
childCount = childCount - childCount % spanCount;
// 如果是最后一行,则不需要绘制底部
if (pos >= childCount)
return true;
} else
// StaggeredGridLayoutManager 且横向滚动
{
// 如果是最后一行,则不需要绘制底部
if ((pos + 1) % spanCount == 0)
{
return true;
}
}
}
return false;
}
@Override
public void getItemOffsets(Rect outRect, int itemPosition,
RecyclerView parent)
{
int spanCount = getSpanCount(parent);
int childCount = parent.getAdapter().getItemCount();
if (isLastRaw(parent, itemPosition, spanCount, childCount))// 如果是最后一行,则不需要绘制底部
{
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
} else if (isLastColum(parent, itemPosition, spanCount, childCount))// 如果是最后一列,则不需要绘制右边
{
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else
{
outRect.set(0, 0, mDivider.getIntrinsicWidth(),
mDivider.getIntrinsicHeight());
}
}
}
使用
也可用同样方式设置每个item宽高等属性
// 准备数据源
lists = new ArrayList<>();
for(int i = 0;i < 30;i++){
lists.add("list"+i);
}
// recyclerView.setLayoutManager(new LinearLayoutManager(this));
// recyclerView.setLayoutManager(new LinearLayoutManager(this,RecyclerView.VERTICAL,false));
// recyclerView.setLayoutManager(new GridLayoutManager(this,4));
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL));
// recyclerView.addItemDecoration(new RecycleViewDivider(this,
// LinearLayoutManager.HORIZONTAL, 10, getResources().getColor(R.color.gray_div)));
// recyclerView.addItemDecoration(new RecycleViewDivider(
// this, LinearLayoutManager.HORIZONTAL, R.drawable.div_rcv_common));
// recyclerView.addItemDecoration(new DividerGridItemDecoration(this));
MyRecycleViewAdapter adapter = new MyRecycleViewAdapter<String>(lists,android.R.layout.simple_list_item_1) {
@Override
public void convert(MyViewHolder holder, int pos) {
TextView tv = holder.getView(android.R.id.text1);
// tv.setLayoutParams(new ViewGroup.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
tv.setGravity(Gravity.CENTER);
tv.setText(lists.get(pos));
int value = (7+pos)%7;
switch (value) {
case 0:
tv.setBackgroundColor(Color.parseColor("#0094ff"));
break;
case 1:
tv.setBackgroundColor(getResources().getColor(android.R.color.holo_red_light));
break;
case 2:
tv.setBackgroundColor(getResources().getColor(android.R.color.holo_orange_dark));
break;
case 3:
tv.setBackgroundColor(getResources().getColor(android.R.color.holo_orange_light));
break;
case 4:
tv.setBackgroundColor(getResources().getColor(android.R.color.holo_green_dark));
break;
case 5:
tv.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_bright));
break;
case 6:
tv.setBackgroundColor(getResources().getColor(android.R.color.holo_purple));
break;
}
//瀑布流
tv.setHeight(100 + ((5+pos) % 5) * 30);
// holder.itemView.setBackgroundColor(Color.YELLOW);
//相当于itemClick
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e("TAG","OnItemClickListener"+pos);
T.toast("click:"+ pos);
}
});
}
};
recyclerView.setAdapter(adapter);