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

程序员一鸣
• 阅读 9

前言

本文基于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)
  }
}

效果如下所示:

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

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

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

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

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

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

设置完后,再看下效果:

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

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

了解nestedScroll

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

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

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

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

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

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

举例使用

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

import webview from '@ohos.web.webview'

@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属性只满足了顶部的组件,而底部的组件在滑动的过程中明显有滑动冲突,并没有达到我们的预期,其实对于底部,上滑是先滚动自己后滚动父组件,下滑是要先滚动父组件,然后再去滚动自身组件的。

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

针对以上的问题,其实处理有多种方式,最简单的莫过于,底部组件在最后一个组件下面,当做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)
                }

  }

我们看下效果:

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

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

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

点赞
收藏
评论区
推荐文章
Stella981 Stella981
3年前
Android 解决NestedScrollView 嵌套 RecyclerView出现的卡顿,上拉刷新无效
解决卡顿的方法最简单的就是设置RecyclerView的android:nestedScrollingEnabled"false",放弃自己的滑动,交给外部的NestedScrollView处理,就没有出现卡顿的现象了至于RecyclerView的上拉刷新,可以监听NestedScrollView的滑动监听,具体代码如下:mNestedSc
Wesley13 Wesley13
3年前
viewpager 和滑动条同步滚动
实现上面的radiobutton和viewpager同步滚动太过复杂,请直接使用开源项目PagerSlidingTabStrip(http://my.oschina.net/sldk/blog/402638)共有6个的页面,导航栏用horizontalscrollview封装radiogroup。点击radiobutton跳转到对应的页面。滑动p
Stella981 Stella981
3年前
Android如何实现一个上拉刷新下拉加载的ListView
20191220关键字:自定义上下拉ListView在APK开发中,一个具备在列表顶部下拉刷新、在列表尾部上拉加载功能的ListView的需求还是比较多的。具备这种功能的优秀开源代码同样也有很多。但今天,笔者就非要自己实现一个这样的控件不可。以下是成品效果图:!(https://oscimg.oschin
陈杨 陈杨
2天前
鸿蒙5开发宝藏案例分享---Web加载时延优化解析
当然可以!下面是一篇详细、易懂的文章,结合鸿蒙官方案例和实际代码,帮你深入理解Web加载完成时延的优化技巧👇🚀鸿蒙开发宝藏:Web加载完成时延优化实战(附代码解析)大家好呀!今天在翻鸿蒙开发者文档时,发现了一个隐藏的​​性能优化宝藏区​​——官方竟然悄
陈杨 陈杨
2天前
鸿蒙5开发宝藏案例分享---Grid性能优化案例
发现鸿蒙宝藏:优化Grid组件性能的实战技巧!大家好呀!最近在鸿蒙开发者社区挖到一个超实用的性能优化案例——​​解决Grid组件加载慢、滚动卡顿的问题​​。官方其实藏了不少宝藏案例,但很多人可能没注意到。今天我就带大家拆解这个案例,加上详细讲解和代码分析,
布局王 布局王
9小时前
鸿蒙Next仓颉语言开发实战教程:下拉刷新和上拉加载更多
在移动应用中,各种列表页面离不开下拉刷新和上拉加载更多,我们的商城应用也是如此。今天介绍一下在仓颉开发语言中如何实现这一功能。下拉刷新仓颉开发语言直接提供了下拉刷新的组件,叫做Refresh,使用起来也非常方便:@StatevarheaderLoading
程序员一鸣 程序员一鸣
9小时前
鸿蒙开发:如何实现列表吸顶
ListItemGroup组件的使用,可以说是非常的简单,如果仅仅是普通的吸顶,建议直接使用即可,如果您需要带有下拉刷新和上拉加载效果的,可以使用refresh组提供的,在使用原生的时候,有一点需要注意,那就是需要设置List组件的sticky属性,否则吸顶效果是不生效的。
程序员一鸣 程序员一鸣
9小时前
鸿蒙开发:实现一个标题栏吸顶
本身并不难,处理好滑动位置和手势即可,当然了,里面也有两个注意的点,一个是解决手势冲突的nestedScroll,这个之前的文章中讲过,还有一个就是拦截瀑布流组件的滑动事件,在某些状态下禁止它的滑动。
陈杨 陈杨
2天前
鸿蒙5开发宝藏案例分享---体验流畅的首页信息流
🌟鸿蒙新闻类首页开发全攻略:流畅动效懒加载实战Hey各位鸿蒙开发者!今天要分享一个超实用的鸿蒙新闻类首页开发方案,官方文档里藏着的宝藏案例被我挖出来了!从流畅的Tab切换动效到丝滑的懒加载列表,手把手带大家实现高性能新闻首页👇🚀整体场景效果用户操作
陈杨 陈杨
2天前
鸿蒙5开发宝藏案例分享---Web页面内点击响应时延分析
当然可以!下面是一篇详细、易懂的文章,结合鸿蒙官方案例和实际代码,帮你深入理解Web加载完成时延的优化技巧👇🚀鸿蒙开发宝藏:Web加载完成时延优化实战(附代码解析)大家好呀!今天在翻鸿蒙开发者文档时,发现了一个隐藏的​​性能优化宝藏区​​——官方竟然悄