一、简介
实现时光轴之前,我们先对RecycleView的ItemDecoration进行学习。
RecyclerView目前在我们的开发中使用十分频繁,其基本概念这些我们也不细细整理了,但是我们添加分割线,点击监听等等更复杂了,现在我们先学习ItemDecoration。
ItemDecoration有3个重要方法,我们简单的说明
public class Decoration extends RecyclerView.ItemDecoration {
/**
* 设置ItemView的内嵌偏移长度,可以实现类似padding的效果
* @param outRect 全为 0 的 Rect(包括着Item)
* @param view 每个Item
* @param parent RecyclerView 本身
* @param state 状态
*/
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
}
/**
* 可以实现类似绘制背景的效果,内容在上面
*/
@Override
public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.onDraw(c, parent, state);
}
/**
* 可以绘制在内容的上面,覆盖内容
*/
@Override
public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.onDrawOver(c, parent, state);
}
}
二、实战理解
1、实现分割线
public class DiverDecoration extends RecyclerView.ItemDecoration {
private Paint dividerPaint;
private int deviderHeight;
public DiverDecoration() {
dividerPaint=new Paint();
dividerPaint.setColor(Color.RED);
// 分割线的高度
deviderHeight=2;
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c,parent,state);
//得到列表所有的条目
int childCount = parent.getChildCount();
//得到条目的宽和高
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
for (int i = 0; i < childCount - 1; i++) {
View view = parent.getChildAt(i);
//计算每一个条目的顶点和底部 float值
float top = view.getBottom();
float bottom = view.getBottom() + deviderHeight;
//重新绘制
c.drawRect(left, top, right, bottom, dividerPaint);
}
}
}
使用方法:
mRecyclerView.addItemDecoration(new DiverDecoration());
2、实现时光轴
实现方法,若下图所示,我们在每个View前加入一个时间节点(如图红色所示),我们求得每个View的圆心后,绘制下面的图形,实现最简单的时间轴。
扩展:我们可以在传入时间集合,在前面加入时间,或者美化下面的时间节点,实现更优雅的时光轴,更完善的封装可能会在后面完整整理MVP中实现。
实现代码
public class TimeLineDecoration extends RecyclerView.ItemDecoration {
private Paint mPaint;
//内容距离左边的距离
private int mOffsetLeft;
//内容距离左边的距离
private int mOffsetTop;
//绘制原点的半径
private int mRadius;
public TimeLineDecoration() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStrokeWidth(7);
mPaint.setColor(Color.RED);
//默认设置距离左边80,圆的半径20
mOffsetLeft = 80;
mRadius = 20;
}
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
//如果是第一个,不需要设置top值
if (parent.getChildAdapterPosition(view) != 0) {
outRect.top = 5;
mOffsetTop = 5;
}
outRect.left = mOffsetLeft;
}
@Override
public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.onDraw(c, parent, state);
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View view = parent.getChildAt(i);
int index = parent.getChildAdapterPosition(view);
//同样,如果是第一个没有view也没有top值
int viewTop = view.getTop() - mOffsetTop;
if (index == 0) {
viewTop = view.getTop();
}
int viewBottom = view.getBottom();
//获取圆心的坐标
int centerX = view.getPaddingLeft() + mOffsetLeft / 2;
int centerY = viewTop + (viewBottom - viewTop) / 2;
//绘制上下2条线
c.drawLine(centerX, viewTop, centerX, centerY - mRadius, mPaint);
c.drawLine(centerX, centerY - mRadius, centerX, viewBottom, mPaint);
//绘制圆
c.drawCircle(centerX, centerY, mRadius, mPaint);
}
}
}
使用
mRecyclerView.addItemDecoration(new TimeLineDecoration());
实现效果:具体的效果我们自行优化,就可以实现很亮丽的效果
时间轴的自定义基本完 ,说白了就是一堆计算加上简单的绘制,因为目前的工作不是Android开发,所以也是边做边学,如有问题请多多留言指教。关于自定义View实战会逐步更新,下一章会整理自定义翻页的知识。
网友评论