HarmonyOS鸿蒙Next中如何实现垂直刻度线,根据数值改变来逐个变色的进度效果
HarmonyOS鸿蒙Next中如何实现垂直刻度线,根据数值改变来逐个变色的进度效果
效果图是这样
随着进度数值变化,进度条逐步改为蓝色。 看了一圈官方文档,感觉也没有合适的组件啊。感谢感谢感谢!
更多关于HarmonyOS鸿蒙Next中如何实现垂直刻度线,根据数值改变来逐个变色的进度效果的实战教程也可以访问 https://www.itying.com/category-93-b0.html
【背景知识】
- 状态管理(V1): 自定义组件中的变量必须被装饰器装饰才可以成为状态变量,状态变量的改变会引起UI的渲染刷新。其中@State、@Prop、@Link、@Provide和@Consume装饰器都只能观察第一层的变化;@Observed/@ObjectLink配套使用是用于嵌套场景的观察,主要是为了弥补上述装饰器仅能观察一层的能力限制,比如二维数组,或者数组项class,或者class的属性是class。
- 状态管理(V2): 提供了一套全新的装饰器,@ObservedV2装饰器装饰class,使得被装饰的类具有深度监听的能力,@ObservedV2和@Trace配合使用可以使类中的属性具有深度观测的能力,尤其对于二维数组使用V2版本更容易实现数据的监听。
【解决方案】
使用 List 实现,ListItem的组件作为刻度。@State绑定一个变量,使用这个变量控制刻度的颜色。
参考代码:
@Entry
@Component
struct Index {
arr:number[] = [];
maxValue:number = 80000;
stepValue:number = 1000;
[@State](/user/State) currValue:number = 8848;
aboutToAppear(): void {
for(let i=this.maxValue;i>0;i=i-this.stepValue) {
this.arr.push(i)
}
}
build() {
Column() {
List({space:4}) {
ListItem() {
Text(`余${this.currValue}ml`)
}
ForEach(this.arr,(item:number)=>{
ListItem(){
Column()
.width('100%')
.height(4)
.backgroundColor(this.currValue>=item ? Color.Blue : Color.Gray)
.borderRadius(4)
}.width(item%(5*this.stepValue)===0 ? 50 : 36)
})
}.height('90%')
Row() {
Button('加1000').onClick(()=>{
if (this.currValue <= this.maxValue - 1000) {
this.currValue += 1000;
} else {
this.currValue = this.maxValue;
}
})
Button('减1000').onClick(()=>{
if (this.currValue >= 1000) {
this.currValue -= 1000;
} else {
this.currValue = 0
}
})
}
}
.height('100%')
.width('100%')
}
}
更多关于HarmonyOS鸿蒙Next中如何实现垂直刻度线,根据数值改变来逐个变色的进度效果的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
1、简单点,使用 List 实现,把 进度值 当做ListItem里的组件,只是宽度和颜色不一样,实现不难。
2、使用 Canvas 去画,熟悉相关api的话,就是多画些圆角矩形, 也比较简单 。
感谢建议,还想请问一下改变颜色这个怎么实现呢,
在HarmonyOS Next中,可通过Canvas组件绘制垂直刻度线。使用CanvasRenderingContext2D的moveTo和lineTo方法绘制垂直线条。通过for循环控制刻度数量与位置。根据数值变化,在绘制时动态判断当前刻度索引与数值比例,使用strokeStyle属性设置不同颜色(如条件判断后分别赋予不同色值),实现逐个变色效果。
在HarmonyOS Next中实现垂直刻度线进度条,可以通过自定义Canvas绘制完成。以下是核心实现思路和代码示例:
1. 绘制垂直刻度线
使用CanvasRenderingContext2D的strokeRect或moveTo/lineTo方法绘制垂直线条,通过循环控制刻度数量和间距。
// 示例:绘制基础刻度线
private drawScale(context: CanvasRenderingContext2D, total: number) {
const scaleWidth = 2;
const scaleSpacing = 10;
const startX = 50;
for (let i = 0; i <= total; i++) {
const yPos = i * scaleSpacing;
context.beginPath();
context.moveTo(startX, yPos);
context.lineTo(startX + 20, yPos); // 刻度长度20
context.lineWidth = scaleWidth;
context.stroke();
}
}
2. 动态变色逻辑
根据进度值计算需要变色的刻度数量,在绘制时动态设置颜色:
private drawProgress(context: CanvasRenderingContext2D, current: number, total: number) {
const progressCount = Math.floor((current / 100) * total);
for (let i = 0; i < total; i++) {
context.strokeStyle = i < progressCount ? '#007DFF' : '#E5E5E5'; // 蓝色/灰色
// 绘制单个刻度(代码略)
}
}
3. 完整组件示例
@Component
struct VerticalProgressBar {
@State currentProgress: number = 30;
private totalScales: number = 20;
build() {
Column() {
Canvas(this.onDraw)
.width(100)
.height(300)
Button('增加进度')
.onClick(() => {
this.currentProgress = Math.min(this.currentProgress + 5, 100);
})
}
}
onDraw(context: CanvasRenderingContext2D) {
const scaleCount = this.totalScales;
const progressScales = (this.currentProgress / 100) * scaleCount;
for (let i = 0; i < scaleCount; i++) {
// 设置颜色
context.strokeStyle = i < progressScales ? '#007DFF' : '#E5E5E5';
context.lineWidth = 3;
// 绘制垂直线段
const yPos = i * 15;
context.beginPath();
context.moveTo(40, yPos);
context.lineTo(60, yPos);
context.stroke();
}
}
}
关键点说明:
- 刻度计算:通过
(currentProgress / 100) * totalScales确定变色刻度数量 - 性能优化:建议使用
@State管理进度值,仅触发必要重绘 - 样式调整:修改
lineWidth控制线条粗细,调整间距参数适应不同高度
此方案完全基于ArkUI的Canvas能力,无需额外组件库。通过控制绘制逻辑中的颜色条件,即可实现动态变色效果。

