您的位置:首页 > 财经 > 金融 > 鸿蒙开发协调布局CollapsibleLayout

鸿蒙开发协调布局CollapsibleLayout

2025/1/17 1:12:16 来源:https://blog.csdn.net/u010074743/article/details/142337593  浏览:    关键词:鸿蒙开发协调布局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结构图

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

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com