从零开始纯血鸿蒙天气预报-城市管理页面(2)

167 阅读1分钟

易得天气

完成了城市列表的拖拽排序功能

给item添加手势

.gesture(
  GestureGroup(GestureMode.Sequence,
    LongPressGesture()
      .onAction(() => {
        if (this.toEditMode) {
          this.toEditMode(this.cityData)
        }
        this.onLongPress()
      }),
    PanGesture()
      .onActionUpdate((event: GestureEvent) => {
        this.onItemMove(event.offsetY)
      })
      .onActionEnd(() => {
        this.onItemDrop()
      })
  ).onCancel(() => {
    if (!this.isLongPress) {
      return;
    }
    this.onItemDrop()
  })
)

给拖拽图片添加手势

Image($r('app.media.ic_menu_icon'))
  .width(24)
  .height(24)
  .colorFilter(ColorUtils.translateColor($r('app.color.special_white')))
  .draggable(false)
  .gesture(
    GestureGroup(GestureMode.Sequence,
      PanGesture()
        .onActionStart(() => {
          console.log('onActionStart')
          this.onMenuPress()
        })
        .onActionUpdate((event: GestureEvent) => {
          this.onItemMove(event.offsetY)
        })
        .onActionEnd(() => {
          this.onItemDrop()
        })
    ).onCancel(() => {
      if (!this.isMenuPress) {
        return;
      }
      this.onItemDrop()
    })
  )

手势监听调用的方法

按下手势监听:

onLongPress() {
  const enable = this.onReorderStart ? this.onReorderStart() : true
  if (enable) {
    this.zIndexValue = 1
    this.isLongPress = true
    this.dragRefOffset = 0
  }
}

onMenuPress() {
  const enable = this.onReorderStart ? this.onReorderStart() : true
  if (enable) {
    this.zIndexValue = 1
    this.isMenuPress = true
    this.dragRefOffset = 0
  }
}

移动手势监听:

onItemMove(offsetY: number) {
  if (!this.isLongPress && !this.isMenuPress) {
    return
  }
  this.offsetY = offsetY - this.dragRefOffset
  const direction = this.offsetY > 0 ? 1 : -1
  if (Math.abs(this.offsetY) > ITEM_HEIGHT / 2) {
    if (this.index === 0 && direction === -1) {
      return
    }
    if (this.index === this.length - 1 && direction === 1) {
      return
    }
    // 目标位置索引
    const target = this.index + direction
    if (this.beforeChange) {
      if (this.beforeChange(target)) {
        return
      }
    }
    animateTo({ curve: Curve.Friction, duration: 300 }, () => {
      this.offsetY -= direction * ITEM_HEIGHT
      this.dragRefOffset += direction * ITEM_HEIGHT
      if (target !== -1 && target <= this.length) {
        console.log('changeItem index = ' + this.index + ' target = ' + target)
        if (this.onChangeItem) {
          this.onChangeItem(this.index, target)
        }
      }
    })
  }
}

手势结束监听:

onItemDrop() {
  if (this.isLongPress || this.isMenuPress) {
    this.isLongPress = false
    this.isMenuPress = false
    this.dragRefOffset = 0;
    if (this.onReorderDone) {
      this.onReorderDone()
    }
    animateTo({
      curve: curves.interpolatingSpring(14, 1, 170, 17), onFinish: () => {
        this.zIndexValue = 0
      }
    }, () => {
      this.offsetY = 0
    })
  }
}

CityManagerItem

CityManagerItem({
  cityData: cityData,
  index: this.addedCityData?.findIndex(it => it.cityid == cityData.cityid),
  length: this.addedCityData?.length,
  isEditMode: this.cityManagerVm.isEditMode,
  isSelected: this.cityManagerVm.isSelected(cityData),
  toEditMode: (cityData) => {
    // 编辑模式
    this.cityManagerVm.toEditMode(this.addedCityData?.length ?? 0, cityData)
  },
  onItemClick: (cityData) => {
    if (this.cityManagerVm.isEditMode) {
      // 编辑模式下选中item
      this.cityManagerVm.selected(cityData)
    }
  },
  onRemoveItem: (cityData) => {
    // 删除item
    this.cityManagerVm.removeItem(cityData, this.addedCityData)
  },
  onReorderStart: () => {
    // 开始拖拽排序的回调
    // 返回值为true表示可以拖拽
    // 此处表示不是定位城市才可进行拖拽排序
    this.cityManagerVm.deleteButtonEnable = false
    return !cityData.isLocationCity
  },
  beforeChange: (target) => {
    // 如果返回值是true 表示不能交换item位置
    const targetCityData = this.addedCityData?.[target]
    return targetCityData?.isLocationCity ?? false
  },
  onChangeItem: (from, to) => {
    // 当item交换位置时 列表数据需要交换
    if (ArrayUtil.isNotEmpty(this.addedCityData)) {
      const tmp = this.addedCityData?.splice(from, 1)
      this.addedCityData?.splice(to, 0, tmp![0])
    }
  },
  onReorderDone: async () => {
    // 拖拽排序结束的回调
    this.cityManagerVm.deleteButtonEnable = true
    const currentCityIdList =
      this.addedCityData!.map(it => it.isLocationCity ? Constants.LOCATION_CITY_ID : it.cityid ?? '')
    await PreferencesUtil.put(Constants.CURRENT_CITY_ID_LIST, currentCityIdList)
  }
})

效果图

2025-03-04 15.05.12.gif