HarmonyOS 鸿蒙Next 如何实现List中 item 左边 checkbox 滑动多选

发布于 1周前 作者 nodeper 来自 鸿蒙OS

HarmonyOS 鸿蒙Next 如何实现List中 item 左边 checkbox 滑动多选

滑动效果如下

https://developer.huawei.com/consumer/cn/doc/design-guides-V1/select-box-0000001156786993-V1

这里的滑动多选,我没找到代码实现文档。

这种效果需要如何实现。


更多关于HarmonyOS 鸿蒙Next 如何实现List中 item 左边 checkbox 滑动多选的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

1、通过onAreaChange()方法记录ListItem的area信息,HSFileDataModel.area;
2、List组件添加onTouch()事件;
3、手势在List组件内滑动时,计算选中的ListItem。
计算逻辑:getOnTouchItem()方法中的,(windowX >= x) && (windowX <= x + width) && (windowY >= y) && (windowY <= y + height)。windowX、windowY触摸位置在窗口中的x、y坐标,area.globalPosition.x、area.globalPosition.y目标元素左上角相对页面左上角的坐标
代码如下:
TimeLineView.ets:

[@Builder](/user/Builder)
private ListView() {
    List({ scroller: this.scroller }) {
      ...
    }
    .onTouch((event: TouchEvent) => {
      if (!this.isOnTouchInParent(event)) {
        return
      }
      // 触摸按下,记录按下的item
      if (event.type === TouchType.Down) {
        console.log(`TouchEvent:::::::::::::Down::isOnTouchInParent: ${event.touches[0].windowX}, ${event.touches[0].windowX}`)
        const imageItem = this.getOnTouchItem(event)
        if (imageItem) {
          console.log(`TouchEvent:::::::::::::Down::${imageItem.index}`)
          this.tempImage = imageItem
        }
      }
      //     触摸抬起,清空tempImage
      if (event.type === TouchType.Up && this.isLongPress) {
        console.log(`TouchEvent:::::::::::::Up::isOnTouchInParent: ${event.touches[0].windowX}, ${event.touches[0].windowX}`)
        // const imageItem = this.getOnTouchItem(event)
        this.tempImage = null
        // 遍历dataSource,设置单次操作选中项
        const data = this.dataSource.getFullData()
        for (const item of data) {
          for (const imageItem of item.fileItem || []) {
            if (imageItem.tempSelected) {
              imageItem.isSelected = true
              // 重置
              imageItem.tempSelected = false
            }
          }
        }
        console.log(`TouchEvent:::::::::::::Up::isOnTouchInParent:: ${JSON.stringify(data[0].fileItem)}`)
      }
      // 滑动时,计算起点-终点,并将范围内的item修改为selected状态
      if (event.type === TouchType.Move && this.isLongPress) {
        console.log(`TouchEvent:::::::::::::Move::isOnTouchInParent: ${event.touches[0].windowX}, ${event.touches[0].windowX}`)
        // 起点不存在
        if (!this.tempImage) {
          return
        }
        const imageItem = this.getOnTouchItem(event)
        // 若起点-终点item不一致
        if (imageItem && imageItem.index !== this.tempImage.index) {
          const start = Math.min(imageItem.index, this.tempImage.index)
          const end = Math.max(imageItem.index, this.tempImage.index)
          // 设置范围选中
          const data = this.dataSource.getFullData()
          for (const item of data) {
            for (const imageItem of item.fileItem || []) {
              if (imageItem.index >= start && imageItem.index <= end) {
              // 增加临时选中变量 tempSelected,在单次滑动多选操作中,记录tempSelected,在TouchType.Up中修改为实际选中isSelected
                imageItem.tempSelected = true
              } else {
                imageItem.tempSelected = false
              }
            }
          }
        }
      }
    })
}
// 判断滑动是否处于父容器List组件内
isOnTouchInParent(event: TouchEvent): boolean {
    if (event.touches[0].x > 0 && event.touches[0].y > 0) {
      return true
    }
    return false
}
getOnTouchItem(event: TouchEvent): HSFileDataModel | null {
    const windowX = event.touches[0].windowX
    const windowY = event.touches[0].windowY
    const data = this.dataSource.getFullData()
    for (const item of data) {
      const imageItem = (item.fileItem || []).find(image => {
        const area = image.area
        if (!area || !area.globalPosition.x || !area.globalPosition.y) {
          return false
        }
        const x = area.globalPosition.x as number
        const y = area.globalPosition.y as number
        const width = area.width as number
        const height = area.height as number
        // 判断是否为触摸item
        return (windowX >= x) && (windowX <= x + width) && (windowY >= y) && (windowY <= y + height)
      })
      if (imageItem) {
        console.log(`TouchEvent:::::::::::::match::${imageItem.index}`)
        console.log(`TouchEvent:::::::::::::Down::touchXY::${windowX}::${windowY}`)
        console.log(`TouchEvent:::::::::::::Down::imagePoint::${imageItem.area?.globalPosition.x}::${imageItem.area?.globalPosition.y}`)
        return imageItem
      }
    }
    return null;
}

