【鸿蒙 HarmonyOS NEXT】组件嵌套滚动:nestedScroll

news2024/9/20 20:23:16

✨本人自己开发的开源项目:土拨鼠充电系统

✨踩坑不易,还希望各位大佬支持一下,在GitHub给我点个 Start ⭐⭐👍👍

GitHub开源项目地址👉:https://github.com/cheinlu/groundhog-charging-system

一、背景

当滚动组件进行嵌套关系时,如果两个组件需要同时滚动可能会产生互斥效果,使用nestedScroll属性来解决嵌套组件的滚动问题

可滚动组件:Scroll、List、WaterFlow,这些组件中都有包含nestedScroll属性,用于解决组件嵌套的滚动联动

二、场景

tabs嵌套list组件,当tabs切换页签时,会与list组件的滚动出现互斥效果,期望按住文本或按钮区域都能实现切换页签效果

具体描述:

tabs下面展示文本信息与按钮,其中按钮是用list组件完成的,当按钮多的情况下是可以滚动按钮,目前问题是按住文本区域是可以左右切换tabs页签的,按住按钮区域切换tab就不行,怀疑是list滚动与tab页签切换互斥了

三、具体实现

3.1、示例代码

@Entry
@Component
struct TabsExample {
  @State fontColor: string = '#182431'
  @State selectedFontColor: string = '#007DFF'
  @State currentIndex: number = 0
  private controller: TabsController = new TabsController()

  @Builder
  tabBuilder(index: number, name: string) {
    Column() {
      Text(name)
        .fontColor(this.currentIndex === index ? this.selectedFontColor : this.fontColor)
        .fontSize(16)
        .fontWeight(this.currentIndex === index ? 500 : 400)
        .lineHeight(22)
        .margin({ top: 17, bottom: 7 })
      Divider()
        .strokeWidth(2)
        .color('#007DFF')
        .opacity(this.currentIndex === index ? 1 : 0)
    }.width('100%')
  }

  build() {
    Column() {
      Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) {
        TabContent() {
          OrderList({ type: '1' })
        }
        .tabBar(this.tabBuilder(0, 'green'))
        .gesture(PanGesture(new PanGestureOptions({ direction: PanDirection.Right })))

        TabContent() {
          OrderList({ type: '2' })
        }.tabBar(this.tabBuilder(1, 'blue'))

        TabContent() {
          OrderList({ type: '3' })
        }.tabBar(this.tabBuilder(2, 'yellow'))

        TabContent() {
          OrderList({ type: '4' })
        }
        .tabBar(this.tabBuilder(3, 'pink'))
        .gesture(PanGesture(new PanGestureOptions({ direction: PanDirection.Left })))
      }
      .vertical(false)
      .barMode(BarMode.Fixed)
      .barWidth(360)
      .barHeight(56)
      .animationDuration(400)
      .onChange((index: number) => {
        this.currentIndex = index
      })
      .width(360)
      .height(296)
      .margin({ top: 52 })
      .backgroundColor('#F1F3F5')
    }.width('100%')
  }
}


@Component
struct OrderList {
  @Prop type: string

