当前位置: 首页 > news >正文

HarmonyOS PC 应用 Flex flexBasis 详解——给子项设定一个“起点宽度“

文章目录

    • 弹性布局的第三个属性
    • flexBasis 的取值
    • 完整 Demo
    • flexBasis、flexGrow、flexShrink 三者的关系
    • PC 端仪表盘的布局建议
    • 小结

弹性布局的第三个属性

学了flexGrow(分配剩余空间)和flexShrink(压缩超出空间),还剩一个问题没解答:在伸缩之前,子项的初始尺寸是多少?

这就是flexBasis的作用:设定 Flex 子项在主轴方向上的基准尺寸,也就是伸缩计算的起始点。

flexBasis的优先级比width高。在 Flex 容器里,如果你同时设了width(100)flexBasis('30%'),布局计算时以flexBasis为准。

在 PC 端仪表盘场景里,flexBasis非常有用:你可以给不同的数据卡片设置不同的基准宽度,组合出各种布局模式,再配合flexGrow让它们在剩余空间内弹性伸展。

flexBasis 的取值

flexBasis接受两类值:

// 像素值(vp).flexBasis(200)// 基准宽度 200vp// 百分比字符串.flexBasis('50%')// 基准宽度是父容器的 50%// 'auto'(默认值).flexBasis('auto')// 以 width 属性为准

完整 Demo

新建文件PcFlexBasisPage.ets

