容器组件Scroll介绍

442 阅读3分钟

可滚动的容器组件,当子组件的布局尺寸超过Scroll的尺寸时,内容可以滚动。当页面内容由多个区域组成,并且可以滚动时,推荐使用 Scroll。

1.核心用法

  1. Scroll 设置尺寸
  2. 设置 子组件(只支持一个子组件)
  3. 设置滚动:
  • 竖向滚动:子组件的高度超出 Scroll
  • 横向滚动:子组件的宽度超出 Scroll,scrollable改为横向滚动
  1. 根据需求调整属性

image.png

Scroll(){
  // 只支持一个子组件
  Column(){
    // 内容放在内部
    // 尺寸超过 200 即可滚动
  }
}
.width('100%')
.height(200)

注意:column里面只能有一个子组件,可以在最外层包裹一个column或者row等等,然后在里面在进行写其他组件

举例:

.scrollBarColor(Color.Pink)//滚动条颜色
.scrollBarWidth(50)//滚动条宽度
.scrollBar(BarState.Off)//关闭滚动条
.edgeEffect(EdgeEffect.Spring)//弹簧效果
.scrollable(ScrollDirection.Horizontal)//设置滚动条的方向

2.Scroll的控制器

有两个方法:

  1. scrollEdge:滚动到边缘
  2. currentOffset: 获取当前的偏移量

举例:

  1. 页面滚动超过一定距离,显示返回顶部(火箭),反之隐藏
  2. 点击返回顶部(火箭),返回顶部

image.png

核心步骤:

  1. 实例化 Scroller的 控制器
  2. 绑定给 Scroll
  3. 调用 控制器的方法控制滚动,通过控制器的属性获取滚动距离

先实现点击火箭马上返回到顶部

@Entry
@Component
struct ScrollDemo {

//1.实例化Scroller的 控制器
  scroller: Scroller = new Scroller()

  build() {
    Column() {
    
    //2绑定给Scroll
      Scroll(this.scroller) {
        // 内容略
      }
      Row() {
        Button('返回顶部')
          .onClick(() => {
            // 滚到顶部,利用scroller上的scrollEdge方法
            this.scroller.scrollEdge(Edge.Top)
          })

scrollEdge方法参数

this.scroller.scrollEdge(Edge.Top)
this.scroller.scrollEdge(Edge.Start)
this.scroller.scrollEdge(Edge.Bottom)
this.scroller.scrollEdge(Edge.End)

其中的Edge.TopEdge.Start表现相同,Edge.BottomEdge.End表现相同。

currentOffset 方法返回值

this.scroller.currentOffset().xOffset // x 轴滚动距离
this.scroller.currentOffset().yOffset // y 轴滚动距离

onWillScroll事件

Scroll(){
  // 内容略
}
  .onScroll((x,y)=>{
    // 滚动时 一直触发
    // 可以结合 scroller的currentOffset方法 获取滚动距离
  })

说明:onScroll在进行滑动的时候可以一直获取滑动的x,y距离,并且能返回一个值

上面的京东案例(部分代码)


1.先实例化Scroller
sc: Scroller = new Scroller()
@State showRocket: boolean = false

...

//在Scroll组件上.出这个属性然后进行随时获取x和y的滑动距离
.onScroll((x, y) => {
          if( this.sc.currentOffset().yOffset>400){
            this.showRocket=true
          }else{
            this.showRocket = false
          }
        })
 
 //这里在进行条件渲染,当y的距离超过400时就显示火箭图标       
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.sc.scrollEdge(Edge.Top)
            })
        }

3. 容器组件Tabs

当页面内容较多时,可以通过Tabs组件进行分类展示,以下这些效果都可以通过Tabs组件来实现

image.png

3.1基本用法

@Entry
@Component
struct TabbarDemo {
  build() {
    Tabs() { // 顶级容器
      TabContent() {
        // 内容区域:只能有一个子组件
      }
      .tabBar('首页') // 导航栏
    }
  }
}

image.png

注意:TabContent里面只能有一个子组件,可以使用column和row等组件进行包裹

3.2常用属性

Tabs默认可以实现切换,可以设置如下图导航位置

image.png

相关属性:

// BarPosition.Start 起始
// BarPosition.End 结尾
Tabs({ barPosition: BarPosition.End }) {
  // 内容略
}
  .vertical(true)// 垂直导航 true / 水平false
  .scrollable(true) // 允许滑动 true / 不允许 false
  .animationDuration(0) // 切换动画的时间,毫秒

注意:BarPosition可以设置在Tabs括号里面,也可以设置在右括号的外面。

3.3滚动的导航栏

也可以设置导航栏的滚动,也可以进行固定,但是如果导航的数量太多了就会显示不全: 如:

image.png

使用可以通过设置

.barMode(BarMode.Scrollable)// 滚动

3.4自定义tabBar

在开发中,可能会遇到如下外观的导航栏

image.png

那么这个时候就需要进行自定义样式了

基本语法如下:

Tabs() {
    TabContent() {
        // 内容略
    }
    //在这里进行引用
    .tabBar(this.tabBarBuilder())
  }

@Builder
tabBarBuilder() {
  // 这里进行自定义的Tabbar结构
   Column() {
      Image(img)
        .width(30)
      Text(text)
    }
}

3.5 Tabs组件的事件

自定义的导航栏在滑动时不会被点亮,那么就需要引入事件了

image.png


//onChange在切换时会有延时效果,一般需要与.animationDuration(0)进行结合使用,而且不管时滑动和点击是都能触发相应的效果
.onChange((index) => {
      console.log('onChange-index:', index)
    })
    
    
    //onTabBarClick没有延时效果,但是它只能在点击时能触发相应的效果
    .onTabBarClick((index) => {
      console.log('tabBarClick-index:', index)
    })

注意:这两个的特点是都可以获取导航栏的索引值,而且都是从0开始的。

3.5.1 自定义 tabBar-高亮切换

思路:

