鸿蒙学习实战之路-Scroll滚动组件全攻略

最近好多朋友问我:"我想在鸿蒙页面里实现滚动效果,为啥子内容超出了却滚不动?是不是我哪里设置错了?"😅

作为一个正在把div炒成Column的前端厨子,我必须得说:“别慌!今天这篇,我就手把手带你搞定Scroll滚动组件,从基础用法到实战案例,保证你看完就能上手!”

🥦 什么是Scroll组件?

Scroll是鸿蒙里的可滚动容器组件,当子组件的布局尺寸超过Scroll的尺寸时,内容就能滚动起来啦!

用大白话说:这玩意儿就像咱们家里的卷帘门,内容太多装不下时,拉一拉就能看到后面的东西~

适用场景

  1. 小米有品:页面内容太长,点击顶部返回顶部
  2. 京东:页面滚动时,右下角的小火箭出现,点击返回顶部
  3. 各种需要上下/左右滑动浏览的长页面

🥦 Scroll核心用法

基础步骤

要让内容滚动起来,其实超简单,就四步:

  1. 给Scroll设置固定尺寸(就像给卷帘门定个框)
  2. 在Scroll里放一个子组件(注意:只能放一个!)
  3. 让子组件的尺寸超过Scroll(内容要比框大才能滚)
  4. 根据需要调整滚动属性

基础代码模板

@Entry
@Component
struct Page01_Scroll {
  build() {
    Column({space: 10}) {
      Text('竖向滚动')
        .fontSize(20)

      // Scroll容器尺寸固定
      Scroll() {
        // 内部只能放一个子组件
        Column() {
          // 这里放具体内容,高度要超过Scroll
        }
        .height(1000) // 内容高度超过Scroll的200
        .width('100%')
      }
      .width('100%')
      .height(200)
      .border({width: 1, color: Color.Orange})

      Divider()

      Text('横向滚动')
        .fontSize(20)

      // 横向滚动的Scroll
      Scroll() {
        // 横向滚动用Row包裹内容
        Row() {
          // 这里放具体内容,宽度要超过Scroll
        }
        .width(1000) // 内容宽度超过Scroll
        .height('100%')
      }
      // 设置为横向滚动
      .scrollable(ScrollDirection.Horizontal)
      .width('100%')
      .height(200)
      .border({width: 1, color: Color.Orange})
    }
    .width('100%')
    .height('100%')
  }
}

常用属性

咱们来看看Scroll组件的常用属性,就像给卷帘门装一些小配件:

属性名 参数类型 描述
scrollable ScrollDirection 设置滚动方向。Vertical(纵向)/Horizontal(横向)
scrollBar BarState 设置滚动条状态。On(显示)/Off(隐藏)/Auto(自动)
scrollBarColor string/number/Color 设置滚动条颜色。比如Color.Pink#FF69B4
scrollBarWidth string/number 设置滚动条宽度。比如50(单位vp)
edgeEffect EdgeEffect 设置边缘滑动效果。None(无)/Spring(弹簧回弹)/Fade(渐变消失)

示例代码

让咱们给Scroll加点颜色看看效果:

@Entry
@Component
struct Page01_Scroll {
  build() {
    Column({ space: 10 }) {
      Text('竖向滚动')
        .fontSize(20)

      Scroll() {
        Column() {
          // 用渐变背景展示滚动区域
        }
        .height(1000)
        .width('100%')
        .linearGradient({
          colors: [['#0094ff', 0], [Color.Orange, 1]],
        })
      }
      .scrollBarColor(Color.Pink)  // 滚动条粉色
      .scrollBarWidth(10)          // 滚动条宽度10vp
      .scrollBar(BarState.Off)     // 隐藏滚动条
      .edgeEffect(EdgeEffect.Spring)// 弹簧回弹效果
      .width('100%')
      .height(200)
      .border({ width: 1, color: Color.Orange })

      Divider()

      Text('横向滚动')
        .fontSize(20)

      Scroll() {
        Row() {
          // 用渐变背景展示滚动区域
        }
        .height('100%')
        .width(1000)
        .linearGradient({
          angle: 90,
          colors: [['#0094ff', 0], [Color.Orange, 1]],
        })
      }
      .scrollable(ScrollDirection.Horizontal)
      .width('100%')
      .height(200)
      .border({ width: 1, color: Color.Orange })
      .edgeEffect(EdgeEffect.Spring)
    }
    .width('100%')
    .height('100%')
  }
}