  build() {
    Column() {
      Column({ space: 30 }) {
        Row() {
          Text('文本' + this.type)
        }

        Row() {
          Text('文本' + this.type)
        }

        Row() {
          Text('文本' + this.type)
        }
      }
      .width('100%')
      .height(150)

      List() {
        ListItem() {
          Row() {
            Text('取消订单' + this.type).fontSize(13).fontColor('#222427')
          }
          .padding({
            left: 12,
            right: 12,
            top: 5,
            bottom: 5
          })
          .border({
            width: 1,
            radius: 4,
            color: '#C9CED3',
            style: BorderStyle.Solid
          })
        }

        ListItem() {
          Row() {
            Text('查看发票' + this.type).fontSize(13).fontColor('#222427')
          }
          .padding({
            left: 12,
            right: 12,
            top: 5,
            bottom: 5
          })
          .border({
            width: 1,
            radius: 4,
            color: '#C9CED3',
            style: BorderStyle.Solid
          })
        }

        ListItem() {
          Row() {
            Text('申请发票' + this.type).fontSize(13).fontColor('#222427')
          }
          .padding({
            left: 12,
            right: 12,
            top: 5,
            bottom: 5
          })
          .border({
            width: 1,
            radius: 4,
            color: '#C9CED3',
            style: BorderStyle.Solid
          })
        }

        ListItem() {
          Row() {
            Text('退换货' + this.type).fontSize(13).fontColor('#222427')
          }
          .padding({
            left: 12,
            right: 12,
            top: 5,
            bottom: 5
          })
          .border({
            width: 1,
            radius: 4,
            color: '#C9CED3',
            style: BorderStyle.Solid
          })
        }

        ListItem() {
          Row() {
            Text('去支付' + this.type).fontSize(13).fontColor('#222427')
          }
          .padding({
            left: 12,
            right: 12,
            top: 5,
            bottom: 5
          })
          .border({
            width: 1,
            radius: 4,
            color: '#C9CED3',
            style: BorderStyle.Solid
          })
        }
      }
      .listDirection(Axis.Horizontal)
      .scrollBar(BarState.Off)
      .edgeEffect(EdgeEffect.None)
      .width('100%')
    }
    .width('100%')
  }
}

3.2、实现效果 

3.3、完成预期效果:按住按钮区域也能切换页签

解决方法:给list添加nestedScroll属性,解决嵌套组件的滚动问题

详细代码:


@Entry
@Component
struct TabsExample {
  @State fontColor: string = '#182431'
  @State selectedFontColor: string = '#007DFF'
  @State currentIndex: number = 0
  private controller: TabsController = new TabsController()

  @Builder
  tabBuilder(index: number, name: string) {
    Column() {
      Text(name)
        .fontColor(this.currentIndex === index ? this.selectedFontColor : this.fontColor)
        .fontSize(16)
        .fontWeight(this.currentIndex === index ? 500 : 400)
        .lineHeight(22)
        .margin({ top: 17, bottom: 7 })
      Divider()
        .strokeWidth(2)
        .color('#007DFF')
        .opacity(this.currentIndex === index ? 1 : 0)
    }.width('100%')
  }

  build() {
    Column() {
      Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) {
        TabContent() {
          OrderList({ type: '1' })
        }
        .tabBar(this.tabBuilder(0, 'green'))
        .gesture(PanGesture(new PanGestureOptions({ direction: PanDirection.Right })))

        TabContent() {
          OrderList({ type: '2' })
        }.tabBar(this.tabBuilder(1, 'blue'))

        TabContent() {
          OrderList({ type: '3' })
        }.tabBar(this.tabBuilder(2, 'yellow'))

        TabContent() {
          OrderList({ type: '4' })
        }
        .tabBar(this.tabBuilder(3, 'pink'))
        .gesture(PanGesture(new PanGestureOptions({ direction: PanDirection.Left })))
      }
      .vertical(false)
      .barMode(BarMode.Fixed)
      .barWidth(360)
      .barHeight(56)
      .animationDuration(400)
      .onChange((index: number) => {
        this.currentIndex = index
      })
      .width(360)
      .height(296)
      .margin({ top: 52 })
      .backgroundColor('#F1F3F5')
    }.width('100%')
  }
}


@Component
struct OrderList {
  @Prop type: string

