關於HarmonyOS 自定義View我們可以學習HarmonyOS自定義組件 這篇文檔,今天描述自定義折線圖的功能,我們從“準備工作”、“初始化畫筆”、“繪畫折線圖”、“運行效果圖”,這四個方面進行描述 1. 準備工作 想要實現折線圖我們瞭解Paint,獲取屏幕的寬高,這幾個功能的實現 獲取屏幕的 ...
关于HarmonyOS 自定义View我们可以学习HarmonyOS自定义组件 这篇文档,今天描述自定义折线图的功能,我们从“准备工作”、“初始化画笔”、“绘画折线图”、“运行效果图”,这四个方面进行描述
1. 准备工作
想要实现折线图我们了解Paint,获取屏幕的宽高,这几个功能的实现
获取屏幕的宽高的代码如下
/**
* 获取屏幕宽
*
* @param context context
* @return int
*/
public static int getWindowWidth(Context context) {
DisplayManager displayManager = DisplayManager.getInstance();
Optional<Display> defaultDisplay = displayManager.getDefaultDisplay(context);
return defaultDisplay.get().getAttributes().width;
}
/**
* 获取屏幕高
*
* @param context context
* @return int
*/
public static int getWindowHeight(Context context) {
DisplayManager displayManager = DisplayManager.getInstance();
Optional<Display> defaultDisplay = displayManager.getDefaultDisplay(context);
return defaultDisplay.get().getAttributes().height;
}
2. 初始化画笔
主要实现画笔的设置颜色,设置宽度,设置画笔风格
private void initPaint() {
myPaint = new Paint();
myPaint.setColor(defaultColor);
myPaint.setStrokeWidth(ringWidth);
myPaint.setStyle(Paint.Style.STROKE_STYLE);
}
3. 绘画折线图
我们要学会Point,和canvas.drawText, canvas.drawLine绘画Y轴的坐标,绘画x轴坐标,绘画折线图三个方面进行实现
3.1 绘画Y轴的坐标代码如下
//Todo 绘画Y轴
//todo 绘画Y线
float mYHeigh = mScreenHeight * mYHeightPercent;
Point mYstartPoint = new Point(mYStartPointX, mYStartPointY);
Point mYEndPoint = new Point(mYStartPointX, mYHeigh);
Line yLine = new Line(mYstartPoint, mYEndPoint);
canvas.drawLine(yLine, myPaint);//绘画y线
//TODO 绘画Y轴刻度线
for (int i = 0; i <= 10; i++) {
Point mYScalesStartPoint = new Point(mYStartPointX, (mYHeigh - mYStartPointY) * i / 10 + mYStartPointY);
Point mYScalesEndPoint = new Point(mYStartPointX + mScaleLength, (mYHeigh - 50) * i / 10 + mYStartPointY);
Line yScalesLine = new Line(mYScalesStartPoint, mYScalesEndPoint);
canvas.drawLine(yScalesLine, myPaint);
//Todo 画Y轴刻度
Paint mPaint = getPaint();
canvas.drawText(mPaint, ((int) (((float) (10 - i) / 10) * 100)) + "", mYStartPointX - 100, (mYHeigh - 50) * i / 10 + mYStartPointY);
}
3.2 绘画X轴的坐标代码如下
//Todo 绘画X轴
Point mXstartPoint = new Point(mYStartPointX, mYHeigh);
Point mXEndPoint = new Point(mScreenWidth, mYHeigh);
Line XLine = new Line(mXstartPoint, mXEndPoint);
canvas.drawLine(XLine, myPaint); //绘画x线
//Todo 获取x轴长度
float mXwidth = mScreenWidth - mYStartPointX;
//TODO 绘画X轴刻度线
for (int i = 0; i <= 12; i++) {
Point mXScalesStartPoint;
Point mXScalesEndPoint;
mXScalesStartPoint = new Point(mYStartPointX + (mXwidth - mScaleLength) / 12 * i, mYHeigh);
mXScalesEndPoint = new Point(mYStartPointX + (mXwidth - mScaleLength) / 12 * i, mYHeigh - mScaleLength);
Line XScalesLine = new Line(mXScalesStartPoint, mXScalesEndPoint);
canvas.drawLine(XScalesLine, myPaint); //Todo 画x轴刻度
//Todo 绘画月份
Paint mPaint = getPaint();
mPaint.setTextSize(30);
if (i != 0) {
canvas.drawText(mPaint, i + "月", mYStartPointX + (mXwidth - mScaleLength) / 12 * i, mYHeigh + 100);
}
}
3.3 绘画折线代码如下
//Todo 绘画折线
Point mXPolyPoint = null;
float Percentage = 0f;
for (int i = 1; i < myData.length + 1; i++) {
if (i == 1) {
Percentage = myData[i - 1] / 100f;
mXPolyPoint = new Point(mYStartPointX + (mXwidth - mScaleLength) / 12 * i,
mYHeigh - (float) (mYHeigh - mYStartPointY) * Percentage);
} else {
Percentage = myData[i - 1] / 100f;
Point mNextPolyPoint = new Point(mYStartPointX + (mXwidth - mScaleLength) / 12 * i,
mYHeigh - (float) (mYHeigh - mYStartPointY) * Percentage);
Paint mPaint = getPaint();
mPaint.setColor(Color.RED);
mPaint.setTextSize(100);
Line mPolyline = new Line(mXPolyPoint, mNextPolyPoint);
canvas.drawLine(mPolyline, mPaint); //绘画两个月份点之间连线
mXPolyPoint = mNextPolyPoint;
}
}
4. 运行效果
4.1 全部代码如下
package com.harmony.alliance.mydemo.view;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.Line;
import ohos.agp.utils.Point;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import java.util.Optional;
public class CustomComponent extends Component implements Component.DrawTask {
private Paint myPaint;
private Color defaultColor = new Color(Color.rgb(237, 98, 98));
//画笔的宽度
private float ringWidth = 10;
private int mScreenWidth;//屏幕宽度
private int mScreenHeight;//屏幕高度
private float mYHeightPercent = 0.8f;//Y轴百分比
//todo Y轴起始点坐标x点
private float mYStartPointX = 200;
//todo Y轴起始点坐标y点
private float mYStartPointY = 50;
private float mScaleLength = 50;
private int[] myData = new int[]{68, 10, 45, 10, 88, 63, 60, 55, 79, 34, 52, 77};
public CustomComponent(Context context) {
this(context, null);
}
//如需支持xml创建自定义组件,必须添加该构造方法
public CustomComponent(Context context, AttrSet attrSet) {
super(context, attrSet);
//todo 获取屏幕宽高
mScreenWidth = getWindowWidth(context);
mScreenHeight = getWindowHeight(context);
// 初始化画笔
initPaint();
// 添加绘制任务
addDrawTask(this);
}
private void initPaint() {
myPaint = new Paint();
myPaint.setColor(defaultColor);
myPaint.setStrokeWidth(ringWidth);
myPaint.setStyle(Paint.Style.STROKE_STYLE);
}
@Override
public void onDraw(Component component, Canvas canvas) {
//Todo 绘画Y轴
//todo 绘画Y线
float mYHeigh = mScreenHeight * mYHeightPercent;
Point mYstartPoint = new Point(mYStartPointX, mYStartPointY);
Point mYEndPoint = new Point(mYStartPointX, mYHeigh);
Line yLine = new Line(mYstartPoint, mYEndPoint);
canvas.drawLine(yLine, myPaint);//绘画y线
//TODO 绘画Y轴刻度线
for (int i = 0; i <= 10; i++) {
Point mYScalesStartPoint = new Point(mYStartPointX, (mYHeigh - mYStartPointY) * i / 10 + mYStartPointY);
Point mYScalesEndPoint = new Point(mYStartPointX + mScaleLength, (mYHeigh - 50) * i / 10 + mYStartPointY);
Line yScalesLine = new Line(mYScalesStartPoint, mYScalesEndPoint);
canvas.drawLine(yScalesLine, myPaint);
//Todo 画Y轴刻度
Paint mPaint = getPaint();
canvas.drawText(mPaint, ((int) (((float) (10 - i) / 10) * 100)) + "", mYStartPointX - 100, (mYHeigh - 50) * i / 10 + mYStartPointY);
}
//Todo 绘画X轴
Point mXstartPoint = new Point(mYStartPointX, mYHeigh);
Point mXEndPoint = new Point(mScreenWidth, mYHeigh);
Line XLine = new Line(mXstartPoint, mXEndPoint);
canvas.drawLine(XLine, myPaint);//绘画x线
//Todo 获取x轴长度
float mXwidth = mScreenWidth - mYStartPointX;
//TODO 绘画X轴刻度线
for (int i = 0; i <= 12; i++) {
Point mXScalesStartPoint;
Point mXScalesEndPoint;
mXScalesStartPoint = new Point(mYStartPointX + (mXwidth - mScaleLength) / 12 * i, mYHeigh);
mXScalesEndPoint = new Point(mYStartPointX + (mXwidth - mScaleLength) / 12 * i, mYHeigh - mScaleLength);
Line XScalesLine = new Line(mXScalesStartPoint, mXScalesEndPoint);
canvas.drawLine(XScalesLine, myPaint); //Todo 画x轴刻度
//Todo 绘画月份
Paint mPaint = getPaint();
mPaint.setTextSize(30);
if (i != 0) {
canvas.drawText(mPaint, i + "月", mYStartPointX + (mXwidth - mScaleLength) / 12 * i, mYHeigh + 100);
}
}
//Todo 绘画折线
Point mXPolyPoint = null;
float Percentage = 0f;
for (int i = 1; i < myData.length + 1; i++) {
if (i == 1) {
Percentage = myData[i - 1] / 100f;
mXPolyPoint = new Point(mYStartPointX + (mXwidth - mScaleLength) / 12 * i,
mYHeigh - (float) (mYHeigh - mYStartPointY) * Percentage);
} else {
Percentage = myData[i - 1] / 100f;
Point mNextPolyPoint = new Point(mYStartPointX + (mXwidth - mScaleLength) / 12 * i,
mYHeigh - (float) (mYHeigh - mYStartPointY) * Percentage);
Paint mPaint = getPaint();
mPaint.setColor(Color.RED);
mPaint.setTextSize(100);
Line mPolyline = new Line(mXPolyPoint, mNextPolyPoint);
canvas.drawLine(mPolyline, mPaint);//绘画两个月份点之间连线
mXPolyPoint = mNextPolyPoint;
}
}
}
/**
* 获取屏幕宽
*
* @param context context
* @return int
*/
public static int getWindowWidth(Context context) {
DisplayManager displayManager = DisplayManager.getInstance();
Optional<Display> defaultDisplay = displayManager.getDefaultDisplay(context);
return defaultDisplay.get().getAttributes().width;
}
/**
* 获取屏幕高
*
* @param context context
* @return int
*/
public static int getWindowHeight(Context context) {
DisplayManager displayManager = DisplayManager.getInstance();
Optional<Display> defaultDisplay = displayManager.getDefaultDisplay(context);
return defaultDisplay.get().getAttributes().height;
}
//初始化刻度线的画笔
public Paint getPaint() {
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setTextSize(50);
return paint;
}
}
4.2 新建AbilitySlice 然后在xml布局中写如下代码
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:alignment="center"
ohos:orientation="vertical">
<com.harmony.alliance.mydemo.view.CustomComponent
ohos:width="match_parent"
ohos:height="match_parent">
</com.harmony.alliance.mydemo.view.CustomComponent>
</DirectionalLayout>
4.3 运行效果图