当前位置:   article > 正文

ArkTS 下拉菜单总结_arkts 下拉刷新

arkts 下拉刷新

使用ArkTS语言开发下拉菜单,需要考虑一下内容:
1、List的edgeEffect、LazyForEach
2、opacity属性可以设置整个组件的透明度
3、容器的.markAnchor可以和offset搭配使用

半成品代码实例、仿京东首页差一部分内容


import display from '@ohos.display';
import media from '@ohos.multimedia.media';
import { MyDataSource } from '../widget/list/datasource';
@Entry
@Component
struct TBListPage {
  @State firstListData : string[] =  ['item value: 0', 'item value: 1', 'item value: 2', 'item value: 3', 'item value: 4', 'item value: 5']
  private data: MyDataSource = new MyDataSource(this.firstListData)


  private scrollerForScroll: Scroller = new Scroller()
  private scrollerForList: Scroller = new Scroller()

  @State offsetY : number = 0
  @State startIndex : number = 0
  @State endIndex : number = 0

  // 下拉刷新的布局高度
  private pullRefreshHeight = 70
  // 下拉刷新文字:下拉刷新、松开刷新、正在刷新、刷新成功
  @State pullRefreshText: string= '下拉刷新'
  // 是否可以刷新:未达到刷新条件,收缩回去
  private isCanRefresh = false
  // 是否正在刷新:刷新中不进入触摸逻辑
  private isRefreshing: boolean = false
  // 是否已经进入了下拉刷新操作
  private isPullRefreshOperation = false
  private lastMoveY = 0

  // 上拉加载的布局默认高度
  private loadMoreHeight = 70
  // 上拉加载的布局是否显示
  @State isVisibleLoadMore: boolean = false
  // 是否可以加载更多
  private isCanLoadMore = false
  // 是否加载中:加载中不进入触摸逻辑
  private isLoading: boolean = false
  private downY = 0

  private showAd : boolean = false;

  private topbarHeight : number = 30

  private adHeight : number = 60

