鸿蒙ArkTS自定义滚动条ScrollBar实战教程
鸿蒙原生 ArkTS 布局精讲:List 自定义滑动器(ScrollBar)从入门到实战



一、引言
在移动端应用开发中,列表(List)是最常见、最核心的交互容器之一。而滚动条(ScrollBar)作为列表的"导航标尺",其视觉风格和交互体验直接影响用户对应用品质的感知。
鸿蒙 ArkTS 在 API 24 中提供了极其灵活的滚动条定制能力——开发者不再局限于系统默认的"灰条",而是可以通过 .scrollBar()、.scrollBarColor()、.scrollBarWidth() 三个链式 API,完全掌控滚动条的显示逻辑与外观风格。
本文将从零开始,带你一步步构建一个支持实时切换滚动条模式、颜色、宽度的交互式演示页面,深刻理解鸿蒙 ArkTS 布局系统的设计哲学。
二、ScrollBar 核心 API 全景
2.1 三大核心方法
| API 方法 | 参数类型 | 作用 | 默认值 |
|---|---|---|---|
.scrollBar(state) |
BarState 枚举 |
控制滚动条显示/隐藏策略 | BarState.Auto |
.scrollBarColor(color) |
ResourceColor |
自定义滚动条轨道颜色 | 系统半透明灰 |
.scrollBarWidth(value) |
number |
自定义滚动条宽度(vp) | 系统默认值(约 4vp) |
2.2 BarState 三态详解
BarState 是控制滚动条"什么时候出现"的关键枚举,包含三个值:
BarState.Auto —— 内容可滚动时显示,静止时自动隐藏(默认值)
BarState.On —— 始终显示滚动条,不随滚动状态改变
BarState.Off —— 始终隐藏滚动条,完全交由开发者自定义
💡 设计洞察:
BarState.Auto适用于绝大多数通用场景;BarState.On适合需要明确提示"此处可滚动"的信息型页面;BarState.Off通常用于完全自定义滚动指示器的场景。
三、项目搭建与前置准备
3.1 创建项目
在 DevEco Studio 中创建 HarmonyOS 工程,选择 Empty Ability 模板,语言选择 ArkTS。核心配置如下:
// build-profile.json5
{
"app": {
"products": [{
"name": "default",
"targetSdkVersion": "6.1.0(23)",
"compatibleSdkVersion": "6.1.0(23)",
"runtimeOS": "HarmonyOS"
}]
}
}
3.2 页面路由注册
在 main_pages.json 中注册新页面:
{
"src": ["pages/Index", "pages/ScrollBarDemo"]
}
⚠️ 注意:所有页面必须显式注册到路由表中才能通过
router.pushUrl()跳转。
3.3 首页导航入口
在 Index.ets 中添加导航卡片,使用 router.pushUrl 跳转到演示页面:
Column() {
Row({ space: 16 }) {
Text('🎨').fontSize(36)
Column({ space: 6 }) {
Text('List 自定义滑动器').fontSize(18)
Text('滚动条显示/隐藏及颜色、宽度自定义').fontSize(13)
}
}
.padding(16)
}
.borderRadius(12)
.onClick(() => {
router.pushUrl({ url: 'pages/ScrollBarDemo' });
})
四、核心实现:ScrollBarDemo 页面
这是整个教程的核心。我们构建一个带控制面板的实时预览页面,让读者可以直观感受每个 API 参数的视觉影响。
4.1 整体结构
页面分为上下两个区域:上方的控制面板(模式/颜色/宽度调节器)和下方的列表预览区(50 条卡片 + 自定义滚动条)。三个 @State 变量驱动控制面板与列表区的联动,任何调节都会触发列表滚动条的实时更新。
4.2 状态变量设计
@State selectedModeIndex: number = 0; // 滚动条模式索引
@State barWidth: number = 6; // 滚动条宽度(vp)
@State barColor: string = '#664096FF'; // 滚动条颜色
🎯 为何用 @State?
鸿蒙 ArkTS 中,@State变量一旦被修改,框架自动触发组件重新渲染。控制面板修改这些变量,列表区自动响应——数据驱动 UI 正是声明式开发的精髓。
4.3 数据层
50 条示例数据确保列表足够长以触发滚动;6 种颜色预设覆盖主流色调:
private readonly colorPresets: ScrollBarColorPreset[] = [
{ label: '蓝色(默认)', color: '#664096FF' },
{ label: '橙色', color: '#66FF7500' },
{ label: '绿色', color: '#66A6D500' },
{ label: '红色', color: '#66F53130' },
{ label: '紫色', color: '#66B620D2' },
{ label: '黑色', color: '#66000000' },
];
private readonly itemSource: string[] = new Array<string>(50).fill('').map(
(_: string, i: number): string => `第 ${i + 1} 项 — 鸿蒙 ArkTS 自定义滚动条演示`
);
private readonly modeList: BarStateItem[] = [
{ label: 'Auto(自适应)', value: BarState.Auto },
{ label: 'On(始终显示)', value: BarState.On },
{ label: 'Off(始终隐藏)', value: BarState.Off },
];
4.4 核心布局:List + ScrollBar
这是整个页面最关键的代码段——仅三行链式调用,完成滚动条全面定制:
List({ space: 8, initialIndex: 0 }) {
ForEach(this.itemSource, (item: string, index: number): void => {
ListItem() {
this.buildListItem(`${index + 1}`, item)
}
}, (item: string, index: number): string => `${index}`)
}
.width('100%')
.layoutWeight(1)
.borderRadius(12)
.padding({ left: 12, right: 12, top: 8, bottom: 8 })
.backgroundColor('#F5F5F5')
// ———— 核心 API:三行定制滚动条 ————
.scrollBar(this.currentMode) // BarState 控制显示策略
.scrollBarColor(this.barColor) // 任意颜色 + 透明度
.scrollBarWidth(this.barWidth) // 2~20 vp 自由调节
.edgeEffect(EdgeEffect.Spring)
.sticky(StickyStyle.Header)
🔑 关键理解:这三个 API 均为 List(及 Scroll)组件的内置方法,通过链式调用直接附加滚动条行为。不需要单独的
ScrollBar组件子节点——这是 API 24 推荐的标准做法。
4.5 控制面板 Builder
控制面板使用 @Builder 装饰器封装,包含三个调节区:
模式选择区——三个按钮对应 BarState 的三个枚举值,点击即切换 selectedModeIndex:
Row({ space: 8 }) {
ForEach(this.modeList, (item: BarStateItem, idx: number): void => {
Button(item.label)
.fontColor(this.selectedModeIndex === idx ? '#FFF' : '#666')
.backgroundColor(this.selectedModeIndex === idx ? '#007DFF' : '#F0F0F0')
.onClick((): void => { this.selectedModeIndex = idx; })
})
}
颜色选择区——6 个圆形色块,选中态使用白色边框加阴影高亮:
Row({ space: 8 }) {
ForEach(this.colorPresets, (preset: ScrollBarColorPreset): void => {
Column() {
Row()
.width(28).height(28).borderRadius(14)
.backgroundColor(preset.color)
.border({ width: this.barColor === preset.color ? 3 : 0, color: '#FFF' })
}
.borderRadius(18)
.border({ width: this.barColor === preset.color ? 2 : 1,
color: this.barColor === preset.color ? '#007DFF' : '#D0D0D0' })
.onClick((): void => { this.barColor = preset.color; })
})
}
宽度调节区——Slider 滑块从 2 vp 到 20 vp 连续调节,实时显示数值:
Row({ space: 12 }) {
Slider({ value: this.barWidth, min: 2, max: 20, step: 1,
style: SliderStyle.OutSet })
.layoutWeight(1).showSteps(true).showTips(true)
.onChange((val: number): void => { this.barWidth = val; })
Text(`${this.barWidth} vp`).fontSize(14)
.fontWeight(FontWeight.Bold).fontColor('#007DFF')
}
4.6 列表项 Builder
每个列表项采用卡片式设计——左侧圆形序号、中间内容文字、右侧箭头:
@Builder
buildListItem(seq: string, text: string) {
Row({ space: 12 }) {
Text(seq).fontSize(16).fontWeight(FontWeight.Bold)
.fontColor('#FFF').textAlign(TextAlign.Center)
.width(36).height(36).borderRadius(18)
.backgroundColor('#007DFF')
Text(text).fontSize(15).fontColor('#333')
.layoutWeight(1)
Text('›').fontSize(20).fontColor('#CCC')
}
.width('100%').height(56)
.padding({ left: 12, right: 12 })
.backgroundColor('#FFF').borderRadius(10)
.shadow({ radius: 2, color: '#10000000', offsetY: 1 })
}
五、关于 import 的重要提醒
这是初学者最容易踩坑的地方,务必注意。
5.1 哪些类型无需 import?
在鸿蒙 ArkTS(API 24)中,以下类型是内置全局类型,不需要 import:
| 类型 | 是否需 import |
|---|---|
BarState |
❌ 不需要 |
FontWeight、TextAlign |
❌ 不需要 |
SliderStyle |
❌ 不需要 |
EdgeEffect、FlexAlign |
❌ 不需要 |
@Entry、@Component、@State、@Builder |
❌ 不需要 |
5.2 哪些类型需要 import?
只有真正来自 @kit.ArkUI 模块的类/函数才需要导入,例如:
import { router } from '@kit.ArkUI'; // 路由API
import { curves } from '@kit.ArkUI'; // 动画曲线
import { ColorMetrics } from '@kit.ArkUI'; // 颜色度量
5.3 常见误区
初学者最容易犯的错误是:试图从 @kit.ArkUI 导入所有名称。这是不必要的——框架级别的枚举和装饰器直接注入全局命名空间,避免在每个文件中重复导入。
📌 原则:如果报错
Cannot find name 'XXX',先检查它是否属于内置全局类型;如果是,直接使用即可。
六、运行效果预览
6.1 默认状态
列表加载 50 条卡片数据,右侧出现半透明蓝色滚动条,模式为 Auto,列表静止时滚动条淡出,滑动时出现,宽度 6vp。
6.2 交互操作一览
| 操作 | 预期效果 |
|---|---|
| 点击「On / 始终显示」 | 滚动条立即变为常驻显示 |
| 点击「Off / 始终隐藏」 | 滚动条立即消失,列表仍可滑动 |
| 点击橙色色块 | 滚动条变色为橙色 |
| 拖动 Slider 至 12 vp | 滚动条宽度明显变粗 |
6.3 组合效果示例
- On + 绿色 + 8vp:始终显示、绿色、8vp 宽的滚动条,适合品牌色统一的应用
- Auto + 紫色半透明 + 4vp:细窄柔和的滚动条,适合阅读类应用
七、性能优化建议
7.1 长列表用 LazyForEach
当列表数据量极大(1000+ 条)时,使用 LazyForEach 替代 ForEach 可显著降低内存占用:
private dataSource: MyDataSource = new MyDataSource(this.itemSource);
LazyForEach(this.dataSource, (item: string): void => {
ListItem() { /* ... */ }
}, (item: string): string => item);
7.2 合理选择 BarState
- 内容少(3~5 项):建议
BarState.Off——滚动条此时无意义 - 内容多(20+ 项):
BarState.Auto最符合用户预期 - 需要提示"此处可滑动":使用
BarState.On
八、延伸思考:ScrollBar 独立组件
除了在 List 上直接使用链式 API,鸿蒙 API 24 还提供了独立的 ScrollBar 组件,可以绑定到任意 Scroller 上实现更灵活的布局:
Scroll(this.scroller) {
// 内容...
}
.scrollBar(BarState.Off) // 隐藏默认滚动条
// 独立悬浮滚动条
ScrollBar({ scroller: this.scroller, state: BarState.Auto })
.scrollBarColor('#664096FF')
.scrollBarWidth(8)
.position({ right: 0 })
这种方式的优势在于:滚动条可以脱离列表边界,自由定位,适用于有特殊布局要求的场景。API 24 还增加了 ArcScrollBar 组件,支持弧形滚动条样式。
九、常见问题排查
Q1:报错 Cannot find name 'BarState'
✅ 原因:尝试 import 了本不需要的内置全局类型。
✅ 解决:删除针对 BarState、FontWeight 等类型的 import 语句。
Q2:报错 Module ... has no exported member 'XXX'
✅ 原因:从 @kit.ArkUI 导入了一个全局内置类型,该类型不应该被 import。
✅ 解决:确认该类型是否为内置全局类型(见第五章表格)。
Q3:滚动条没有显示
✅ 可能原因 1:列表内容高度未超出容器高度。
✅ 解决:确保有足够子节点(如 50 条)且高度超出容器显示区。
✅ 可能原因 2:误将 BarState 设置为 Off。
✅ 解决:切换为 Auto 或 On 模式验证。
Q4:.scrollBarWidth() 设置无效
✅ 原因:targetSdkVersion 低于 API 24。
✅ 解决:确认 build-profile.json5 中 targetSdkVersion 为 6.1.0 或更高。
十、总结
通过本文的完整实战,我们系统性地掌握了鸿蒙 ArkTS 中 List 自定义滑动器的全部核心知识点:
.scrollBar(BarState)——控制滚动条显示策略的入口.scrollBarColor(ResourceColor)——任意自定义颜色,支持透明度.scrollBarWidth(number)——从 2vp 到 20vp 的宽度自由调节
这三个 API 的组合使用可以覆盖绝大多数定制场景。更重要的是,通过控制面板的实时交互,我们直观地验证了鸿蒙声明式 UI 的核心哲学:数据驱动视图,@State 一变,UI 自动更新。
下一步实践建议
- 将自定义滚动条应用到真实项目中的消息列表、商品列表、设置页
- 结合
LazyForEach优化千级数据量的列表性能 - 探索
ScrollBar独立组件和ArcScrollBar弧形滚动条 - 使用
.edgeEffect(EdgeEffect.Spring)等辅助 API 优化滚动交互手感
本文为鸿蒙 ArkTS 布局系列教程之一,欢迎在实践中反馈问题与建议。
更多推荐


所有评论(0)