// PcFlexBasisPage.ets// HarmonyOS PC 端仪表盘 — flexBasis 四种布局模式演示interfaceDashCard{id:number;title:stringvalue:stringunit:stringtrend:number// 正值上升,负值下降color:stringbasis?:string// flexBasis 值}interfaceLayoutModeParams{id:numbername:stringdesc:stringbases:string[]// 每张卡片的 flexBasis 值}@Entry@Componentstruct PcFlexBasisPage{@StatecurrentMode:number=0privatecards:DashCard[]=[{id:1,title:'今日活跃用户',value:'128,450',unit:'人',trend:12.3,color:'#0A59F7'},{id:2,title:'本月新增用户',value:'23,890',unit:'人',trend:-2.1,color:'#00B578'},{id:3,title:'应用崩溃率',value:'0.12',unit:'%',trend:-0.03,color:'#FF7A00'},{id:4,title:'平均响应时间',value:'186',unit:'ms',trend:8.5,color:'#8B5CF6'},{id:5,title:'今日收入',value:'¥45,320',unit:'',trend:18.7,color:'#EF4444'},]privatelayoutModes:LayoutModeParams[]=[{id:0,name:'自适应',desc:'flexBasis: auto',bases:['auto','auto','auto','auto','auto']},{id:1,name:'双列',desc:'flexBasis: 50%',bases:['50%','50%','50%','50%','50%']},{id:2,name:'黄金比例',desc:'大卡 flexBasis: 40%,小卡 30%',bases:['40%','30%','30%','40%','60%']},{id:3,name:'全宽单列',desc:'flexBasis: 100%',bases:['100%','100%','100%','100%','100%']},]build(){Column(){// ── 页面标题 ──Row(){Text('数据仪表盘').fontSize(20).fontWeight(FontWeight.Bold).fontColor('#1A1A1A')Blank()Text('今日 09:00 更新').fontSize(12).fontColor('#AAAAAA')}.width('100%').padding({left:24,right:24,top:20,bottom:4})// ── 布局模式切换 ──Row({space:8}){Text('布局模式:').fontSize(13).fontColor('#666666')ForEach(this.layoutModes,(mode:LayoutModeParams)=>{Column({space:2}){Text(mode.name).fontSize(13).fontColor(this.currentMode===mode.id?'#0A59F7':'#666666').fontWeight(this.currentMode===mode.id?FontWeight.Bold:FontWeight.Normal)Text(mode.desc).fontSize(10).fontColor(this.currentMode===mode.id?'#4D87F7':'#AAAAAA')}.padding({left:12,right:12,top:6,bottom:6}).backgroundColor(this.currentMode===mode.id?'#EBF2FF':'#F5F5F5').border({width:1,color:this.currentMode===mode.id?'#0A59F7':'transparent',radius:8}).onClick(()=>{this.currentMode=mode.id})})}.width('100%').padding({left:24,right:24,top:4,bottom:16})Divider().color('#EEEEEE')// ── 卡片区域 ──Scroll(){Column(){// flexBasis 演示:Flex wrap 布局Flex({wrap:FlexWrap.Wrap,alignItems:ItemAlign.Stretch}){ForEach(this.cards,(card:DashCard,index:number)=>{this.buildDataCard(card,this.layoutModes[this.currentMode].bases[index])})}.width('100%').padding({left:16,right:16,top:16,bottom:16})// ── flexBasis 说明 ──this.buildExplainSection()}}.layoutWeight(1).scrollBar(BarState.Auto)}.width('100%').height('100%').backgroundColor('#F5F6F8')}// ── 数据卡片 ──@BuilderbuildDataCard(card:DashCard,basis:string){Column({space:8}){// 标题Text(card.title).fontSize(13).fontColor('rgba(255,255,255,0.8)').maxLines(1).textOverflow({overflow:TextOverflow.Ellipsis})// 数值Row({space:4}){Text(card.value).fontSize(28).fontWeight(FontWeight.Bold).fontColor('#FFFFFF')if(card.unit){Text(card.unit).fontSize(14).fontColor('rgba(255,255,255,0.7)').margin({top:8})}}// 趋势标签Row({space:4}){Text(card.trend>=0?'↑':'↓').fontSize(12).fontColor('#FFFFFF')Text(`${Math.abs(card.trend)}%`).fontSize(12).fontColor('#FFFFFF')Text(card.trend>=0?'环比上升':'环比下降').fontSize(11).fontColor('rgba(255,255,255,0.7)')}.padding({left:8,right:8,top:3,bottom:3}).backgroundColor('rgba(0,0,0,0.15)').borderRadius(12)}.flexBasis(basis)// 关键:从外部传入 flexBasis 值.flexGrow(1)// 配合 flexGrow,弹性填充剩余空间.padding(20).margin(8).backgroundColor(card.color).borderRadius(16).alignItems(HorizontalAlign.Start).shadow({radius:12,color:`${card.color}40`,offsetX:0,offsetY:4}).animation({duration:300,curve:Curve.EaseInOut})}// ── 说明区域 ──@BuilderbuildExplainSection(){Column({space:12}){Text('flexBasis 工作原理').fontSize(15).fontWeight(FontWeight.Bold).fontColor('#1A1A1A')Column({space:8}){this.buildExplainRow('flexBasis: auto','以 width/height 属性为基准(默认行为)')this.buildExplainRow('flexBasis: 50%','基准尺寸为父容器的 50%,两列等宽布局')this.buildExplainRow('flexBasis: 200','固定 200vp 作为基准,再根据 flexGrow 伸展')this.buildExplainRow('flexBasis vs width','Flex 容器内 flexBasis 优先级高于 width')}.padding(16).backgroundColor('#FFFFFF').borderRadius(10)Text('上方切换布局模式,观察不同 flexBasis 值对卡片排列的影响').fontSize(12).fontColor('#AAAAAA').margin({top:4})}.width('100%').padding({left:24,right:24,top:0,bottom:24}).alignItems(HorizontalAlign.Start)}@BuilderbuildExplainRow(term:string,desc:string){Row({space:8}){Text(term).fontSize(13).fontColor('#0A59F7').fontFamily('monospace').width(160)Text(desc).fontSize(13).fontColor('#555555').layoutWeight(1)}.width('100%').padding({top:6,bottom:6})}}

flexBasis、flexGrow、flexShrink 三者的关系

这三个属性经常配合使用,用一个简单的公式理解:

实际尺寸 = flexBasis(基准) + flexGrow × (剩余空间 / 总flexGrow值) - flexShrink × (超出空间 / 总flexShrink值)

在实际代码里,最常见的组合是:

