HarmonyOS7 侧滑删除要给撤销机会:别让列表操作变成惊吓

基于文章标题《HarmonyOS7 侧滑删除要给撤销机会:别让列表操作变成惊吓》,绘制一张手绘笔记风

前言

邮件、通知、收藏夹这类列表,很容易做出“左滑一下就删除”的爽感,也很容易让用户后悔。手指一滑,内容没了,如果页面没有恢复入口,用户会立刻紧张。

我的习惯是:只要删除会影响用户数据,就给一次撤销机会。它不一定要复杂,但必须存在。

HarmonyOS7 里可以用 ListItem.swipeAction() 做侧滑入口。真正要想清楚的是删除之后的状态流转:先从列表移除,再保留最近删除项,给用户一个可见的撤销入口。

为什么这个问题经常被写乱

侧滑删除要给撤销机会 这类内容很容易被写成“代码能跑就算讲完了”,但对初学者来说,这恰恰是最不够的地方。真正让人卡住的,往往不是某个组件名记不住,而是不知道这段代码为什么要这样拆、状态为什么要这样放、以后需求变化时应该从哪里改。

所以这篇文章不只想给你一个能跑的例子,更想把背后的判断过程讲清楚。你只要把这个判断过程吃透,后面自己改页面、补需求、查问题时,心里会稳很多。

删除不是一个动作,是一段流程

侧滑删除看起来只有一下,其实至少包含四个阶段。

阶段页面表现状态变化
侧滑露出删除按钮不改数据
点击删除项目从列表消失写入 lastDeleted
点击撤销项目回到原位置清空 lastDeleted
再删一条新记录覆盖旧记录只保留最近一次

我不建议普通列表一次保留很多撤销记录。移动端页面空间有限,“救回最近一次误删”已经能覆盖大多数场景。

状态要保存 item,也要保存位置

只保存被删的数据还不够。撤销时如果只能追加到末尾,用户会觉得列表顺序乱了。更好的做法是同时保存原始 index

| 字段 | 作用 |

基于文章中“删除不是一个动作,是一段流程”这一段,绘制一张手绘流程图,表现 HarmonyOS7 侧

|—|—|
| mails | 当前列表数据 |
| lastDeleted.item | 最近被删除的邮件 |
| lastDeleted.index | 删除前所在位置 |
| notice | 顶部提示文案 |

删除时用 filter 生成新数组,撤销时用 splice 插回原位置。代码不复杂,但状态语义很清楚。

ArkUI/ArkTS 完整示例

interface MailItem42 {
  id: number
  sender: string
  subject: string
  time: string
}

interface DeletedMail42 {
  item: MailItem42
  index: number
}

@Entry
@Component
struct SwipeDeleteMailPage {
  @State mails: MailItem42[] = [
    { id: 101, sender: '系统通知', subject: '你的设备登录提醒', time: '09:30' },
    { id: 102, sender: '账单助手', subject: '本月云空间扣费成功', time: '昨天' },
    { id: 103, sender: '项目成员', subject: '评审会议改到下午三点', time: '周一' }
  ]
  @State lastDeleted: DeletedMail42 | null = null
  @State notice: string = '左滑邮件可以删除'

  private deleteMail(item: MailItem42): void {
    const index: number = this.mails.findIndex((mail: MailItem42) => mail.id === item.id)
    if (index < 0) {
      return
    }
    this.lastDeleted = { item: item, index: index }
    this.mails = this.mails.filter((mail: MailItem42) => mail.id !== item.id)
    this.notice = `已删除:${item.subject}`
  }

  private undoDelete(): void {
    const deleted: DeletedMail42 | null = this.lastDeleted
    if (deleted === null) {
      return
    }
    const next: MailItem42[] = this.mails.slice()
    const insertIndex: number = Math.min(deleted.index, next.length)
    next.splice(insertIndex, 0, deleted.item)
    this.mails = next
    this.lastDeleted = null
    this.notice = `已恢复:${deleted.item.subject}`
  }

  @Builder
  DeleteButton(item: MailItem42) {
    Button('删除')
      .fontColor(Color.White)
      .backgroundColor('#E5484D')
      .height('100%')
      .onClick(() => {
        this.deleteMail(item)
      })
  }

  build() {
    Column({ space: 12 }) {
      Text('收件箱')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .width('100%')

      Text(this.notice)
        .fontSize(13)
        .fontColor('#666666')
        .width('100%')

      List({ space: 8 }) {
        ForEach(this.mails, (item: MailItem42) => {
          ListItem() {
            Column({ space: 6 }) {
              Row() {
                Text(item.sender).fontSize(16).fontWeight(FontWeight.Medium)
                Blank()
                Text(item.time).fontSize(12).fontColor('#888888')
              }
              Text(item.subject).fontSize(14).fontColor('#555555')
            }
            .padding(14)
            .backgroundColor(Color.White)
            .borderRadius(8)
          }
          .swipeAction({ end: this.DeleteButton(item) })
        }, (item: MailItem42) => item.id.toString())
      }
      .layoutWeight(1)

      if (this.lastDeleted !== null) {
        Row() {
          Text('已删除一封邮件')
            .fontSize(14)
            .fontColor(Color.White)
          Blank()
          Button('撤销')
            .height(32)
            .onClick(() => {
              this.undoDelete()
            })
        }
        .padding(12)
        .backgroundColor('#303133')
        .borderRadius(8)
      }
    }
    .padding(16)
    .backgroundColor('#F5F7FA')
    .height('100%')
  }
}

基于文章中“状态要保存 item,也要保存位置”这一段,绘制一张手绘框架图,展示 HarmonyOS

把关键代码一段段拆开

DeletedMail42 保存原始位置。 撤销不是简单地把项目加回来,而是尽量回到用户刚才看到的位置。用户的视觉记忆还在,位置恢复会让操作更可信。

删除时重新赋值 this.mailsfilter 生成新数组,状态变化更直观。不要直接依赖数组下标删除,因为列表后续排序、筛选以后很容易删错。

swipeAction 只提供入口。 侧滑按钮不适合承载复杂确认流程。普通邮件删除可以“删后撤销”;账号注销、永久清空这类高风险动作,才需要更重的确认。

撤销策略怎么选

策略适合场景注意点
只撤销最近一条邮件、通知、浏览记录状态简单,页面占用少
批量撤销文件管理、批量清理要保存多条记录和顺序
删除前二次确认账户注销、永久删除交互更重,但风险更低
软删除后后台同步服务端数据要处理接口失败和恢复

普通业务先做“最近一条撤销”就够实用。它能覆盖误触,又不会让页面底部堆满提示条。

容易踩坑的地方

  1. 只保存 item 不保存 index 撤销后只能追加到末尾,顺序会让用户困惑。
  2. 删除后立刻永久提交。 服务端已经彻底删掉,再撤销就会变得很复杂。可以先软删除,或延迟同步。
  3. 多个撤销条同时出现。 手机空间不够,用户也很难判断每个撤销对应哪条数据。
  4. 撤销按钮太小。 删除是高风险动作,恢复入口要足够明显。

小结

侧滑删除的重点不是手势,而是错误恢复。HarmonyOS7 的 ArkUI 能很快搭出交互,但产品体验要靠状态设计兜住。给一次撤销机会,列表才不会让用户紧张。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值