鴻蒙開源第三方組件——進度輪ProgressWheel

目錄:
一、前言
二、背景
三、組件功能展現
四、Sample解析
五、Library解析
六、做者系列文章合集git

前言github

          基於安卓平臺的進度輪組件ProgressWheel(https://github.com/Alford087/ProgressWheel),實現了鴻蒙化遷移和重構,代碼已經開源到(https://gitee.com/isrc_ohos/progress-wheel_ohos),歡迎各位下載使用並提出寶貴意見!canvas

背景服務器

      進度輪是UI界面中常見的組件,一般用於向用戶顯示某個耗時操做完成的百分比,例如:加載狀態、下載進度、刷新網頁等。進度輪能夠動態地顯示操做進度,避免用戶誤覺得程序失去響應,從而更好地提升用戶界面的友好性。dom

組件功能展現  ide

       基於鴻蒙系統,經過自定義控件屬性的方式實現了進度輪組件,該組件支持進度輪的旋轉、進度增長兩種功能。post

一、旋轉動畫

        點擊「Start spinning」按鈕,此時進度輪會開始旋轉,在旋轉過程當中按鈕上的「Start spinning」變成「Stop spinning」,點擊「Stop spinning」用戶能夠隨時中止旋轉,效果如圖1所示。進度輪旋轉功能主要用於展現服務器正在加載數據的狀態,此時的做用和加載動畫庫AVLoadingIndicatorView相似。url

鴻蒙開源第三方組件——進度輪ProgressWheel

圖1 進度輪旋轉spa

二、進度增長

       點擊「Increment」按鈕,進度輪會定量增長進度,進度值會實時顯示在進度輪的中間,效果如圖2所示,進度增長功能主要用於展現服務器加載數據的進度。

鴻蒙開源第三方組件——進度輪ProgressWheel

圖2 按鈕控制進度增長

Sample解析

       在Sample中向用戶提供了5個場景,分別是:(1)進度輪旋轉、(2)按鈕控制進度增長、(3)原生進度條控制進度增長、(4)背景改變、(5)樣式改變。其中(1)、(2)兩種場景較爲簡單,均爲按鈕觸發,調用ProgressWheel類的開始旋轉、進度增長方法便可,在Library解析部分會詳解解釋。此處重點介紹(3)、(4)、(5)三種場景。

一、原生進度條控制進度增長

鴻蒙開源第三方組件——進度輪ProgressWheel

 圖3 原生進度條控制進度增長

        原生進度條是指鴻蒙系統的基本組件slider,它也能夠用於顯示內容加載或操做處理的進度,此處咱們經過拖動原生進度條來改變進度輪的進度值,並將進度值實時顯示。效果如圖3所示,代碼實現以下:

@Override
public void onProgressUpdated(Slider seekBar, int i, boolean b){
    //原生進度條和進度輪換算,100表明原生進度條的進度最大值,360表明進度輪的進度最大值
    double progress = 360.0 * (seekBar.getProgress() / 100.0);
    //進度輪進度設置
    wheel.setProgress((int) progress);
}

二、背景改變

鴻蒙開源第三方組件——進度輪ProgressWheel

圖4 進度輪背景改變

使用Random 類產生隨機數,特定處理後做爲背景像素點。點擊「Random bg」按鈕,背景像素點顯示,進度輪的背景會發生隨機變化。效果如圖4所示。代碼以下:

//背景改變
private static void randomBg(ProgressWheel wheel) {
    //隨機產生背景元素
    Random random = new Random();
    int firstColour = random.nextInt();//隨機數獲取
    int secondColour = random.nextInt();
    int patternSize = (1 + random.nextInt(3)) * 8;//隨機數處理
    int patternChange = (1 + random.nextInt(3)) * 8;
    int[] pixels = new int[patternSize];
    for (int i = 0; i < patternSize; i++) {
        pixels[i] = (i > patternChange) ? firstColour : secondColour;//獲得像素點
    }
    PixelMap.InitializationOptions options=new PixelMap.InitializationOptions();
    options.size=new Size(1,patternSize);
    options.pixelFormat=PixelFormat.ARGB_8888;
    //設置背景元素
    wheel.setRimShader(new PixelMapShader(
            new PixelMapHolder(PixelMap.create(pixels, options)),
            Shader.TileMode.REPEAT_TILEMODE,
            Shader.TileMode.REPEAT_TILEMODE), Paint.ShaderType.RADIAL_SHADER);
}

三、樣式改變

鴻蒙開源第三方組件——進度輪ProgressWheel

圖5 進度輪樣式改變

經過自定義進度輪的長度、寬度、背景等來設計不一樣的樣式,點擊「A different style」按鈕觸發樣式改變,效果如圖5所示,代碼以下:

//樣式改變
private static void styleRandom(ProgressWheel wheel, Context ctx) {
    wheel.setRimShader(null, Paint.ShaderType.RADIAL_SHADER);
    wheel.setRimColor(0xFFFFFFFF);
    wheel.setCircleColor(0x00000000);//內圓顏色
    wheel.setBarColor(0xFF000000);//進度輪體顏色
    wheel.setContourColor(0xFFFFFFFF);//外圓顏色
    wheel.setBarWidth(pxFromDp(ctx, 8));//寬度
    wheel.setBarLength(pxFromDp(ctx, 100));//長度
    wheel.setSpinSpeed(2);//旋轉速度
    wheel.setDelayMillis(3);//間隔時間
}

 Library解析

1.功能實現

      (1)進度輪繪製。

     該功能是經過ProgressWheel類來實現的,在該類中首先聲明setupBounds()、setupPaints()方法,後使用canvas繪製進度輪,設定內圓、外圓、條紋等、文字等屬性。文字用於顯示進度輪的屬性值,不侷限於顯示當前進度。

public ProgressWheel(Context context)  {
    super(context);
    DrawTask task = (component, canvas) -> {
        //初始化元素邊界
        setupBounds();
        //初始化繪製屬性
        setupPaints();
        //繪製內圓
        canvas.drawArc(innerCircleBounds, new Arc(360, 360, false), circlePaint);
        //繪製外圓
        canvas.drawArc(circleBounds, new Arc(360, 360, false), rimPaint);
        canvas.drawArc(circleOuterContour, new Arc(360, 360, false), contourPaint);
        //繪製條紋
        if (isSpinning) {
            canvas.drawArc(circleBounds, new Arc(progress - 90, barLength, false), barPaint);
        } else {
            canvas.drawArc(circleBounds, new Arc(-90, progress, false), barPaint);
        }
        //設置文字於圓心處顯示
        float textHeight = textPaint.descent() - textPaint.ascent();
        float verticalTextOffset = (textHeight / 2) - textPaint.descent();
        for (String line : splitText) {
            float horizontalTextOffset = textPaint.measureText(line) / 2;
            canvas.drawText(
                    textPaint,
                    line,
                    (float) component.getWidth() / 2 - horizontalTextOffset,
                    (float) component.getHeight() / 2 + verticalTextOffset);
        }
        //旋轉時在不一樣的位置畫進度條
        if (isSpinning) {
            scheduleRedraw();
        }
    };
    addDrawTask(task);
}

(2)進度輪旋轉

該功能只提供給用戶進度輪旋轉的展現形式,不提供當前線程的量化進度。

1)開始旋轉。進度輪進入旋轉模式時,須要開闢新的線程,每隔必定時間從新繪製進度,來達到旋轉的效果。

