• 如何在快应用中实现滑动操作组件


     1. 什么是滑动操作组件

    在实际的移动应用程序交互方式中,最常见的就是滑动操作。像左右滑动切换页面,手指张开来放大图片等,都是由滑动操作来完成的。本文滑动操作组件是指通过手势滑动呼出隐藏的操作按钮。

    如下图所示:

    cke_258.png

    cke_259.png

    图1 QQ app

    图2 华为短信app

    以上滑动操作组件具有如下特点:

    • 左右滑动均支持,滑动可呼出、隐藏操作按钮栏;
    • 操作按钮可配置多个;
    • 操作按钮可设置背景色、字体、宽度等;
    • 点击操作按钮,可隐藏操作栏;
    • 呼出操作栏时,界面所有的UI元素都相应移动;

    2 基本实现

    2.1 滑动操作组件化设计

    定义支持滑动操作的组件swipe_item,父组件引用,引用时传递操作按钮、操作按钮样式。滑动操作子组件需要实现手势滑动处理。

    代码结构如下:

    1. <import name="swipeitem" src="../Component/swipe_item.ux"></import>
    2. <template>
    3. <div class="container">
    4. <swipeitem right-options="{{rightBtns}}" left-options="{{leftBtns}}" @swipebtnclick="swipeItemClick">
    5. <text>左右都有混合滚动</text>
    6. </swipeitem>
    7. </div>
    8. </template>

    2.2子组件swipe_item属性设计

    2.3支持的属性

    属性

    类型

    是否必选

    默认值

    描述

    identity

    Number

    组件唯一标识,当autoClose为true时,必须要设置

    disabled

    Boolean

    false

    是否禁止滑动

    autoClose

    Boolean

    true

    滑动打开当前组件,是否关闭其他组件

    threshold

    Number

    30

    滑动缺省距离

    leftOptions

    Array[Option]

    左侧操作栏内容及样式

    rightOptions

    Array[Option]

    右侧操作栏内容及样式

    Option对象参数如下:

    属性

    类型

    是否必选

    描述

    txt

    String

    按钮文字

    style

    Object

    按钮样式

    style对象参数如下:

    属性

    类型

    是否必选

    描述

    backgroundColor

    Color

    按钮背景色

    txtColor

    Color

    按钮颜色

    fontsize

    Number

    文字大小

    btnwidth

    Number

    按钮宽度

    支持的事件

    事件名称

    事件传递参数

    描述

    swipebtnclick

    {clickIndex:1,

    position:left|right,

    btnValue:btnText}

    点击操作栏按钮时触发事件;

    clickIndex:左或右操作栏上点击的按钮数组索引;

    position:所点击的操作栏位置,参数值有left和right;

    btnValue:所点击的按钮文字;

    centerclick

    {}

    点击显示在屏幕中间内容时触发事件

    swipestatechange

    {isOpened:true|false}

    操作栏打开或关闭时触发

    2.4 swipe_item子组件布局

    • 布局结构:由左侧操作栏+中间屏幕显示内容+右侧操作栏组成的横向div;
    • 左侧操作栏、右侧操作栏都是基于leftOptions、rightOptions操作选项内容数组,采用用for循环形成横向布局渲染;
    • 中间在屏幕内显示内容是动态变化的,每个产品要显示的内容和UI是不同的,所以采用了slot插槽,由使用swipe_item组件的页面来完成中间内容的布局。
    • 中间布局宽度需设置整个屏幕的宽度,即750px;

    cke_260.png

    2.5 swipe_item子组件css

    • 宽度:虽然滑动操作组件在初始状态下左右操作栏都是隐藏的,但是实际属于整个布局的一部分,如果不能正确计算根节点的宽度,会导致滑动的时候,操作栏上无内容。
    • 动画:初始状态下,需要满足左右操作栏都是隐藏的,只有中间内容是可见的。正常布局下(见图3),左操作栏是显示的,所以使用了transform动画样式,将根节点平移左操作栏宽度的距离,这样就确保初始状态下操作栏都是隐藏的。

    cke_261.png

    • 按鈕背景色、文字大小、文字顔色: 如果父组件没有设置,子组件设置默认的值,见图4;

    cke_262.png

    cke_263.png

    图3 正常布局效果

    图4 操作栏按钮默认背景色效果

    2.6 手势滑动

    监听手势touchstart、touchmove、touchend事件,计算手指滑动像素,同时调用X轴的平移动画animate方法,实现组件的移动效果。

    • touchstart:记录起始触摸点;
    • touchmove:滑动距离ds>0 表示手指向右滑动,反之向左滑动,滑动过程中调用animate()移动组件,达到打开或者隐藏操作栏的效果;如果滑动距离小于阈值threshold,不触发移动效果;如果禁止滑动即disabled值为true时,也不能触发滑动效果;
    • touchend:滑动结束时触发,调用animate()控制操作栏最终显示位置,需要计算准确,防止组件移动过远或者过近,从而UI效果异常。

    2.8 父子组件通信

    当点击子组件操作栏上的按钮时,需要父组件处理业务逻辑,通过$emit()向父组件发送通知。注意,不要在子组件中处理业务逻辑,否则代码无法维护。

    1) 操作栏按钮点击事件通知

    • 页面调用子组件时,监听swipebtnclick事件;
    • 子组件调用$emit()向页面发送通知;

    2)中间内容部分点击事件通知

    • 页面调用子组件时,监听centerclick事件;
    • 当操作栏处于打开状态时,点击中间部分效果是隐藏操作栏。只有操作栏处于隐藏状态时,点击中间部分时,子组件调用$emit()向页面发送通知,页面自行处理业务逻辑,比如打开新的页面。

    3)操作栏打开、关闭事件通知

    • 页面调用子组件时,监听swipestatechange事件;
    • 当操作栏处于打开或者关闭状态时,子组件调用$emit()向页面发送通知。

    相关代码如下:

    cke_264.png

    cke_265.png

    2.9 autoClose实现

    滑动打开当前组件时,是否关闭其他组件,当autoClose设置为true时,identity属性必须设置,且唯一标识当前子组件。

    • 子组件1操作栏打开时,通过$emit()向页面发送状态事件swipestatechange
    • 父组件监听swipestatechange事件,通过$broadcast()方法向子组件发送关闭通知事件closeSwipeItem,通知其他子组件2,3,4等要关闭已经打开的操作栏;
    • 子组件1,2,3,4等监听关闭closeSwipeItem事件,在事件句柄中处理关闭逻辑,注意操作栏打开的子组件1也会收到关闭事件,此处我们需要判断identity值,确保最新打开的子组件1不会出现打开又关闭的现象。

    3总结

    • 学习和熟悉快应用子组件的设计和属性定义;
    • 学习和熟悉快应用手势事件;
    • 学习和熟悉快应用动画;
    • 注意滑动操作子组件swipe_item在list-item中不生效。

    4代码附录

    滑动操作子组件swipe_item.ux

    1. <template>
    2. <!-- Only one root node is allowed in template. -->
    3. <div class="container" style="{{containerStyle}}" >
    4. <div id="swipe_item" class="swipe" ontouchstart="dealTouchStart" ontouchmove="dealTouchMove" ontouchend="dealTouchEnd" >
    5. <div class="left" id="leftbtns">
    6. <block for="(index,item) in leftOptions">
    7. <input type="button" class="btn"
    8. style="background-color: {{calBtnBgColor(item.style.backgroundColor)}};
    9. color:{{calBtnTxtColor(item.style.txtColor)}};
    10. font-size:{{calBtnFontSize(item.style.fontsize)}}px;width:{{item.style.btnwidth}}px;"
    11. value="{{item.txt}}" onclick="btnsClick(index,'left',item.txt)">
    12. </input>
    13. </block>
    14. </div>
    15. <div class="center" style="width:{{deviceLogicWidth}}px" onclick="dealClickCenter">
    16. <slot ></slot>
    17. </div>
    18. <div class="right" id="rightbtns">
    19. <block for="(index,item) in rightOptions">
    20. <input type="button" class="btn"
    21. style="background-color: {{calBtnBgColor(item.style.backgroundColor)}};
    22. color:{{calBtnTxtColor(item.style.txtColor)}};
    23. font-size:{{calBtnFontSize(item.style.fontsize)}}px;width:{{item.style.btnwidth}}px;"
    24. value="{{item.txt}}" onclick="btnsClick(index,'right',item.txt)">
    25. </input>
    26. </block>
    27. </div>
    28. </div>
    29. </div>
    30. </template>
    31. <style>
    32. .container {
    33. flex-direction: column;
    34. justify-content: center;
    35. }
    36. .swipe {
    37. flex-direction: row;
    38. align-items: center;
    39. }
    40. .txt {
    41. font-size: 40px;
    42. width: 100%;
    43. height: 100%;
    44. }
    45. .btn {
    46. height: 100%;
    47. }
    48. .left {
    49. flex-direction: row;
    50. flex-shrink: 0;
    51. height: 100%;
    52. background-color: #a9a9a9;
    53. }
    54. .center {
    55. flex-direction: row;
    56. align-items: center;
    57. padding: 16px;
    58. flex-shrink: 0;
    59. }
    60. .right {
    61. flex-direction: row;
    62. flex-shrink: 0;
    63. height: 100%;
    64. background-color: #a9a9a9;
    65. }
    66. </style>
    67. <script>
    68. import device from '@system.device';
    69. const defaultBtnBg="#f01f1f";
    70. const defaultBtnFontSize=32;
    71. const defaultBtnTxtColor="#dcdcdc";
    72. module.exports = {
    73. props: {
    74. // 禁用
    75. disabled: {
    76. type: Boolean,
    77. default: false
    78. },
    79. identity:{
    80. type: String,
    81. default: '0',
    82. },
    83. // 是否自动关闭
    84. autoClose: {
    85. type: Boolean,
    86. default: true
    87. },
    88. // 滑动缺省距离
    89. threshold: {
    90. type: Number,
    91. default: 30
    92. },
    93. // 左侧按钮内容
    94. leftOptions: {
    95. type: Array,
    96. default() {
    97. return []
    98. }
    99. },
    100. // 右侧按钮内容
    101. rightOptions: {
    102. type: Array,
    103. default() {
    104. return []
    105. }
    106. }
    107. },
    108. data: {
    109. movestartX: 0,
    110. lastMoveX:0,
    111. translateEndX: 0,
    112. leftbtnsWidth: 0,
    113. rightbtnsWidth: 0,
    114. deviceLogicWidth:750,
    115. isLeftOpened: false,
    116. isRightOpened: false
    117. },
    118. computed: {
    119. containerStyle() {
    120. console.info("computed containerStyle begin")
    121. var style = '';
    122. let totalwidth=0;
    123. let leftwidth=0;
    124. this.leftOptions.forEach((item, index, array) => {
    125. console.info("computed item="+JSON.stringify(item));
    126. leftwidth+=item.style.btnwidth;
    127. })
    128. this.rightOptions.forEach((item, index, array) => {
    129. totalwidth+=item.style.btnwidth;
    130. })
    131. totalwidth=totalwidth+this.deviceLogicWidth+leftwidth;
    132. console.info("computed totawidth="+totalwidth+", left width="+leftwidth);
    133. style += 'width:' + totalwidth + 'px;'
    134. style += 'transform: translateX(-' + leftwidth + 'px);'
    135. return style;
    136. }
    137. },
    138. calBtnBgColor(color){
    139. if(color!==undefined){
    140. return color;
    141. }
    142. return defaultBtnBg;
    143. },
    144. calBtnFontSize(size){
    145. if(size!==undefined){
    146. return size;
    147. }
    148. return defaultBtnFontSize;
    149. },
    150. calBtnTxtColor(color){
    151. if(color!==undefined){
    152. return color;
    153. }
    154. return defaultBtnTxtColor;
    155. },
    156. onInit() {
    157. console.info("oninit()");
    158. this.$on('closeSwipeItem', this.closeFromParent);
    159. setTimeout(() => {
    160. this.calWidth();
    161. }, 500);
    162. },
    163. calWidth() {
    164. this.calLeftBtnsWidth();
    165. this.calRightBtnsWidth();
    166. },
    167. calLeftBtnsWidth() {
    168. var that = this;
    169. this.$element('leftbtns').getBoundingClientRect({
    170. success(res) {
    171. let msg = JSON.stringify(res);
    172. console.log('calLeftBtnsWidth 当前坐标:' + msg);
    173. // that.leftbtnsWidth = res.width;
    174. that.convertRealPx(true, res.width);
    175. },
    176. fail() {
    177. console.log('calBoxWidth 获取失败');
    178. },
    179. complete() {
    180. console.log('calBoxWidth complete')
    181. }
    182. })
    183. },
    184. calRightBtnsWidth() {
    185. var that = this;
    186. this.$element('rightbtns').getBoundingClientRect({
    187. success(res) {
    188. let msg = JSON.stringify(res);
    189. console.log('calRightBtnsWidth 当前坐标:' + msg);
    190. // that.rightbtnsWidth = res.width;
    191. that.convertRealPx(false, res.width);
    192. },
    193. fail() {
    194. console.log('calBoxWidth 获取失败');
    195. },
    196. complete() {
    197. console.log('calBoxWidth complete')
    198. }
    199. })
    200. },
    201. convertRealPx(isLeftWidth, data) {
    202. var d = device.getInfoSync();
    203. console.info("calBannerPostion1 d= " + JSON.stringify(d));
    204. //获取页面内可见窗口的高度和宽度,此值不包括标题栏和状态栏高度
    205. let windowWidth = d.windowWidth;
    206. //logicWidth对应manifest.json文件设置的designWidth值,默认是750
    207. let logicWidth = d.windowLogicWidth;
    208. let result = data * 1.0 * windowWidth / logicWidth;
    209. if (isLeftWidth) {
    210. this.leftbtnsWidth = result;
    211. } else {
    212. this.rightbtnsWidth = result;
    213. }
    214. },
    215. dealTouchStart: function (e) {
    216. if (this.disabled) {
    217. return;
    218. }
    219. this.movestartX = e.touches[0].clientX;
    220. console.info("dealTouchStart movestartX="+this.movestartX);
    221. },
    222. dealTouchMove: function (e) {
    223. if (this.disabled) {
    224. return;
    225. }
    226. let moveX = e.touches[0].clientX;
    227. let dis = moveX - this.movestartX;
    228. console.info("dealTouchMove moveX= " + moveX + ", dis=" + dis);
    229. if (Math.abs(dis) < this.threshold) {
    230. return;
    231. }
    232. if (dis > 0) {
    233. //右滑动呼出左边的按钮或者隐藏右边按钮恢复初始状态
    234. if (this.isRightOpened) {
    235. //隐藏右边的按钮,恢复初始状态
    236. this.animate(dis-this.rightbtnsWidth, dis);
    237. } else {
    238. //右滑动,呼出左边的按钮
    239. if (this.leftbtnsWidth > 0) {
    240. if (!this.isLeftOpened) {
    241. console.info("begin to show the left buttons");
    242. this.animate(dis, dis);
    243. }
    244. }
    245. }
    246. }
    247. else if (dis < 0) {
    248. console.info("dealTouchMove left this.isLeftOpened=" + this.isLeftOpened);
    249. if (this.isLeftOpened) {
    250. //慢慢滑动将左边按钮隐藏
    251. this.animate(this.leftbtnsWidth + dis, dis);
    252. } else {
    253. //呼出右边的按钮
    254. if (this.rightbtnsWidth > 0) {
    255. if (!this.isRightOpened) {
    256. console.info("dealTouchMove begin to show the right buttons");
    257. this.animate(dis, dis);
    258. }
    259. }
    260. }
    261. }
    262. },
    263. dealTouchEnd: function (e) {
    264. if (this.disabled) {
    265. return;
    266. }
    267. let endX = e.changedTouches[0].clientX;
    268. let dis = endX - this.movestartX;
    269. if (Math.abs(dis) < this.threshold) {
    270. return;
    271. }
    272. console.info("dealTouchEnd dis=" + dis + ", endX=" + endX + ", isLeftOpened=" + this.isLeftOpened + ",isRightOpened=" + this.isRightOpened);
    273. if (dis > 0) {
    274. //往右边滑动
    275. if (this.isRightOpened) {
    276. //隐藏右边按钮
    277. this.animate(dis - this.rightbtnsWidth, 0);
    278. this.isRightOpened = false;
    279. this.$emit('swipestatechange', {params: {"isOpened":false}});
    280. } else {
    281. if (!this.isLeftOpened) {
    282. //呼出左边按钮,将左边按钮完整显示出来;
    283. if (this.leftbtnsWidth > 0) {
    284. this.animate(dis, this.leftbtnsWidth);
    285. this.isLeftOpened = true;
    286. this.$emit('swipestatechange', {params: {"isOpened":true}});
    287. }
    288. }
    289. }
    290. } else if (dis < 0) {
    291. //往左滑动
    292. if (this.isLeftOpened) {
    293. //隐藏左边按钮
    294. this.animate(this.leftbtnsWidth + dis, 0);
    295. this.isLeftOpened = false;
    296. this.$emit('swipestatechange', {params: {"isOpened":false}});
    297. } else {
    298. if (this.rightbtnsWidth > 0 && !this.isRightOpened) {
    299. //呼出右边按钮,将右边按钮完整显示出来
    300. this.animate(dis, -this.rightbtnsWidth);
    301. this.isRightOpened = true;
    302. this.$emit('swipestatechange', {params: {"isOpened":true}});
    303. }
    304. }
    305. }
    306. },
    307. animate(value1, value2) {
    308. console.info("aninate translateX from: " + value1 + ", to:" + value2);
    309. let cmp = this.$element('swipe_item');
    310. var options = {
    311. duration: 300, easing: 'linear',
    312. delay: 0,
    313. fill: 'forwards'
    314. }
    315. console.info("dealTouchMove value2=" + value2);
    316. var frames = [
    317. {
    318. transform: {
    319. translateX: value1,
    320. }
    321. },
    322. {
    323. transform: {
    324. translateX: value2,
    325. }
    326. }];
    327. var animation = cmp.animate(frames, options);
    328. animation.play();
    329. animation.onfinish = function () {
    330. console.log("animation onfinish");
    331. }
    332. animation.oncancel = function () {
    333. console.log("animation oncancel");
    334. }
    335. },
    336. btnsClick: function(index,direction,btnValue) {
    337. console.info("swipe.ux item click direction="+direction);
    338. this.$emit('swipebtnclick', {params: {"clickIndex":index,"position":direction,"btnValue":btnValue}});
    339. //按钮关闭
    340. if(direction=='left'){
    341. this.animate(this.leftbtnsWidth, 0);
    342. this.isLeftOpened = false;
    343. }else{
    344. this.animate( - this.rightbtnsWidth, 0);
    345. this.isRightOpened = false;
    346. }
    347. this.$emit('swipestatechange', {params: {"isOpened":false}});
    348. },
    349. close:function() {
    350. if(this.isLeftOpened){
    351. //关闭
    352. this.animate(this.leftbtnsWidth, 0);
    353. this.isLeftOpened = false;
    354. this.$emit('swipestatechange', {params: {"isOpened":false}});
    355. }else if(this.isRightOpened){
    356. //关闭
    357. this.animate( - this.rightbtnsWidth, 0);
    358. this.isRightOpened = false;
    359. this.$emit('swipestatechange', {params: {"isOpened":false}});
    360. }else{
    361. //中间部分响应自身的点击事件
    362. this.$emit('centerclick', {params: {}});
    363. }
    364. },
    365. closeFromParent:function(e) {
    366. console.info("closeFromParent e="+JSON.stringify(e));
    367. if(!this.autoClose){
    368. return;
    369. }
    370. //最新滑动打开的操作栏不关闭,其他的才关闭
    371. let excludeCloseId=e.detail.exclude;
    372. if(excludeCloseId==this.identity){
    373. return;
    374. }
    375. if(this.isLeftOpened){
    376. //关闭
    377. this.animate(this.leftbtnsWidth, 0);
    378. this.isLeftOpened = false;
    379. }else if(this.isRightOpened){
    380. //关闭
    381. this.animate( - this.rightbtnsWidth, 0);
    382. this.isRightOpened = false;
    383. }
    384. },
    385. dealClickCenter: function() {
    386. console.info("dealClickCenter");
    387. this.close();
    388. },
    389. }
    390. </script>
    391. 页面main.ux
    392. <import name="swipeitem" src="../Component/swipe_item.ux"></import>
    393. <template>
    394. <!-- Only one root node is allowed in template. -->
    395. <div class="container">
    396. <div class="section">
    397. <text class="sec_txt">只有左边</text>
    398. </div>
    399. <swipeitem identity='111' left-options="{{leftBtns}}" @swipebtnclick="swipeItemClick" @swipestatechange="swipeItemChange('111')">
    400. <text>只有左边按钮</text>
    401. </swipeitem>
    402. <div class="section">
    403. <text class="sec_txt">只有右边</text>
    404. </div>
    405. <swipeitem identity='112' right-options="{{rightBtns}}" @swipebtnclick="swipeItemClick" @swipestatechange="swipeItemChange('112')">
    406. <text>只有右边按钮</text>
    407. </swipeitem>
    408. <div class="section">
    409. <text class="sec_txt">混合滚动</text>
    410. </div>
    411. <swipeitem identity='113' right-options="{{rightBtns}}" left-options="{{leftBtns}}" @swipebtnclick="swipeItemClick" @swipestatechange="swipeItemChange('113')">
    412. <text>左右都有混合滚动</text>
    413. </swipeitem>
    414. <div class="section">
    415. <text class="sec_txt">禁止左右滚动</text>
    416. </div>
    417. <swipeitem disabled="{{disabled}}" left-options="{{leftBtns}}" right-options="{{rightBtns}}" @swipebtnclick="swipeItemClick">
    418. <text>禁止左右滚动</text>
    419. </swipeitem>
    420. <div class="section">
    421. <text class="sec_txt">div列表</text>
    422. </div>
    423. <div class="swipelist" id="swiplist">
    424. <swipeitem identity="{{item.id}}" auto-close={{isautoclose}} right-options="{{item.options}}" for="(index,item) in swipeList" @swipestatechange="listSwipeItemChange(index)"
    425. @swipebtnclick="listSwipeItemClick(index)" @centerclick="listCenterItemClick(index)">
    426. <text onclick="clickText">{{item.content}}</text>
    427. </swipeitem>
    428. </div>
    429. </div>
    430. </template>
    431. <style>
    432. .container {
    433. flex-direction: column;
    434. width: 100%;
    435. }
    436. .section {
    437. background-color: #f5f5f5;
    438. height: 100px;
    439. width: 100%;
    440. border: 1px solid #f5f5f5;
    441. }
    442. .swipelist {
    443. flex-direction: column;
    444. }
    445. .istItemStyle {
    446. width: 1300px;
    447. }
    448. .liststyle {
    449. flex-direction: column;
    450. }
    451. .sec_txt {
    452. font-size: 32px;
    453. font-weight: 600;
    454. margin-left: 25px;
    455. margin-top: 10px;
    456. }
    457. </style>
    458. <script>
    459. import prompt from '@system.prompt';
    460. module.exports = {
    461. data: {
    462. isautoclose:true,
    463. leftBtns: [],
    464. disabled: true,
    465. rightBtns: [],
    466. unstyleleftBtns: [],
    467. unstylerightBtns: [],
    468. swipeList: []
    469. },
    470. onInit: function () {
    471. let btn1 = { "txt": "置顶", "style": { "backgroundColor": "#00bfff", "txtColor": "#dcdcdc", "fontsize": 30, "btnwidth": 150 } };
    472. let btn2 = { "txt": "ok", "style": { "backgroundColor": "#00bfff", "txtColor": "#dcdcdc", "fontsize": 30, "btnwidth": 200 } };
    473. let btn3 = { "txt": "取消置顶", "style": { "backgroundColor": "#f01f1f", "txtColor": "#dcdcdc", "fontsize": 30, "btnwidth": 150 } };
    474. let btn4 = { "txt": "cancel", "style": { "backgroundColor": "#00bfff", "txtColor": "#dcdcdc", "fontsize": 30, "btnwidth": 180 } };
    475. let unstylebtn1 = { "txt": "置顶", "style": { "btnwidth": 230 } };
    476. let unstylebtn2 = { "txt": "ok", "style": { "btnwidth": 200 } };
    477. let unstylebtn3 = { "txt": "取消置顶", "style": { "btnwidth": 150 } };
    478. let unstylebtn4 = { "txt": "cancel", "style": { "txtColor": "#ff9900", "fontsize": 30, "btnwidth": 150 } };
    479. this.leftBtns.push(btn1);
    480. this.leftBtns.push(btn2);
    481. this.rightBtns.push(btn3);
    482. this.rightBtns.push(btn4);
    483. this.unstyleleftBtns.push(unstylebtn1);
    484. this.unstyleleftBtns.push(unstylebtn2);
    485. this.unstylerightBtns.push(unstylebtn3);
    486. this.unstylerightBtns.push(unstylebtn4);
    487. },
    488. onReady(options) {
    489. this.swipeList = [{
    490. options: [{
    491. txt: '添加',
    492. style: {
    493. backgroundColor: 'rgb(255,58,49)',
    494. txtColor: "#dcdcdc",
    495. fontsize: 36,
    496. btnwidth: 150
    497. }
    498. }],
    499. id: '10',
    500. content: 'item1'
    501. },
    502. {
    503. id: '11',
    504. options: [{
    505. txt: '添加',
    506. style: {
    507. backgroundColor: 'rgb(255,58,49)',
    508. txtColor: "#dcdcdc",
    509. fontsize: 30,
    510. btnwidth: 150
    511. }
    512. },
    513. {
    514. txt: '删除',
    515. style: {
    516. backgroundColor: 'rgb(255,58,49)',
    517. txtColor: "#dcdcdc",
    518. fontsize: 30,
    519. btnwidth: 150
    520. }
    521. }
    522. ],
    523. content: 'item2'
    524. },
    525. {
    526. id: '12',
    527. options: [{
    528. txt: '置顶',
    529. style: {
    530. backgroundColor: 'rgb(255,58,49)',
    531. txtColor: "#dcdcdc",
    532. fontsize: 30,
    533. btnwidth: 150
    534. }
    535. },
    536. {
    537. txt: '标记为已读',
    538. style: {
    539. backgroundColor: 'rgb(255,58,49)',
    540. txtColor: "#dcdcdc",
    541. fontsize: 30,
    542. btnwidth: 150
    543. }
    544. },
    545. {
    546. txt: '删除',
    547. style: {
    548. backgroundColor: 'rgb(255,58,49)',
    549. txtColor: "#dcdcdc",
    550. fontsize: 30,
    551. btnwidth: 150
    552. }
    553. }
    554. ],
    555. content: 'item3'
    556. }
    557. ]
    558. },
    559. listSwipeItemClick: function (index, e) {
    560. console.info("main swipeItemClick e:" + JSON.stringify(e) + ",index=" + index);
    561. let position = e.detail.params.position;
    562. // // let index = e.detail.params.clickIndex;
    563. // let itemListId = e.detail.params.itemListIndex;
    564. let btnValue = e.detail.params.btnValue;
    565. let msg = '';
    566. if (position == 'left') {
    567. // msg='点击了左侧 ${e.detail.params.btnValue}按钮 ' ;
    568. msg = '点击了左侧' + btnValue + '按钮 ';
    569. } else {
    570. msg = '点击了右侧' + btnValue + '按钮 ';
    571. }
    572. prompt.showToast({
    573. message: msg,
    574. duration: 2000,
    575. gravity: 'center'
    576. })
    577. if (btnValue == "添加") {
    578. console.info("begin to add ")
    579. this.addSwipteItem();
    580. } else if (btnValue == "删除") {
    581. this.delSwipteItem(index);
    582. }
    583. },
    584. addSwipteItem: function () {
    585. this.swipeList.push({
    586. id: new Date().getTime(),
    587. content: '新增' + new Date().getTime(),
    588. options: [{
    589. txt: '置顶',
    590. style: {
    591. fontsize: 30,
    592. btnwidth: 150
    593. }
    594. },
    595. {
    596. txt: '标记为已读',
    597. style: {
    598. backgroundColor: 'rgb(254,156,1)',
    599. fontsize: 30,
    600. btnwidth: 150
    601. }
    602. },
    603. {
    604. txt: '删除',
    605. style: {
    606. backgroundColor: 'rgb(255,58,49)',
    607. fontsize: 30,
    608. btnwidth: 150
    609. }
    610. }
    611. ],
    612. });
    613. },
    614. delSwipteItem: function (index) {
    615. var that = this;
    616. prompt.showDialog({
    617. title: '提示',
    618. message: '是否删除',
    619. buttons: [
    620. {
    621. text: '确定',
    622. color: '#33dd44'
    623. }, {
    624. text: '取消',
    625. color: '#33dd44'
    626. }],
    627. success: function (data) {
    628. console.log("delSwipteItem showDialog handling callback data:" + JSON.stringify(data));
    629. if (data.index == 0) {
    630. //delete
    631. that.swipeList.splice(index, 1);
    632. }
    633. },
    634. fail: function (data, code) {
    635. console.log("handling fail, code = " + code);
    636. }
    637. })
    638. },
    639. swipeItemClick: function (e) {
    640. console.info("main swipeItemClick e:" + JSON.stringify(e));
    641. let position = e.detail.params.position;
    642. let btnValue = e.detail.params.btnValue;
    643. let msg = '';
    644. if (position == 'left') {
    645. // msg='点击了左侧 ${e.detail.params.btnValue}按钮 ' ;
    646. msg = '点击了左侧' + btnValue + '按钮 ';
    647. } else {
    648. msg = '点击了右侧' + btnValue + '按钮 ';
    649. }
    650. prompt.showToast({
    651. message: msg,
    652. duration: 2000,
    653. gravity: 'center'
    654. })
    655. },
    656. clickText: function () {
    657. console.info("click text");
    658. prompt.showToast({
    659. message: 'click text',
    660. duration: 2000,
    661. gravity: 'center'
    662. })
    663. },
    664. listCenterItemClick: function (index, e) {
    665. console.info("main listCenterItemClick e:" + JSON.stringify(e) + ",index=" + index);
    666. prompt.showToast({
    667. message: 'click text',
    668. duration: 2000,
    669. gravity: 'center'
    670. })
    671. },
    672. listSwipeItemChange: function (index, e) {
    673. console.info("main listSwipeItemChange e:" + JSON.stringify(e) + ",index=" + index);
    674. this.$broadcast('closeSwipeItem', { 'exclude': this.swipeList[index].id });
    675. },
    676. swipeItemChange: function(id,e) {
    677. console.info("main swipeItemChange e:" + JSON.stringify(e)+",id="+id);
    678. this.$broadcast('closeSwipeItem', { 'exclude': id });
    679. },
    680. }
    681. </script>

    欲了解更多更全技术文章,欢迎访问https://developer.huawei.com/consumer/cn/forum/?ha_source=zzh

  • 相关阅读:
    Spring工具类--AnnotatedElementUtils的使用
    深圳市商务局2022年度中央资金(跨境电子商务企业市场开拓扶持事项)申报指南
    nodejs+vue+elementui在线公益-帮助流浪动物网站python java
    2022最新Java高频面试集锦,让你“金九银十”轻松斩获大厂offer
    从【臀部监控】到【电脑监控软件】,企业如何在隐私权与管理权博弈中找到平衡
    Python-IO
    ue5 小知识点 ue的world type,pie editor game
    手机便签怎么设置每月18号提醒
    Codewhisperer 使用评价
    微软S2C2F框架已被OpenSSF开源安全体系采用
  • 原文地址:https://blog.csdn.net/weixin_44708240/article/details/125633056