写点什么

【HarmonyOS】鸿蒙实现刻度尺

作者:
  • 2025-05-07
    广东
  • 本文字数:2224 字

    阅读完需:约 7 分钟

前言

近期在做鸿蒙 app 项目,有一个如图 1 所示的刻度尺,多次翻阅相关资料未找到类似的,所以纯手写了一份,在此与各位同行分享,也欢迎各位大佬点评。

图一

功能简介

  • 刻度尺可以精确到小数点后一位

  • 可以自定义刻度尺的刻度间隔,起始刻度数,总刻度数,当前选中的值

  • 根据默认选中值,滑动到对应刻度

  • 根据当前刻度尺滚动的距离自动贴合到附近最近的刻度

  • 左右滑动刻度尺,停止滑动的时候,得到当前刻度尺值

使用

  1. 复制组件 RulerComponent 组件源码(在下面) 到 ArkTs 文件中。

  2. 在所需要的组件中引入

import { RulerComponent } from '../../component/ruler/RulerComponent';
复制代码
  1. 放入组件合适的位置:


组件源码

@Preview@Componentexport struct RulerComponent {  @Prop scaleWidth: number = 12 // 刻度间隔  @Prop totalScale: number = 33 //总刻度数  @Prop startScale: number = 1 //起始值  @Prop currentValue: number = 1.0 //当前值  @State totalArray: number[] = []  //总刻度  private scroller: Scroller = new Scroller();  scrollStopEvent: (scaleValue: number) => void = () => {  };
aboutToAppear(): void { // 根据总刻度,创建一个刻度值组成的数组,总刻度*10,是因为需要精确到小数据后一位, for (let i = 1; i <= this.totalScale * 10; i++) { if ((i / 10) >= this.startScale) { this.totalArray.push(i); } } }
onDidBuild() { // 计算滚动距离 let defaultScroll = (this.currentValue - this.startScale) * 10 * this.scaleWidth this.scroller.scrollTo({ xOffset: defaultScroll, yOffset: 0 }) //吸附效果 }
build() { RelativeContainer() { this.contentBuilder() } .height('100') .width('100%'); }
// 主题内容 @Builder contentBuilder() { Column() { // 数值显示 Text(`${this.currentValue} mmol/L`) .fontSize(22) .margin({ bottom: 18 }) .fontColor("#4ad5c6") // 刻度尺主体 Stack() { Scroll(this.scroller) { Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start }) { ForEach(this.totalArray, (index: number) => { this.CaleMarkBuilder(index % 10 === 0, (index / 10).toString()) }) } .padding({ left: "50.5%", right: "46%" }) } .scrollable(ScrollDirection.Horizontal) .scrollBar(BarState.Off) .onScrollStop(() => { this.getScaleValue() })
// 中心指示器 this.Indicator() } .width("100%") .border({ color: "#d4d5d7", width: { top: 2 } }) .clip(true) } .width("100%") .padding({ left: 12, right: 12 }) }
// 刻度线和数据 @Builder CaleMarkBuilder(isBold: boolean, boldText: string) { RelativeContainer() { Rect() .width(2) .height(isBold ? 30 : 20) .fill('#d4d5d7') .alignRules({ top: { anchor: "__container__", align: VerticalAlign.Top }, left: { anchor: "__container__", align: HorizontalAlign.Center } })
if (isBold) { Text(boldText) .fontSize(10) .fontColor("#d4d5d7") .width("100%") .textAlign(TextAlign.Center) .alignRules({ bottom: { anchor: "__container__", align: VerticalAlign.Bottom }, }) } } .width(this.scaleWidth) .height(48) }
//中心指示器 @Builder Indicator() { Column() { Text() .width(0) .height(0) .border({ width: 10, color: { top: "#4ad5c6", left: Color.Transparent, right: Color.Transparent, bottom: Color.Transparent } }) Rect() .width(2) .height(25) .fill('#4ad5c6') .position({ x: 9, y: 8 }) } .position({ x: '50%', y: 0 }) }
private getScaleValue() { let x = this.scroller.currentOffset().xOffset //偏移距离 let endX: number = 0 // 四舍五入取整 const quotient = Math.floor(x / this.scaleWidth) //121=12.1 // 计算当前数字除以 10 的余数 const remainder = x % 10 // 如果余数小于 5,最近的 10 的倍数是商乘以 10 if (remainder < 5) { endX = quotient * this.scaleWidth } // 如果余数大于等于 5,最近的 10 的倍数是(商 + 1)乘以 10 else { endX = (quotient + 1) * this.scaleWidth } this.scroller.scrollTo({ xOffset: endX, yOffset: 0 }) //吸附效果 this.currentValue = (this.startScale + (endX / this.scaleWidth / 10)) this.scrollStopEvent(this.currentValue) }}
复制代码


发布于: 刚刚阅读数: 5
用户头像

关注

还未添加个人签名 2025-05-06 加入

还未添加个人简介

评论

发布
暂无评论
【HarmonyOS】鸿蒙实现刻度尺_鸿蒙_鑫_InfoQ写作社区