public void startSpinning() {
    isSpinning = true;//設置當前爲旋轉狀態
    pinHandler.sendEvent(0);//更新進度
}

2)中止旋轉。進度輪中止旋轉時,進度值被置零。

public void stopSpinning() {
    isSpinning = false;//設置當前爲中止狀態
    progress = 0;//進度清零
    invalidate();
}

(3)進度增長

該功能需提早設定好增量,每次增長固定的進度,進度的最大值設置爲360,當超過最大值時,進度值被置零。該模式在旋轉時提供當前的量化進度數據,用戶能夠清晰地瞭解當前的線程進度,是一種對用戶更友好的交互模式。

public void incrementProgress(int amount) {
    isSpinning = false;//增長進度時進度輪不旋轉
    progress+= amount;//定量增長
    if (progress > 360){
        progress %= 360;//超過360會自動重置
    }
    invalidate();
}

2.移植方法

本組件在移植時大部分採用API替換的方法,少數方法須要重寫,如處理進度輪旋轉的時候重寫spinHandler()方法,該方法的功能是:進度輪旋轉時在不一樣的像素位置繪製進度條,移動的位置超過360度則置爲0度,從新旋轉。代碼以下:

//每次繪製要移動的像素數目
private float spinSpeed = 2f;
//繪製過程的時間間隔
private int delayMillis = 100;
private EventHandler spinHandler = new EventHandler(EventRunner.getMainEventRunner())
{
    @Override
    public void processEvent(InnerEvent msg)
    {
        invalidate();
        if (isSpinning)
        {
            //更新畫進度的位置
            progress += spinSpeed;
            //要移動的像素數目超過360則重置
            if (progress > 360)
            {
                progress = 0;
            }
            spinHandler.sendEvent(0, delayMillis);
        }
         super.processEvent(msg);
    }
};

 項目貢獻人

劉磊 鄭森文 朱偉 陳美汝 張馨心

做者:小雪糕123
想了解更多內容,請訪問: 51CTO和華爲官方戰略合做共建的鴻蒙技術社區https://harmonyos.51cto.com

相關文章
相關標籤/搜索