HarmonyOS7 SliderShowcase 教程:一次讲清 4 种常见滑块写法
文章目录

前言
很多人第一次学 Slider,容易把它当成一个“拖动取值”的基础控件,觉得会用就完了。
但你真开始写页面以后,很快就会发现,滑块根本不是只有一种样子。
有的滑块适合拿来调音量、亮度这种连续值;有的适合做垂直方向的控制条;有的更强调视觉风格;还有的本质上是在做“固定档位选择”。
也就是说,Slider 这类控件看起来是一个组件,实际落到业务里,往往会分成好几种不同的用法。
这篇文章就带你把一个综合案例拆开看清楚。你不需要一开始就把所有 API 都背下来,先弄懂这 4 种写法分别适合解决什么问题,比死记属性有用得多。
先看这个案例到底展示了什么
这个页面把 Slider 的 4 种常见能力放在了一起:
- 带提示的基础水平滑块
- 两个垂直方向滑块
- 自定义颜色的滑块
- 带刻度的固定档位滑块
如果你把它翻译成真实业务场景,其实就很容易理解了:
| 页面部分 | 更像什么业务场景 |

| — | — |
| 基础滑块(带提示) | 音量、亮度、进度比例调节 |
| 垂直滑块 | 调音台、设备控制面板、图像参数调整 |
| 自定义颜色滑块 | 品牌主题设置、色彩分级、风格化设置页 |
| 带刻度滑块 | 档位选择、等级切换、分段百分比选择 |
所以这篇真正值得学的,不是“一个页面摆了四个滑块”,而是:
同样是滑块,面对不同交互目标,写法和重点也会不一样。
先把页面里的状态看懂
这个案例里最关键的几个状态是:
@State val1: number = 50
@State val2: number = 30
@State val3: number = 75
它们分别用来保存三个可以变化的值:
val1:基础水平滑块当前的值val2:第一个垂直滑块的值val3:第二个垂直滑块的值
你可以把它们理解成这个页面里三份“当前结果”。
只要用户拖动对应滑块,状态就会更新;状态一更新,页面上和它相关的显示内容也会立刻变化。
为什么这里一定要用 @State
因为滑块不是静态展示,它是可交互输入。
用户每拖一下,值都会变。如果这些值不是状态,页面就不会自动刷新,交互看起来就会很僵。
所以你可以先记住一句很实用的话:
只要一个值会随着用户操作变化,而且变化后还要反映到界面上,它通常就应该是状态。
这条规律不只适用于 Slider,后面学 Rating、Picker、TextInput 也一样。
先看完整代码
先把案例代码整体看一遍,后面讲每一块时更容易对得上:
/**
* SliderShowcase - Slider 综合演示
*/
import { PRESET_COLORS, generateListItems, PAGE_BG_COLOR, PANEL_BG_COLOR, ACCENT_COLOR, MUTED_TEXT_COLOR } from './types'
@Entry
@Component
struct SliderShowcase {
@State isShow: boolean = true
@State val1: number = 50
@State val2: number = 30
@State val3: number = 75
build() {
Column() {
if (this.isShow) {
Scroll() {
Column() {
Text('Slider 综合演示').fontSize(16).fontWeight(FontWeight.Bold).margin({ bottom: 16 })
Text('1. 基础滑块(带提示)').fontSize(14).fontWeight(FontWeight.Bold).margin({ bottom: 8 })
Text(`${this.val1.toFixed(0)}`).fontSize(20).fontWeight(FontWeight.Bold)
.fontColor(ACCENT_COLOR).margin({ bottom: 6 })
Slider({ value: this.val1, min: 0, max: 100 }).showTips(true)
.onChange((v: number) => { this.val1 = v })
.width('100%').margin({ bottom: 20 })
Text('2. 垂直滑块').fontSize(14).fontWeight(FontWeight.Bold).margin({ bottom: 8 })
Row({ space: 20 }) {
Column() {
Slider({ value: this.val2, min: 0, max: 100, direction: Axis.Vertical })
.height(150)
.selectedColor(PRESET_COLORS[3].value)
.onChange((v: number) => { this.val2 = v })
Text(`${this.val2.toFixed(0)}`).fontSize(12).fontColor(MUTED_TEXT_COLOR).margin({ top: 4 })
}
Column() {
Slider({ value: this.val3, min: 0, max: 100, direction: Axis.Vertical })
.height(150)
.selectedColor(PRESET_COLORS[5].value)
.onChange((v: number) => { this.val3 = v })
Text(`${this.val3.toFixed(0)}`).fontSize(12).fontColor(MUTED_TEXT_COLOR).margin({ top: 4 })
}
}.justifyContent(FlexAlign.SpaceEvenly).width('100%').margin({ bottom: 20 })
Text('3. 自定义颜色滑块').fontSize(14).fontWeight(FontWeight.Bold).margin({ bottom: 8 })
ForEach([0, 1, 2], (i: number, _: number) => {
Slider({ value: (i + 1) * 30, min: 0, max: 100 })
.trackColor('#F0F0F0')
.selectedColor(PRESET_COLORS[i].value)
.blockColor(PRESET_COLORS[i].value)
.width('100%').margin({ bottom: 20 })
})
Text('4. 带刻度滑块').fontSize(14).fontWeight(FontWeight.Bold).margin({ bottom: 8 })
Slider({ value: 50, min: 0, max: 100, step: 25 }).showSteps(true)
.selectedColor(ACCENT_COLOR).blockColor(ACCENT_COLOR)
.width('100%')
}
.width('100%').padding(16).backgroundColor(PANEL_BG_COLOR).borderRadius(12)
}
}
Text('Slider 综合 - 水平/垂直/颜色/刻度/提示')
.fontSize(12).fontColor(MUTED_TEXT_COLOR).margin({ top: 12 })
}
.width('100%').height('100%').backgroundColor(PAGE_BG_COLOR).padding(16)
}
}

