目录

左右滑动页面切换卡顿无动效

问题现象

左右滑动页面切换时卡顿,无页面切换过渡动画效果。

背景知识

问题定位

左右滑动页面切换时卡顿无过渡动效,可先确认采用了什么组件显示页面内容。使用ArkUI Inspector抓取页面布局,如下图可看到Swiper组件,可在右侧属性栏中查看curve和duration属性值确定页面切换的动画曲线和时长,可看到动画曲线为线性动画,而动画时长为50毫秒,可知动画时长过短,造成了卡顿、无动效的现象。

除了使用ArkUI Inspector工具,可以在日志中搜索Swiper start property animation with|Swiper finish property animation with,查看两个日志打印的时间间隔来确定Swiper组件的切换动画时长。

08-29 10:54:57.982   18874-18874  C03915/com.exa...ion/AceSwiper ...  I     Swiper start property animation ...
08-29 10:54:58.036   18874-18874  C03915/com.exa...ion/AceSwiper ...  I     Swiper finish property animation ...

分析结论

Swiper组件设置的切换动画时长较短,导致页面切换卡顿无动效。

修改建议

设置较长的切换动画时长。

import { image } from '@kit.ImageKit';

class SwiperItemData {
  image: image.PixelMap | ResourceStr | DrawableDescriptor = ''; // 图片

  constructor(image: image.PixelMap | ResourceStr | DrawableDescriptor) {
    this.image = image;
  }
}

class SwiperItemDataSource implements IDataSource {
  private dataArray: SwiperItemData[] = [];

  private listeners: DataChangeListener[] = [];

  totalCount(): number {
    return this.dataArray.length;
  }

  getData(index: number): SwiperItemData {
    return this.dataArray[index];
  }

  addData(data: SwiperItemData): void {
    this.dataArray.push(data);
    this.notifyDataAdd(this.dataArray.length - 1);
  }

  registerDataChangeListener(listener: DataChangeListener): void {
    this.listeners.push(listener);
  }

  unregisterDataChangeListener(listener: DataChangeListener): void {
    let index = this.listeners.indexOf(listener);
    if (index >= 0) {
      this.listeners.splice(index, 1);
    }
  }

  notifyDataAdd(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataAdd(index);
    });
  }
}

@Entry
@Component
struct ImageSwiperPage {
  private swiperController: SwiperController = new SwiperController();

  private swiperItemDataSource: SwiperItemDataSource = new SwiperItemDataSource();

  initPageData(): void {
    // 测试需要替换成可引用到的资源
    let data1 = new SwiperItemData($r('app.media.picture1'));
    let data2 = new SwiperItemData($r('app.media.picture2'));
    let data3 = new SwiperItemData($r('app.media.picture3'));
    let data4 = new SwiperItemData($r('app.media.picture4'));
    let data5 = new SwiperItemData($r('app.media.picture5'));
    let data6 = new SwiperItemData($r('app.media.picture6'));
    this.swiperItemDataSource.addData(data1);
    this.swiperItemDataSource.addData(data2);
    this.swiperItemDataSource.addData(data3);
    this.swiperItemDataSource.addData(data4);
    this.swiperItemDataSource.addData(data5);
    this.swiperItemDataSource.addData(data6);
  }

  aboutToAppear(): void {
    this.initPageData();
  }

  build() {
    Swiper(this.swiperController) {
      LazyForEach(this.swiperItemDataSource, (item: SwiperItemData) => {
        Image(item.image)
          .width('100%')
          .height('100%')
      })
    }
    .duration(300) // 切换动画时长设置成300ms
    .curve(Curve.Linear)
    .autoPlay(false)
    .cachedCount(2)
    .loop(false)
    .indicator(false)
    .height('100%')
    .width('100%')
  }
}