鸿蒙开发协调布局CollapsibleLayout

鸿蒙开发协调布局CollapsibleLayout

首先鸿蒙我暂时没找到官方提供的协调布局,所以得自己自定义。

一、思路

可滚动头部、粘性头部、可滚动内容布局
可折叠区域高度=可滚动头部高度-粘性头部高度

二、效果图

鸿蒙开发协调布局CollapsibleLayout

三、关键代码
// 联系:893151960
@Component
export struct CollapsibleLayout {@Builder AppBarInitBuilder() {}// 标题栏@BuilderParam AppBarBuilder: () => void = this.AppBarInitBuilder@Builder ScrollableHeaderInitBuilder() {}// 可滚动头部@BuilderParam ScrollableHeaderBuilder: () => void = this.ScrollableHeaderInitBuilder@Builder StickyHeaderInitBuilder() {}// 粘性头部@BuilderParam StickyHeaderBuilder: () => void = this.StickyHeaderInitBuilder// 页面内容部分,通常为列表@Builder ContentInitBuilder() {}@BuilderParam ContentBuilder: () => void = this.ContentInitBuilder@ObjectLink mediator: CollapsibleMediator// 标题栏高度@State appBarHeight: number = 0// 可滚动头部高度@State  scrollableHeaderHeight: number = 0// 粘性头部高度@State  stickyHeaderHeight: number = 0//  组件高度@State  totalHeight: number = 0lastProgress = 0showAppBar:boolean = truecalculateContentHeight() {if (this.totalHeight != 0 && this.stickyHeaderHeight != 0 ) {return this.totalHeight - this.stickyHeaderHeight - this.appBarHeight}return 2000}/*** 计算可折叠区域高度、内容区域高度*/calculateCoordinatorScrollableHeight() {if ( this.scrollableHeaderHeight != 0 && this.totalHeight != 0 && this.stickyHeaderHeight != 0) {this.mediator.coordinatorScrollableHeight = this.scrollableHeaderHeight - this.appBarHeight}}updateCollapsibleScrollProgress() {if (this.mediator.collapsibleScrollProgressCallback) {const progress = this.mediator.curCoordinatorOffset() / this.mediator.coordinatorScrollableHeightif (this.lastProgress != progress && Math.abs(this.lastProgress - progress) >= 0.01 || progress == 1) {// if (this.lastProgress != progress) {this.mediator.collapsibleScrollProgressCallback(progress)this.lastProgress = progress}}}@Builder BodyBuilder() {// 粘性头部Stack() {this.StickyHeaderBuilder()}.onAreaChange((_, newValue: Area) => {this.stickyHeaderHeight = newValue.height as numberthis.calculateCoordinatorScrollableHeight()})// .zIndex(100)Stack() {this.ContentBuilder()}.height(this.calculateContentHeight())}build() {Stack({ alignContent: Alignment.Top }) {Scroll(this.mediator.outScroller) {Column() {// 可滚动容器Stack() {this.ScrollableHeaderBuilder()}.onAreaChange((_, newValue: Area) => {this.scrollableHeaderHeight = newValue.height as numberthis.calculateCoordinatorScrollableHeight()})this.BodyBuilder()}}.scrollable(ScrollDirection.Vertical).scrollBar(BarState.Off).edgeEffect(EdgeEffect.None).height(this.totalHeight != 0 ? this.totalHeight : 10000).onWillScroll(() => {this.updateCollapsibleScrollProgress()}).onScrollFrameBegin((offset: number, _) => {if (offset > 0) { // 向上if (this.mediator.isShrink()) { // 可折叠区域完全折叠return { offsetRemain: 0 }} else {return { offsetRemain: offset }}}if (offset < 0) { // 向下if (this.mediator.isExpand()) { // 可折叠区域完全张开return { offsetRemain: 0 }} else {return { offsetRemain: offset }}}return { offsetRemain: offset }})// 固定标题栏if (this.showAppBar){Stack() {this.AppBarBuilder()}.width("100%").onAreaChange((_, newValue: Area) => {this.appBarHeight = newValue.height as numberthis.calculateCoordinatorScrollableHeight()})}}.width("100%").onAreaChange((_, newValue: Area) => {this.totalHeight = newValue.height as numberthis.calculateCoordinatorScrollableHeight()})}
}@Observed
export class CollapsibleMediator {// 内部可滚动容器集合innerScrollerArrays: Scroller[] = new Array<Scroller>()// 可折叠区域的高度(scrollableHeader-appBarHeight-stickyHeaderHeight)coordinatorScrollableHeight: number = 0curInnerScrollerIndex = 0// 可折叠区域滑动进度回调collapsibleScrollProgressCallback?: (progress: number) => voidoutScroller = new Scroller()constructor(coordinatorScrollProgressCallback?: (progress: number) => void ) {this.collapsibleScrollProgressCallback = coordinatorScrollProgressCallback}getCurrentInnerScroller(index?: number) {const curIndex = index ? index : 0if (this.innerScrollerArrays[curIndex] == null) {this.innerScrollerArrays[curIndex] = new Scroller()}return this.innerScrollerArrays[curIndex]}getCurrentInnerScrollerOffset() {let y = this.innerScrollerArrays?.[this.curInnerScrollerIndex]?.currentOffset()?.yOffsetreturn (y ? y : 0) | 0}curCoordinatorOffset() {return this.outScroller.currentOffset().yOffset}getScrollerFrameRemainOffset(offset: number): number {if (!this.isShrink() && offset > 0) { // 向上this.outScroller.scrollBy(0, offset)return 0}if (this.getCurrentInnerScrollerOffset() == 0 && offset < 0) { // 向下this.outScroller.scrollBy(0, offset)return 0}return offset}setCurInnerScrollerIndex(index: number) {if (this.curInnerScrollerIndex !== index) {this.curInnerScrollerIndex = index}}isExpand() {return this.curCoordinatorOffset() === 0}isShrink() {return this.coordinatorScrollableHeight !== 0 && Math.abs(this.curCoordinatorOffset() - this.coordinatorScrollableHeight) <= 0.0001}expand() {this.outScroller.scrollTo({ xOffset: 0, yOffset: 0,animation: { duration: 300, curve: Curve.Linear } })}shrink() {this.outScroller.scrollTo({ xOffset: 0, yOffset: this.coordinatorScrollableHeight,animation: { duration: 300, curve: Curve.Linear } })}
}
四、项目demo结构图

