原文:RecyclerView之ItemDecoration由浅入深
一个RecyclerView使用ItemDecoration实现滑动悬停的效果
public class SectionDecoration extends RecyclerView.ItemDecoration {
private DecorationCallback callback;
private TextPaint textPaint;
private Paint paint;
private int topGap;
private Paint.FontMetrics fontMetrics;
public SectionDecoration(Context context, DecorationCallback callback) {
this.callback = callback;
paint = new Paint();
paint.setColor(context.getResources().getColor(R.color.colorAccent));
textPaint = new TextPaint();
textPaint.setAntiAlias(true);
textPaint.setColor(Color.BLACK);
textPaint.setTypeface(Typeface.DEFAULT_BOLD);
textPaint.setTextSize(80);
textPaint.getFontMetrics(fontMetrics);
textPaint.setTextAlign(Paint.Align.LEFT);
fontMetrics = new Paint.FontMetrics();
topGap = 100;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
int index = parent.getChildAdapterPosition(view);
long groupId = callback.getGroupId(index);
if (groupId < 0) {
return;
}
if (groupId == 0 || isFirstInGroup(index)) {
//同组的第一个才添加padding
outRect.top = topGap;
} else {
outRect.top = 0;
}
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
// int left = parent.getPaddingLeft();
// int right = parent.getWidth() - parent.getPaddingRight();
//
// int count = parent.getChildCount();
// for (int i = 0; i < count; i++) {
// View view = parent.getChildAt(i);
// int index = parent.getChildAdapterPosition(view);
// long groupId = callback.getGroupId(index);
// if (groupId < 0) {
// return;
// }
//
// String textLine = callback.getGroupFirstLine(index).toUpperCase();
// if (index == 0 || isFirstInGroup(index)) {
// int top = view.getTop() - topGap;
// int bottom = view.getTop();
// c.drawRect(left, top, right, bottom, paint);
// c.drawText(textLine, left, bottom, textPaint);
// }
// }
}
private boolean isFirstInGroup(int pos) {
if (pos == 0) {
return true;
} else {
long lastGroupId = callback.getGroupId(pos - 1);
long groupId = callback.getGroupId(pos);
return lastGroupId != groupId;
}
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
int itemCount = state.getItemCount();
int childCount = parent.getChildCount();
float left = parent.getPaddingLeft();
float right = parent.getWidth() - parent.getPaddingRight();
float lineHeight = textPaint.getTextSize() + fontMetrics.descent;
long lastGroupId, groupId = -1;
for (int i = 0; i < childCount; i++) {
View view = parent.getChildAt(i);
int position = parent.getChildAdapterPosition(view);
lastGroupId = groupId;
groupId = callback.getGroupId(position);
if (groupId < 0 || lastGroupId == groupId) {
continue;
}
String textLine = callback.getGroupFirstLine(position).toUpperCase();
if (TextUtils.isEmpty(textLine)) {
continue;
}
int viewBottom = view.getBottom();
float textY = Math.max(topGap, view.getTop());
if (position + 1 < itemCount) {
//下一个和当前不一样,移动当前
long nextGroupId = callback.getGroupId(position + 1);
if (nextGroupId != groupId && viewBottom < textY) {
//组内最后一个view进入了header
textY = viewBottom;
}
}
c.drawRect(left, textY - topGap, right, textY, paint);
c.drawText(textLine, left, textY - 15, textPaint);
}
}
}
调用
LinearLayoutManager manager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(manager);
list = getList();
adapter = new RecyclerViewAdapter(this, list);
recyclerView.addItemDecoration(new SectionDecoration(this, new DecorationCallback() {
@Override
public long getGroupId(int position) {
return Character.toUpperCase(list.get(position).getA().charAt(0));
}
@Override
public String getGroupFirstLine(int position) {
return list.get(position).getA().substring(0, 1).toUpperCase();
}
}));
recyclerView.setAdapter(adapter);