一、引言:Scroll—— 内容溢出场景的交互中枢

在鸿蒙应用开发中,当界面内容超出屏幕可视范围时,Scroll 容器组件成为实现流畅滚动交互的核心方案。作为从 API 7 开始支持的基础组件,它通过极简的属性配置与强大的滚动控制能力,完美解决长列表、大数据展示、富文本阅读等场景的内容溢出问题。本文将系统解析 Scroll 的核心特性、滚动控制技巧及多端适配方案,帮助开发者掌握丝滑滚动体验的实现精髓。

二、核心架构与基础应用

2.1 组件定位与工作原理

  • 核心功能:为超出可视范围的内容提供水平 / 垂直滚动能力,仅支持单个子组件(需包裹在 Column/Row 等容器中)
  • 滚动条件:子组件在滚动方向的尺寸必须大于 Scroll 组件对应尺寸(如垂直滚动需子组件高度 > Scroll 高度)
  • 典型场景:长文本阅读、图片列表浏览、无限滚动加载、表单内容录入

2.2 基础语法与最简实现

// xxx.ets
import { curves } from '@kit.ArkUI';@Entry
@Component
struct ScrollExample {scroller: Scroller = new Scroller();private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];build() {Stack({ alignContent: Alignment.TopStart }) {Scroll(this.scroller) {Column() {ForEach(this.arr, (item: number) => {Text(item.toString()).width('90%').height(150).backgroundColor(0xFFFFFF).borderRadius(15).fontSize(16).textAlign(TextAlign.Center).margin({ top: 10 })}, (item: string) => item)}.width('100%')}.scrollable(ScrollDirection.Vertical) // 滚动方向纵向.scrollBar(BarState.On) // 滚动条常驻显示.scrollBarColor(Color.Gray) // 滚动条颜色.scrollBarWidth(10) // 滚动条宽度.friction(0.6).edgeEffect(EdgeEffect.None).onWillScroll((xOffset: number, yOffset: number, scrollState: ScrollState) => {console.info(xOffset + ' ' + yOffset);}).onScrollEdge((side: Edge) => {console.info('To the edge');}).onScrollStop(() => {console.info('Scroll Stop');})Button('scroll 150').height('5%').onClick(() => { // 点击后下滑指定距离150.0vpthis.scroller.scrollBy(0, 150);}).margin({ top: 10, left: 20 })Button('scroll 100').height('5%').onClick(() => { // 点击后滑动到指定位置,即下滑100.0vp的距离const yOffset: number = this.scroller.currentOffset().yOffset;this.scroller.scrollTo({ xOffset: 0, yOffset: yOffset + 100 });}).margin({ top: 60, left: 20 })Button('scroll 100').height('5%').onClick(() => { // 点击后滑动到指定位置,即下滑100.0vp的距离,滑动过程配置有动画let curve = curves.interpolatingSpring(10, 1, 228, 30); //创建一个阶梯曲线const yOffset: number = this.scroller.currentOffset().yOffset;this.scroller.scrollTo({ xOffset: 0, yOffset: yOffset + 100, animation: { duration: 1000, curve: curve } });}).margin({ top: 110, left: 20 })Button('back top').height('5%').onClick(() => { // 点击后回到顶部this.scroller.scrollEdge(Edge.Top);}).margin({ top: 160, left: 20 })Button('next page').height('5%').onClick(() => { // 点击后滑到下一页this.scroller.scrollPage({ next: true ,animation: true });}).margin({ top: 210, left: 20 })Button('fling -3000').height('5%').onClick(() => { // 点击后触发初始速度为-3000vp/s的惯性滚动this.scroller.fling(-3000);}).margin({ top: 260, left: 20 })Button('scroll to bottom 700').height('5%').onClick(() => { // 点击后滑到下边缘,速度值是700vp/sthis.scroller.scrollEdge(Edge.Bottom, { velocity: 700 });}).margin({ top: 310, left: 20 })}.width('100%').height('100%').backgroundColor(0xDCDCDC)}
}

三、核心属性与滚动控制

3.1 滚动方向与交互配置

属性名称类型功能描述
scrollableScrollDirection设置滚动方向(Vertical/Horizontal/None),默认 Vertical
edgeEffectEdgeEffect边缘弹性效果(Spring/Fade),可配置摩擦系数等物理参数
enablePagingboolean启用分页滚动模式,滑动时整页切换(API 11+)

水平滚动示例

Scroll().scrollable(ScrollDirection.Horizontal) // 水平滚动.width(300) // 固定容器宽度.edgeEffect(EdgeEffect.Spring, { friction: 0.7 }) // 弹簧回弹效果

3.2 滚动条定制

属性名称类型功能描述
scrollBarBarState滚动条显示策略(Auto/On/Off),默认 Auto
scrollBarColorstring自定义滚动条颜色
scrollBarWidthnumber设置滚动条宽度(单位 vp)

滚动条定制示例

.scrollBar(BarState.On) // 始终显示滚动条
.scrollBarColor('#007DFF') // 蓝色滚动条
.scrollBarWidth(4) // 4vp宽度

3.3 编程式滚动控制

通过 Scroller 对象实现精准滚动定位:

@Entry
@Component
struct Index {scroller: Scroller = new Scroller;private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];build() {Scroll(this.scroller) {Column() {ForEach(this.arr, (item: number) => {Text(item.toString()).width('90%').height(200).backgroundColor(0xFFFFFF).borderWidth(1).borderColor(Color.Black).borderRadius(15).fontSize(16).textAlign(TextAlign.Center)}, (item: string) => item)}.width('100%').backgroundColor(0xDCDCDC)}.backgroundColor(Color.Yellow).height('100%').edgeEffect(EdgeEffect.Spring).scrollSnap({snapAlign:ScrollSnapAlign.START, snapPagination:400, enableSnapToStart:true, enableSnapToEnd:true})}
}