🥦 Scroll控制器(Scroller)

日常开发中,咱们经常需要通过代码控制滚动,比如点击按钮返回顶部,或者获取当前滚动距离。这时候,就需要用到Scroll的控制器——Scroller

核心步骤

  1. 创建控制器:实例化一个Scroller对象
  2. 绑定控制器:把Scroller对象传给Scroll组件
  3. 调用方法:使用控制器的方法控制滚动或获取滚动距离

基础代码

@Entry
@Component
struct Page03_Scroller {
  // 1. 创建Scroller控制器
  scroller: Scroller = new Scroller()

  build() {
    Column({ space: 10 }) {
      Text('Scroll的控制器')
        .fontSize(20)

      // 2. 把控制器绑定给Scroll
      Scroll(this.scroller) {
        // 内容区域
        Image($r('app.media.ic_xiaomi_scroll_01'))
      }
      .scrollBar(BarState.Off)
      .edgeEffect(EdgeEffect.Spring)
      .width('100%')
      .height(200)
      .border({ width: 1, color: Color.Orange })

      // 3. 使用控制器方法
      Button('滚动到底部')
        .onClick(() => {
          this.scroller.scrollEdge(Edge.Bottom) // 滚动到边缘
        })

      Button('获取滚动距离')
        .onClick(() => {
          const offset = this.scroller.currentOffset()
          console.log('横向滚动距离:', offset.xOffset)
          console.log('纵向滚动距离:', offset.yOffset)
        })
    }
    .width('100%')
    .height('100%')
  }
}

常用方法

方法名 功能
scrollEdge() 滚动到容器边缘。比如Edge.Top(顶部)、Edge.Bottom(底部)
currentOffset() 获取当前滚动偏移量。返回{xOffset: number, yOffset: number}
scrollPage() 滚动到指定页面(适用于分页场景)
scrollTo() 滚动到指定位置

🥦 Scroll事件

Scroll组件还提供了一些事件,让咱们能在滚动时做一些额外操作。最常用的就是onScroll事件啦!

基础代码

@Entry
@Component
struct Page04_ScrollEvent {
  // 创建控制器
  scroller: Scroller = new Scroller()

  build() {
    Column({ space: 10 }) {
      Text('Scroll的事件')
        .fontSize(20)

      Scroll(this.scroller) {
        Image($r('app.media.ic_xiaomi_scroll_01'))
      }
      .scrollBarColor(Color.Pink)
      .scrollBarWidth(20)
      .edgeEffect(EdgeEffect.Spring)
      .width('100%')
      .height(200)
      .border({ width: 1, color: Color.Orange })
      // 添加滚动事件
      .onScroll((x, y) => {
        console.log('当前滚动距离:', this.scroller.currentOffset().yOffset)
        // 这里可以根据滚动距离做一些逻辑处理
      })
    }
    .width('100%')
    .height('100%')
  }
}

🥦 实战案例1:小米有品首页滚动

咱们先从简单的开始,实现小米有品首页的滚动效果:

需求分析

  1. 页面内容可以滚动
  2. 隐藏滚动条(更美观)
  3. 滚动到边缘时有弹簧效果

代码实现