// 等比例弹性卡片:每张卡片基准 50%,有剩余空间就平分.flexBasis('50%').flexGrow(1).flexShrink(1)// 固定宽度保底,有多余空间再扩展.flexBasis(200).flexGrow(1).flexShrink(0)// 不允许压缩到 200vp 以下

PC 端仪表盘的布局建议

PC 端屏幕宽,仪表盘卡片可以放 3-4 列。推荐用以下基准:

布局flexBasis 值适用场景
四列等宽25%数据指标密集型
三列等宽33.33%标准仪表盘
两列等宽50%数据内容丰富
主次布局60%+40%主图 + 辅助数据

小结

flexBasis是 Flex 弹性布局的"起点设定":先确定基准尺寸,再用flexGrow伸展、flexShrink收缩。三个属性合在一起,构成完整的 Flex 弹性尺寸控制体系。

在 PC 端仪表盘场景里,用不同的flexBasis值配合FlexWrap.Wrap换行,可以非常灵活地控制卡片的排列密度和比例关系。

http://www.jsqmd.com/news/1002658/

相关文章:

  • 百度网盘提取码智能获取:如何用3秒解决传统搜索的5分钟难题?
  • 2026年桥梁防撞护栏定做厂家实力评测:工艺、案例与行业趋势深度分析 - 优质品牌商家
  • LabVIEW实战:用反馈节点和属性节点,5分钟打造一个带状态记忆的简易计数器UI
  • 2026年青岛发电机出租公司哪家可靠?实测6家服务商表现,附避坑指南 - 优质品牌商家
  • 有限元方法在正曲率流形等距嵌入中的应用与实现
  • UVa 465 Overflow
  • 部署了不会用?来学Claude Code 的 10 个“邪修”秘籍
  • 别再凭感觉调MySQL内存了!手把手教你用SQL监控innodb_buffer_pool命中率
  • 用FreeRTOS和裸机代码两种方式理解STM32平衡小车PID控制逻辑
  • SteamShutdown终极指南:告别熬夜等待,让电脑自动关机的智能解决方案
  • 保姆级教程:在Yolov5/v7/v8中手把手集成CARAFE上采样算子(附完整代码与配置文件)
  • 2026年钦州旅游攻略公司怎么选?本地老牌餐厅与海鲜路线深度评测 - 优质品牌商家
  • 别再只用Web界面了!Proxmox VE 8.x 命令行高手必备的 qm 命令实战手册
  • 保姆级教程:在ROS Noetic下,为你的URDF机器人模型添加一个可用的深度摄像头(Gazebo仿真)
  • 鸿蒙原生应用实战(五):路由导航与工程优化 — 从开发到上线的完整流程
  • 上海ECO棉床垫怎么挑?去了5家店说点大实话 - 深圳市民HLL
  • 2026年高杆桂花苗木基地评价解析:从品种到工程应用的多维观察 - 优质品牌商家
  • 自适应系统中的运行时伦理挑战与解决方案
  • 基于ARM Cortex-M0+的WPR1516无线充电接收芯片:15W Qi标准方案解析与开发实战
  • 2026年近期,选择诚信的平板除雾器品牌为何成为企业的关键决策? - 品牌鉴赏官2026
  • 电赛备赛笔记:用STM32驱动AD9959信号发生器模块,从接线到出波保姆级教程
  • 从‘为什么拒贷我’到‘AI医生怎么看片’:可解释性AI(XAI)如何重塑我们与算法的信任关系
  • shell作业
  • Flutter Hero 动画与共享元素转场:从原理到跨页面动效的工程实践
  • PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis, OceanBase, Sql Server等数据库
  • 新手避坑指南:RK3566开发板IO电源域配置,从原理图到DTS修改全流程
  • Win11 专属部署教程,OpenClaw 智能体稳定运行方案【包含安装包】
  • Plain Craft Launcher 2:快速上手指南与完整功能解析
  • CSDN|美团点评推广到底选极速还是标准?
  • 保姆级教程:从零集成华为ScanKit到你的Android项目(含权限、依赖、回调全流程)