鸿蒙Next轮播组件Swiper使用了解

本文介绍一下轮播组件Swiper的基本使用,各属性的含义已在代码中注释说明,可以通过动态修改,查看各属性起到的作用。
通过一个Row容器组件添加属性动画,设置动画持续时间与swiper播放时间匹配,实现一个带进度的指示器,如图。
看一下效果图:

演示.gif

源码

@Entry
@ComponentV2
struct SwiperTest{
  private swiperController: SwiperController = new SwiperController();
  datas:string[]=['0','1','2','3','4','5','6'];
  @Local autoPlay:boolean = true//是否自动播放
  @Local loop:boolean = true//是否开启循环
  @Local interval:number=4000 //自动播放时播放的时间间隔
  @Local duration:number=1000 //子组件切换的动画时长
  @Local itemSpace:number=5 //子组件与子组件之间间隙
  @Local displayCount:number=1  //视窗内元素显示个数
  @Local nextMargin:number=35  //设置后边距,用于露出后一项的一小部分
  @Local prevMargin:number=35  //设置前边距,用于露出前一项的一小部分
  @Local showBackground:boolean=true  //箭头底板是否显示
  @Local isSidebarMiddle:boolean=true  //箭头显示位置
  @Local displayArrow:boolean=true  //箭头显示
  @Local indicator:IndicatorComponentController | DotIndicator | DigitIndicator | boolean=
    new DotIndicator()
    .itemWidth(15)
    .itemHeight(15)
    .selectedItemWidth(15)
    .selectedItemHeight(15)
    .color(Color.Gray)
    .selectedColor(Color.Blue)  //组件控制器

