android自定义星级进度条

207 阅读2分钟

image.png

业务需求 需要创建等级任务进度条 开始自定义 上面为全景样式 下面贴自定义布局的整体样式

image.png

首先分析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 )