HarmonyOS swiper的disableSwipe所传的state不会马上生效,需要在一次滑动事件结束后才能生效

interface OffsetRemain {
  offsetRemain: number
}

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';
  private scroller = new Scroller()
  @State
  private refreshOffset: number = 0
  private refreshThreshold: number = 100
  // 当次滑动的总偏移量,需要滑动开始时重置
  private scrollOffset: number = 0.0
  @State
  private refreshing: boolean = false
  @State
  innerScrollEnabled: boolean = true
  swiperController = new SwiperController()

  build() {
    Stack() {
      Scroll(this.scroller) {
        Swiper(this.swiperController) {
          ForEach([1, 2, 3, 4], (item: number) => {
            Column() {
              Text('Page ' + item).fontSize(30)
              Text('Hello World').fontSize(30)
            }.width('100%').height('100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).backgroundColor('#f00')
          })
        }
        .effectMode(EdgeEffect.None)
        .nestedScroll(SwiperNestedScrollMode.SELF_FIRST)
        .width('100%')
        .height('100%')
        .loop(false)
        .vertical(true)
        .indicator(false)
        .disableSwipe(!this.innerScrollEnabled)
        .enabled(this.innerScrollEnabled)
        // .enabled(this.innerScrollEnabled)
      }
      .edgeEffect(EdgeEffect.None)
      .enablePaging(true)
      .height('100%')
      .width('100%')
      .onScrollFrameBegin((offset: number, state: ScrollState) => {
        console.info('onScrollFrameBegin')
        return this.onScrollFrameBegin(offset, state)
      })
      .onScrollStart(() => {
        this.onScrollStart()
      })
      .onScrollStop(() => {
        this.onScrollStop()
      })
      .onWillScroll((xOffset: number, yOffset: number, scrollState: ScrollState, scrollSource: ScrollSource) => {
        return this.onWillScroll(xOffset, yOffset, scrollState, scrollSource)
      })


      Column() {
        Text(`pull to refresh ${this.refreshOffset}`)
      }.width('100%').height(100).position({
        top: this.refreshing? 0 : this.refreshOffset - 100,
        left: 0,
        right: 0
      }).backgroundColor('#0f0')
    }.height('100%').width('100%')
  }

  private onScrollStart() {
    // reset this.scrollOffset when scroll start
    console.info('onScrollStart')
    this.scrollOffset = 0
  }

  private onScrollStop() {
    // console.info('onScrollStop', this.refreshOffset)
    // // check if should trigger refresh when scroll stop
    // if (this.refreshOffset >= this.refreshThreshold) {
    //   animateTo({duration: 100}, ()=>{
    //     this.refreshing = true
    //   })
    //
    //   // do refresh
    //   setTimeout(() => {
    //     this.refreshing = false
    //     this.refreshOffset = 0
    //   }, 5000)
    // }
  }

  private onScrollFrameBegin(offset: number, state: ScrollState): OffsetRemain {

    if (state != ScrollState.Scroll) {
      return { offsetRemain: offset }
    }

    this.scrollOffset += offset
    console.info('onScrollFrameBegin', offset, ScrollState[state], this.scrollOffset)

    // update inner scroll enabled status
    if (this.scrollOffset < 0.001) {
      console.info("disable inner scroll")
      this. innerScrollEnabled = false
    } else {
      console.info("enable inner scroll")
      this.innerScrollEnabled = true
    }

    const atBegin = this.scroller.currentOffset().yOffset <= 0.001
    const atEnd = this.scroller.isAtEnd()

    // 当前滑动的方向,以当前滑动的偏移量的正负来判断
    const scrollForward = offset < 0.001
    const scrollBackward = offset > 0.001

    // 如果当前在顶部且向前滑动,则触发下拉刷新,更新 this.refreshOffset, 当 this.refreshOffset 大于等于 this.refreshThreshold 时触发刷新且后续的下拉距离也减半
    if (atBegin) {
      this.refreshOffset = -this.scrollOffset
    }

    return { offsetRemain: offset }
  }

  // onWillScroll 在 overscroll 时, xOffset / yOffset 永远为 0
  private onWillScroll(xOffset: number, yOffset: number, scrollState: ScrollState,
    scrollSource: ScrollSource): void | OffsetResult {
    const atBegin = this.scroller.currentOffset().yOffset <= 0.001
    const atEnd = this.scroller.isAtEnd()

    const pullForward = yOffset > 0.001
    const pullBackward = yOffset < 0.001

    console.info('atBegin', atBegin, 'atEnd', atEnd, 'pullForward', pullForward, 'pullBackward', pullBackward,
      'yOffset', yOffset)
    // 如果向前拉并当前已经在顶部,则触发下拉刷新,更新 this.refreshOffset
    // 如果当前在顶部且向后拉,则刷新 this.refreshOffset 直到其值为 0
    if (atBegin && pullForward) {
      this.refreshOffset = yOffset
    } else if (atBegin && pullBackward) {
      this.refreshOffset = Math.max(0, this.refreshOffset + yOffset)
    }
  }
}
HarmonyOS
2024-12-24 16:55:59
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
superinsect

状态变量更新的时候,手势还是被之前的组件消费,没有作用在swipe上,所以要抬手,再重新滑动一次swiper, swiper才能接受到滑动事件,开始滑动

分享
微博
QQ
微信
回复
2024-12-24 19:40:24
相关问题
点击事件,@State 页面未生效,在线等
3100浏览 • 0回复 待解决
HarmonyOS SwiperdisableSwipe问题
168浏览 • 1回复 待解决
HarmonyOS 每秒执行一次函数
470浏览 • 2回复 待解决
Web组件onKeyEvent键盘事件生效
2212浏览 • 1回复 待解决
HarmonyOS 如何只取消某一次监听
239浏览 • 1回复 待解决
有没有一次编译,多端部署资料
610浏览 • 1回复 待解决