HarmonyOS 小游戏《对战五子棋》开发第23篇 - 保持棋盘正方形
一个属性解决正方形问题——ArkUI布局的优雅之处
棋盘图片:
问题:如何保证棋盘永远是正方形
棋盘必须是正方形(15x15等比例),但屏幕通常是长方形。如果设置width('100%')和height('100%'),棋盘会被拉伸变形。
方案对比
方案1:硬编码尺寸(不推荐)
Canvas(this.context).width(320).height(320)问题:不同设备上尺寸固定,小屏太大、大屏太小。
方案2:手动计算(不推荐)
Canvas(this.context).width('100%').height(this.calculatedHeight)// 需要手动计算问题:需要监听宽度变化,手动计算高度,代码复杂。
方案3:aspectRatio(本项目使用)
Canvas(this.context).width('100%').aspectRatio(1)// 宽高比1:1 → 正方形aspectRatio详解
aspectRatio(ratio)设置组件的宽高比:
aspectRatio(1):宽=高(正方形)aspectRatio(2):宽=2×高aspectRatio(0.5):高=2×宽
工作原理:当设置了宽度(如width('100%')),aspectRatio自动计算高度。
宽度 = 父容器宽度 (如360vp) 高度 = 宽度 / aspectRatio = 360 / 1 = 360vp → 正方形!棋盘容器的布局
Column(){ChessBoardView({boardData:this.boardData,lastMoveRow:this.lastMoveRow,lastMoveCol:this.lastMoveCol,onCellClick:(row:number,col:number)=>{this.onCellClick(row,col);}})}.width('92%')// 棋盘容器占页面92%.backgroundColor('#D4A868')// 木色背景.borderRadius(8)// 圆角.clip(true)// 裁剪超出部分布局层次:
页面 (100%) └─ Column (92%) ← 棋盘外框,有边距 └─ Canvas (100%, aspectRatio 1) ← 棋盘画布,正方形clip(true)的作用
.clip(true)Canvas是矩形,但外层Column有borderRadius(8)圆角。clip(true)让Canvas被裁剪为圆角矩形,避免棋盘四角超出圆角边框。
无clip: 有clip: ┌──────────┐ ╭──────────╮ │ Canvas │ │ Canvas │ │ (直角) │ │ (圆角) │ └──────────┘ ╰──────────╯布局完整性
整个页面的布局结构:
Column(){// 顶部导航栏 (固定高度56)Row(){...}.height(56)// 状态栏 (自适应)Row(){...}.width('92%')// 状态文字 (自适应)Text(...)// 棋盘 (92%宽度,正方形)Column(){ChessBoardView(...)}.width('92%').borderRadius(8).clip(true)// 底部按钮 (自适应)Row(){...}.width('92%')}.width('100%').height('100%').backgroundColor('#F5F0E8')垂直空间分配:
- 导航栏:固定56vp
- 状态栏:内容高度
- 棋盘:92%宽度的正方形
- 底部按钮:内容高度
- 剩余空间:自动分配
在小屏设备上的适配
如果屏幕太小,棋盘可能占满垂直空间。此时需要确保其他元素仍然可见:
Column(){Row(){...}.height(56)// 导航栏固定Row(){...}// 状态栏Text(...)// 状态文字Column(){ChessBoardView(...)}.width('92%')// 棋盘Row(){...}// 底部按钮}ArkUI的Column默认从上到下排列,如果内容超出屏幕,可以滚动。但五子棋的布局通常不会超出——棋盘宽度92%意味着高度也是92%宽,在大多数设备上都能容纳。
