사용자 지정 아크 진행률 표시줄(Kotlin&Compose)

Compose를 사용하기 시작하면서 이전에 커스터마이징이 필요했던 뷰가 수십, 수백 줄의 코드로 레이아웃 속성을 커스터마이징해야 하고, View를 상속해야 하고, Paint를 사용해야 한다는 것을 알게 되었습니다. 하나의 방법으로 20줄을 직접 사용할 수 있습니다.

아래 그림과 같이 사용자 지정 호 진행률 표시줄을 구현하려면:

호 진행률 표시줄

Kotlin을 사용하여 구현

초기에는 이렇게 작은 데모
완료 코드를 작성했습니다: https://github.com/yaoxiawen/CircleProgressBar

사용자 정의 레이아웃 속성

attrs.xml에서 필수 속성 정의(만들지 않은 경우)

    <!--圆环形进度条-->
    <declare-styleable name="CircleProgressBar">
        <attr name="ringMax" format="integer" />
        <attr name="progress" format="integer" />
        <attr name="startAngle" format="float" />
        <attr name="endAngle" format="float" />
        <attr name="reverse" format="boolean" />
        <attr name="roundCap" format="boolean" />
        <attr name="ringWidth" format="dimension" />
        <attr name="ringColor" format="color" />
        <attr name="ringBackgroundColor" format="color" />
    </declare-styleable>

사용자 지정 보기

보기를 상속할 CircleProgressBar 만들기

class CircleProgressBar @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) 

AttributeSet을 통해 속성 구문 분석

생성자에서 AttributeSet 매개변수를 통해 레이아웃에 전달된 속성 값을 구문 분석하고 모든 속성에는 기본값이 있어야 합니다.

        val ta = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressBar)
        max = ta.getInt(R.styleable.CircleProgressBar_ringMax, DEFAULT_MAX)
        if (max <= 0) {
            max = DEFAULT_MAX
        }
        startAngle = ta.getFloat(R.styleable.CircleProgressBar_startAngle, DEFAULT_START_ANGLE)
        endAngle = ta.getFloat(R.styleable.CircleProgressBar_endAngle, DEFAULT_END_ANGLE)
        reverse = ta.getBoolean(R.styleable.CircleProgressBar_reverse, DEFAULT_REVERSE)
        roundCap = ta.getBoolean(R.styleable.CircleProgressBar_roundCap, DEFAULT_ROUND_CAP)
        progress = ta.getInt(R.styleable.CircleProgressBar_progress, DEFAULT_PROGRESS)
        ringWidth =
            ta.getDimension(R.styleable.CircleProgressBar_ringWidth, DEFAULT_RING_WIDTH)
        ringColor = ta.getColor(R.styleable.CircleProgressBar_ringColor, DEFAULT_RING_COLOR)
        ringBackgroungColor = ta.getColor(
            R.styleable.CircleProgressBar_ringBackgroundColor,
            DEFAULT_RING_BACKGROUND_COLOR
        )
        ta.recycle()

페인트 초기화

사용자 지정 보기는 그리기 위해 캔버스를 사용하며 자연스럽게 그림판이 필요합니다.

        mArcPaint = Paint()
        mArcPaint.isAntiAlias = true

onDraw에서 호 그리기

캔버스의 drawArc를 사용하여 호를 그리고 Paint에서 strokeCap을 Paint.Cap.ROUND로 설정하여 둥근 캡 효과를 그립니다.

        with(mArcPaint) {
            color = ringBackgroungColor
            style = Paint.Style.STROKE
            strokeWidth = ringWidth
            if (roundCap) {
                strokeCap = Paint.Cap.ROUND
            }
        }
        //绘制圆环背景
        canvas.drawArc(mRectF, startAngle, endAngle - startAngle, false, mArcPaint)
        with(mArcPaint) {
            color = ringColor
            if (roundCap) {
                strokeCap = Paint.Cap.ROUND
            }
        }
        var sweepAngle = progress.toFloat() / max * (endAngle - startAngle)
        if (reverse) {
            sweepAngle = -sweepAngle  //逆时针滚动
        }
        canvas.drawArc(mRectF, startAngle, sweepAngle, false, mArcPaint)

에서 사용되는 xml 레이아웃

    <com.example.circleprogressbar.CircleProgressBar
        android:layout_width="200dp"
        android:layout_height="200dp"
        app:progress="30"
        app:startAngle="-225"
        app:endAngle="45"
        app:ringWidth="10dp" />

Compose를 사용하여 구현

일부 유사한 API의 경우 Canvas의 drawArc를 사용하여 호를 그리고 cap = StrokeCap.Round를 설정하여 둥근 캡 효과를 얻습니다.

@Composable
fun CircleProgress(
    modifier: Modifier = Modifier,
    progress: Int,
    startAngle: Float,
    endAngle: Float,
    progressBgColor: Color,
    progressColor: Color,
) {
    Canvas(
        modifier = modifier,
        onDraw = {
            drawArc(
                color = progressBgColor,
                startAngle = startAngle,
                sweepAngle = endAngle - startAngle,
                useCenter = false,
                style = Stroke(size.width / 11, cap = StrokeCap.Round)
            )
            drawArc(
                color = progressColor,
                startAngle = startAngle,
                sweepAngle = (endAngle - startAngle) * progress / 100,
                useCenter = false,
                style = Stroke(size.width / 11, cap = StrokeCap.Round)
            )
        }
    )
}

메소드를 호출하여 일부 해당 매개변수를 전달하고 매개변수를 기본값으로 직접 설정할 수도 있습니다.

        CircleProgress(
            modifier = Modifier.padding(5.dp).size(66.dp),
            startAngle = -225f,
            endAngle = 45f,
            progress = 30,
            progressBgColor = Color.LightGray,
            progressColor = Color.Blue
        )

Supongo que te gusta

Origin blog.csdn.net/yuantian_shenhai/article/details/131603362
Recomendado
Clasificación