在这里插入图片描述有需要完整源码可私信或者看昵称联系我

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

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

相关文章

优思学院|如何从零开始自己学习六西格玛?

优思学院为学习六西格玛管理的学员&#xff0c;精心推荐了几本由浅入深、系统全面的书籍&#xff0c;帮助大家从入门到精通&#xff0c;逐步掌握六西格玛这一强大的管理工具。无论你是刚接触六西格玛的初学者&#xff0c;还是想在专业领域提升的高级学员&#xff0c;这几本书都…

【ARM】Trustzone和安全架构

Trustzone的基本概念&背景和历史 什么是Trustzone&#xff1f; 什么是TEE&#xff1f; Trustzone是一个技术&#xff0c;是一个技术的设计&#xff0c;一个安全架构&#xff0c;既不是软件也不是硬件。 TEE (Trusted Execution Environment) 可信执行环境。就是依托Trust…

速响低代码平台:升级营销管理系统,开启高效无忧新体验!

当前日新月异的商业环境&#xff0c;企业面临着前所未有的挑战与机遇。随着市场竞争的日益加剧和企业业务的不断拓展&#xff0c;传统的营销方式和管理手段逐渐显露出其局限性&#xff0c;难以适应快速变化的市场需求。 数据收集难&#xff1a;传统的营销管理缺乏对客户数据的收…

战神诸神黄昏9月19日登录PC端! 手机怎么玩战神诸神黄昏

9月19日&#xff0c;《战神&#xff1a;诸神黄昏》正式登录PC端&#xff0c;这是一部动作冒险游戏。要是你想随时随地在手机或平板上也能玩《战神&#xff1a;诸神黄昏》&#xff0c;可以使用网易GameViewer远程帮你实现。 网易GameViewer远程作为一款专为游戏玩家打造的远程软…

轻松让U盘数据恢复的教程:一步步指导,快速找回丢失文件

在日常使用U盘的过程中&#xff0c;我们可能会不小心删除或格式化了一些重要文件&#xff0c;导致数据丢失。面对这种情况&#xff0c;很多人可能会感到焦虑和无助。但其实&#xff0c;只要掌握了正确的方法&#xff0c;U盘数据的恢复并不复杂。本文将为大家提供一份详细的教程…

LIN总线CAPL函数——校验和段(Checksum)测试(linGetChecksum)

&#x1f345; 我是蚂蚁小兵&#xff0c;专注于车载诊断领域&#xff0c;尤其擅长于对CANoe工具的使用&#x1f345; 寻找组织 &#xff0c;答疑解惑&#xff0c;摸鱼聊天&#xff0c;博客源码&#xff0c;点击加入&#x1f449;【相亲相爱一家人】&#x1f345; 玩转CANoe&…

57.【C语言】字符函数和字符串函数(strerror函数)

11.strerror函数 *简单使用 strerror string error cpuscplus的介绍 点我跳转 翻译: 函数 strerror char * strerror ( int errnum ); 得到指向错误信息字符串(简称错误码)的指针 解释errnum的值,产生一条描述错误情况的信息的字符串,就像被库函数设置为errno一样 这个返回的…

【新手上路】衡石分析平台使用手册-系统管理员手册

用户管理​ 用户管理页面可以创建管理用户、对用户进行分组管理、组织架构管理及用户属性的维护和管理。下面详细介绍用户管理相关功能。 用户管理​ 用户管理子页面展示了当前系统中所有用户的信息&#xff0c;可以添加新用户&#xff0c;查看、编辑已有用户&#xff0c;可…

解锁社交业务增长与合规“秘笈”,泛娱乐行业沙龙杭州站亮点一览!

在全球数字化浪潮的推动下&#xff0c;泛娱乐行业正迎来广阔的发展空间&#xff0c;与此同时&#xff0c;社交产品监管日益规范&#xff0c;海外市场机遇与挑战并存&#xff0c;游戏行业增速放缓等情况也不容忽视。如何在合规前提下&#xff0c;探求新的增长点成为从业者共同关…

