HarmonyOS 鸿蒙Next Scroller.scrollEdge(Edge.Bottom) 每隔一段时间执行一次,总是一次有效一次无效,我用 scroller.scrollTo 则没有这个问题

发布于 1周前 作者 gougou168 最后一次编辑是 5天前 来自 鸿蒙OS

HarmonyOS 鸿蒙Next Scroller.scrollEdge(Edge.Bottom) 每隔一段时间执行一次,总是一次有效一次无效,我用 scroller.scrollTo 则没有这个问题

请看有问题的演示视频:video.mp4

下面是有问题的代码:

/**

  • 消息发送按钮 */ @Builder SendButton() { Button($r(‘app.string.ChatPage_send’)).flexShrink(0) .onClick(() => { let str = this.inputValue this.inputValue = ‘’

         setInterval(() => {
             <span class="hljs-keyword">this</span>.messageDataList.push({
                 role: <span class="hljs-string">'assistant'</span>,
                 content: str,
                 createTime: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>()
             })
             <span class="hljs-keyword">this</span>.scroller.scrollEdge(Edge.Bottom)
         }, <span class="hljs-number">1000</span>)
     })
    

}

如果我把 this.scroller.scrollEdge(Edge.Bottom) 替换为下面的函数,就不会有问题:

/**

  • 滚动到底部
  • @param scroller */ function scrollToBottom(scroller: Scroller) { scroller.scrollTo({ xOffset: 0, yOffset: scroller.getItemRect(0).height, animation: true }) }

我的目标效果是,每隔一秒钟向数组中插入一项,并且滚动到底部来显示刚才插入的项。 

9 回复

应该确实是scrollEdge优化了,可以用下面的写法来规避,试试:

setInterval(() => {
            let str = "nihao" + this.messageDataList.length.toString()
            this.messageDataList.push(str)
            setTimeout(()=>{
              this.scroller.scrollEdge(Edge.Bottom)
            },20)
            console.info("testaaaa: " + this.messageDataList.length)
          }, 1000)

setInterval里面套的setTimeout超时时间设置为20, 试下呢

是的,怀疑是定时器把scrollEdge方法做了优化。我去除了定时器,用按键onclick触发,是可以正常触发下滑到最底部的。

我觉得最可能的是,当滚动条位置未发生变化时,重复触发 scrollEdge 将会被忽略,以此节省 scrollEdge 带来的性能消耗,然后当输入框弹出软键盘时,滚动条的位置还是记录为软键盘弹出之前的,所以被认为滚动条和上次 scrollEdge 后的位置未发生变化,就会导致弹出软键盘时的 scrollEdge 失效,而当我加了定时器后,为的是等待软键盘完全弹出,这样的话滚动条的位置就会发生变化,isAtEnd() 将从 true 变为 false,才能有效触发 scrollEdge。 ----------------- 补充上面的 --------------------- 不完全准确,在上一次 scrollEdge(Edge.Bottom) 后,滚动条到达底部,系统启用 scrollEdgeBottomLock,表示下一次的 scrollEdge(Edge.Bottom) 将被忽略。当滚动条位置发生变化后,scrollEdgeBottomLock 自动解除,此时 scrollEdge(Edge.Bottom) 将生效,并在到达底部后再次启用 scrollEdgeBottomLock。每次 scrollEdge(Edge.Bottom) 将会判断当前是否是 scrollEdgeBottomLock,如果是则忽略请求,不触发达到滚动条底部的动作,并解除 scrollEdgeBottomLock;如果不是,则正常触发滚动到底部动作,并启用 scrollEdgeBottomLock。这就是为什么,我滚动条位置不动的情况下,循环重复执行 scrollEdge(Edge.Bottom),会出现 有效->无效->有效->无效… 的不断切换。

如果使用 scroller.scrollTo 触发滚动条滚动到指定位置,将不受限制,可以重复触发且均有效。 如果要用 scrollEdge(Edge.Bottom),我有个好办法是,触发 2 次 scrollEdge(Edge.Bottom),这样的话,如果当前是 Lock 状态,那第一次负责解除 Lock,如果不是 Lock,那第一次执行滚动条动作,并启用 Lock,这样第二次因为有 Lock,就会被忽略动作并启用 Lock。

好了,测试发现,上面我的猜测是错的

希望HarmonyOS能继续推出更多实用的功能,满足用户的不同需求。

在定时器里面加个setTimeout可以规避,试试

针对你提到的HarmonyOS鸿蒙系统中Next Scroller的scrollEdge(Edge.Bottom)方法每隔一段时间执行一次时,出现一次有效一次无效的问题,这可能是由于scrollEdge方法的内部实现机制或者状态管理导致的。

scrollEdge方法通常用于滚动到指定的边缘位置,其行为可能受到当前滚动状态、动画状态、边界条件等多种因素的影响。相比之下,scrollTo方法则直接设置滚动位置,不依赖于内部状态或动画,因此表现更为稳定。

考虑到scrollEdge方法的这种不确定性,如果你的应用场景需要稳定的滚动行为,建议使用scrollTo或类似的直接控制方法。此外,也可以检查是否在调用scrollEdge之前或之后,有其他代码或事件影响了Scroller的状态,导致滚动行为不一致。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部