四、实战场景与代码实现

4.1 横向滚动图片画廊

@Entry
@Component
struct ImageGallery {// 显式声明类型并初始化图片数组private images: string[] = ['img_1', 'img_2', 'img_3', 'img_4', 'img_5','img_6', 'img_7', 'img_8', 'img_9', 'img_10']build() {Scroll() {Row() {// 使用ForEach遍历图片数组ForEach(this.images,(img: string) => {Image(img).size({ width: 120, height: 120 })  // 使用对象参数指定尺寸.objectFit(ImageFit.Cover).margin(8)},(img: string) => img  // 使用图片路径作为唯一键)}.width(this.images.length * 136) // 计算总宽度触发滚动}.scrollable(ScrollDirection.Horizontal).scrollBar(BarState.Off).height(150).margin(24)}
}

4.2 嵌套滚动吸顶效果

import { LengthMetrics } from '@kit.ArkUI';@Entry
@Component
struct NestedScroll {@State listPosition: number = 0; // 0代表滚动到List顶部,1代表中间值,2代表滚动到List底部。private arr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];private scrollerForScroll: Scroller = new Scroller();private scrollerForList: Scroller = new Scroller();build() {Flex() {Scroll(this.scrollerForScroll) {Column() {Text("Scroll Area").width("100%").height("40%").backgroundColor(0X330000FF).fontSize(16).textAlign(TextAlign.Center).onClick(() => {this.scrollerForList.scrollToIndex(5, false, ScrollAlign.START, { extraOffset: LengthMetrics.vp(5) });})List({ space: 20, scroller: this.scrollerForList }) {ForEach(this.arr, (item: number) => {ListItem() {Text("ListItem" + item).width("100%").height("100%").borderRadius(15).fontSize(16).textAlign(TextAlign.Center).backgroundColor(Color.White)}.width("100%").height(100)}, (item: string) => item)}.width("100%").height("50%").edgeEffect(EdgeEffect.None).friction(0.6).onReachStart(() => {this.listPosition = 0;}).onReachEnd(() => {this.listPosition = 2;}).onScrollFrameBegin((offset: number) => {if ((this.listPosition == 0 && offset <= 0) || (this.listPosition == 2 && offset >= 0)) {this.scrollerForScroll.scrollBy(0, offset);return { offsetRemain: 0 };}this.listPosition = 1;return { offsetRemain: offset };})Text("Scroll Area").width("100%").height("40%").backgroundColor(0X330000FF).fontSize(16).textAlign(TextAlign.Center)}}.width("100%").height("100%")}.width('100%').height('100%').backgroundColor(0xDCDCDC).padding(20)}
}