ListItemView.ets:

Column() {
    Stack({ alignContent: Alignment.TopEnd }) {
        ...
    }
    .onAppear(() => {
        // this.fileItem.isSelected = this.itemSelectMap.get(this.fileItem.index)!
    })
}
.onAreaChange((oldValue: Area, newValue: Area) => {
    // 保存image的坐标信息
    this.fileItem.area = newValue
})

HSFileDataModel.ets:

export class HSFileDataModel {
    ...
    tempSelected: boolean = false // 临时选中
    area?: Area
}

更多关于HarmonyOS 鸿蒙Next 如何实现List中 item 左边 checkbox 滑动多选的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


可以尝试参考以下demo进行开发,实现了text组件的滑动多选。

[@Entry](/user/Entry)
[@Component](/user/Component)
struct Second {
  [@State](/user/State) displayMsg: string = 'Hello World'
  private color_list1 = [Color.Red,Color.White,Color.Blue,Color.Gray,Color.Orange,Color.Pink,Color.Red,Color.Yellow]
  private text_list1 = ['A', 'B', 'C', 'D', 'E']
  private textTemp = ''
  private childWidth:number = 60
  private childHeight:number = 60
  isOnTouchInParent(event: TouchEvent) :boolean{
    if (event.touches[0].x>0 &&event.touches[0].x<=this.childWidth*this.text_list1.length && event.touches[0].y>0&&event.touches[0].y<this.childWidth) {
      return true;
    }
    return false
  }
  getChildText(event: TouchEvent) :string{
    return this.text_list1[Math.floor(event.touches[0].x/this.childWidth)]
  }
  build() {
    Column() {
      //
      Column() {
        Row() {
        }.height('10%')
        //ABCDE Text组件行,采用gesture()事件方法 滑动
        Row() {
          ForEach(this.text_list1, (value: string,idx:number) => {
            Text(value)
              .width(this.childWidth)
              .height(this.childHeight)
              .fontSize(20)
              .backgroundColor(this.color_list1[Math.floor(8*Math.random())])
              .textAlign(TextAlign.Center)
          })
        }
        .height(this.childHeight)
        .width(this.childWidth*this.text_list1.length)
        .onTouch((event: TouchEvent) => {
          if (event.type === TouchType.Down) {
            if (this.isOnTouchInParent(event)) {
              this.displayMsg = '#<'
              this.textTemp = this.getChildText(event)
              this.displayMsg = this.displayMsg + this.textTemp
            }
          }
          if (event.type === TouchType.Up) {
            if (this.isOnTouchInParent(event)) {
              this.displayMsg = this.displayMsg + '>'
              this.textTemp = ''
            }
          }
          if (event.type === TouchType.Move) {
            if (this.isOnTouchInParent(event)) {
              if (this.textTemp === this.getChildText(event)) {
              }else {
                this.textTemp = this.getChildText(event)
                this.displayMsg = this.displayMsg + this.textTemp
              }
            }
          }
        })
        Row() {
          Text('测试可删除').gesture(
            SwipeGesture().onAction((event:GestureEvent)=>{
            })
          )
        }.height('10%')
      }.height('70%')
      //
      Column() {
        //输出显示区域
        Row() {
          Text(this.displayMsg).width(800).height(200).backgroundColor(Color.Gray).fontSize(30)
        }.align(Alignment.Start).height('20%')
      }.height('30%')
    }
  }
}<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

在HarmonyOS鸿蒙Next系统中,实现List中item左边checkbox的滑动多选功能,可以通过以下方式实现:

  1. UI布局:在XML布局文件中,为List的每个item定义一个Checkbox组件,并将其放置在左侧。确保Checkbox的ID和事件绑定正确。

  2. 数据绑定:为每个item的数据模型添加一个布尔类型的字段,用于表示Checkbox的选中状态。在数据绑定时,将该字段与Checkbox的选中状态绑定。

  3. 滑动监听:为List添加滑动监听事件,当用户滑动并选中或取消选中多个item时,通过监听事件更新数据模型中对应item的选中状态。

  4. 批量操作:如果需要实现全选、全不选或反选功能,可以在事件处理函数中遍历数据模型,批量更新Checkbox的选中状态。

  5. UI刷新:每次更新数据模型的选中状态后,确保UI能够即时刷新,以反映最新的选中情况。

  6. 状态保存:在适当的时候,如用户离开页面或应用进入后台时,保存当前所有Checkbox的选中状态,以便用户再次进入时能够恢复。

以上步骤概述了在HarmonyOS鸿蒙Next系统中实现List中item左边checkbox滑动多选的基本方法。如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部