Compose Canvas 折线图

这篇博客展示了如何使用Jetpack Compose创建一个自定义的积分图表,通过Canvas组件绘制背景横线、小圆圈和折线,以及如何根据数据动态调整图表。文章还提到了使用AsyncImage加载图片和Text组件显示文字。示例代码中,pointsOfWeek变量存储了图表数据,用于展示一周内积分变化情况。
摘要由CSDN通过智能技术生成
package com.anguomob.compose.ui.components

import android.util.Log
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Divider
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.layoutId
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.constraintlayout.compose.ConstraintSet
import androidx.constraintlayout.compose.Dimension
import coil.compose.AsyncImage
import com.anguomob.compose.model.ArticleEntity
import com.anguomob.compose.model.VideoEntity

private const val TAG = "ChartView"

@Composable
fun ChartView(modifier: Modifier = Modifier, points: List<Float>) {
    //每一行的高度
    val heightForRow = 24

    //总行数
    val countForRow = 5

    //小圆圈半径
    val circleRadius = 2.5

    //画布宽度
    val canvasWidth = LocalConfiguration.current.screenWidthDp - 8 * 2
    //画布高度
    val canvasHeight = heightForRow * countForRow + circleRadius * 2

    //没8 dp 代表1积分 每一行 3积分
    val perY = 8 //24 * 5 /15

    //七平分宽度
    val averageOfWidth = canvasWidth / 7


    Canvas(modifier = modifier.size(width = canvasWidth.dp, canvasHeight.dp), onDraw = {
        //背景横线
        for (index in 0..countForRow) {
            val startY = (index * heightForRow.toFloat() + circleRadius).dp.toPx()
            val endX = size.width
            val endY = startY
            drawLine(Color(0xFFEEEEEE),
                start = Offset(x = 0f, y = startY),
                end = Offset(x = endX, y = endY),
                strokeWidth = 2.5f)
        }

        //画小圆圈、折线
        for (index in 0 until points.count()) {
            Log.e(TAG, "index:${index} ");
            val centerX = (averageOfWidth * index + averageOfWidth / 2).dp.toPx()
            val centerY =
                (heightForRow * countForRow - points[index] * perY + circleRadius).dp.toPx()
            val circleCenter = Offset(centerX, centerY)
            //点
            drawCircle(Color(0xff149ee7), radius = circleRadius.dp.toPx(),
                center = circleCenter,
                style = Stroke(width = 5f)
            )
            //线
            if (index < points.count() - 1) {
                val nextPointOffsetX = (averageOfWidth * (index + 1) + averageOfWidth / 2).dp.toPx()
                val nextPointOffsetY =
                    (heightForRow * countForRow - points[(index + 1)] * perY + circleRadius).dp.toPx()
                val nextPoint = Offset(nextPointOffsetX, nextPointOffsetY)
                drawLine(Color(0xFF149EE7), start = circleCenter, end = nextPoint, strokeWidth = 5f)
            }

        }
    })
}

数据为

var pointsOfWeek by mutableStateOf(listOf(3f, 2f, 6f, 9.3f, 10f, 15f, 8f))
    private set

效果为

下面的周几是因为没有drawText

所以

            Row() {
                        taskViewModel.weeks.forEach {
                            Text(text = it,
                                color = Color(0xff999999),
                                fontSize = 12.sp,
                                modifier = Modifier.weight(1f),
                                textAlign = TextAlign.Center
                            )
                        }
                    }

 

    val weeks = listOf("02.05", "02.06", "02.07", "02.08", "02.09", "02.10", "今日")

安卓的Compose框架是一种用于构建用户界面的现代UI工具包。它与传统的View系统相比,提供了更加简洁、灵活和高效的方式来创建界面元素。 在Compose中监听手势事件并进行相应的绘制操作,可以通过使用Canvas API来实现。首先,我们需要在Compose中创建一个自定义的绘制组件,例如CanvasView。 在这个组件中,我们可以使用Modifier.pointerInput来为Canvas添加手势监听器。例如,我们可以使用onPointerInput函数来监听手势的移动、按下和抬起等事件。 具体实现时,可以在一个PointerEventPass中使用awaitPointerEvent函数来监听手势事件。可以通过event.action来获取手势的动作类型,例如MotionEvent.ACTION_DOWN表示按下动作,MotionEvent.ACTION_MOVE表示移动动作,MotionEvent.ACTION_UP表示抬起动作。 一旦监听到对应的手势动作,我们可以根据事件的坐标信息来更新Canvas上的绘图内容。比如,可以使用Canvas的drawCircle方法在指定位置绘制一个圆形。 除此之外,我们还可以根据手势事件的特性来实现更加复杂的交互效果,例如根据手指的移动来绘制路径、随手势的放大缩小来改变绘制的形状等等。 综上所述,通过在Compose中使用Canvas API并监听手势事件,我们可以实现Canvas的交互式绘制。这为我们提供了更多创造性的可能性,使我们能够灵活地响应用户的手势操作,并实时更新界面的绘制效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安果移不动

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值