4.3 分页滚动长列表(API 11+)

// xxx.ets
@Entry
@Component
struct EnablePagingExample {private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]build() {Stack({ alignContent: Alignment.Center }) {Scroll() {Column() {ForEach(this.arr, (item: number) => {Text(item.toString()).width('100%').height('100%').borderRadius(15).fontSize(16).textAlign(TextAlign.Center).backgroundColor(0xFFFFFF)}, (item: string) => item)}}.width('90%').height('90%').enablePaging(true)}.width('100%').height('100%').backgroundColor(0xDCDCDC)}
}

五、工程实践优化指南

5.1 性能优化策略

  1. 固定子组件尺寸
ListItem().height(48) // 固定列表项高度,避免动态计算
  1. 大数据懒加载
Scroll() {LazyForEach(largeData, (item) => ListItem(), item => item.id)
}
.cachedCount(5) // 预加载相邻5项
  1. 减少重渲染
GridItem().forceRebuild(false) // 静态内容禁止重建

5.2 常见问题解决方案

问题场景解决方案
滚动条不显示1. 确认子组件尺寸超出容器;2. 设置.scrollBar(BarState.On)强制显示
滚动方向错误检查.scrollable属性设置,水平滚动需子组件宽度 > 容器宽度
嵌套滚动冲突使用.nestedScroll配置滚动优先级,如SELF_FIRSTPARENT_FIRST
分页滚动异常确保.height设置为固定值,每项高度一致(API 11+)

5.3 多端适配方案

#if (DeviceType == DeviceType.Tablet)Scroll().scrollable(ScrollDirection.Horizontal) // 平板默认水平滚动
#elif (DeviceType == DeviceType.Phone)Scroll().scrollable(ScrollDirection.Vertical) // 手机默认垂直滚动
#endif// 禁用手势滚动(仅编程控制)
.enableScrollInteraction(false)

六、总结:全场景滚动交互的核心能力

鸿蒙 Scroll 组件通过标准化接口实现了从基础内容滚动到复杂交互控制的全场景覆盖,核心能力包括:

  1. 方向控制:支持垂直 / 水平滚动模式与边缘弹性效果
  2. 视觉定制:滚动条样式与分页滚动的个性化配置
  3. 编程控制:Scroller 实现精准定位与滚动状态监听
  4. 性能优化:懒加载、固定尺寸等策略提升滚动流畅度

在实际开发中,建议结合 DevEco Studio 的实时预览功能调试滚动效果,针对手机、平板、车机等设备特性进行定向优化。随着鸿蒙生态向全场景设备拓展,Scroll 组件将在长内容展示、多任务交互等场景中持续发挥关键作用,助力开发者打造丝滑流畅的用户体验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/86716.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/86716.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/86716.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第十节:Vben Admin 最新 v5.0 (vben5) 快速入门 - 菜单管理(下)

Vben5 系列文章目录 💻 基础篇 ✅ 第一节:Vben Admin 最新 v5.0 (vben5) 快速入门 ✅ 第二节:Vben Admin 最新 v5.0 (vben5) 快速入门 - Python Flask 后端开发详解(附源码) ✅ 第三节:Vben Admin 最新 v5.0 (vben5) 快速入门 - 对接后端登录接口(上) ✅ 第四节:Vben Ad…

