一、基本思路
- 创建自定义控件的数据模型;
- 创建一个自定义 View 类,继承自 View;
- 在初始化方法中获取自定义属性的值。
- 创建设置数据方法,将数据模型列表转换成自定义绘制时的数据;
- 重写 onDraw 方法,以实现自定义的绘制逻辑。
二、主要绘制方法
1、drawLine 绘制直线
public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint)
- startX 和 startY:起点的 x 和 y 坐标。
- stopX 和 stopY:终点的 x 和 y 坐标。
- 线条的样式是 Paint.Style.STROKE。
2、 drawLines 绘制一系列直线
public void drawLines(@Size(multiple = 4) @NonNull float[] pts, int offset, int count, @NonNull Paint paint)
- pts:包含点坐标的数组。每条线由数组中的 4 个连续值定义,例如 pts[0] 和 pts[1] 是起点,pts[2] 和 pts[3] 是终点。因此,数组的长度必须是 4 的倍数。
- offset:从数组中跳过的值的数量。
- count:在跳过 offset 个值后要处理的值的数量。由于每条线需要 4 个值,因此实际绘制的线条数量为 count / 4,也说明 count 值必须是 4 的倍数。
- 应用场景:drawLines 方法适用于绘制简单的直线,例如:绘制网格线,绘制坐标轴,绘制界线,在游戏或图表中绘制路径。
3、drawText 绘制文本
public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint)
- text:要绘制的字符串。
- x 和 y:文本的起始点坐标(y 是基线的坐标)。
- paint:用于绘制文本的 Paint 对象。
- 绘制文本时,可通过设置 paint 属性来配置文本的颜色、大小、样式(粗体、斜体、下划线)等属性。
val paint = Paint()
// 设置文本颜色
paint.color = resources.getColor(R.color.red, null)
// 设置文本大小
paint.textSize = resources.getDimension(R.dimen.sp_18)
// 设置文本为粗体
paint.isFakeBoldText = true
// 设置文本为斜体
paint.textSkewX = -0.2f
// 设置文本为下划线
paint.isUnderlineText = true
4、drawCircle 绘制圆形
public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint)
- cx:圆心的 x 坐标。
- cy:圆心的 y 坐标。
- radius:圆的半径。如果半径小于或等于 0,则不会绘制任何内容。
- paint:用于绘制圆形的 Paint 对象,可以设置颜色、样式等属性。
- Paint 样式:Paint.Style.FILL 样式绘制实心圆形;Paint.Style.STROKE 样式绘制空心圆形,绘制空心圆形时,还需要设置 trokeWidth 来定义线条宽度;Paint.Style.FILL_AND_STROKE:填充圆形并绘制边框。
- 抗锯齿:可以通过 paint.setAntiAlias(true) 开启抗锯齿,使圆形边缘更平滑。
三、demo 示例
1、数据模型定义
data class ChartModel(val label: String, val value: Int)
2、res/values/attrs.xml 中自定义属性
<declare-styleable name="LineChartView">
<attr name="android:textColor" format="color"/>
<attr name="android:textSize" format="dimension"/>
<attr name="android:max" format="integer"/>
</declare-styleable>
3、自定义折线图控件
package com.android.androidfunctiondemo.customview
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
import android.view.View
import androidx.core.content.withStyledAttributes
import com.android.androidfunctiondemo.R
import java.text.NumberFormat
import java.util.Locale
class LineChartView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
) : View(context, attrs, defStyleAttr) {
// 折线颜色
private var chartColor = resources.getColor(R.color.red, null)
private val chartNodeRadius = resources.getDimension(R.dimen.dp_5)
// 坐标文本字体大小、颜色
private var labelTextSize = resources.getDimension(R.dimen.sp_18)
private var labelTextColor = resources.getColor(R.color.textColor, null)
// 坐标线颜色
private val coordinateLineColor = resources.getColor(R