HarmonyOS 鸿蒙Next中如何使用PanGesture实现列表项的滑动删除?

HarmonyOS 鸿蒙Next中如何使用PanGesture实现列表项的滑动删除? 想实现一个类似邮件或待办事项应用的列表,用户可以向左滑动列表中的某一项,滑出后显示一个“删除”按钮。这个滑动操作应该如何监听?

3 回复

使用场景

滑动删除是提升列表操作效率的经典交互模式。比如消息列表:左滑删除一条消息;待办事项:左滑标记完成或删除任务;文件管理器:左滑删除或分享文件等都是其经典的使用交互场景。

实现效果

cke_463.png

完成思路

一、封装与复用:将滑动逻辑封装在SwipeItem组件中,使其成为一个可复用的UI单元。父组件只需关心数据和删除逻辑,无需关心滑动实现细节。

二、状态是桥梁:@State translateX是连接手势事件和UI视图的桥梁。手势改变状态,状态驱动UI更新。

三、@BuilderParam的妙用:使用@BuilderParam让SwipeItem组件更加灵活,父组件可以自由定义列表项内部的具体内容,实现了高内聚低耦合。

四、动画是点睛之笔:在onActionEnd中使用animateTo处理“收尾”工作,无论是自动滑出还是平滑回弹,都极大地提升了精致感。

完整代码

@Component
export struct SwipeItem {
  // 子组件接收一个删除回调函数
  onDelete?: () => void;
  // 子组件接收要显示的内容,使用构建器函数 [@BuilderParam](/user/BuilderParam)
  [@BuilderParam](/user/BuilderParam) content?: () => void;

  // 1. 状态变量:控制列表项的水平偏移
  [@State](/user/State) translateX: number = 0;
  // 定义删除按钮的宽度
  private readonly DELETE_BUTTON_WIDTH: number = 80;
  // 定义触发删除的阈值
  private readonly DELETE_THRESHOLD: number = -100;

  build() {
    Stack({ alignContent: Alignment.End }) {
      // 删除按钮(在底层)
      Button('删除')
        .width(this.DELETE_BUTTON_WIDTH)
        // .height('100%')
        .backgroundColor(Color.Red)
        .fontColor(Color.White)
        .onClick(() => {
          // 点击删除按钮时,执行删除动画并调用回调
          animateTo({ duration: 300 }, () => {
            this.translateX = -this.DELETE_BUTTON_WIDTH;
          });
          if (this.onDelete) {
            this.onDelete();
          }
        })

      // 列表项主内容(在顶层)
      Row() {
        // 使用 [@BuilderParam](/user/BuilderParam) 渲染父组件传入的内容
        if (this.content) {
          this.content()
        }
      }
      .width('100%')
      .height(60)
      .backgroundColor('#FFFFFF')
      .borderRadius(8)
      // 2. 将位移与状态变量绑定
      .translate({ x: this.translateX })
      // 3. 绑定滑动手势
      .gesture(
        PanGesture({ fingers: 1, direction: PanDirection.Horizontal })
          .onActionUpdate((event: GestureEvent) => {
            // 实时更新偏移量,限制只能向左滑
            this.translateX = Math.max(event.offsetX, -this.DELETE_BUTTON_WIDTH);
          })
          .onActionEnd(() => {
            // 4. 手势结束时的判断与动画
            if (this.translateX < this.DELETE_THRESHOLD) {
              // 如果滑动距离超过阈值,则自动滑到删除按钮位置
              animateTo({ duration: 200, curve: Curve.EaseOut }, () => {
                this.translateX = -this.DELETE_BUTTON_WIDTH;
              });
            } else {
              // 否则,回弹到原位
              animateTo({ duration: 200, curve: Curve.EaseOut }, () => {
                this.translateX = 0;
              });
            }
          })
      )
    }
    .width('100%')
    .margin({ bottom: 8 })
  }
}

// 文件名: Index.ets

import { SwipeItem } from './SwipeItem'; // 导入子组件

@Entry
@Component
struct Index {
  // 父组件管理数据源
  [@State](/user/State) messageList: string[] = [
    '鸿蒙OS 5 正式发布',
    'ArkTS 成为第一开发语言',
    '元服务生态蓬勃发展',
    '滑动删除交互体验极佳',
    '学习鸿蒙,正逢其时'
  ];

  build() {
    Column() {
      Text('消息列表 (左滑删除)')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 20, bottom: 20 })

      List({ space: 8 }) {
        ForEach(this.messageList, (item: string, index: number) => {
          ListItem() {
            // 5. 使用自定义的 SwipeItem 组件
            SwipeItem({
              // 传入删除逻辑的回调函数
              onDelete: () => {
                this.messageList.splice(index, 1);
              },
              // 使用 @Builder 传入自定义内容
              content: () => {
                this.ItemContent(item)
              }
            })
          }
        }, (item: string) => item)
      }
      .layoutWeight(1)
      .width('90%')
      .padding({ left: 10, right: 10 })
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F1F3F5')
  }

  // 定义列表项内容的构建器函数
  @Builder ItemContent(text: string) {
    Text(text)
      .fontSize(18)
      .fontColor('#333333')
      .margin({ left: 15 })
  }
}

更多关于HarmonyOS 鸿蒙Next中如何使用PanGesture实现列表项的滑动删除?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,使用PanGesture实现列表项滑动删除的步骤如下:

  1. 为列表项组件添加PanGesture手势识别器。
  2. 监听PanGesture的onActionUpdate事件,获取手指移动距离(offsetX)。
  3. 根据offsetX动态设置列表项的平移(translate)属性,实现跟随手指滑动的效果。
  4. 在onActionEnd事件中判断滑动距离,若超过阈值则触发删除操作,否则回弹复位。
  5. 结合条件渲染或状态变量控制删除按钮的显示与隐藏。

关键代码涉及手势事件处理和组件属性绑定。

在HarmonyOS Next中,可以使用PanGesture配合RowList组件实现滑动删除效果。核心思路是为列表项容器添加PanGesture手势监听,通过手势偏移量动态控制内容布局。

以下是关键实现步骤:

  1. 布局结构:使用Row组件作为列表项容器,内部包含两个子组件:主内容区域(如文本)和隐藏的删除按钮。通过justifyContentalignItems控制布局。

  2. 手势监听:为主内容区域添加PanGesture

    .gesture(
      PanGesture()
        .onActionUpdate((event: GestureEvent) => {
          // 根据event.offsetX更新偏移量
        })
        .onActionEnd(() => {
          // 判断滑动距离,决定是否展开/收起删除按钮
        })
    )
    
  3. 状态管理:使用@State装饰器定义偏移量变量,根据手势的offsetX动态更新。通过translateposition属性实现滑动动画。

  4. 滑动阈值:在onActionEnd回调中判断滑动距离,若超过阈值则固定显示删除按钮,否则复位。

  5. 删除操作:为删除按钮绑定点击事件,通过@Link或事件回调通知父组件删除对应数据项。

注意:在List中使用时,需确保每个列表项的偏移状态独立管理,避免联动。可结合ListItemSwipeAction组件简化实现,后者为滑动操作提供了封装好的布局和动画。

回到顶部