c#激光设备行业ERP软件进销存软件库存管理软件财务管理软件

# 激光设备行业ERP软件进销存软件库存管理软件财务管理软件 # 开发背景 本软件是给广东河源某客户开发的激光设备行业ERP软件进销存软件库存管理软件财务管理软件 # 功能描述 软件由基础资料、库存管理、 属性管理、 用户管理、 销售管理、 财务管理。主要功能模块是库存管理…

python学习打卡day57

DAY 57 经典时序模型1 知识点回顾 序列数据的处理&#xff1a; 处理非平稳性&#xff1a;n阶差分处理季节性&#xff1a;季节性差分自回归性无需处理 模型的选择 AR(p) 自回归模型&#xff1a;当前值受到过去p个值的影响MA(q) 移动平均模型&#xff1a;当前值收到短期冲击的影响…

python小记(十七):Python 使用“继承”来管理yaml文件

Python 使用“继承”来管理yaml文件 引言 引言 在 Python 中有时候我们会把参数都储存在yaml文件中然后进行调用。当我们在进行一个很大的项目的时候&#xff0c;我们可能先需要一个base.yaml文件&#xff0c;然后再使用一个task1.yaml文件进行参数导入&#xff0c;并且task1.…

Windows搭建opencv cuda开发环境并验证是否成功

编译opencv cuda源码 电脑安装cuda 12.0或者11.8&#xff0c;根据你的电脑配置自行选择 下载opencv 源码 git clone https://github.com/opencv/opencv.git git clone https://github.com/opencv/opencv_contrib.git 在opencv目录里新建 build 文件夹 cd build后 cmake…

【go】初学者入门环境配置,GOPATH,GOROOT,GOCACHE,以及GoLand使用配置注意

一、环境变量配置步骤 1. 打开环境变量设置 Win R 后输入 sysdm.cpl → 点击 确定在弹出窗口中点击 高级 → 环境变量 2. 配置 GOROOT&#xff08;Go语言安装根目录&#xff09; 作用&#xff1a;告诉系统Go语言的安装位置&#xff08;编译器、标准库等核心文件所在路径&a…

gantt-task-react的改造使用

gantt-task-react的镜像地址 例子 改造1&#xff1a;切断父子关联关系&#xff0c;父为project组件&#xff0c;子为task组件&#xff0c; 原来的功能是task组件拖动会影响到父组件&#xff0c;现在切断两者关联关系&#xff0c;数据都用task组件&#xff0c; 给task组件重…

kotlin 协程(Coroutine)

Coroutine&#xff08;协程&#xff09;的转换原理&#xff1a; 在 kotlin 中&#xff0c;Coroution 是一种轻量级的线程管理方式&#xff0c;其转换原理涉及 状态机生成、挂起函数转换和调度器机制。 一、协程的本质&#xff1a;状态机 kotlin 协程通过 编译器生成状态机 实…

线性变换之维数公式(秩-零化度定理)

秩数-零化度定理(rank-nullity theorem) 目录 1. (映射)零空间(线性映射或变换的核)(null-space或nullspace) 2. 跨度(或开度)(span) 3. (线性映射的)零化度(nullity) 4. 线性变换的维数公式(秩数-零化度定理)(rank-nullity theorem) 5. 函数的上域(codomain) 1…

Spring Cloud Gateway 实战:网关配置与 Sentinel 限流详解

Spring Cloud Gateway 实战&#xff1a;网关配置与 Sentinel 限流详解 在微服务架构中&#xff0c;网关扮演着统一入口、负载均衡、安全认证、限流等多种角色。Spring Cloud Gateway 是 Spring Cloud 官方推出的新一代网关组件&#xff0c;相比于第一代 Netflix Zuul&#xff…

