鸿蒙开源第三方组件-进度轮ProgressWheel

开源
进度轮是UI界面中常见的组件,通常用于向用户显示某个耗时操作完成的百分比,例如:加载状态、下载进度、刷新网页等。进度轮可以动态地显示操作进度,避免用户误以为程序失去响应,从而更好地提高用户界面的友好性。

[[384269]]

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

前言

基于安卓平台的进度轮组件ProgressWheel(https://github.com/Alford087/ProgressWheel),实现了鸿蒙化迁移和重构,代码已经开源到(https://gitee.com/isrc_ohos/progress-wheel_ohos),欢迎各位下载使用并提出宝贵意见!

背景

进度轮是UI界面中常见的组件,通常用于向用户显示某个耗时操作完成的百分比,例如:加载状态、下载进度、刷新网页等。进度轮可以动态地显示操作进度,避免用户误以为程序失去响应,从而更好地提高用户界面的友好性。

组件功能展示

基于鸿蒙系统,通过自定义控件属性的方式实现了进度轮组件,该组件支持进度轮的旋转、进度增加两种功能。

1、旋转

点击“Start spinning”按钮,此时进度轮会开始旋转,在旋转过程中按钮上的“Start spinning”变成“Stop spinning”,点击“Stop spinning”用户可以随时停止旋转,效果如图1所示。进度轮旋转功能主要用于展示服务器正在加载数据的状态,此时的作用和加载动画库AVLoadingIndicatorView类似。

图1 进度轮旋转

2、进度增加

点击“Increment”按钮,进度轮会定量增加进度,进度值会实时显示在进度轮的中间,效果如图2所示,进度增加功能主要用于展示服务器加载数据的进度。

图2 按钮控制进度增加

Sample解析

在Sample中向用户提供了5个场景,分别是:(1)进度轮旋转、(2)按钮控制进度增加、(3)原生进度条控制进度增加、(4)背景改变、(5)样式改变。其中(1)、(2)两种场景较为简单,均为按钮触发,调用ProgressWheel类的开始旋转、进度增加方法即可,在Library解析部分会详解解释。此处重点介绍(3)、(4)、(5)三种场景。

1、原生进度条控制进度增加

图3 原生进度条控制进度增加

 

原生进度条是指鸿蒙系统的基本组件slider,它也可以用于显示内容加载或操作处理的进度,此处我们通过拖动原生进度条来改变进度轮的进度值,并将进度值实时显示。效果如图3所示,代码实现如下:

  1. @Override 
  2. public void onProgressUpdated(Slider seekBar, int i, boolean b){ 
  3.     //原生进度条和进度轮换算,100代表原生进度条的进度最大值,360代表进度轮的进度最大值 
  4.     double progress = 360.0 * (seekBar.getProgress() / 100.0); 
  5.     //进度轮进度设置 
  6.     wheel.setProgress((int) progress); 

2、背景改变

图4 进度轮背景改变

使用Random 类产生随机数,特定处理后作为背景像素点。点击“Random bg”按钮,背景像素点显示,进度轮的背景会发生随机变化。效果如图4所示。代码如下:

  1. //背景改变 
  2. private static void randomBg(ProgressWheel wheel) { 
  3.     //随机产生背景元素 
  4.     Random random = new Random(); 
  5.     int firstColour = random.nextInt();//随机数获取 
  6.     int secondColour = random.nextInt(); 
  7.     int patternSize = (1 + random.nextInt(3)) * 8;//随机数处理 
  8.     int patternChange = (1 + random.nextInt(3)) * 8; 
  9.     int[] pixels = new int[patternSize]; 
  10.     for (int i = 0; i < patternSize; i++) { 
  11.         pixels[i] = (i > patternChange) ? firstColour : secondColour;//得到像素点 
  12.     } 
  13.     PixelMap.InitializationOptions options=new PixelMap.InitializationOptions(); 
  14.     options.size=new Size(1,patternSize); 
  15.     options.pixelFormat=PixelFormat.ARGB_8888; 
  16.     //设置背景元素 
  17.     wheel.setRimShader(new PixelMapShader( 
  18.             new PixelMapHolder(PixelMap.create(pixels, options)), 
  19.             Shader.TileMode.REPEAT_TILEMODE, 
  20.             Shader.TileMode.REPEAT_TILEMODE), Paint.ShaderType.RADIAL_SHADER); 

3、样式改变

图5 进度轮样式改变

通过自定义进度轮的长度、宽度、背景等来设计不同的样式,点击“A different style”按钮触发样式改变,效果如图5所示,代码如下:

  1. //样式改变 
  2. private static void styleRandom(ProgressWheel wheel, Context ctx) { 
  3.     wheel.setRimShader(null, Paint.ShaderType.RADIAL_SHADER); 
  4.     wheel.setRimColor(0xFFFFFFFF); 
  5.     wheel.setCircleColor(0x00000000);//内圆颜色 
  6.     wheel.setBarColor(0xFF000000);//进度轮体颜色 
  7.     wheel.setContourColor(0xFFFFFFFF);//外圆颜色 
  8.     wheel.setBarWidth(pxFromDp(ctx, 8));//宽度 
  9.     wheel.setBarLength(pxFromDp(ctx, 100));//长度 
  10.     wheel.setSpinSpeed(2);//旋转速度 
  11.     wheel.setDelayMillis(3);//间隔时间 

Library解析

1.功能实现

(1)进度轮绘制。

该功能是通过ProgressWheel类来实现的,在该类中首先声明setupBounds()、setupPaints()方法,后使用canvas绘制进度轮,设定内圆、外圆、条纹等、文字等属性。文字用于显示进度轮的属性值,不局限于显示当前进度。

  1. public ProgressWheel(Context context)  { 
  2.     super(context); 
  3.     DrawTask task = (component, canvas) -> { 
  4.         //初始化元素边界 
  5.         setupBounds(); 
  6.         //初始化绘制属性 
  7.         setupPaints(); 
  8.         //绘制内圆 
  9.         canvas.drawArc(innerCircleBounds, new Arc(360, 360, false), circlePaint); 
  10.         //绘制外圆 
  11.         canvas.drawArc(circleBounds, new Arc(360, 360, false), rimPaint); 
  12.         canvas.drawArc(circleOuterContour, new Arc(360, 360, false), contourPaint); 
  13.         //绘制条纹 
  14.         if (isSpinning) { 
  15.             canvas.drawArc(circleBounds, new Arc(progress - 90, barLength, false), barPaint); 
  16.         } else { 
  17.             canvas.drawArc(circleBounds, new Arc(-90, progress, false), barPaint); 
  18.         } 
  19.         //设置文字于圆心处显示 
  20.         float textHeight = textPaint.descent() - textPaint.ascent(); 
  21.         float verticalTextOffset = (textHeight / 2) - textPaint.descent(); 
  22.         for (String line : splitText) { 
  23.             float horizontalTextOffset = textPaint.measureText(line) / 2; 
  24.             canvas.drawText( 
  25.                     textPaint, 
  26.                     line, 
  27.                     (float) component.getWidth() / 2 - horizontalTextOffset, 
  28.                     (float) component.getHeight() / 2 + verticalTextOffset); 
  29.         } 
  30.         //旋转时在不同的位置画进度条 
  31.         if (isSpinning) { 
  32.             scheduleRedraw(); 
  33.         } 
  34.     }; 
  35.     addDrawTask(task); 

(2)进度轮旋转

该功能只提供给用户进度轮旋转的展示形式,不提供当前线程的量化进度。

1)开始旋转。进度轮进入旋转模式时,需要开辟新的线程,每隔一定时间重新绘制进度,来达到旋转的效果。

  1. public void startSpinning() { 
  2.     isSpinning = true;//设置当前为旋转状态 
  3.     pinHandler.sendEvent(0);//更新进度 

2)停止旋转。进度轮停止旋转时,进度值被置零。

  1. public void stopSpinning() { 
  2.     isSpinning = false;//设置当前为停止状态 
  3.     progress = 0;//进度清零 
  4.     invalidate(); 

(3)进度增加

该功能需提前设定好增量,每次增加固定的进度,进度的最大值设置为360,当超过最大值时,进度值被置零。该模式在旋转时提供当前的量化进度数据,用户可以清晰地了解当前的线程进度,是一种对用户更友好的交互模式。

  1. public void incrementProgress(int amount) { 
  2.     isSpinning = false;//增加进度时进度轮不旋转 
  3.     progress+= amount;//定量增加 
  4.     if (progress > 360){ 
  5.         progress %= 360;//超过360会自动重置 
  6.     } 
  7.     invalidate(); 

2.移植方法

本组件在移植时大部分采用API替换的方法,少数方法需要重写,如处理进度轮旋转的时候重写spinHandler()方法,该方法的功能是:进度轮旋转时在不同的像素位置绘制进度条,移动的位置超过360度则置为0度,重新旋转。代码如下:

  1. //每次绘制要移动的像素数目 
  2. private float spinSpeed = 2f; 
  3. //绘制过程的时间间隔 
  4. private int delayMillis = 100; 
  5. private EventHandler spinHandler = new EventHandler(EventRunner.getMainEventRunner()) 
  6.     @Override 
  7.     public void processEvent(InnerEvent msg) 
  8.     { 
  9.         invalidate(); 
  10.         if (isSpinning) 
  11.         { 
  12.             //更新画进度的位置 
  13.             progress += spinSpeed; 
  14.             //要移动的像素数目超过360则重置 
  15.             if (progress > 360) 
  16.             { 
  17.                 progress = 0; 
  18.             } 
  19.             spinHandler.sendEvent(0, delayMillis); 
  20.         } 
  21.          super.processEvent(msg); 
  22.     } 
  23. }; 

项目贡献人

刘磊 郑森文 朱伟 陈美汝 张馨心

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

 

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2021-08-26 16:07:46

鸿蒙HarmonyOS应用

2021-03-10 15:03:40

鸿蒙HarmonyOS应用

2021-04-29 14:32:24

鸿蒙HarmonyOS应用

2021-03-24 09:30:49

鸿蒙HarmonyOS应用

2021-08-03 10:07:41

鸿蒙HarmonyOS应用

2021-03-03 09:42:26

鸿蒙HarmonyOS图片裁剪

2021-07-06 18:21:31

鸿蒙HarmonyOS应用

2021-04-20 15:06:42

鸿蒙HarmonyOS应用

2021-04-08 14:57:52

鸿蒙HarmonyOS应用

2021-08-30 17:55:58

鸿蒙HarmonyOS应用

2021-08-05 15:06:30

鸿蒙HarmonyOS应用

2021-01-27 10:04:46

鸿蒙HarmonyOS动画

2021-11-02 14:54:21

鸿蒙HarmonyOS应用

2021-11-17 15:37:43

鸿蒙HarmonyOS应用

2021-04-15 17:47:38

鸿蒙HarmonyOS应用

2021-07-20 15:20:40

鸿蒙HarmonyOS应用

2021-03-12 16:35:33

鸿蒙HarmonyOS应用

2017-12-11 15:53:56

2021-10-19 10:04:51

鸿蒙HarmonyOS应用

2021-08-10 15:23:08

鸿蒙HarmonyOS应用
点赞
收藏

51CTO技术栈公众号