图片滑动和点击切换效果和轮播组件Swiper 原创

X叶域Q
发布于 2024-12-18 16:10
浏览
0收藏

开始只写了点击切换图片效果,然后在运行调试的时候发现总是习惯性的想要滑动图片达到切换的目的。
针对此需求就开始研究起了图片轮播,研究触摸事件写完后突然发现了一个挺方便的轮播图组件,于是就有了如下内容。
先看展示:上图为触摸事件判断图片左右滑动,下图为轮播组件

图片滑动和点击切换效果和轮播组件Swiper-鸿蒙开发者社区

图片滑动和点击切换效果和轮播组件Swiper-鸿蒙开发者社区

一、图片滑动和点击切换效果

1、定义需要的变量

自定义按钮的文字,展示的图片列表,正在展示的图片和按钮选中的图片编号。
触摸事件需要判断用户滑动方向,需要记录一下开始和结束位置做判断

// 按钮文字
btnList: Array<string> = ["图片1","图片2","图片3","图片4"]
imgList: Array<Resource> = [
    $r("app.media.img1"),
    $r("app.media.img2"),
    $r("app.media.img3"),
    $r("app.media.img4"),
]
// @State页面与数据进行双向数据绑定,当数据改变时页面刷新。
// showImg是我们要展示的图片,selectImg是对应数组中的图片编号
@State showImg: Resource = this.imgList[0];
@State selectImg: number = 0;
// 通过触摸事件记录滑动前的位置和滑动后的位置判断用户滑动方向
imgStartX: number = 0;
imgEndX: number = 0;

2、按钮样式切换

  • 当按钮被点击时,会执行一个动画过渡效果(animateTo),动画持续时间设定为 300 毫秒,在动画执行过程中,会更新this.selectImg的值为当前点击按钮对应的index,并且相应地更新this.showImgthis.imgList数组中对应索引位置的图片,以此来实现图片切换的效果。
  • 按钮的字体颜色和背景颜色会根据this.selectImg的值与当前索引index是否相等来决定是哪种颜色
Row(){
    ForEach(this.btnList,(item: string, index)=>{
        Button({ type: ButtonType.Normal, stateEffect: true}) {
           Text(item)
              .fontSize(14)
              .fontColor(this.selectImg===index ? Color.White:Color.Green)
        }
        .width('23%')
        .height("100%")
        .borderRadius(4)
        .backgroundColor(this.selectImg===index ? Color.Blue:Color.Gray)
        .onClick(() => {
            // 为切换图片设置动画效果,可以根据需求自定义更好的动画效果,使图片切换更丝滑
            animateTo({duration: 300,}, () => {
                this.selectImg = index;
                this.showImg = this.imgList[this.selectImg];
            })
        })
    })
}
.justifyContent(FlexAlign.SpaceBetween)
.width(260)
.height(30)

3、触摸事件实现滑动切换效果

展示图片,每次只展示选中的那张图片

Image(this.showImg)
   .height(140)
   .width(260)
   .borderRadius(8)

通过不同的触摸事件的类型来保存触摸点相对于应用窗口左上角的X坐标,根据需求需要下面三种

  • 用户按下时记录按下时的位置
  • 滑动后记录滑动后的位置
  • 手指抬起时执行判断,切换图片
.onTouch((event) => {
    // 用户按下时记触摸点相对于应用窗口左上角的X坐标
    if(event.type == TouchType.Down){
        this.imgStartX = event.touches[0].x;
        this.imgEndX = this.imgStartX;	// 结束点也要同时更新以判断用户不滑动的情况
    }
    // 手指按压态在屏幕上移动时触发,保存滑动后触摸点相对于应用窗口左上角的X坐标
    else if(event.type == TouchType.Move){
        this.imgEndX = event.touches[0].x;
    }
    // 手指抬起时触发。
    else if(event.type == TouchType.Up){
        // 如果结束位置在开始位置左边,说明用户是右滑+1,反之左滑-1
        if(this.imgStartX > this.imgEndX){
            this.selectImg = (this.selectImg+1) % 4;
            animateTo({duration: 300}, () => {
                this.showImg = this.imgList[this.selectImg];
            })
        }
    	else if(this.imgStartX < this.imgEndX){
        	this.selectImg = ((this.selectImg-1) % 4 + 4) % 4;
           	animateTo({duration: 300=}, () => {
               this.showImg = this.imgList[this.selectImg];
            })
        }
    }
})

这样就实现了滑动轮播效果,然后如果加上定时器可以实现自动轮播还可以根据需求修改样式,非常的灵活

二、轮播 (Swiper)组件

1、轮播

非常方便这里就直接贴代码拉 (图片数据还是上面)

private swiperController: SwiperController = new SwiperController();

