利用RecyclerView.ItemDecoration实现的悬浮效果
getItemOffsets:通过Rect为每个Item设置偏移,用于绘制Decoration。
onDraw:通过该方法,在Canvas上绘制内容,在绘制Item之前调用。(如果没有通过getItemOffsets设置偏移的话,Item的内容会将其覆盖)
onDrawOver:通过该方法,在Canvas上绘制内容,在Item之后调用。(画的内容会覆盖在item的上层)
RecyclerView rv_list = (RecyclerView) findViewById(R.id.rv_list);
rv_list.setLayoutManager(new LinearLayoutManager(this));
CityAdapter cityAdapter = new CityAdapter(list);
rv_list.setAdapter(cityAdapter);
rv_list.addItemDecoration(new StickyItemDecoration(new StickyItemDecoration.OnTagListener() {
@Override
public String getGroupName(int position) {
return list.get(position).getPinyin().substring(0, 1);
}
@Override
public boolean isGroupFirst(int position) {
return position == 0 || !TextUtils.equals(list.get(position).getPinyin().substring(0, 1), list.get(position - 1).getPinyin().substring(0, 1));
}
}));
public class StickyItemDecoration extends RecyclerView.ItemDecoration {
private int decorationHeight = 100;
private OnTagListener onTagListener;
private final Paint bgPaint;
private final Paint textPaint;
public StickyItemDecoration(OnTagListener onTagListener) {
this.onTagListener = onTagListener;
bgPaint = new Paint();
bgPaint.setAntiAlias(true);
bgPaint.setColor(Color.parseColor("#3F51B5"));
textPaint = new Paint();
textPaint.setAntiAlias(true);
textPaint.setColor(Color.parseColor("#ffffff"));
textPaint.setTextSize(45);
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
int itemCount = state.getItemCount();
int childCount = parent.getChildCount();
int left = parent.getLeft() + parent.getPaddingLeft();
int right = parent.getRight() + parent.getPaddingRight();
int viewLeft;
String currentTag = null;
for (int i = 0; i < childCount; i++) {
View childView = parent.getChildAt(i);
viewLeft = childView.getLeft() + childView.getPaddingLeft();
int position = parent.getChildAdapterPosition(childView);
if (TextUtils.equals(currentTag, onTagListener.getGroupName(position))) {
continue;
}
currentTag = onTagListener.getGroupName(position);
int viewBottom = childView.getBottom();
int top = Math.max(decorationHeight, childView.getTop());
if (position + 1 < itemCount) {
if (!TextUtils.equals(currentTag, onTagListener.getGroupName(position + 1)) && viewBottom < top) {
top = viewBottom;
}
}
c.drawRect(left, top - decorationHeight, right, top, bgPaint);
Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
float baseLine = top - (decorationHeight - (fontMetrics.bottom - fontMetrics.top)) / 2 - fontMetrics.bottom;
c.drawText(currentTag.toUpperCase(), viewLeft, baseLine, textPaint);
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
int position = parent.getChildAdapterPosition(view);
if (position == 0 || onTagListener.isGroupFirst(position)) {
outRect.top = decorationHeight;
}
}
public interface OnTagListener {
String getGroupName(int position);
boolean isGroupFirst(int position);
}
}