@Entry
@Component
struct Page02_ScrollDemo_Xiaomi {
  build() {
    Scroll() {
      Column() {
        // 这里放小米有品的轮播图、分类、商品等内容
        Image($r('app.media.ic_xiaomi_scroll_01'))
          .width('100%')
        Image($r('app.media.ic_xiaomi_scroll_02'))
          .width('100%')
        Image($r('app.media.ic_xiaomi_scroll_03'))
          .width('100%')
      }
    }
    .scrollBar(BarState.Off)  // 隐藏滚动条
    .edgeEffect(EdgeEffect.Fade) // 边缘渐变效果
  }
}

🥦 实战案例2:京东"小火箭"返回顶部

这个案例稍微复杂一点,但绝对实用!实现京东的"小火箭"返回顶部效果:

需求分析

  1. 页面内容可以滚动
  2. 默认隐藏"小火箭"
  3. 滚动距离超过400vp时显示"小火箭"
  4. 点击"小火箭"返回页面顶部

代码实现

@Entry
@Component
struct Page05_JDRocket {
  // 创建控制器
  scroller: Scroller = new Scroller()
  // 控制火箭显示状态
  @State showRocket: boolean = false

  build() {
    Column() {
      Stack({ alignContent: Alignment.BottomEnd }) {
        // 滚动内容区域
        Scroll(this.scroller) {
          Column() {
            Image($r('app.media.ic_jd_scroll_01'))
            Image($r('app.media.ic_jd_scroll_02'))
            Image($r('app.media.ic_jd_scroll_03'))
          }
        }
        .scrollBar(BarState.Off)  // 隐藏滚动条
        .width('100%')
        .onScroll((x, y) => {
          // 监听滚动距离,控制火箭显示
          if (this.scroller.currentOffset().yOffset > 400) {
            this.showRocket = true
          } else {
            this.showRocket = false
          }
        })

        // 小火箭按钮
        if (this.showRocket) {
          Image($r('app.media.ic_jd_rocket'))
            .width(40)
            .backgroundColor(Color.White)
            .borderRadius(20)
            .padding(5)
            .offset({ x: -20, y: -20 })  // 定位在右下角
            .onClick(() => {
              this.scroller.scrollEdge(Edge.Top)  // 点击返回顶部
            })
        }
      }
      .layoutWeight(1)

      // 底部标签栏
      Image($r('app.media.ic_jd_scroll_tab'))
        .width('100%')
    }
  }
}

🥦 西兰花警告

  1. 只能有一个子组件:Scroll里面只能放一个直接子组件!如果有多个内容,一定要用Column或Row包裹起来。

  2. 尺寸设置要正确:子组件的尺寸必须超过Scroll的尺寸,否则不会滚动。

  3. 控制器不要加@State:Scroller控制器不需要用@State装饰器,直接创建即可。

  4. 滚动条状态:如果不需要滚动条,记得设置.scrollBar(BarState.Off),不然会影响美观。

🥦 西兰花小贴士

  1. 边缘效果选择

    • Spring(弹簧):有物理回弹效果,适合活泼的页面
    • Fade(渐变):边缘渐变消失,适合优雅的设计
    • None(无):没有效果,适合需要精确控制的场景
  2. 滚动性能优化

    • 长列表尽量使用List组件,性能更好
    • 避免在onScroll事件中做复杂计算,会影响滚动流畅度
    • 大图片记得压缩,减少滚动时的内存占用
  3. 兼容性考虑

    • 不同设备的屏幕尺寸不同,记得使用相对单位(如%、vp)
    • 测试横竖屏切换时的滚动效果

🥦 总结

今天咱们学习了鸿蒙Scroll滚动组件的全攻略,从基础用法到实战案例,相信你已经掌握了:

  1. Scroll组件的核心概念:可滚动容器,内容超出时可滚动
  2. 基础用法:设置尺寸、添加子组件、配置滚动方向
  3. 常用属性:滚动条设置、边缘效果、滚动方向等
  4. 控制器使用:用Scroller控制滚动和获取滚动距离
  5. 实战案例:小米有品滚动页面、京东小火箭返回顶部

📚 推荐资料:

我是盐焗西兰花,
不教理论,只给你能跑的代码和避坑指南。
下期见!🥦

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