业务需求 需要创建等级任务进度条 开始自定义 上面为全景样式 下面贴自定义布局的整体样式
首先分析view的结构
1.最下层进度的线 分灰色的线->>>>>默认进度
2.最下层进度的线 分黄色的线->>>>>已完成进度
3.已完成的目标星级view->>>>>黄色圆形+内部等级
4.下一目标星级view->>>>>带一半黄色圆形边框的实心锁logo图标
4.未完成星级view->>>>>带圆形实心锁logo图标
5.在每个logo图上方的等级文案描述 (下一目标星级颜色为黄色)
画布局前先定义好一些坐标点和自定义NodeProgress的宽高
1. 等级圆的半径 nodeRadius 等级文案描述的文字大小 textSize 星级logo和上方文字的间距 startMarginTitle
2. NodeProgress的宽度 val widthSize = MeasureSpec.getSize(widthMeasureSpec)//父view给我的宽度
3. NodeProgress的高度 看布局的整体样式可以计算出 nodeRadius*2+processTitleTextSize+startMarginTitle+paddingBottom + paddingTop
4.然后算出各个圆心的点 例如五个等级 把宽度分为四节 每个圆心坐标计算方式为 并且用集合保存五个圆心的坐标
nodeWidth = (mWidth - paddingLeft - paddingRight).toFloat() / (nodeCount - 1)
for (i in 0 until nodeCount) {
val node = Node()
node.level = "V${i + 1}" node.score = getStartName(i + 1)
node.mPoint = Point(
nodeWidth.toInt() * (i) + paddingLeft,
mHeight - nodeRadius - paddingBottom )
node.type = if (currNodeNO == i) 1 else 0 nodes.add(node)
}
知道了一些关键坐标后 可以开始写代码画布局了
1.先画进度线条
//默认进度条
mPaint.strokeWidth = DensityUtils.dp2px(2f).toFloat() //设置画笔的粗细 mPaint.color = Color.parseColor("#5E6258")
mCanvas?.drawLine(
(paddingLeft).toFloat(),
(mHeight - nodeRadius - paddingBottom).toFloat(),
(mWidth - paddingRight).toFloat(),
(mHeight - nodeRadius - paddingBottom).toFloat(),
mPaint ) //没有进度的颜色
//有进度的线条颜色 currNodeNO为目标星级下标
mCanvas?.drawLine(
(paddingLeft).toFloat(),
(mHeight - nodeRadius - paddingBottom).toFloat(),
(nodes[currNodeNO].mPoint.x).toFloat(),
(nodes[currNodeNO].mPoint.y).toFloat(),
mPaint )
2.再画等级图标(包括已解锁、未解锁、目标星级)
for (i in nodes.indices) {
val node = nodes[i]
//已经解锁的
if (i < currNodeNO) {
drawCompletedNode(node)
} else if (i == currNodeNO) {// //目标解锁的
drawCurrentNode(node)
} else {//没有解锁的
drawUncompletedNode(node)
}
}
3.再画等级圆内部的等级(v1、v2)
val textWidth = mPaint.measureText(node.level)
val textHeight = mPaint.fontMetrics.bottom - mPaint.fontMetrics.top //drawScore true 在圆心内绘制v1 v2 if (drawScore) {
mCanvas?.drawText(
node.level,
rect.centerX() - textWidth / 2,
rect.centerY() + textHeight / 4,
mPaint )
}
4.再画等级圆上方的等级文本(一星、二星)
if (drawCurrentStar){
mStarTitlePaint.color = Color.parseColor("#FBDA95")
}else{
mStarTitlePaint.color = Color.parseColor("#99ffffff")
}
mCanvas?.drawText(
node.score,
rect.centerX().toFloat(),
(paddingTop + processTitleTextSize).toFloat(),
mStarTitlePaint )