前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >HarmonyOS 开发实践 —— 基于Swiper的页面布局

HarmonyOS 开发实践 —— 基于Swiper的页面布局

原创
作者头像
小帅聊鸿蒙
发布2024-12-19 16:52:36
发布2024-12-19 16:52:36
1520
举报
文章被收录于专栏:鸿蒙开发笔记鸿蒙开发笔记

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

方案:

1.给Swiper组件设置.nextMargin(50).prevMargin(50)属性。

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

核心代码:

代码语言:ts
复制
.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获取下面数据,通过滑动的距离来计算滑动过程中图片的缩放值。

代码语言:ts
复制
.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 属性去设置指示器点的部分样式。

代码语言:ts
复制
@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组件下面写一个自定义的指示器。

代码语言:ts
复制
// 自定义指示器,可以通过定位 
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})

写在最后

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:

  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力;
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识;
  • 想要获取更多完整鸿蒙最新学习知识点,可关注B站:码牛课堂;

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 场景一:Swiper页面支持自定义动画
    • 方案:
  • 场景二:Swiper指示器距离底部位置
    • 方案:
  • 场景三:Swiper自定义指示器
    • 方案:
  • 写在最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档