  build() {
      Stack(){
        Column(){
          Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
            Image($r("app.media.flo"))
              .width(18)
              .height(18)

            Text(this.pullRefreshText)
              .margin({ left: 7, bottom: 1 })
              .fontSize(17)
          }
          .backgroundColor(Color.Red)
          .width('100%')
          .height(vp2px(this.adHeight))
          .offset({ x: 0, y: `${this.offsetY}px` })
          //列表
          List({scroller : this.scrollerForList}){
            LazyForEach(this.data, (item: string) => {
              ListItem() {
                Row() {
                  Text(`${item}`)
                    .width('100%')
                    .height(100)
                    .fontSize(20)
                    .margin({top : 10})
                    .fontColor(Color.White)
                    .textAlign(TextAlign.Center)
                    .borderRadius(10)
                    .backgroundColor(0x007DFF)
                }
              }
            }, item => item)
          }
          .edgeEffect(EdgeEffect.None)
          .onScrollIndex((start, end) => {
            this.startIndex = start
            this.endIndex = end
          })
          .offset({ x: 0, y: `${this.offsetY}px` })
          .onReachEnd(()=>{
            if (this.data.totalCount() < 15) {
              this.data.pushData('item value: ' + this.data.totalCount())
              this.data.pushData('item value: ' + this.data.totalCount())
              this.data.pushData('item value: ' + this.data.totalCount())
              this.data.pushData('item value: ' + this.data.totalCount())
              this.data.pushData('item value: ' + this.data.totalCount())
            }
          }).onTouch((event) => this.listTouchEvent(event))
          .height('100%')
          .width('100%')
        }.markAnchor({x:0, y:`${vp2px(this.adHeight + this.topbarHeight)}px`})

        Column(){
          Text('首页')
            .fontColor(Color.White)
            .fontSize(24)
            .margin(6)
          TextInput()
            .backgroundColor(Color.White)

        }.opacity(this.getTopBarOpacity())
        .backgroundColor(Color.Blue)
        .padding({left: 10, right: 10})
        .width('100%')
        .height(vp2px(this.topbarHeight))

      }
      .height('100%')
      .alignContent(Alignment.TopStart)
    }

  getTopBarOpacity() : number{
    if (this.offsetY == 0) {
      return 1;
    }
    if (this.offsetY > 100) {
      return 0
    }
    return  ((100 - this.offsetY) * 0.01)
  }

  listTouchEvent(event: TouchEvent){
    switch (event.type) {
      case TouchType.Down: // 手指按下
      // 记录按下的y坐标
        this.downY = event.touches[0].y
        this.lastMoveY = event.touches[0].y
        break
      case TouchType.Move: // 手指移动
      // 下拉刷新中 或 加载更多中,不进入处理逻辑
        if(this.isRefreshing || this.isLoading){
          console.info('========Move刷新中,返回=========')
          return
        }
      // 判断手势
        let isDownPull = event.touches[0].y - this.lastMoveY > 0
      // 下拉手势 或 已经进入了下拉刷新操作
        if ((isDownPull || this.isPullRefreshOperation) && !this.isCanLoadMore) {
          this.touchMovePullRefresh(event)
        } else {
          this.touchMoveLoadMore(event)
        }
        this.lastMoveY = event.touches[0].y
        break
      case TouchType.Up: // 手指抬起
      case TouchType.Cancel: // 触摸意外中断:来电界面
      // 刷新中 或 加载更多中,不进入处理逻辑
        if(this.isRefreshing || this.isLoading){
          console.info('========Up刷新中,返回=========')
          return
        }
        if (this.isPullRefreshOperation) {
          this.touchUpPullRefresh()
        } else {
          this.touchUpLoadMore()
        }
        break
    }
  }

  //============================================加载更多==================================================
  // 手指移动,处理加载更多
  touchMoveLoadMore(event:TouchEvent) {
    // 因为加载更多是在列表后面新增一个item,当一屏能够展示全部列表,endIndex 为 length+1
    if (this.endIndex == this.data.totalCount() - 1 || this.endIndex == this.data.totalCount()) {
      // 滑动的偏移量
      this.offsetY = event.touches[0].y - this.downY
      if (Math.abs(this.offsetY) > vp2px(this.loadMoreHeight)/2) {
        // 可以刷新了
        this.isCanLoadMore = true
        // 显示加载更多布局
        this.isVisibleLoadMore = true
        // 偏移量缓慢增加
        this.offsetY = - vp2px(this.loadMoreHeight) + this.offsetY * 0.1
      }
    }
  }

  // 手指抬起,处理加载更多
  touchUpLoadMore() {
    animateTo({
      duration: 200, // 动画时长
    }, () => {
      // 偏移量设置为0
      this.offsetY = 0
    })
    if (this.isCanLoadMore) {
      console.info('======执行加载更多========')
      // 加载中...
      this.isLoading = true
      // 模拟耗时操作
      setTimeout(() => {
        this.closeLoadMore()
        this.loadMoreData()
      }, 2000)
    } else {
      console.info('======关闭加载更多!未达到条件========')
      this.closeLoadMore()
    }
  }

  // 关闭加载更多
  closeLoadMore() {
    this.isCanLoadMore = false
    this.isLoading = false
    this.isVisibleLoadMore = false
  }

  // 手指抬起,处理下拉刷新
  touchUpPullRefresh(){
    // 是否可以刷新
    if (this.isCanRefresh) {
      console.info('======执行下拉刷新========')
      // 偏移量为下拉刷新布局高度
      this.offsetY = vp2px(this.pullRefreshHeight)
      // 状态2:正在刷新
      this.pullRefreshState(2)

      // 模拟耗时操作
      setTimeout(() => {
        this.refreshData()
        this.closeRefresh()
      }, 2000)

    } else {
      console.info('======关闭下拉刷新!未达到条件========')
      // 关闭刷新
      this.closeRefresh()
    }
  }

  // 刷新测试数据
  private refreshData(){
    // this.list = []
    // for (var i = 0; i < 10; i++) {
    //   this.list.push(i)
    // }
  }

  // 加载更多测试数据
  private loadMoreData(){
    // let initValue = this.list[this.list.length-1] + 1
    // for (var i = initValue; i < initValue + 10; i++) {
    //   this.list.push(i)
    // }
  }

  // 关闭刷新
  closeRefresh() {
    // 如果允许刷新,延迟进入,为了显示刷新中
    setTimeout(() => {
      var delay = 50
      if (this.isCanRefresh) {
        // 状态3:刷新成功
        this.pullRefreshState(3)
        // 为了显示刷新成功,延迟执行收缩动画
        delay = 500
      }
      animateTo({
        duration: 150, // 动画时长
        delay: delay, // 延迟时长
        onFinish: () => {
          // 状态0:下拉刷新
          this.pullRefreshState(0)
          this.isPullRefreshOperation = false
        }
      }, () => {
        this.offsetY = 0
      })
    }, this.isCanRefresh ? 500 : 0)
  }

  // 手指移动,处理下拉刷新
  touchMovePullRefresh(event:TouchEvent){
    // 当首部索引位于0
    if (this.startIndex == 0) {
      this.isPullRefreshOperation = true
      // 下拉刷新布局高度
      var height = vp2px(this.pullRefreshHeight)
      // 滑动的偏移量
      this.offsetY = event.touches[0].y - this.downY

      // 偏移量大于下拉刷新布局高度,达到刷新条件
      if (this.offsetY >= height) {
        // 状态1:松开刷新
        this.pullRefreshState(1)
        // 偏移量的值缓慢增加
        this.offsetY = height + this.offsetY * 0.15
      } else {
        // 状态0:下拉刷新
        this.pullRefreshState(0)
      }

      if (this.offsetY < 0) {
        this.offsetY = 0
        this.isPullRefreshOperation = false
      }
    }
  }


  // 下拉刷新状态
  // 0下拉刷新、1松开刷新、2正在刷新、3刷新成功
  pullRefreshState(state:number){
    switch (state) {
      case 0:
      // 初始状态
        this.pullRefreshText = '下拉刷新'
        this.isCanRefresh = false
        this.isRefreshing = false
        this.showAd = false
        break;
      case 1:
        this.pullRefreshText = '松开刷新'
        this.isCanRefresh = true
        this.isRefreshing = false
        break;
      case 2:
        this.offsetY = vp2px(this.pullRefreshHeight)
        this.pullRefreshText = '正在刷新'
        this.isCanRefresh = true
        this.isRefreshing = true
        break;
      case 3:
        this.pullRefreshText = '刷新成功'
        this.isCanRefresh = true
        this.isRefreshing = true
        break;
      case 4:
        this.offsetY = vp2px(this.adHeight)
        this.pullRefreshText = '展示广告'
        this.isCanRefresh = false
        this.isRefreshing = false
        this.showAd = true
        break;
    }
  }
}



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348

项目迟点提交。

参考来源:
https://gitee.com/liangdidi/ListPullRefreshLoadMoreDemo/blob/master/entry/src/main/ets/default/pages/index.ets
https://developer.harmonyos.com/cn/docs/documentation/doc-references-V3/ts-universal-attributes-location-0000001427584824-V3

鸿蒙有中文的开发文档,对于初次使用ArkTS的开发者来说很友好。有过Flutter开发经验的会较快上手。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/219050
推荐阅读
相关标签
  

闽ICP备14008679号