  build() {
    Column() {
      Column({ space: 30 }) {
        Row() {
          Text('文本' + this.type)
        }

        Row() {
          Text('文本' + this.type)
        }

        Row() {
          Text('文本' + this.type)
        }
      }
      .width('100%')
      .height(150)

      List() {
        ListItem() {
          Row() {
            Text('取消订单' + this.type).fontSize(13).fontColor('#222427')
          }
          .padding({
            left: 12,
            right: 12,
            top: 5,
            bottom: 5
          })
          .border({
            width: 1,
            radius: 4,
            color: '#C9CED3',
            style: BorderStyle.Solid
          })
        }

        ListItem() {
          Row() {
            Text('查看发票' + this.type).fontSize(13).fontColor('#222427')
          }
          .padding({
            left: 12,
            right: 12,
            top: 5,
            bottom: 5
          })
          .border({
            width: 1,
            radius: 4,
            color: '#C9CED3',
            style: BorderStyle.Solid
          })
        }

        ListItem() {
          Row() {
            Text('申请发票' + this.type).fontSize(13).fontColor('#222427')
          }
          .padding({
            left: 12,
            right: 12,
            top: 5,
            bottom: 5
          })
          .border({
            width: 1,
            radius: 4,
            color: '#C9CED3',
            style: BorderStyle.Solid
          })
        }

        ListItem() {
          Row() {
            Text('退换货' + this.type).fontSize(13).fontColor('#222427')
          }
          .padding({
            left: 12,
            right: 12,
            top: 5,
            bottom: 5
          })
          .border({
            width: 1,
            radius: 4,
            color: '#C9CED3',
            style: BorderStyle.Solid
          })
        }

        ListItem() {
          Row() {
            Text('去支付' + this.type).fontSize(13).fontColor('#222427')
          }
          .padding({
            left: 12,
            right: 12,
            top: 5,
            bottom: 5
          })
          .border({
            width: 1,
            radius: 4,
            color: '#C9CED3',
            style: BorderStyle.Solid
          })
        }
      }
      .listDirection(Axis.Horizontal)
      .scrollBar(BarState.Off)
      .edgeEffect(EdgeEffect.None)
      .width('100%')
      .nestedScroll({
        scrollForward: NestedScrollMode.SELF_FIRST,
        scrollBackward: NestedScrollMode.SELF_FIRST
      })
    }
    .width('100%')
  }
}

四、nestedScroll介绍

nestedScroll:设置向前向后两个方向上的嵌套滚动模式,实现与父组件的滚动联动。

参数名类型必填说明
valueNestedScrollOptions嵌套滚动选项。

NestedScrollOptions对象说明

名称类型必填描述
scrollForwardNestedScrollMode滚动组件往末尾端滚动时的嵌套滚动选项。
scrollBackwardNestedScrollMode滚动组件往起始端滚动时的嵌套滚动选项。

NestedScrollMode枚举说明

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2145032.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java SE基础知识详解:源于技术书籍的深度解读

写在前面 ⭐️在无数次的复习巩固中,我逐渐意识到一个问题:面对同样的面试题目,不同的资料来源往往给出了五花八门的解释,这不仅增加了学习的难度,还容易导致概念上的混淆。特别是当这些信息来自不同博主的文章或是视…

Day02Day03

1. 为什么拦截器不会去拦截/admin/login上,是因为在SpringMvc中清除了这种可能。 2.使用自己定义注解,实现AOP(insert ,update) 3.使用update最好使用动态语句,可以使用多次 4.使用阿里云的OSS存储。用common类 5.在写…

Python 课程16-Pygame

前言 Pygame 是一个基于 Python 的游戏开发库,专门用于多媒体应用程序开发,特别是 2D 游戏。它提供了处理图像、声音、键盘、鼠标等交互功能的 API,并且能够与 OpenGL 集成,用于更复杂的图形操作。Pygame 是初学者和业余开发者学…

erlang学习:mnesia数据库与ets表1

Mnesia 和 ETS 都是 Erlang 提供的表管理工具,用于存储和检索数据,但它们之间有一些重要的区别和共同点。 共同点 都是Erlang提供的表存储机制:ETS 和 Mnesia 都允许你在内存中创建表,并且可以用来存储键值对或者更复杂的数据结…

实战16-RVP定义完成适配

新增文件 //设计搞总宽度 const DRAFT_WIDTH 360//将元素的设计搞大小转化为真机中的大小 export default function rvp(val: number) {/*计算元素真正的大小;* 元素在设计稿的大小 / 设计搞总宽度 x / 真机宽度 (保证元素在不同设备占比相同)x 元素在设计稿的大…

论文不会写?分享6款AI论文写作免费一键生成网站!

在当今学术研究和写作领域,AI论文写作工具的出现极大地提高了写作效率和质量。这些工具不仅能够帮助研究人员快速生成论文草稿,还能进行内容优化、查重和排版等操作。本文将分享6款免费一键生成AI论文写作网站,并重点推荐千笔-AIPassPaper。 …

uniapp富文本editor输入二次扩展兼容微信小程序

