HarmonyOS ArkUI之聊天列表滑动删除(TS)

开发 前端 OpenHarmony
本项目基于ArkUI中TS扩展的声明式开发范式,本文介绍列表滑动删除:列表中只允许滑出其中一项,如果有打开的项,点击或滑动其他项都会关闭打开的项,点击删除,刷新列表界面。

[[436946]]

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

简介

本项目基于ArkUI中TS扩展的声明式开发范式,关于语法和概念直接看官网官方文档地址:

基于TS扩展的声明式开发范式1基于TS扩展的声明式开发范式2

本文介绍列表滑动删除:

列表中只允许滑出其中一项

如果有打开的项,点击或滑动其他项都会关闭打开的项

点击删除,刷新列表界面

ArKUI系列文章

效果演示

HarmonyOS ArkUI之聊天列表滑动删除(TS)-鸿蒙HarmonyOS技术社区

主要知识点

可滑动的容器组件(Scroll)、触摸事件(onTouch)

实现思路

我把界面精简了一下,减少代码量,帮助更好的理解主要逻辑。

HarmonyOS ArkUI之聊天列表滑动删除(TS)-鸿蒙HarmonyOS技术社区

1、item布局

主要使用scroll包裹内容,scroll设置为横向滑动(部分代码)

  1. ..... 
  2. Scroll() { 
  3.       Row() { 
  4.         Text('内容数据'
  5.           .width('100%').height(65) 
  6.  
  7.         Button() { 
  8.           Text('删除'
  9.         } 
  10.         .width(100).height(65) 
  11.       } 
  12.  }.scrollable(ScrollDirection.Horizontal) // 设置为横向滑动 
  13. ..... 

2、Scroll容器

给Scroll容器绑定滑动组件的控制器,只用到其中的一个方法:滑动到指定位置 scrollTo

  1. scrollTo( 
  2.     value: { 
  3.     xOffset: number | string, yOffset: number | string, animation? 
  4.         : { duration: number, curve: Curve } 
  5.     } 
  6. ); 

看源码得知可以设置动画时间,注意:时间目前好像不能设置300毫秒以上,往下设置可以 (部分代码)

  1. ..... 
  2. // 初始化控制器 
  3. private scroller= new Scroller() 
  4. Scroll(scroller) { // 控制器绑定到滑动容器中 
  5.       Row() { 
  6.         Text('内容数据'
  7.           .width('100%').height(65) 
  8.  
  9.         Button() { 
  10.           Text('删除'
  11.         } 
  12.         .width(100).height(65) 
  13.       } 
  14.  }.scrollable(ScrollDirection.Horizontal) 
  15.  
  16. Button() { 
  17.   Text('点击回到原位')            
  18. }.onClick(()=>{ 
  19.   scroller.scrollTo({ xOffset: 0, yOffset: 0, animation: { duration: 200, curve: Curve.Linear } }) 
  20. }) 
  21. ..... 

3、设置触摸事件

根据移动的偏移量,判断大于删除布局宽度的一半则:打开删除布局(部分代码)

  1. ..... 
  2. // 初始化控制器 
  3. private scroller= new Scroller() 
  4. // 按下的x轴坐标 
  5. private downX = 0 
  6. // 删除按钮的宽度 
  7. private deleteWidth = 100 
  8.  
  9. Scroll(scroller) { // 控制器绑定到滑动容器中 
  10.       Row() { 
  11.         Text('内容数据'
  12.           .width('100%').height(65) 
  13.  
  14.         Button() { 
  15.           Text('删除'
  16.         } 
  17.         .width(this.deleteWidth).height(65) 
  18.       } 
  19.  }.scrollable(ScrollDirection.Horizontal) 
  20. .onTouch((event: TouchEvent) => { // 触摸事件 
  21.       // 根据触摸类型判断 
  22.       switch (event.type) { 
  23.         case TouchType.Down: // 触摸按下 
  24.           // 记录按下的x轴坐标 
  25.           this.downX = event.touches[0].x 
  26.           break 
  27.         case TouchType.Up: // 触摸抬起 
  28.           // 触摸抬起,根据x轴总偏移量,判断是否打开删除 
  29.           let xOffset = event.touches[0].x - this.downX 
  30.           // 滑到目标x轴的位置 
  31.           var toxOffset = 0           
  32.           // 偏移量超过删除按钮一半且左滑,设置打开 
  33.           if (Math.abs(xOffset) > vp2px(this.deleteWidth) / 2 && xOffset < 0) { 
  34.               // 删除布局宽度 
  35.               toxOffset = vp2px(this.deleteWidth) 
  36.           } 
  37.           // 滑动指定位置,设置动画 
  38.           item.scroller.scrollTo({ xOffset: toxOffset, yOffset: 0, 
  39.             animation: { duration: 300, curve: Curve.Linear } }) 
  40.           // 重置按下的x轴坐标 
  41.           this.downX = 0 
  42.           break 
  43.       } 
  44.     }) 
  45. ..... 

4、使用列表加载

需要主要的点:

  • 需要给每个item绑定控制器,这样才能控制对应的item打开或关闭
  • 打开的item记录一下数据,点击内容或删除、滑动其他item:如果有带打开的item,进行关闭

以下是完整代码,可直接粘贴运行使用。

  1. class TestData { 
  2.   content: string 
  3.   scroller: Scroller 
  4.  
  5.   constructor(content: string, scroller: Scroller) { 
  6.     this.content = content 
  7.     this.scroller = scroller 
  8.   } 
  9.  
  10. @Entry 
  11. @Component 
  12. struct SlidingDeleteList { 
  13.   // 删除按钮的宽度 
  14.   private deleteWidth = 100 
  15.   // 按下的x轴坐标 
  16.   private downX = 0 
  17.   // 已经打开删除的数据 
  18.   private openDeleteData: TestData = null 
  19.   // 测试数据 
  20.   @State private listData: Array<TestData> = [ 
  21.     { content: '内容数据1', scroller: new Scroller() }, { content: '内容数据2', scroller: new Scroller() }, 
  22.     { content: '内容数据3', scroller: new Scroller() }, { content: '内容数据4', scroller: new Scroller() }, 
  23.     { content: '内容数据5', scroller: new Scroller() }, { content: '内容数据6', scroller: new Scroller() }, 
  24.     { content: '内容数据7', scroller: new Scroller() }, { content: '内容数据8', scroller: new Scroller() }, 
  25.   ] 
  26.  
  27.   @Builder CustomItem(item:TestData) { 
  28.     Scroll(item.scroller) { 
  29.       Row() { 
  30.         Text(item.content) 
  31.           .width('100%').height(65) 
  32.           .fontSize(16).textAlign(TextAlign.Center) 
  33.           .onClick(() => { 
  34.             // 如果删除按钮打开,关闭删除按钮且返回 
  35.             if (this.openDeleteData != null) { 
  36.               this.openDeleteData.scroller.scrollTo({ xOffset: 0, yOffset: 0, 
  37.                 animation: { duration: 100, curve: Curve.Linear } }) 
  38.               this.openDeleteData = null 
  39.               return 
  40.             } 
  41.             console.log('========点击内容========='
  42.           }) 
  43.  
  44.         Button() { 
  45.           Text('删除'
  46.             .fontSize(15) 
  47.             .fontColor(Color.White) 
  48.         } 
  49.         .type(ButtonType.Normal) 
  50.         .width(this.deleteWidth).height(65) 
  51.         .backgroundColor(Color.Red) 
  52.         .onClick(() => { 
  53.           // 删除当前数据 
  54.           this.listData.splice(this.listData.indexOf(item), 1) 
  55.  
  56.           // 关闭删除按钮 
  57.           if (this.openDeleteData != null) { 
  58.             this.openDeleteData.scroller.scrollTo({ xOffset: 0, yOffset: 0, 
  59.               animation: { duration: 100, curve: Curve.Linear } }) 
  60.             this.openDeleteData = null 
  61.           } 
  62.           console.log('========点击删除========='
  63.         }) 
  64.       } 
  65.     }.scrollable(ScrollDirection.Horizontal) 
  66.     .onTouch((event: TouchEvent) => { // 触摸事件 
  67.       // 判断是否有打开删除组件,有则关闭 
  68.       if (this.openDeleteData != null && this.openDeleteData != item) { 
  69.         this.openDeleteData.scroller.scrollTo({ xOffset: 0, yOffset: 0, 
  70.           animation: { duration: 100, curve: Curve.Linear } }) 
  71.       } 
  72.  
  73.       // 根据触摸类型判断 
  74.       switch (event.type) { 
  75.         case TouchType.Down: // 触摸按下 
  76.           // 记录按下的x轴坐标 
  77.           this.downX = event.touches[0].x 
  78.           break 
  79.         case TouchType.Up: // 触摸抬起 
  80.           // 触摸抬起,根据x轴总偏移量,判断是否打开删除 
  81.           let xOffset = event.touches[0].x - this.downX 
  82.           // 防止消费点击事件 
  83.           if (xOffset == 0) { 
  84.             return 
  85.           } 
  86.           // 滑到x轴的位置 
  87.           var toxOffset = 0 
  88.           // 开启删除的对象置为null 
  89.           this.openDeleteData = null
  90.           // 偏移量超过删除按钮一半且左滑,设置打开 
  91.           if (Math.abs(xOffset) > vp2px(this.deleteWidth) / 2 && xOffset < 0) { 
  92.             // 删除布局宽度 
  93.             toxOffset = vp2px(this.deleteWidth) 
  94.             this.openDeleteData = item 
  95.           } 
  96.           // 滑动指定位置,设置动画 
  97.           item.scroller.scrollTo({ xOffset: toxOffset, yOffset: 0, 
  98.             animation: { duration: 300, curve: Curve.Linear } }) 
  99.           // 重置按下的x轴坐标 
  100.           this.downX = 0 
  101.           break 
  102.       } 
  103.     }) 
  104.   } 
  105.  
  106.   build() { 
  107.     Column() { 
  108.       List() { 
  109.         ForEach(this.listData, item => { 
  110.           ListItem() { 
  111.             this.CustomItem(item) 
  112.           } 
  113.         }, item => item.toString()) 
  114.       }.divider({ color: '#f1efef', strokeWidth: 1 }) 
  115.     } 
  116.     .width('100%'
  117.     .height('100%'
  118.   } 

结尾

因为ArkUI声明式开发,是鸿蒙新出的东西,API还不是那么完善,后续跟进官网更新。以下是需要优化点:

ArkUI中的TS没有JS中的新出的插槽概念,要不然直接封装成组件,提供两个对外的接口,一个传入内容布局、一个操作布局,就像Android的组件库一样,使用者不需要知道内部实现。

每天进步一点点、需要付出努力亿点点。

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

 

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2021-12-01 10:02:57

鸿蒙HarmonyOS应用

2022-08-23 16:07:02

ArkUI鸿蒙

2022-04-08 14:47:11

ArkUI列表字母索引鸿蒙

2021-12-03 09:49:59

鸿蒙HarmonyOS应用

2021-11-23 10:00:55

鸿蒙HarmonyOS应用

2022-09-26 15:16:03

ArkUITS

2022-08-08 19:46:26

ArkUI鸿蒙

2022-07-20 15:32:25

时钟翻页Text组件

2022-11-21 16:15:41

ArkUI鸿蒙

2022-05-20 14:34:20

list组件鸿蒙操作系统

2021-11-19 09:48:33

鸿蒙HarmonyOS应用

2021-11-16 09:38:10

鸿蒙HarmonyOS应用

2021-11-24 10:02:53

鸿蒙HarmonyOS应用

2022-11-02 16:06:54

ArkUIETS

2022-10-24 14:49:54

ArkUI心电图组件

2022-02-23 15:07:22

HarmonyOS常用控制ArkUI-eTS

2022-08-24 16:08:22

ETS鸿蒙

2014-12-31 14:52:27

SwipeMenuLiSwipeMenu

2022-06-27 14:12:32

css鸿蒙自定义

2022-09-14 15:17:26

ArkUI鸿蒙
点赞
收藏

51CTO技术栈公众号