Swiper(this.swiperController){
    ForEach(this.imgList, (item: Resource) => {
       Image(item)
         .height(140)
         .width(260)
         .borderRadius(8)
    })
}
.loop(true)		// 通过loop属性控制是否循环播放,该属性默认值为true
.autoPlay(true)	// Swiper通过设置autoPlay属性,控制是否自动轮播子组件。该属性默认值为false。
.interval(1000)	// autoPlay为true时,会自动切换播放子组件,子组件与子组件之间的播放间隔通过interval属性设置。interval属性默认值为3000,单位毫秒。
属性 类型 说明
loop boolean 通过loop属性控制是否循环播放,该属性默认值为true
autoPlay boolean Swiper通过设置autoPlay属性,控制是否自动轮播子组件。该属性默认值为false。
interval number autoPlay为true时,会自动切换播放子组件,子组件与子组件之间的播放间隔通过interval属性设置。interval属性默认值为3000,单位毫秒。
indicator DotIndicator | DigitIndicator | boolean 通过indicator属性,开发者可以设置导航点相对于Swiper组件上下左右四个方位的位置,同时也可以设置每个导航点的尺寸、颜色、蒙层和被选中导航点的颜色。
vertical boolean 当vertical为true时,表示在垂直方向上进行轮播;为false时,表示在水平方向上进行轮播。vertical默认值为false。
displayCount value: number | string | SwiperAutoFill, swipeByGroup?: boolean 每页显示多个子页面

2、页面切换方式

Swiper支持手指滑动、点击导航点和通过控制器三种方式切换页面。

通过控制器切换页面,定义控制器。

private swiperController: SwiperController = new SwiperController();

通过控制器滑动轮播

 Row(){
     Button('Next')
         .onClick(() => {
         this.swiperController.showNext();   // 通过controller切换到后一页
     })
     Button('Previous')
         .onClick(() => {
         this.swiperController.showPrevious(); // 通过controller切换到前一页
     })
     Button('changeIndex-1')
         .onClick(() => {
         this.swiperController.changeIndex(0);   // 切换到第一张图
     })
 }

三、总结

整体图片和代码
图片滑动和点击切换效果和轮播组件Swiper-鸿蒙开发者社区

@Entry
@Component
struct ImgCarousel {
  btnList: Array<string> = ["图片1","图片2","图片3","图片4"]
  imgList: Array<Resource> = [
    $r("app.media.img1"),
    $r("app.media.img2"),
    $r("app.media.img3"),
    $r("app.media.img4"),
  ]
  @State showImg: Resource = this.imgList[0]
  @State selectImg: number = 0;
  imgStartX: number = 0;
  imgEndX: number = 0;
  private swiperController: SwiperController = new SwiperController();
  build() {
    Column() {
      Swiper(this.swiperController){
        ForEach(this.imgList, (item: Resource) => {
          Image(item)
            .height(140)
            .width(260)
            .borderRadius(8)
        })
      }
      .loop(true)
      .autoPlay(true)	// Swiper通过设置autoPlay属性,控制是否自动轮播子组件。该属性默认值为false。
      .interval(1000)	// autoPlay为true时,会自动切换播放子组件,子组件与子组件之间的播放间隔通过interval属性设置。interval属性默认值为3000,单位毫秒。

      Row(){
        Button('Next')
          .onClick(() => {
            this.swiperController.showNext();   // 通过controller切换到后一页
          })
        Button('Previous')
          .onClick(() => {
            this.swiperController.showPrevious(); // 通过controller切换到前一页
          })
        Button('changeIndex-1')
          .onClick(() => {
            this.swiperController.changeIndex(0);   // 切换到第一张图
          })
      }

      Row(){
        ForEach(this.btnList,(item: string, index)=>{
          Button({ type: ButtonType.Normal, stateEffect: true }) {
            Text(item)
              .fontSize(14)
              .fontColor(this.selectImg===index ? Color.White:Color.Green)
          }
          .width('23%')
          .height("100%")
          .borderRadius(4)
          .backgroundColor(this.selectImg===index ? Color.Blue:Color.Gray)
          .onClick(() => {
            animateTo({
              duration: 300, // 设置动画持续时间
              onFinish: () => {} // 动画结束时执行的操作
            }, () => {
              this.selectImg = index;
              this.showImg = this.imgList[this.selectImg];
            })
          })
        })
      }
      .justifyContent(FlexAlign.SpaceBetween)
      .width(260)
      .height(30)
      .margin({bottom: 12, top: 120})

      Image(this.showImg)
        .height(140)
        .width(260)
        .borderRadius(8)
        .onTouch((event) => {
          if(event.type == TouchType.Down){
            this.imgStartX = event.touches[0].x;
            this.imgEndX = this.imgStartX;
          }
          else if(event.type == TouchType.Move){
            this.imgEndX = event.touches[0].x;
          }
          else if(event.type == TouchType.Up){
            if(this.imgStartX > this.imgEndX){
              this.selectImg = (this.selectImg+1) % 4;
              animateTo({
                duration: 300
              }, () => {
                this.showImg = this.imgList[this.selectImg];
              })
            }
            else if(this.imgStartX < this.imgEndX){
              this.selectImg = ((this.selectImg-1) % 4 + 4) % 4;
              animateTo({
                duration: 300
              }, () => {
                this.showImg = this.imgList[this.selectImg];
              })
            }
          }
        })
    }
    .justifyContent(FlexAlign.Center)
    .height('100%')
    .width('100%')
  }
}
  • 通过以上会发现自定义的方式会更加灵活可以添加更多细节调整。
  • 轮播组件也非常方便,滑动样式也挺好

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2024-12-18 16:23:45修改
4
收藏
回复
举报
1条回复
按时间正序
/
按时间倒序
Crips
Crips

写的太好了!


回复
2024-12-18 19:15:39
回复
    相关推荐