JAVA-常用API(二)

目录 1.Arrays 1.1认识Arrays 1.2Arrays的排序 2.JDK8的新特性&#xff1a;Lambda表达式 2.1认识Lambda表达式 2.2用Lambda表达式简化代码、省略规则 3.JDK8的新特性&#xff1a;方法引用&#xff08;进一步简化Lambda表达式&#xff09; 3.1 静态方法引用 3.2 实例方法引…

深入理解PHP的命名空间

命名空间是PHP 5.3引入的一个特性&#xff0c;它的主要目的是解决在大型应用程序中可能出现的名称冲突问题。在没有命名空间的情况下&#xff0c;如果两个不同的库或模块定义了相同名称的函数或类&#xff0c;那么在使用这些库或模块的时候就会引发冲突。为了解决这个问题&…

SwiftUI学习笔记day5:Lecture 5 Stanford CS193p 2023

SwiftUI学习笔记day5:Lecture 5 Stanford CS193p 2023 课程链接&#xff1a;Lecture 5 Stanford CS193p 2023代码仓库&#xff1a;iOS课程大纲&#xff1a; Enum 定义&#xff1a;enum MyType { … }关联值&#xff1a;case drink(name: String, oz: Int)匹配&#xff1a;switc…

idea 报错:java: 非法字符: ‘\ufeff‘

idea 报错&#xff1a;java: 非法字符: ‘\ufeff‘ 解决方案&#xff1a;

数据结构与算法之美:图

Hello大家好&#xff01;很高兴我们又见面啦&#xff01;给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 我的博客&#xff1a;<但凡. 我的专栏&#xff1a;《编程之路》、《数据结构与算法之美》、《题海拾贝》、《C修炼之路》 欢迎点赞&#xff0c;关注&am…

SpringBoot -- 热部署

9.SpringBoot 热部署&#xff08;自动重启&#xff09; 在实际开发过程中&#xff0c;每次修改代码就得将项目重启&#xff0c;重新部署&#xff0c;对于一些大型应用来说&#xff0c;重启时间需要花费大量的时间成本。对于一个后端开发者来说&#xff0c;重启过程确实很难受啊…

HarmonyOS 5浏览器引擎对WebGL 2.0的支持如何?

以下是HarmonyOS 5浏览器引擎对‌WebGL 2.0‌支持的详细技术分析&#xff1a; 一、核心支持能力 ‌系统能力声明 HarmonyOS 5 浏览器引擎通过 SystemCapability.Graphic.Graphic2D.WebGL2 提供对 WebGL 2.0 的底层支持 支持的关键特性包括&#xff1a; OpenGL ES 3.0 特性…

Class1线性回归

Class1线性回归 买房预测 要根据历史数据来预测一套房子的价格。你发现影响房价的因素有很多&#xff0c;于是你决定使用线性回归模型来预测房价。 影响房价的因素如下&#xff1a; 房屋面积&#xff08;平方米&#xff09; 房龄&#xff08;年&#xff09; 离地铁站的距离&a…

Vue.js 3:重新定义前端开发的进化之路

Vue.js 3&#xff1a;重新定义前端开发的进化之路 引言&#xff1a;一场酝酿已久的革新 2020年9月18日&#xff0c;Vue.js团队以代号"One Piece"正式发布3.0版本&#xff0c;这不仅是框架发展史上的重要里程碑&#xff0c;更是前端工程化领域的一次革命性突破。历经…

Unity性能优化-渲染模块(1)-CPU侧(1)-优化方向

Unity 中渲染方面的优化大致可以划分为以下几块核心内容&#xff1a; CPU 优化 (减少 Draw Calls 和 CPU 瓶颈) GPU 优化 (减少像素着色和 GPU 瓶颈) 内存和显存优化 (Resource Management) 光照优化 (Lighting & Global Illumination) 这四个方面是相互关联的。一个方…