跳到主要内容

手势卡顿或者不生效

现象描述

地图页面操作手势卡顿或者不生效。

可能原因

  1. 手势遮盖或者手势冲突。

    • 手势遮盖:地图组件的上层存在没有做手势穿透的组件。
    • 手势冲突:以Swiper容器组件中使用地图组件为例,Swiper容器组件和地图组件手势会存在冲突。
  2. 主线程阻塞。

    应用主线程处理大批量逻辑时,存在主线程阻塞,此时进行地图手势操作,手势应答会变慢甚至手势响应失败。

处理步骤

  1. 手势遮盖或者手势冲突。

    • 手势遮盖:参考触摸测试控制做手势穿透。

    • 手势冲突:以Swiper容器组件和地图组件手势存在冲突为例,解决方案参考如下代码:

      import { AsyncCallback, BusinessError } from '@kit.BasicServicesKit';
      import { map, mapCommon, MapComponent } from '@kit.MapKit';

      class MyDataSource implements IDataSource {
      private list: number[] = [];

      constructor(list: number[]) {
      this.list = list;
      }

      // 获取数组长度
      totalCount(): number {
      return this.list.length;
      }

      // 根据索引获取数据
      getData(index: number): number {
      return this.list[index];
      }

      // 注册数据变化监听器
      registerDataChangeListener(listener: DataChangeListener): void {
      }

      // 取消注册数据变化监听器
      unregisterDataChangeListener(listener: DataChangeListener): void {
      }
      }

      @Entry
      @Component
      struct SwiperExample {
      private swiperController: SwiperController = new SwiperController();
      private data: MyDataSource = new MyDataSource([]);
      private mapOptions?: mapCommon.MapOptions;
      private callback?: AsyncCallback<map.MapComponentController>;
      private mapController?: map.MapComponentController;
      private mapEventManager?: map.MapEventManager;
      @State mapPositionX: number = 0;
      @State mapPositionY: number = 0;
      @State mapHeight: number = 0;
      @State mapWidth: number = 0;
      @State index: number = 0;

      // 判断坐标是否在地图矩形内
      isMap(event: TouchEvent) {
      if (event.changedTouches[0].displayX > this.mapPositionX
      && event.changedTouches[0].displayX < this.mapPositionX + this.mapWidth
      && event.changedTouches[0].displayY > this.mapPositionY
      && event.changedTouches[0].displayY < this.mapPositionY + this.mapHeight) {
      return true;
      }
      return false;
      }

      aboutToAppear(): void {
      let list: number[] = [];
      for (let i = 1; i <= 10; i++) {
      list.push(i);
      }
      this.data = new MyDataSource(list);

      this.mapOptions = {
      position: {
      target: {
      latitude: 31.98441025,
      longitude: 118.766253
      },
      zoom: 10,
      tilt: 10,
      bearing: 90
      },
      scaleControlsEnabled: true
      }

      this.callback = async (err, mapController) => {
      if (!err) {
      this.mapController = mapController;
      this.mapEventManager = this.mapController.getEventManager();
      let callback = () => {
      console.info(`on-mapLoad`);
      };
      this.mapEventManager.on("mapLoad", callback);
      } else {
      console.error(`Failed to initialize the map, code is:${err.code}, message is ${err.message}`);
      }
      }
      }

      build() {
      Column({ space: 5 }) {
      Swiper(this.swiperController) {
      LazyForEach(this.data, (item: string) => {
      if (item == "3") {
      Column() {
      Text(item.toString())
      .width('90%')
      .height(160)
      .backgroundColor(0xAFEEEE)
      .textAlign(TextAlign.Center)
      .fontSize(30)
      MapComponent({ mapOptions: this.mapOptions, mapCallback: this.callback })
      // 获取MapComponent的位置和长宽
      .width('100%')
      .height('65%')
      .onAreaChange((_oldValue: Area, newValue: Area) => {
      try {
      if (newValue.globalPosition.x !== undefined && newValue.globalPosition.y !== undefined) {
      this.mapPositionX = Number(newValue.globalPosition.x);
      this.mapPositionY = Number(newValue.globalPosition.y);
      this.mapHeight = Number(newValue.height);
      this.mapWidth = Number(newValue.width);
      }
      } catch (error) {
      let e: BusinessError = error as BusinessError;
      console.error("onAreaChange error code:" + e.code + "message:" + e.message);
      }
      })
      }.height("100%")
      } else {
      Text(item.toString())
      .width('90%')
      .height(160)
      .backgroundColor(0xAFEEEE)
      .textAlign(TextAlign.Center)
      .fontSize(30)
      }
      }, (item: string) => item)
      }
      // 手势判断 当index为存在地图页面且点击在地图矩形内时为HitTestMode.None(不响应Swiper手势,响应子组件手势)
      .onTouchIntercept((event: TouchEvent) => {
      if (this.index === 2 && this.isMap(event)) {
      return HitTestMode.None;
      }
      return HitTestMode.Transparent;
      })
      .cachedCount(2)
      .index(1)
      .loop(true)
      .itemSpace(0)
      // 设置圆点导航点样式
      .indicator(
      new DotIndicator()
      .itemWidth(15)
      .itemHeight(15)
      .selectedItemWidth(15)
      .selectedItemHeight(15)
      .color(Color.Gray)
      .selectedColor(Color.Blue))
      .displayArrow({
      // 设置导航点箭头样式
      showBackground: true,
      isSidebarMiddle: true,
      backgroundSize: 24,
      backgroundColor: Color.White,
      arrowSize: 18,
      arrowColor: Color.Blue
      }, false)
      .curve(Curve.Linear)
      .onChange((index: number) => {
      this.index = index;
      })
      .onGestureSwipe((index: number, extraInfo: SwiperAnimationEvent) => {
      console.info("index: " + index);
      console.info("current offset: " + extraInfo.currentOffset);
      })

      Row({ space: 12 }) {
      Button('showNext')
      .onClick(() => {
      this.swiperController.showNext();
      })
      Button('showPrevious')
      .onClick(() => {
      this.swiperController.showPrevious();
      })
      }.margin(5)
      }.width('100%')
      .margin({ top: 5 })
      }
      }
  2. 主线程阻塞。

    请分析应用的业务逻辑,将复杂逻辑放到子线程中处理。