photoshop网站视觉设计步骤,东平网站建设,购物商城网站开发目的文档,软件开发外包公司有哪些HarmonyOS鸿蒙 Next 实现协调布局效果
假期愉快! 最近大A 的涨势实在是红的让人晕头转向#xff0c;不知道各位收益如何#xff0c;这会是在路上#xff0c;还是已经到目的地了?
言归正传#xff0c;最近有些忙#xff0c;关于鸿蒙的实践系列有些脱节了#xff0c;…HarmonyOS鸿蒙 Next 实现协调布局效果
假期愉快! 最近大A 的涨势实在是红的让人晕头转向不知道各位收益如何这会是在路上还是已经到目的地了?
言归正传最近有些忙关于鸿蒙的实践系列有些脱节了趁着放假给大家上点干货.
我们先来看个效果 源码地址放这里了想看具体实现的接着往下看 ↓↓↓↓ 做过Android开发的都知道 这个是Android Material Design中的 协调布局CoordinatorLayout的效果。协调布局能够让页面元素在滚动时动态响应比如可滚动的头部、悬停的 Tab 栏以及可滚动的内容区域。 这种布局提升了用户的交互体验特别是在内容较多且需要分段展示的场景下。
但是我们翻遍了 鸿蒙的ARK UI都没有这个组件和效果的实现。所以我们今天一起来实现一下这个效果.
首先我们分析下这个效果要实现的三个关键要素
可滚动的头部区域如图片、标题等。粘性头部区域Tab 页签等当页面滑动到一定程度时需要悬停。可滚动的内容区域具体的 Tab 页面内容如列表或其他内容。
接下来我们将详细介绍如何在 HarmonyOS Next 实现协调布局包括滑动冲突的处理和粘性头部悬停的实现。 实现原理
协调布局的核心在于处理页面的多区域滑动冲突并确保粘性头部在滚动时能够悬停。实现这种布局需要使用以下几个关键组件
CoordinatorLayout用于整体布局管理处理可滚动的头部、粘性头部和内容区域的协调滚动。CollapsibleMediator负责管理滚动状态协调可滚动头部、粘性头部与内容区域的联动关系。自定义 Builder也就是我们上面所介绍的3个核心要素实现不同布局部分的构建如 ScrollableHeaderBuilder、StickyHeaderBuilder 和 ContentBuilder。 组件介绍
1. CoordinatorLayout 组件
CoordinatorLayout 是页面的主要布局容器负责管理页面中不同区域头部、粘性头部、内容区域的布局和滚动逻辑。它的核心任务是根据用户的滚动行为动态调整各区域的显示状态确保当页面滚动到某个位置时粘性头部能够悬停。
Component
export struct CoordinatorLayout {BuilderParam ScrollableHeaderBuilder: () voidBuilderParam StickyHeaderBuilder: () voidBuilderParam ContentBuilder: () voidObjectLink mediator: CollapsibleMediatorbuild() {Stack({ alignContent: Alignment.Top }) {Scroll(this.mediator.outScroller) {Column() {// 可滚动的头部区域Stack() {this.ScrollableHeaderBuilder()}.onAreaChange((_, newValue: Area) {this.mediator.scrollableHeaderHeight newValue.height as number;this.mediator.calculateCoordinatorScrollableHeight();})// 粘性头部和内容区域this.BodyBuilder()}}.scrollable(ScrollDirection.Vertical).height(this.mediator.totalHeight ! 0 ? this.mediator.totalHeight : 10000).onScrollFrameBegin((offset: number, _) {return { offsetRemain: this.mediator.handleScroll(offset) };})}}Builder BodyBuilder() {// 粘性头部区域Stack() {this.StickyHeaderBuilder()}.onAreaChange((_, newValue: Area) {this.mediator.stickyHeaderHeight newValue.height as number;this.mediator.calculateCoordinatorScrollableHeight();})// 内容区域Stack() {this.ContentBuilder()}.height(this.mediator.calculateContentHeight())}
}2.CollapsibleMediator 组件
CollapsibleMediator 是协调滚动行为的核心组件。它管理了页面的滚动状态处理各个区域的联动确保粘性头部悬停和内容的平滑滚动。关键任务包括计算折叠区域高度、处理滚动进度并在不同滚动方向时作出响应。
Observed
export class CollapsibleMediator {innerScrollerArrays: Scroller[] new ArrayScroller()coordinatorScrollableHeight: number 0curInnerScrollerIndex 0collapsibleScrollProgressCallback?: (progress: number) voidoutScroller new Scroller()getCurrentInnerScroller(index: number) {if (!this.innerScrollerArrays[index]) {this.innerScrollerArrays[index] new Scroller()}return this.innerScrollerArrays[index]}handleScroll(offset: number): number {if (offset 0 this.isShrink()) {return 0;} else if (offset 0 this.isExpand()) {return 0;}return offset;}isExpand() {return this.curCoordinatorOffset() 0;}isShrink() {return Math.abs(this.curCoordinatorOffset() - this.coordinatorScrollableHeight) 0.0001;}curCoordinatorOffset() {return this.outScroller.currentOffset().yOffset;}calculateCoordinatorScrollableHeight() {if (this.scrollableHeaderHeight ! 0 this.totalHeight ! 0 this.stickyHeaderHeight ! 0) {this.coordinatorScrollableHeight this.scrollableHeaderHeight - this.appBarHeight;}}calculateContentHeight() {if (this.totalHeight ! 0 this.stickyHeaderHeight ! 0) {return this.totalHeight - this.stickyHeaderHeight;}return 2000;}
}
3.滑动冲突的处理
在协调布局中页面通常包含多个滚动区域如可滚动的头部、粘性头部和可滚动的内容区域。这些区域之间的滑动冲突需要通过 CollapsibleMediator 来协调。 问题滑动冲突
当页面有多个可滚动区域时滚动冲突容易发生。例如当用户向上滑动时如何确定是滚动头部、粘性头部还是内容区域为了解决这些冲突我们需要确保不同区域在特定条件下有不同的滚动响应。 解决方案滚动优先级处理
CollapsibleMediator 通过监控滚动事件根据滚动的方向和当前区域的状态来决定如何处理滚动 向上滑动如果粘性头部未完全折叠则优先折叠头部当头部完全折叠后内容区域开始滚动。 向下滑动如果内容区域已经滚动到顶部则展开粘性头部当粘性头部完全展开后再展开可滚动头部。
关键逻辑: handleScroll(offset: number): number {if (offset 0) { // 向上滑动if (this.isShrink()) { // 当折叠区域完全折叠时return 0; // 停止滑动} else {return offset; // 继续折叠头部}} else if (offset 0) { // 向下滑动if (this.isExpand()) { // 当折叠区域完全展开时return 0; // 停止滑动} else {return offset; // 继续展开头部}}return offset;
}
4.粘性头部悬停的判断
悬停效果的关键是 粘性头部区域通常是滑动组件在滚动时应固定在页面顶部。为了实现这一效果CollapsibleMediator 会监听页面的滚动位置当粘性头部到达顶部时将其固定不再滚动。 悬停的核心逻辑悬停的判断依赖于当前滚动偏移量和可折叠区域的高度。当滚动达到某个临界值时粘性头部进入悬停状态
isShrink() {return Math.abs(this.curCoordinatorOffset() - this.coordinatorScrollableHeight) 0.0001;
}isExpand() {return this.curCoordinatorOffset() 0;
}当 curCoordinatorOffset() 等于 coordinatorScrollableHeight 时表示头部区域已经折叠完毕此时粘性头部应悬停。
自定义布局的使用
我们前面介绍的三要素当中
可滚动的头部区域 以及粘性头部区域 直接使用普通组件即可关于可滚动的内容区域 下面要着重做一下讲解因为这块的滑动和CoordinatorLayout在外层的滑动存在着滑动冲突所以我们在以下情况需要特殊处理: 当外部容器未完全展开/收起时,优先处理外部容器的滚动。 当外部容器已完全展开/收起时,内部列表可以正常滚动。 在滚动过程中,可以平滑地过渡between外部容器和内部列表的滚动。
Builder
ContentBuilder() {List({ scroller: this.collapsibleMediator.getCurrentInnerScroller(0) }) {ForEach(new Arraynumber(10).fill(0).map((_, index: number) index), (item: number) {ListItem() {Text(${测试}${item}).width(100%).height(50).fontSize(16).textAlign(TextAlign.Center)}.height(180)})}.onScrollFrameBegin((offset: number, _) {// 联动 CollapsibleMediator 处理滚动return { offsetRemain: this.collapsibleMediator?.getScrollerFrameRemainOffset(offset) };})
}上述代码代码主要通过以下几个方面来处理滑动冲突:
使用 CollapsibleMediator:
this.collapsibleMediator 是一个 CollapsibleMediator 实例,用于协调外部滚动容器和内部滚动列表之间的滚动行为。
设置内部滚动器:
通过 scroller: this.collapsibleMediator.getCurrentInnerScroller(0) 将列表的滚动器与 CollapsibleMediator 关联起来。这样可以让 mediator 控制内部列表的滚动。
处理滚动事件:
.onScrollFrameBegin() 方法用于捕获每一帧的滚动事件。
计算剩余滚动量:
在滚动事件处理中,调用 this.collapsibleMediator?.getScrollerFrameRemainOffset(offset) 来计算实际应该滚动的距离。
返回剩余滚动量:
将计算得到的剩余滚动量作为 offsetRemain 返回,系统会根据这个值来决定实际的滚动行为。
整体实现效果
可滚动头部通过 ScrollableHeaderBuilder 定义一个可滚动的头部区域当用户滚动页面时头部内容首先向上折叠。 粘性头部悬停使用 StickyHeaderBuilder 创建粘性头部包含 Tabs 组件。通过 CollapsibleMediator 的滚动逻辑当用户滚动页面到达该区域时粘性头部悬停在页面顶部。 可滚动内容区域通过 ContentBuilder 创建内容区域该区域在粘性头部悬停后继续滚动。
本文介绍的实现方案不仅能够处理复杂的滑动冲突还可以在不同区域间实现平滑的滚动体验和粘性头部的悬停效果。 这种布局在实际开发中非常有用特别是在有多个滚动区域和悬停需求的场景中如电商首页、新闻应用等。