在uni-app中开发富文本输入功能,并使其兼容微信小程序,需要注意一些特定的限制和解决方案。由于微信小程序本身对HTML的支持有限,直接在小程序中实现像Web那样完整的富文本编辑功能(如使用CKEditor、Quill等)是不可能的…

算法笔记/USACO Guide GOLD金组DP 3. Paths on Grids

今天学习背包DP(Knapsack DP) 是USACO Guide的DP章节中第三点 What is grid DP? -Summary DP problems often involve a 2D grid where paths are analyzed. Movement is restricted to one direction on the x-axis and y-axis, typically starting from one c…

AI修手有救了?在comfyui中使用Flux模型实现局部重绘案例

🐱‍🐉背景 局部重绘相关的话题我们已经讨论和测试过很多次了,比如说inpaint模型、brushnet模型、powerpaint模型等等,最近对于flux模型重绘画面的案例也越来越多了,那我们就结合flux模型的重绘来试试看效果。 &…

体验几款AI论文写作工具后,我认为这个最值得尝试!

开学随之而来的论文写作肯定又让你头疼了吧,而现如今随着AI技术的飞快发展,许多人巧妙地借助AI论文辅助工具,迅速搭建起论文的基本框架,然后一键生成万字正文内容,准确获得大量文献引用,使得整个论文创作过…

[深度学习]Pytorch框架

1 深度学习简介 应用领域:语音交互、文本处理、计算机视觉、深度学习、人机交互、知识图谱、分析处理、问题求解 2 发展历史 1956年人工智能元年2016年国内开始关注深度学习2017年出现Transformer框架2018年Bert和GPT出现2022年,chatGPT出现&#xff0…

基于python+django+vue的美术馆预约系统

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于协同过滤pythondjangovue…

WSL中使用AMBER GPU串行版

前提是已经安装过wsl 1 在 WSL 2 中启用 NVIDIA CUDA 参考在 WSL 2 上启用 NVIDIA CUDA | Microsoft Learn 注意:勿在 WSL 中安装任何 Linux 显示驱动程序。Windows 显示驱动程序将同时安装本机 Windows 和 WSL 支持的常规驱动程序组件。 2 在WSL2中配置Cuda 不安…

SEO之页面优化(一-页面标题2)

初创企业搭建网站的朋友看1号文章;想学习云计算,怎么入门看2号文章谢谢支持: 1、我给不会敲代码又想搭建网站的人建议 2、“新手上云”能够为你开启探索云世界的第一步 博客:阿幸SEO~探索搜索排名之道 (接上一篇。。…

OpenCV_最简单的鼠标截取ROI区域

在OpenCV中也存在鼠标的操作,今天我们先介绍一下鼠标中的操作事件 void setMousecallback(const string& winname, MouseCallback onMouse, void* userdata0) setMousecallback参数说明: winname:窗口的名字 onMouse:鼠标响应函数,回调…

基于Springboot+vue的音乐网站

随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了音乐网站的开发全过程。通过分析音乐网站管理的不足,创建了一个计算机管理音乐网站的方案。文章介绍了音乐网站的系统分析部分,包括可行性分析…

828华为云征文|Flexus云服务器X实例部署宝塔运维面板

本次华为云Flexus云服务器X实例部署宝塔运维面板教学,这次是推陈出新啊 之前的云耀云服务器L实例已经很不错了,大力赞叹华为云的 同时感谢华为云提供优惠卷,只能说白嫖真是太棒了 华为云近期正在筹办华为云828企业节活动,90款免…

人类行为识别系统源码分享

人类行为识别检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

【资料分析】刷题日记1

第一套 第二个是相比2019年的增长率,错找为同比增长率 延申: 当出口和进口相比2019年的增长率相同时,可以用盐水解决 √ 一个假设分配(第二次是1.4取1)加法对比选项 基期倍数: 求A是B的多少倍&#x…

DBeaver纵向展示一行数据

DBeaver查询结果如果列数太多,横着看并不方便,这时可以点击左下角的【记录】按钮,然后可看到纵向的展示结果。如图 就这么一个小功能,没细看的话直接上网搜,不知为啥出来的都是一堆错误方法。所以这里记一下。