HarmonyOS Next ArkUl带你玩转Swiper组件

307 阅读3分钟

环境及工具

HarmonyOS 5.0.0 Release
DevEcoStudio
适用于HarmonyOS Next原生开发

1 Swiper

鸿蒙(HarmonyOS)中的 Swiper 组件是一个非常有用且直观的UI组件,它允许用户通过滑动手势在多个页面或卡片之间进行切换。这个组件非常适合用于展示一系列图片、产品列表、教程介绍等场景,为用户提供流畅且交互性强的浏览体验。下面我们将详细介绍如何在鸿蒙应用中使用 Swiper 组件,并探讨一些配置选项和最佳实践。

概念:滑块视图容器,提供子组件滑动轮播显示的能力。

1.1适用场景

使用场景:Swiper组件提供滑动轮播显示的能力。Swiper本身是一个容器组件,当设置了多个子组件后,可以对这些子组件进行轮播显示。
比如:京东首页 image.png

1.2基本用法

首先来看看如何设置轮播内容,以及设置尺寸

  1. 轮播内容:内容作为Swiper的子组件即可
  2. 尺寸:
    1. 设置 Swiper 的尺寸:内容会拉伸为和 Swiper 一致(优先级高
    2. 设置内容尺寸:会将Swiper撑开
Swiper() {
  // 轮播内容 
  // (设置尺寸,撑开swiper)
}
// 设置尺寸(内容拉伸、优先级高)
.width('100%')
.height(100)

juejin_swiper_1.gif

@Entry
@Component
struct Index {
  build() {
    Column() {
      Swiper() {
        // 轮播内容
        Image($r('app.media.ic_swiper_xmyp01'))
        Image($r('app.media.ic_swiper_xmyp02'))
        Image($r('app.media.ic_swiper_xmyp03'))
        Image($r('app.media.ic_swiper_xmyp04'))
        // (设置尺寸,撑开swiper)
      }
      // 设置尺寸(内容拉伸、优先级高)
      .width('100%')
      .height(160)
    

1.3常用属性

设置了内容以及尺寸之后已经可以实现基础的轮播效果啦,接下来看看一些常见属性

loopboolean是否开启循环。设置为true时表示开启循环,在LazyForEach懒循环加载模式下,加载的组件数量建议大于5个。默认值:true
autoPlayboolean子组件是否自动播放。默认值:false说明:loop为false时,自动轮播到最后一页时停止轮播。手势切换后不是最后一页时继续播放。
intervalnumber使用自动播放时播放的时间间隔,单位为毫秒。默认值:3000
verticalboolean是否为纵向滑动。默认值:false

image.png

1.4综合案例分析

1.4.广告分析

juejin_swiper_1.gif
关键信息:

  1. 宽高:100%、160
  2. 循环、自动轮播,间隔 4000
  3. 圆点指示器:
    1. 选中颜色:白色
    2. 选中宽高:30、4
    3. 默认宽高:10、4
@Entry
@Component
struct Index {
  build() {
    Column() {

      Swiper() {
        // 轮播内容
        Image($r('app.media.ic_swiper_xmyp01'))
        Image($r('app.media.ic_swiper_xmyp02'))
        Image($r('app.media.ic_swiper_xmyp03'))
        Image($r('app.media.ic_swiper_xmyp04'))
        // (设置尺寸,撑开swiper)
      }
      // 设置尺寸(内容拉伸、优先级高)

      .width('100%')
      .height(160)
      // 循环
      .loop(true)
      // 自动播放
      .autoPlay(true)
      // 时间
      .interval(4000)
      .borderRadius(5)
      // 动画曲线
      .curve(Curve.Linear)
      .indicator(
        // 条状
        Indicator.dot()
          // 数字样式
          // Indicator.digit()
          // 未选中时滚动条的宽、高
          .itemWidth(10)
          .itemHeight(4)
          // 选中后的颜色、宽、高
          .selectedColor(Color.White)
          .selectedItemWidth(30)
          .selectedItemHeight(4)

      )

1.4.2垂直滚动

juejin_swiper_2.gif
代码实现

 Column() {
    Swiper() {
      // 轮播内容
      Image($r('app.media.1')).borderRadius(50)
      Image($r('app.media.2')).borderRadius(50)
      Image($r('app.media.3')).borderRadius(20)
      Image($r('app.media.4')).borderRadius(20)
      Image($r('app.media.5')).borderRadius(20)
      // (设置尺寸,撑开swiper)
    }
    // 设置尺寸(内容拉伸、优先级高)
    .width('100%')
    .height('100%')
    .loop(true)
    .autoPlay(true)
    .interval(4000)
    .vertical(true)
    .indicator(
      Indicator.dot()
        .itemWidth(40)
        .itemHeight(10)
        .selectedColor(Color.White)
        .selectedItemWidth(50)
        .selectedItemHeight(10)
    )
  }
  .width('100%')
  .height('100%')
  .padding(2)
  // .backgroundColor(Color.Pink)
}
.width('100%')
.height('100%')
.padding(2)

1.4.3 案例分析-图片留边

juejin_swiper_3.gif

// swiper
@Builder
swiperBuilder() {
  Swiper() {
    Image($r('app.media.ic_swiper_xmyp01'))
      .width('90%')
      .borderRadius(5)
    Image($r('app.media.ic_swiper_xmyp02'))
      .width('90%')
      .borderRadius(5)

    Image($r('app.media.ic_swiper_xmyp03'))
      .width('90%')
      .borderRadius(5)
    Image($r('app.media.ic_swiper_xmyp04'))
      .width('90%')
      .borderRadius(5)
  }
  .margin({
    top: 10,
    bottom: 10
  })
  // .borderRadius(5)
     //前后图片设置距离
  .prevMargin(15) 
  .nextMargin(15)
  .itemSpace(20)
  // .width('100%')
  // .height(160)
  .loop(true)
  .autoPlay(true)
  .indicator(
    DotIndicator.dot()
      .selectedColor('#ff0000')
      .color('#ffffff')
    // .bottom(500)

  )
}

2.@Builder自定义构建函数

ArkUI提供了一种轻量的UI元素复用机制@Builder,该自定义组件内部UI结构固定,仅与使用方进行数据传递,开发者可以将重复使用的UI元素抽象成一个方法,在build方法里调用。

为了简化语言,我们将@Builder装饰的函数也称为“自定义构建函数”。
作用: 它可以将结构相同的代码块封装成一个函数,方便调用

限制条件

  • @Builder通过按引用传递的方式传入参数,才会触发动态渲染UI,并且参数只能是一个。
  • @Builder如果传入的参数是两个或两个以上,不会触发动态渲染UI。
  • @Builder传入的参数中同时包含按值传递和按引用传递两种方式,不会触发动态渲染UI。
  • @Builder的参数必须按照对象字面量的形式,把所需要的属性一一传入,才会触发动态渲染UI。 image.png

2.1基本语法

// 自定义 全局 构建函数
@Builder function MyGlobalBuilderFunction(param1,param2...) {
  // 结构
}
// 使用
MyGlobalBuilderFunction(param1,param2...)



// 自定义 组件内 构建函数
@Builder MyBuilderFunction( param1,param2...) {
  // 结构
}
// 通过 this 来使用
this.MyBuilderFunction(param1,param2...)

实现效果图:

image.png
示例代码:

@Builder
function AutoBuilder1() {
  Text('这是一个建立在struct外的一个自定义函数组件')
    .fontSize(25)
    .fontWeight(900)
}
@Entry
@Component
struct Index {
 @Builder
  AutoBuilder2(){
    Text('这是一个建立在struct内的一个自定义函数组件,调用方法前边必须加this')
      .fontSize(30)
      .fontWeight(900)
      .fontColor(Color.Red)
  }
  build() {
    Column() {
      AutoBuilder1()
      this.AutoBuilder2()
    }
    .width('100%')
    .height('100%')
    // .backgroundColor(Color.Pink)
  }
}

struct内置自定义函数有两个位置,不分先后顺序,需要的时候,直接调用

image.png

3 综合案例

创业app界面,主要练习自定义函数的书写以及调用。

juejin_案例.gif

@Entry
@Component
struct Index {
  // 首页
  @Builder
  firstbuilder(text1: string, img1: Resource, img2: Resource) {
    Row() {
      Row() {

      }
      .layoutWeight(1)

      Row() {
        Text(text1)
          .fontSize(25)
          .layoutWeight(1)
          .width('100%')
        Row({ space: 10 }) {
          Image(img1)
            .height(16)
            .fillColor('#0b0b0b')
          Text('')
            .fontSize(16)
            .width(2)
            .height(20)
            .backgroundColor('#eaeaea')
          Image(img2)
            .height(16)
            .fillColor('#0b0b0b')
        }
        .padding({
          left: 15,
          right: 15,
          top: 5,
          bottom: 5
        })
        .border({
          width: 1,
          color: '#eaeaea'
        })
        .borderRadius(25)

      }
      .layoutWeight(1.25)
    }
    .padding({
      right: 15
    })
    .width('100%')

    // .backgroundColor(Color.Yellow)

  }

  // swiper
  @Builder
  swiperBuilder() {
    Swiper() {
      Image($r('app.media.ic_swiper_xmyp01'))
        .width('90%')
        .borderRadius(5)
      Image($r('app.media.ic_swiper_xmyp02'))
        .width('90%')
        .borderRadius(5)

      Image($r('app.media.ic_swiper_xmyp03'))
        .width('90%')
        .borderRadius(5)

      Image($r('app.media.ic_swiper_xmyp04'))
        .width('90%')
        .borderRadius(5)
    }
    .margin({
      top: 10,
      bottom: 10
    })
    // .borderRadius(5)
    .prevMargin(15)
    .nextMargin(15)
    .itemSpace(20)
    // .width('100%')
    // .height(160)
    .loop(true)
    .autoPlay(true)
    .indicator(
      DotIndicator.dot()
        .selectedColor('#ff0000')
        .color('#ffffff')
      // .bottom(500)

    )
  }

  // 宫格导航
  @Builder
  commonBuilder(imgurl: Resource, text1: string) {
    Column() {
      Image(imgurl)
        .height(35)
      Text(text1)
        .fontSize(13)
    }
    .margin({
      bottom: 5
    })
    .width('20%')
  }

  // 广告
  @Builder
  sloganBuilder(imgurl: Resource) {
    Column() {
      Image(imgurl)
        .width('100%')
    }
    .padding({
      left: 10,
      right: 10,
      bottom: 10
    })

  }

  // 热门服务
  @Builder
  PopularserviceBulider(txt1: string) {

    Row() {
      Text(txt1)
        .fontSize(20)
        .fontWeight(600)
    }
    .width('100%')
    .padding({
      left: 15
    })
  }

  // 宫格图片
  // 1.1不带文字
  @Builder
  commoneBuilder(imgurl: Resource) {
    Image(imgurl)
      .width('47%')
      .borderRadius(10)
  }

  // 1.2带文字
  @Builder
  textBuilder(imgurl: Resource, txt1: string, txt2: string) {
    Column({ space: 10 }) {
      Image(imgurl)
        .width('100%')
      Column({ space: 3 }) {
        Text(txt1)
          .fontSize(18)
          .fontColor('#ff0c0c')
          .width('100%')
        Text(txt2)
          .width('100%')
          .fontSize(14)
          .fontColor('#727272')

      }
      .padding({
        left: 10,
        bottom: 10
      })
    }
    .alignItems(HorizontalAlign.Start)
    .backgroundColor('#efefef')
    .width('47%')
    .margin({
      bottom: 7
    })
  }

  // 创始人七堂课

  @Builder
  footer1Builder(imgurl: Resource) {
    Column() {
      Image(imgurl)
        .width('100%')
        .margin({
          top: 10,
          bottom: 20
        })
        .borderRadius(5)
    }.padding({
      left: 15,
      right: 15
    })

  }

  // 底部导航栏
  @Builder
  footerBuilder(imgurl: Resource, txt1: string, color: string = '#808080') {

    Column() {
      Image(imgurl)
        .width(30)
        .fillColor(color)

        .margin({
          bottom: 3
        })
      Text(txt1)
        .fontSize(16)
        .fontColor(color)

    }
    .height(80)
  }

  build() {
    Scroll() {
      Column() {
        // 首页
        this.firstbuilder('首页', $r('app.media.cy_more'), $r('app.media.cy_exit'))
        // swiper
        this.swiperBuilder()

        // 宫格导航
        Flex({
          wrap: FlexWrap.Wrap
        }) {
          this.commonBuilder($r('app.media.buder1'), '课时简介')
          this.commonBuilder($r('app.media.buder2'), '课时简介')
          this.commonBuilder($r('app.media.buder3'), '课时简介')
          this.commonBuilder($r('app.media.buder1'), '课时简介')
          this.commonBuilder($r('app.media.buder2'), '课时简介')
          this.commonBuilder($r('app.media.buder3'), '课时简介')
          this.commonBuilder($r('app.media.buder1'), '课时简介')
          this.commonBuilder($r('app.media.buder2'), '课时简介')
          this.commonBuilder($r('app.media.buder3'), '课时简介')
          this.commonBuilder($r('app.media.buder1'), '课时简介')
        }
        .padding(15)

        // 广告
        this.sloganBuilder($r('app.media.slogan'))
        // 热门服务
        this.PopularserviceBulider('热门服务')
        // this.PopularserviceBulider('热门服务','¥300起','联合办公',$r('app.media.cy_second'))
        // 宫格图片
        // 1.1不带文字
        Flex({
          wrap: FlexWrap.Wrap,
          justifyContent: FlexAlign.SpaceEvenly,
          alignContent: FlexAlign.SpaceBetween
        }) {
          this.commoneBuilder($r('app.media.cy_first'))
          this.commoneBuilder($r('app.media.cy_second'))
          this.commoneBuilder($r('app.media.cy_first'))
          this.commoneBuilder($r('app.media.cy_first'))
        }
        .padding(10)

        // 热门服务
        this.PopularserviceBulider('热销商品')
        // this.PopularserviceBulider('热门服务','¥300起','联合办公',$r('app.media.cy_second'))
        // 宫格图片
        // 1.1不带文字
        Flex({
          wrap: FlexWrap.Wrap,
          justifyContent: FlexAlign.SpaceEvenly,
          alignContent: FlexAlign.SpaceBetween
        }) {
          this.textBuilder($r('app.media.cy_1'), '¥400起', '商标注册')
          this.textBuilder($r('app.media.cy_2'), '¥300起', '联合办公')
          this.textBuilder($r('app.media.cy_3'), '¥600起', '公众号吸粉')
          this.textBuilder($r('app.media.cy_4'), '¥800起', '五险一金代缴')

        }
        .padding(10)

        // 创始人七堂课
        this.PopularserviceBulider('创始人必学的股权7堂课')
        this.footer1Builder($r('app.media.cy_5'))
        // 底部导航栏
        Row() {
          this.footerBuilder($r('app.media.cy_shouye'), '首页', '#ef331f')
          this.footerBuilder($r('app.media.cy_print'), '印刷')
          this.footerBuilder($r('app.media.cy_lipin'), '礼品')
          this.footerBuilder($r('app.media.cy_fuwu'), '服务')
          this.footerBuilder($r('app.media.cy_wode'), '我的')

        }
        .width('100%')
        .justifyContent(FlexAlign.SpaceBetween)
        .padding({
          left: 15,
          right: 15
        })
      }


      // .backgroundColor(Color.Pink)
    }.width('100%')
    .height('100%')
  }
}