1. 程式人生 > 其它 >【HarmonyOS】【JAVA UI】鴻蒙 自定義折線圖

【HarmonyOS】【JAVA UI】鴻蒙 自定義折線圖

關於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.drawTextcanvas.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 執行效果圖