  @Local  slide: boolean = false; //判断页面是否跟手滑动
  @Local  currentIndex: number=0
  @Local  changeDuration: number=this.interval
  build() {
    Column({space:10}){
      Swiper(this.swiperController){
        ForEach(this.datas,(item: string, index:number)=>{
          Text(item.toString())
            .width('100%')
            .height(160)
            .backgroundColor(getRandomColor())
            .textAlign(TextAlign.Center)
            .fontSize(30)
        })
      }
      .index(this.currentIndex) //当前在容器中显示的子组件的索引值
      .autoPlay(this.autoPlay) //是否自动播放
      .interval(this.interval)  //自动播放时播放的时间间隔
      .indicator(this.indicator)// 设置圆点导航点样式
      .loop(this.loop)//是否开启循环
      .duration(this.duration) //子组件切换的动画时长
      .vertical(false) //是否为纵向滑动
      .itemSpace(this.itemSpace) //子组件与子组件之间间隙
      .displayMode(SwiperDisplayMode.STRETCH) //主轴方向上元素排列的模式
      .cachedCount(2) //预加载子组件个数
      .disableSwipe(false) //禁用组件滑动切换功能
      .curve(Curve.Linear) //动画曲线
      .displayCount(this.displayCount) //视窗内元素显示个数
      .effectMode(EdgeEffect.Spring) //边缘滑动效果
      .displayArrow(this.displayArrow?{ // 设置导航点箭头样式
        showBackground: this.showBackground,  //设置箭头底板是否显示
        isSidebarMiddle: this.isSidebarMiddle,  //设置箭头显示位置 true时箭头居中显示在swiper组件两侧,为false时显示在导航点指示器两侧
        backgroundSize: 24,  //设置底板大小
        backgroundColor: Color.White, //设置底板颜色
        arrowSize: 18,  //设置箭头大小
        arrowColor: Color.Blue  //设置箭头颜色
      }:false , false)
      .nextMargin(this.nextMargin) //设置后边距,用于露出后一项的一小部分
      .prevMargin(this.prevMargin) //设置前边距,用于露出前一项的一小部分
      .indicatorInteractive(true) //禁用组件导航点交互功能
      .onAppear(()=>{
        this.currentIndex=0
      })
      //当前显示的子组件索引变化时触发该事件,返回值为当前显示的子组件的索引值
      .onChange((index: number) => {
        this.currentIndex = index
        this.changeDuration =this.interval
        console.info(index.toString());
      })
      //在页面跟手滑动过程中   currentOffset Swiper当前显示元素在主轴方向上,相对于Swiper起始位置的位移
      .onGestureSwipe((index: number, extraInfo: SwiperAnimationEvent) => {
        this.slide = true;
        if (extraInfo.currentOffset > 200 && this.currentIndex > 0) {
          this.currentIndex = index - 1;
        }
        console.info("index: " + index);
        console.info("current offset: " + extraInfo.currentOffset);
      })
      //切换动画开始时触发该回调。参数为动画开始前的index值
      .onAnimationStart((index: number, targetIndex: number, extraInfo: SwiperAnimationEvent) => {
        console.info("index: " + index);
        console.info("targetIndex: " + targetIndex);
        console.info("current offset: " + extraInfo.currentOffset);
        console.info("target offset: " + extraInfo.targetOffset);
        console.info("velocity: " + extraInfo.velocity);
      })
      .onAnimationEnd((index: number, extraInfo: SwiperAnimationEvent) => {
        console.info("index: " + index);
        console.info("current offset: " + extraInfo.currentOffset);
      })
      Text('自定义进度条指示器')
      this.progressComponent()
      Row(){
        Button('自动播放'+(this.autoPlay?'开':'关')).onClick(()=>{
          this.autoPlay=!this.autoPlay
        })
        Column(){
          Text("自动播放时间间隔")
          Counter() {
            Text(this.interval.toString())
          }.width(120)
          .onInc(() => {
            this.interval+=1000;
          })
          .onDec(() => {
            if (this.interval>0) {
              this.interval-=1000;
            }
          })
        }
        Button('循环'+(this.loop?'开':'关')).onClick(()=>{
          this.loop=!this.loop
        })
      }
      Row(){
        Button('圆点指示器').onClick(()=>{
          this.indicator= new DotIndicator()
            .itemWidth(8) //圆点导航指示器的宽
            .itemHeight(8)
            .selectedItemWidth(16) //选中Swiper组件圆点导航指示器的宽
            .selectedItemHeight(8)
            .color(Color.Gray)
            .selectedColor(Color.Blue)
            .maxDisplayCount(9)//导航点显示个数最大值
        })
        Button('数字指示器').onClick(()=>{
          this.indicator=Indicator.digit() // 设置数字导航点样式
            .top(200)
            .fontColor(Color.Gray)
            .selectedFontColor(Color.Gray)
            .digitFont({ size: 20, weight: FontWeight.Bold })
            .selectedDigitFont({ size: 20, weight: FontWeight.Normal })
        })
        Button('取消指示器').onClick(()=>{
          this.indicator=false
        })
      }
      Row(){
        Column(){
          Text("切换动画时长")
          Counter() {
            Text(this.duration.toString())
          }.width(120)
          .onInc(() => {
            this.duration+=100;
          })
          .onDec(() => {
            if (this.duration>0) {
              this.duration-=100;
            }
          })
        }
        Column(){
          Text("组件间隙")
          Counter() {
            Text(this.itemSpace.toString())
          }.width(120)
          .onInc(() => {
            this.itemSpace+=1;
          })
          .onDec(() => {
            if (this.itemSpace>0) {
              this.itemSpace-=1;
            }
          })
        }
      }
      Row(){
        Column(){
          Text("视窗内元素个数")
          Counter() {
            Text(this.displayCount.toString())
          }
          .onInc(() => {
            this.displayCount+=1;
          })
          .onDec(() => {
            if (this.displayCount>1) {
              this.displayCount-=1;
            }
          })
        }
        Column(){
          Text("前边距")
          Counter() {
            Text(this.prevMargin.toString())
          }
          .onInc(() => {
            this.prevMargin+=1;
          })
          .onDec(() => {
            if (this.prevMargin>0) {
              this.prevMargin-=1;
            }
          })
        }
        Column(){
          Text("后边距")
          Counter() {
            Text(this.nextMargin.toString())
          }
          .onInc(() => {
            this.nextMargin+=1;
          })
          .onDec(() => {
            if (this.nextMargin>0) {
              this.nextMargin-=1;
            }
          })
        }
      }
      Row(){
        Button('箭头背景'+(this.showBackground?'显示':'隐藏')).onClick(()=>{
          this.showBackground=!this.showBackground
        })
        Button('箭头'+(this.isSidebarMiddle?'swiper两侧':'指示器两侧')).onClick(()=>{
          this.isSidebarMiddle=!this.isSidebarMiddle
        })
        Button('箭头'+(this.displayArrow?'显示':'隐藏')).onClick(()=>{
          this.displayArrow=!this.displayArrow
        })
      }
    }
  }
  //自定义进度条指示器
  @Builder
  progressComponent() {
    Row({ space: 5 }) {
      ForEach(this.datas, (item: string, index: number) => {
        Stack({ alignContent: Alignment.Start }) {
          Row()
            .zIndex(0)
            .width("100%")
            .height(2)
            .borderRadius(2)
            .backgroundColor(Color.Grey)
          Row()
            .zIndex(1)
            .width(this.currentIndex >= index && !this.slide ? '100%' : '0')
            .height(2)
            .borderRadius(2)
            .backgroundColor(Color.White)
            .animation(!this.slide ? {
              duration: this.changeDuration,
              curve: Curve.Linear,
              iterations: 1,
              playMode: PlayMode.Normal,
              onFinish: () => {
                if (this.currentIndex === this.datas.length - 1) {
                  this.changeDuration=0
                  this.currentIndex = -1;
                }
              }
            } : { duration: 0, iterations: 1 })
          Row()
            .zIndex(2)
            .width(this.currentIndex >= index && this.slide ?'100%':'0')
            .height(2)
            .borderRadius(2)
            .backgroundColor(Color.White)
        }
        .width('100%')
        .height(2)
        .borderRadius(2)
        .backgroundColor(this.currentIndex >= index && this.slide ? Color.White : Color.Grey)
        .layoutWeight(1)
      })
    }
    .width('70%')
    .height(50)
    .backgroundColor(getRandomColor())
  }
}
export function getRandomColor(): string {
  let letters = '0123456789abcdef'
  let color = '#'

  for (let i = 0; i < 6; i++) {
    // 生成0-15的随机数
    const randomIndex = Math.floor(Math.random() * 16)
    // 添加随机字符
    color += letters[randomIndex]
  }
  return color
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容