场景一:Swiper页面支持自定义动画

方案:

  1. 给Swiper组件设置.nextMargin(50).prevMargin(50)属性。
  2. 给Swiper组件添加onChange事件,设置当前this.currentIndex=index,当currentIndex为首页或者尾页时,设置上一张以及下一张图片的缩放值。

    核心代码:

    .onChange((index) => {
      console.info('changeIndex' + index)
      this.currentIndex = index
      // 设置当前index缩放值为最大值
      this.scaleArray[this.currentIndex] = MAX_SCALE;
      if (this.currentIndex == 0) {
        // 当前index=0时,设置上一张图片的缩放值
        this.scaleArray[this.scaleArray.length - 1] = MIN_SCALE
      } else
      // 当前index不为0时,设置上一张图片的缩放值
      {
        this.scaleArray[this.currentIndex -1] = MIN_SCALE
      }
    
      if (this.currentIndex == this.scaleArray.length - 1) {
        // 当index为最后一张图片时,设置下一张图片的缩放值
        this.scaleArray[0] = MIN_SCALE
      } else
      // 当index不为最后一张时,设置上一张图片的缩放值
      {
        this.scaleArray[this.currentIndex + 1] = MIN_SCALE
      }
    })
  3. 设置Swiper组件的.displayMode(SwiperDisplayMode.STRETCH)使其Swiper滑动一页的宽度为Swiper组件自身的宽度,如果displayMode属性为SwiperDisplayMode.AUTO\_LINEAR时,customContentTransition接口不生效。
  4. 给Swiper添加customContentTransition(transition: SwiperContentAnimatedTransition)事件,设置页面移除视窗时超时1000ms下渲染树,然后对视窗内所有页面逐帧回调transition。想要实现显示在视窗内正中间的Index为正常状态,两边的index图片为缩小状态。通过事件回调的proxy获取下面数据,通过滑动的距离来计算滑动过程中图片的缩放值。

    .customContentTransition({
      // 页面移除视窗时超时1000ms下渲染树
      timeout: 1000,
      // 对视窗内所有页面逐帧回调transition,在回调中修改opacity、scale、translate、zIndex等属性值,实现自定义动画
      transition: (proxy: SwiperContentTransitionProxy) => {
        if (this.startSwiperOffset == 0) {
          this.startSwiperOffset = proxy.position * proxy.mainAxisLength;
          console.info('startSwiperOffset:' + this.startSwiperOffset)
        }
        console.info('proxy-selectedIndex:' + proxy.selectedIndex + '--index:' + proxy.index +
          '--position:' + proxy.position + '--mainAxisLength:' + proxy.mainAxisLength)
        let offset: number = proxy.position * proxy.mainAxisLength // 移动距离
        let currentScale: number = this.scaleArray[proxy.index] //当前index缩放值
    
        let nextIndex = (proxy.index == this.scaleArray.length - 2 ? 0 : proxy.index + 1) //计算下一个index
        let preIndex = (proxy.index == 0 ? this.scaleArray.length - 2 : proxy.index - 1) //计算上一个index
    
        let nextScale: number = this.scaleArray[nextIndex] //下一个index缩放值
        let preScale: number = this.scaleArray[preIndex] //上一个index缩放值
        // 通过滑动的距离来计算滑动过程中图片的缩放值
        let distance = Math.abs(offset)
        currentScale = MAX_SCALE - Math.min(distance / DRAGGING_MAX_DISTANCE, MAX_SCALE - MIN_SCALE) //当前缩放值
        if (this.startSwiperOffset > offset) {
          nextScale = MIN_SCALE + Math.min(distance / DRAGGING_MAX_DISTANCE, MAX_SCALE - MIN_SCALE)
          preScale = MIN_SCALE
        } else {
          preScale = MIN_SCALE + Math.min(distance / DRAGGING_MAX_DISTANCE, MAX_SCALE - MIN_SCALE)
          nextScale = MIN_SCALE
        }
        this.scaleArray[this.currentIndex] = currentScale //当前index缩放值
        this.scaleArray[nextIndex] = nextScale //下一个index缩放值
        this.scaleArray[preIndex] = preScale //上一个index缩放值
      }
    })

场景二:Swiper指示器距离底部位置

方案:

此方案只适用于指示点距离底部的位置

将Swiper分成两个部分上部分为Swiper内容区,下部分为一块空白区域, 空白区域专门放置指示器点。可以通过indicator 属性去设置指示器点的部分样式。

@Entry
@Component
struct SwiperPageTwo {
  @State message: string = 'Hello World';
  private bannerInfo: number[] = [1, 2, 3, 4]
  dataList:Color[] = [Color.Gray, Color.Yellow, Color.Blue,Color.Pink,Color.Orange]

  build() {
    if (this.bannerInfo && this.bannerInfo.length > 0) {
      Swiper() {
        ForEach(this.bannerInfo, (item: number, index: number) => {
          Column() {
            // 第一部分 Swiper内容区域
            Column()
              .width("100%")
              .height(200)
              .borderRadius("8vp")
              .backgroundColor(this.dataList[index])
            // 第二部分 指示点区域
            Column() {

            }.width('100%')
            .height(35)
          }

        })
      }
      .cachedCount(2)
      .autoPlay(true)
      .interval(3000)
      .vertical(false)
      .loop(true)
      .margin({ left: "16vp", right: "16vp" })
      .indicator(
        new DotIndicator()
          .bottom(5)
          .itemWidth("8vp")
          .itemHeight("8vp")
          .selectedItemWidth("10vp")
          .selectedItemHeight("10vp")
          .color(Color.Green)
          .selectedColor(Color.Orange)
      )
    }
  }
}

场景三:Swiper自定义指示器

目前Swiper自带的指示器位置限定比较固定,不能完全靠底部、左边或者右边以及不能调整指示器中间间距,因此可以考虑自定义指示器,将指示器位置定位到我们所需的地方。

方案:

给Swiper自带指示器设置.indicator(false),然后在Swiper组件下面写一个自定义的指示器。

// 自定义指示器,可以通过定位
Row() {
  ForEach(this.data, (item: string, index: number) => {
    Column()
      .width(this.currentIndex === index ? 10 : 5)
      .height(5)// 设置指示点中间间距
      .margin(5)
      .borderRadius(5)
      .backgroundColor(Color.Green)
      .backgroundColor(this.currentIndex === index ? Color.Red : Color.Gray)
  }, (item: string) => item)
}
//设置指示点距离Swiper上下的距离
.margin({ top: 5 })

// 设置指示点在Swiper的左边或者右边或者其他地方
// .position({x:0,y:300})

HarmonyOS码上奇行
5k 声望2.5k 粉丝