鸿蒙开发:使用nestedScroll解决滑动冲突

前言

本文基于Api13

在实际的开发中,滑动冲突在所难免,常见于可滚动的容器组件嵌套使用,比如Scroll组件嵌套List组件,List组件嵌套了Grid组件等等,只要是滚动容器组件嵌套,令人厌烦的滑动冲突就会扑面而来,十分让人抓狂;如何处理滑动冲突,成了开发中的必修之课,然而,鸿蒙当中的处理方式,相对与Android端而言,似乎更加的直观和简单,使用一个属性便可以搞定,那就是nestedScroll。

简单案例

案例很是简单,外层是一个Scroll滚动容器,内部也有一个List组件滚动组件,在List上面有一个普通的组件。

@Entry
@Component
struct Index {
  build() {
    Scroll() {
      Column() {
        Text("我是顶部的组件")
          .width("100%")
          .height(200)
          .textAlign(TextAlign.Center)
          .backgroundColor(Color.Pink)
          .fontColor(Color.White)

        List() {
          ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], (item: number) => {
            ListItem() {
              Text(item.toString())
                .width("100%")
                .height(80)
                .textAlign(TextAlign.Center)
            }
          })
        }
        .width("100%")
        .height("100%")
        .scrollBar(BarState.Off)
        .divider({ color: Color.Gray, strokeWidth: 1 })
        .edgeEffect(EdgeEffect.None)

      }
    }.width("100%")
    .height("100%")
    .scrollBar(BarState.Off)
  }
}

效果如下所示:

image.png

我们想要的效果是,先让顶部的组件滚动上去,然后再滚动下面的List组件,我们运行看下效果:

91001.gif

显然未达到我们的效果,这就是滑动冲突导致的,这种情况下,做为子组件的List组件,一定是先把滑动事件交给Scroll组件,等Scroll组件滚动到边缘后,再把滑动事件交给自己,这样的流程也是正确的,如何做到呢,前边已经说过了,那就是nestedScroll属性。

每个滚动容器组件都有一个nestedScroll属性,主要解决嵌套滚动模式下的的滑动冲突,我们给List组件设置一下,代码如下:

.nestedScroll({
          scrollForward: NestedScrollMode.PARENT_FIRST,
          scrollBackward: NestedScrollMode.SELF_FIRST
        })

设置完后,再看下效果:

91002.gif

可以看到,已经完美的解决了滑动冲突,达到了我们想要的效果。

了解nestedScroll

通过前言中的案例,我们基本上已经知道了nestedScroll属性的作用,主要是,用于设置嵌套滚动选项,设置前后两个方向的嵌套滚动模式,实现与父组件的滚动联动。

image.png

我们重点关注一下NestedScrollOptions这个参数,其中有两个值,分别是scrollForward和scrollBackward,一个代表往末尾端滚动,一个代表往起始端滚动。

image.png

两个参数都有一个共同的值类型NestedScrollMode,可供选择的有以下几个值:

名称 说明
SELF_ONLY 只自身滚动,不与父组件联动。
SELF_FIRST 自身先滚动,自身滚动到边缘以后父组件滚动。父组件滚动到边缘以后,如果父组件有边缘效果,则父组件触发边缘效果,否则子组件触发边缘效果。
PARENT_FIRST 父组件先滚动,父组件滚动到边缘以后自身滚动。自身滚动到边缘后,如果有边缘效果,会触发自身的边缘效果,否则触发父组件的边缘效果。
PARALLEL 自身和父组件同时滚动,自身和父组件都到达边缘以后,如果自身有边缘效果,则自身触发边缘效果,否则父组件触发边缘效果。

举例使用

前言中,我们简单使用Scroll组件嵌套List组件举了一个例子,我们再来看一个Scroll组件嵌套Web组件的案例。

import webview from **********'

@Entry
@Component
struct Index {
  private controller: webview.WebviewController = new webview.WebviewController()

  build() {

    Scroll() {
      Column() {
        Text("我是顶部的组件")
          .width("100%")
          .height(200)
          .textAlign(TextAlign.Center)
          .backgroundColor(Color.Pink)
          .fontColor(Color.White)

        Web({
          src: "https://juejin.cn/user/1398234520239095/columns",
          controller: this.controller
        })
          .nestedScroll({
            scrollForward: NestedScrollMode.PARENT_FIRST,
            scrollBackward: NestedScrollMode.SELF_FIRST
          })

      }
    }.width("100%")
    .height("100%")
    .scrollBar(BarState.Off)

  }
}

以上的效果和前言中基本一致,不在贴效果了,其实再多的案例,基本上都是一样的,只是nestedScroll中的值不一样而已。

相关总结

在实际的开发中,远远要比前边的案例复杂,比如我之前封装的刷新库,滚动组件上面有刷新头,下面也有加载尾,还有更复杂的,列表吸顶操作等等,一个nestedScroll属性是远远不够的,往往还要和滑动监听,是否滚动到了顶部和尾部等相结合,才能实现我们实际的效果。

比如,还是以上的案例,我们在List组件下面再增加一个底部的组件,我们运行看下效果:

显然之前配置的nestedScroll属性只满足了顶部的组件,而底部的组件在滑动的过程中明显有滑动冲突,并没有达到我们的预期,其实对于底部,上滑是先滚动自己后滚动父组件,下滑是要先滚动父组件,然后再去滚动自身组件的。

91003.gif

针对以上的问题,其实处理有多种方式,最简单的莫过于,底部组件在最后一个组件下面,当做List组件的部分,当然了顶部组件也可以这么去做,这样就不存在滑动冲突。

if (index == this.dataArray.length - 1) {
                Column() {
                  Text(item.toString())
                    .width("100%")
                    .height(80)
                    .textAlign(TextAlign.Center)
                  
                  Text("我是底部的组件")
                    .width("100%")
                    .height(200)
                    .textAlign(TextAlign.Center)
                    .backgroundColor(Color.Pink)
                    .fontColor(Color.White)
                }

  }

我们看下效果:

91004.gif

把组件加到首尾数据的位置,这种方式会存在一个问题,比如说,如果没有数据呢?顶部组件和底部组件那么就无法显示,再比如如果加载的不是List组件,而是一个Grid组件或者其他的滚动组件呢?显然处理上有很大的问题。

这个作业留给友友们,你们知道如何解决吗?

#鸿蒙开发#
鸿蒙点石成金 文章被收录于专栏

简单的也好,复杂的也罢,关于HarmonyOS,总要深入浅出,总要步步为赢。

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务