第一部分:基础滑块为什么最像真实业务
先看这一段:
Text(`${this.val1.toFixed(0)}`)
Slider({ value: this.val1, min: 0, max: 100 }).showTips(true)
.onChange((v: number) => { this.val1 = v })
这一块最接近日常业务开发。
它的逻辑很直白:
val1保存当前值。- 滑块显示这个值。
- 用户拖动后,通过
onChange把新值写回val1。 - 上面的数字文案跟着刷新。
这就是一个很标准的“输入 -> 状态 -> 回显”流程。
showTips(true) 为什么很适合新手先学
这里有个很关键的配置:
.showTips(true)
它的作用是把当前值提示直接显示出来。
对新手来说,这个效果很友好,因为你拖动的时候,能立刻知道自己调到了多少,不用再猜当前值到底是多少。
这类写法特别适合这些页面:
- 调音量
- 调亮度
- 调字号
- 调播放进度
- 调透明度
因为这些场景的共同点是:
用户需要连续调整,并且希望马上看到当前数值。
所以如果你只是刚开始学 Slider,建议先把这一段吃透。它已经覆盖了最核心的使用方式。
第二部分:垂直滑块适合什么场景
再看中间这两组垂直滑块:
Slider({ value: this.val2, min: 0, max: 100, direction: Axis.Vertical })
.height(150)
.selectedColor(PRESET_COLORS[3].value)
.onChange((v: number) => { this.val2 = v })
Slider({ value: this.val3, min: 0, max: 100, direction: Axis.Vertical })
.height(150)
.selectedColor(PRESET_COLORS[5].value)
.onChange((v: number) => { this.val3 = v })
这里和前面的基础滑块相比,最核心的区别就是:
direction: Axis.Vertical
它把滑块方向从水平改成了垂直。
垂直滑块不是为了炫技,而是为了贴合场景
很多小白第一次看到垂直滑块,会觉得这只是换了个方向。
其实不是。
方向一变,页面给人的操作感觉也会变。垂直滑块更适合这些场景:
- 调音台里的多通道音量控制
- 图像编辑里的亮度、对比度、饱和度调节
- 智能家居控制面板里的温度、风速调节
- 工业设备参数面板
为什么?
因为这些页面往往会把多个控制项并排摆出来。垂直滑块更节省横向空间,也更像现实设备里的“推杆”或“控制条”。
为什么下面还要再配一个数字文案
你会看到每个垂直滑块下面都配了一行:
Text(`${this.val2.toFixed(0)}`)
Text(`${this.val3.toFixed(0)}`)
这个设计很实用。
因为垂直滑块不像水平滑块那样天然容易读数,尤其当控件比较细时,用户更难一眼判断自己调到了多少。
所以这里给每个滑块补一个明确的数值回显,体验会更完整。
这也是你以后写真实页面时值得保留的习惯:
只要用户不容易直接看懂当前结果,就补一层清晰的数值反馈。
第三部分:自定义颜色滑块到底在解决什么问题
接着看这一块:
ForEach([0, 1, 2], (i: number, _: number) => {
Slider({ value: (i + 1) * 30, min: 0, max: 100 })
.trackColor('#F0F0F0')
.selectedColor(PRESET_COLORS[i].value)
.blockColor(PRESET_COLORS[i].value)
.width('100%').margin({ bottom: 20 })
})
这一部分的重点不是交互逻辑,而是视觉表达。
它做了三件事:
- 用
trackColor('#F0F0F0')设定轨道底色 - 用
selectedColor(...)设定已选区域颜色 - 用
blockColor(...)设定滑块按钮颜色
为什么要改颜色
因为很多时候,滑块不只是功能控件,它还是页面视觉系统的一部分。
比如:
- 红色可以表示高强度、高优先级
- 蓝色可以表示冷色调设置、科技感主题
- 绿色可以表示安全、健康、节能
如果你的页面本身就有品牌色、场景色或者风险等级色,那么滑块颜色跟着业务语义走,会比默认样式更容易让用户理解。
ForEach 在这里的价值是什么
这里没有手写三段重复代码,而是用了:
ForEach([0, 1, 2], (i: number, _: number) => {
这样做的好处是,重复结构更容易统一管理。
如果你后面要把这组滑块改成“低、中、高”三档配置,或者改成三组主题色,只需要调整数据和少量样式,不用复制三份结构。
对于初学者来说,这里可以先学到一个很重要的意识:
当页面里出现重复结构时,优先想一想能不能通过列表或循环把它收拢。
第四部分:带刻度滑块本质上是在做分段选择
最后看这一段:
Slider({ value: 50, min: 0, max: 100, step: 25 }).showSteps(true)
.selectedColor(ACCENT_COLOR).blockColor(ACCENT_COLOR)
这段代码和第一篇 SliderStepMarks 的核心思路是一样的:它不是在做自由拖动,而是在做固定档位选择。
这里最关键的是两个点:
step: 25.showSteps(true)
它们一起决定了这个滑块的结果只会落在这些值上:
0255075100
这种写法适合哪些页面
特别适合下面这类业务:
- 低 / 中 / 高 三档或多档强度选择
- 固定百分比档位设置
- 会员等级、权限等级、风险等级切换
- 满意度、推荐度这类分段选择
也就是说,当用户要的不是一个随意数值,而是“明确落在哪个档位上”,就更适合这种写法。
这个案例最值得你记住的 4 件事
1. 同样是 Slider,不一定都是同一种交互
基础滑块、垂直滑块、彩色滑块、带刻度滑块,解决的问题并不一样。
不要只盯着“控件名一样”,要先看它在页面里承担什么角色。
2. onChange 是滑块真正活起来的关键
像下面这些代码:
.onChange((v: number) => { this.val1 = v })
.onChange((v: number) => { this.val2 = v })
.onChange((v: number) => { this.val3 = v })
它们本质上都在做同一件事:把用户拖动后的结果写回状态。
这一步一旦省掉,页面就会变成“看起来能拖,实际上结果没连起来”的假交互。
3. 回显文案不是装饰,是结果说明层
无论是顶部的大数字,还是垂直滑块下面的小数字,它们都不是可有可无的排版。
它们承担的是“告诉用户现在到底选到了什么值”的职责。
4. 真实业务里,滑块往往要同时考虑功能和视觉
这一篇里既有方向变化,也有颜色变化,还有刻度变化。
这说明 Slider 不是单纯只管数值,它经常还要和页面布局、品牌色、操作场景一起配合。
小白最容易踩的坑
1. 只会拖值,不知道为什么要选这种写法
很多人学完以后,只记住了 showTips(true)、direction: Axis.Vertical、showSteps(true) 这些属性。
但更重要的问题是:你的业务到底适合哪一种滑块。
如果场景没想清楚,控件再会写,页面也可能不顺手。
2. 状态和显示不是同一份数据
比如滑块内部读一个值,页面文本又显示另一个值,最后提交接口再单独拼一份值。
这样最容易出问题。
一个结果,尽量由一个核心状态负责。
3. 只做滑块,不做结果反馈
用户能拖,不代表用户知道自己拖到了哪里。
尤其垂直滑块和分档滑块,更应该给清晰反馈。
4. 为了展示效果堆很多样式,却没想业务含义
颜色、方向、刻度都可以改,但每一项最好都有理由。
比如颜色是不是在表达等级?垂直方向是不是为了节省空间?刻度是不是为了固定档位?这些问题想清楚,页面才会更像产品,而不是几个示例效果随手拼在一起。
这篇代码可以怎么继续改成真实页面
如果你已经看懂了这个综合案例,可以继续往这些方向练习:
| 方向 | 可以怎么改 |
|---|---|
| 系统设置页 | 用基础滑块调音量、亮度、字号 |
| 调音台面板 | 把垂直滑块扩展成多通道控制列 |
| 主题配置页 | 用不同颜色滑块表示不同主题项 |
| 档位选择页 | 把带刻度滑块改成 5 档模式切换 |
这类练习很有价值,因为它能逼着你把“控件功能”真正翻译成“页面用途”。
动手改一改
建议你自己马上试 4 个小练习:
- 把基础滑块的范围从
0 ~ 100改成0 ~ 10,模拟音量档位。 - 给两个垂直滑块加标题,比如“低音”“高音”。
- 把彩色滑块改成“低风险 / 中风险 / 高风险”三种颜色方案。
- 给带刻度滑块补一行标签文案,让每个档位更好理解。
这些练习都不复杂,但会让你更快把今天这篇真的吃透。
写在最后
这篇案例看起来是在“展示 Slider 的各种效果”,但你真正应该带走的,是另一层理解:同一个控件,面对不同业务目标,写法和侧重点都可以完全不同。
如果你是 HarmonyOS7 初学者,我建议你不要只停在“看懂代码”这一步,最好自己把这 4 段都改成一个你能叫得出业务名字的页面。等你能从“组件效果”走到“页面场景”,这类基础控件你才算真的用进去了。
更多推荐
所有评论(0)