  1. 用状态变量保存,onChange,ontabBarClick中获取到的索引值
  2. 给每个 tabBar起个标记,0,1,2.。。
  3. 在tabBar内部比较 标记==this.index?高亮:不高亮

关键代码:

// 1. ✨✨✨定义一个状态变量,用来存储当前用户选中的tabbar索引
  @State currentIndex: number = 0
  
  
  // 2. 定义构建函数
  @Builder
  tabbarBuilder(title: string, icon: string, selectedIcon: string, index: number) {
    Column({ space: 5 }) {
      // 3. ✨✨✨在自定义构建函数中使用三元表达式来进行高亮功能的处理
      Image(this.currentIndex == index ? $r(selectedIcon) : $r(icon))
        .width(35)
      Text(title)
        // 4. ✨✨✨在自定义构建函数中使用三元表达式来进行高亮功能的处理
        .fontColor(this.currentIndex == index ? Color.Red : Color.Black)
    }
  }
  
  
  Tabs() {
        TabContent() {
          Text('首页')
            .fontSize(50)
        }
        // 5. ✨✨✨在调用自定义构建函数的时候,需要传入当前tabbar的索引(固定值),同时要传入点亮的图片路径和正常的图片路径
 .tabBar(this.tabbarBuilder('首页', 'app.media.ic_tabbar_icon_0', 'app.media.ic_tabbar_icon_0_selected', 0))


//6.将索引值index赋给状态变量
//这里使用animationDuration配合使用消除延时
 .animationDuration(0)
 .onChange((index) => {
        this.currentIndex = index
      })

3.6 Badge角标组件

image.png

Badge({
//这里count为number类型,也可以换成value,他是一个字符串类型
  count: 8,
  style: {},
  position: { x: 25, y: -5 }
}) {

//这里表示这个角标放在Text的身上
  Text(title)
    .fontWeight(this.a == index ? 800 : 400)
    .fontColor(Color.Gray)
}