CAN_FD和CAN2.0的不同点——深入浅出理解CAN协议(二)

本系列是在同公司硬件设计和验证同事&#xff0c;1、在完成了CANFD硬件接口IP开发 2、熟悉ISO-11898系列、ISO16845、CAN2.0协议、CANFD协议等以及大量学习资料 3、深入研究其他家CANFD IP&#xff08;NXP、BOSCH&#xff09;4、独立开发了对应底层驱动 5、通过CANoe和周立功CA…

Java Web服务运行一段时间后出现cpu升高导致的性能下降问题排查

背景 有个web服务&#xff0c;运行一段时间后&#xff0c;出现cpu逐渐占用高&#xff0c;服务处理请求整体性能下降问题。 异常情况时&#xff0c; 同时jvm的cpu上涨 最终表现为&#xff0c;处理内部逻辑执行耗时变高。 排查原因 原来服务的jvm启动参数带了 -XX:-TieredCom…

rocky9虚拟机配置双网卡的详细过程

编辑虚拟机配置->添加->选择网络适配器->确认->打开虚拟机 1.ip add查看第二个网卡的名称&#xff0c;我这里是ens36 2.cd到网卡的配置文件目录 cd /etc/NetworkManager/system-connections/ ls3.复制一份网卡的配置文件并改名为ens36.nmconnection(根据自己的第…

5V全桥驱动芯片单通道可替代型号LG9110S,应用于牙刷,电子锁,共享单车锁等产品中具有过温保护功能

芯片描述&#xff1a; GC9110 是一款低压 5V 全桥驱动芯片&#xff0c;为摄像机、消费类产品、玩具和其他低压或者电池供电的运动控制类应用提供了集成的电机驱动解决方案。GC9110 能提供高达 1.3A 的持续输出电流。可以工作在 2~6V 的电源电压上。GC9110 具有 PWM&#xff08;…

香橙派zero2w上手——环境配置添加OLED小屏幕

0 硬件参数 origin pi zero2W 硬件参数 CPU全志 H618 四核 64 位 1.5GHz Cortex-A53 处理器GPUMali G31 MP2&#xff0c;支持OpenGL ES 1.0/2.0/3.2&#xff0c;OpenCL 2.0&#xff0c;Vulkan 1.1内存LPDDR4:1GB/1.5GB/2GB/4GB (可选)存储SPI Flash: 16MBWiFi蓝牙WiFi蓝牙二合…

mysql时间戳格式化yyyy-mm-dd

格式化到 年月日 # 将时间换成列名就行&#xff1b;当前是秒级时间戳&#xff0c;如果是毫秒的 / 1000即可 # SELECT FROM_UNIXTIME(1602668106666.777888999 / 1000,%Y-%m-%d) AS a; # SELECT FROM_UNIXTIME(列名 / 1000,%Y-%m-%d) AS a; SELECT FROM_UNIXTIME(1602668106.666…

办公生产力工具 职场打工人早下班宝藏神器推荐

当你外出时&#xff0c;电脑不在身边&#xff0c;但需要处理文件怎么办&#xff1f;这时&#xff0c;你需要一个提高办公生产力工具。网易GameViewer远程控制软件可以帮助你轻松实现这一目标&#xff0c;简直是职场打工人早下班宝藏神器。 GameViewer远程可以一键直连无需复杂配…

光控资本:美股,又新高!比特币也大涨!静待“关键时刻”

隔夜道指、标普500指数盘中再创新高后&#xff0c;日股开盘也体现强势。 当地时刻9月17日&#xff0c;美股三大指数收盘涨跌纷歧&#xff0c;标普500指数和道指盘中创新高后底子收平。中概股体现亮眼&#xff0c;纳斯达克我国金龙指数收涨1.83%&#xff0c;盘中一度涨超2.7%。…

Doris docker 安装

Doris docker 安装 安装地址 1. 操作系统配置初始化 1.1. 配置 vm.max_map_count sudo vim /etc/sysctl.conf追加以下配置&#xff1a; vm.max_map_count20000001.2. 关闭swap vim /etc/fstab注释配置如下&#xff1a; # /dev/mapper/centos-swap swap …

分布式锁总结1 - 为什么需要分布式锁?

目录 1. 最基本的业务逻辑是&#xff1a; 2. 高并发场景下常见的缓存问题 2.1问题一 缓存穿透 : 一直查询不存在的数据 解决方案 : 短暂缓存null结果 2.2 问题二 缓存雪崩 : 大量key同时过期大量请求直击数据库 解决方案 : 在原有的过期时间上加一个随机的值&#xff0c;…

Vue 自定义指令实战

引言 Vue自定义指令是Vue.js框架中强大而灵活的功能之一&#xff0c;它允许开发者根据具体需求创建自定义的指令&#xff0c;以实现更加精细化的交互和数据绑定效果。本文将带你深入探索Vue自定义指令的使用方法、原理和实战&#xff0c;为你打开前端开发的新视野。 我们前面…