鸿蒙项目实战 - 社区活动编排板:标签云布局算法与自动换行

发布时间:2026/8/22 3:47:11
鸿蒙项目实战 - 社区活动编排板:标签云布局算法与自动换行 实例社区活动编排板技术CustomLayoutAlgorithm、onMeasure、onLayout、自动换行、DynamicLayout一、本篇范围本篇只拆标签云算法和页面入口。真正的核心是“何时换行”和“换行后 y 坐标怎样累计”因此onMeasure与onLayout两段必须直接给代码。二、导入与布局依赖import{CustomLayoutAlgorithm,DynamicLayout,DynamicLayoutAttribute,FrameNode,LayoutConstraint,Position,curves}fromkit.ArkUI;这里依赖的仍然是CustomLayoutAlgorithm路线只不过策略从“找最短列”换成了“超宽换行”。技术文要把这个依赖层写清楚否则读者只会看到标签排布结果不知道页面为什么能自动换行。三、标签云算法换行测量与坐标布局ObservedV2classTagCloudLayoutextendsCustomLayoutAlgorithm{TracehorizontalGap:number10;TraceverticalGap:number10;onMeasure(self:FrameNode,constraint:LayoutConstraint):void{constmaxWidthconstraint.maxSize.width;letcurrentLineWidth0;letcurrentLineHeight0;lettotalHeight0;for(letindex0;indexself.getChildrenCount();index){constchildself.getChild(index);if(!child){continue;}child.measure({maxSize:{width:maxWidth,height:constraint.maxSize.height},minSize:{width:0,height:0},percentReference:constraint.percentReference});constsizechild.getMeasuredSize();if(currentLineWidth0currentLineWidthsize.widthmaxWidth){totalHeightcurrentLineHeightthis.verticalGap;currentLineWidth0;currentLineHeight0;}currentLineWidthsize.widththis.horizontalGap;currentLineHeightMath.max(currentLineHeight,size.height);}if(self.getChildrenCount()0){totalHeightcurrentLineHeight;}self.setMeasuredSize({width:maxWidth,height:totalHeight});}onLayout(self:FrameNode,_:Position):void{constmaxWidthself.getMeasuredSize().width;letx0;lety0;letlineHeight0;for(letindex0;indexself.getChildrenCount();index){constchildself.getChild(index);if(!child){continue;}constsizechild.getMeasuredSize();if(x0xsize.widthmaxWidth){x0;ylineHeightthis.verticalGap;lineHeight0;}child.layout({x:x,y:y});xsize.widththis.horizontalGap;lineHeightMath.max(lineHeight,size.height);}}}onMeasure负责累计当前行宽度一旦超出最大宽度就把当前行高度记入totalHeightonLayout负责在真正摆放时同步执行换行。只有这两个阶段遵循同一条换行规则标签云才不会出现测量正常、布局错位的问题。四、页面入口与间距切换EntryComponentV2struct CommunityPlannerPage{LocallayoutAlgorithm:TagCloudLayoutnewTagCloudLayout();privateswitchGap(horizontalGap:number,verticalGap:number):void{this.getUIContext()?.animateTo({curve:curves.springMotion(0.42,0.86)},(){this.layoutAlgorithm.horizontalGaphorizontalGap;this.layoutAlgorithm.verticalGapverticalGap;});}build(){Column(){Column({space:4}){Text( 61 社区活动编排板).fontSize(22).fontWeight(FontWeight.Bold)Text(利用 API 24 的自定义 DynamicLayout 标签云把活动岗位卡片自动换行收纳到一屏里。).fontSize(12).fontColor(#64748B).lineHeight(18)}.width(100%).alignItems(HorizontalAlign.Start).padding({left:16,right:16,top:14,bottom:10})Row({space:8}){Button(紧凑排布).height(36).backgroundColor(#E0F2FE).fontColor(#0C4A6E).onClick(()this.switchGap(8,8))Button(舒展排布).height(36).backgroundColor(#FEF3C7).fontColor(#92400E).onClick(()this.switchGap(12,12))}.width(100%).padding({left:16,right:16,bottom:10})Scroll(){Column({space:14}){DynamicLayout(this.layoutAlgorithm){VolunteerTagCard()LogisticsTagCard()StageTagCard()MaterialTagCard()SecurityTagCard()TeaBreakTagCard()}.width(100%)Column({space:8}){Text(编排说明).fontSize(15).fontWeight(FontWeight.Bold).fontColor(#111827)Text(岗位卡片采用标签云式布局后可以根据每张卡片的内容宽度自动换行。签到、布场、串场、茶歇这些不同职责不会被硬塞进固定列宽里信息利用率更高。).fontSize(12).fontColor(#64748B).lineHeight(20)}.width(100%).padding(16).backgroundColor(#FFFFFF).borderRadius(18)}.width(100%).padding({left:16,right:16,bottom:24})}.layoutWeight(1).scrollBar(BarState.Off)}.width(100%).height(100%).backgroundColor(#F7F7F6)}}页面入口只持有一个TagCloudLayout实例并通过按钮改horizontalGap和verticalGap。也就是说这页的模式切换不是“紧凑版组件”和“舒展版组件”两套代码而是同一套标签卡配不同的布局参数。五、代表性标签卡签到ComponentV2struct VolunteerTagCard{Locallabel:string签到;Localcount:number6;Localnote:string东门;build(){Row({space:8}){Text(this.label).fontSize(14).fontWeight(FontWeight.Bold).fontColor(#0F172A)Text(${Math.round(this.count)}人).fontSize(12).fontColor(#334155)TextInput({text:this.note,placeholder:区域}).width(88).height(32).backgroundColor(#F8FAFC).borderRadius(8).onChange((value:string)this.notevalue)}.padding({left:14,right:14,top:10,bottom:10}).backgroundColor(#FFFFFF).borderRadius(16)}}这张卡保留了TextInput目的不是为了表单复杂度而是为了让卡片宽度和内容长度都保持真实。标签云示例如果没有真实输入就无法体现自动换行的实际价值。六、布局层代码定位表代码块关注点改动入口导入与布局依赖标签云依赖类型调整布局能力先看 import标签云算法换行测量与坐标布局自动换行算法主体调换行逻辑和 gap 看这里页面入口与间距切换页面如何调布局参数加更多排布模式时改这里代表性标签卡签到可变宽度的标签卡示例要扩区域或人数字段从这张卡入手七、本篇小结社区活动编排板第一篇的核心是换行算法不是岗位名称。只要onMeasure和onLayout讲清楚这一页的技术价值就立住了。