鸿蒙UI开发
大家也可以将个人在UI布局设计中的独到见解和实践经验贡献于此文档,共同完善,总结出一套标准高效的UI设计思路。Text("我的宽度占剩余的宽度"+"111111111111")//这个margin自我调整,一般为做组件所有icon的宽度和。// 当前折叠屏状态(若当前为折叠屏设备才有效)// 监听折叠屏状态变更,更新折叠态。Text("文字标题")Text("我的宽度不固定")Text("健康使用
可以叫我小崔 · 2025-03-27 20:24:23 发布 鸿蒙UI开发
本文旨在分享一些鸿蒙UI布局开发上的一些建议,特别是对屏幕宽高比发生变化时的应对思路和好的实践。
折叠屏适配
一般情况(自适应布局/响应式布局)
1.自适应布局
1.1自适应拉伸

左右组件定宽
|
TypeScript
//左右定宽
Row() {
Text("健康使用手机")
.fontSize(16)
.width(135)
Blank()
Toggle({ type: ToggleType.Switch })
.width(36)
}
.borderRadius(12)
.padding({ left: 13, right: 13 })
.backgroundColor('#FFFFFF')
.width('100%') |
左右组件不定宽(左组件占剩余宽度,右组件不定宽)
|
TypeScript
//layoutWeight
//左右不定宽,
Row() {
...
Text("我的宽度占剩余的宽度"+"111111111111")
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
...
}
.layoutWeight(1)
Text("我的宽度不固定")
.textAlign(TextAlign.End)
//这个margin自我调整,一般为做组件所有icon的宽度和
.margin({ left: 54 })
}
.width('100%') |
1.2均分拉伸

灵活使用弹性布局Flex
|
TypeScript
//不换行
Flex({ justifyContent: FlexAlign.SpaceEvenly }) {
ForEach(this.list, () => {
this.Item()
})
}
//换行
Flex({ justifyContent: FlexAlign.Center ,wrap:FlexWrap.Wrap}) {
ForEach(this.list, () => {
this.Item()
})
} |
1.3自适应延伸

|
TypeScript
Scroll() {
Row({ space: 10 }) {
ForEach(this.appList, () => {
Column() {
Image($r('app.media.icon'))
.width(48)
.height(48)
Text($r('app.string.show_app_name'))
.fontSize(12)
.textAlign(TextAlign.Center)
}.width(80).height(102)
})
}
}
.scrollable(ScrollDirection.Horizontal)
.width("100%") |
2.响应式布局
2.1媒体查询

|
TypeScript
//核心代码 private breakpoints: BreakpointEntity[] = [
{ name: 'xs', size: 0 }, { name: 'sm', size: 320 },
{ name: 'md', size: 600 }, { name: 'lg', size: 840 }
]
/**
* 更新当前断点 * 当传入的断点与当前断点不同时,更新当前断点并持久化 */
private updateCurrentBreakpoint(breakpoint: string) {
if (this.currentBreakpoint !== breakpoint) {
this.currentBreakpoint = breakpoint;
AppStorage.Set<string>('currentBreakpoint', this.currentBreakpoint);
console.log('on current breakpoint: ' + this.currentBreakpoint);
}
}
/**
* 注册断点监听器 * 为每个断点创建媒体查询监听器,当屏幕尺寸匹配时,更新当前断点 */
public register() {
this.breakpoints.forEach((breakpoint: BreakpointEntity, index) => {
let condition :string = '';
// 监听句柄,反应视窗宽度和breakpoint.size的关系 if (index === this.breakpoints.length - 1) {
condition = '(' + breakpoint.size + 'vp<=width' + ')';
} else {
condition = '(' + breakpoint.size + 'vp<=width<' + this.breakpoints[index + 1].size + 'vp)';
}
console.log(condition);
// breakpoint.size vp <= width 的条件改变时触发回调,传递此时视窗大小 breakpoint.mediaQueryListener = mediaQuery.matchMediaSync(condition);
breakpoint.mediaQueryListener.on('change', (mediaQueryResult) => {
if (mediaQueryResult.matches) {
this.updateCurrentBreakpoint(breakpoint.name);
}
})
})
} |
3.典型布局场景
3.1挪移布局

栅格布局GridRow
|
TypeScript
GridRow() {
GridCol({ span: { sm: 12, md: 6, lg: 6 } }) {
Text("图片内容")
}
.width("100%")
.height("50%")
.backgroundColor(Color.Red)
GridCol({ span: { sm: 12, md: 6, lg: 6 } }) {
Text("文字标题")
}
.width("100%")
.height("50%")
.backgroundColor(Color.Blue)
} |
3.2重复布局
栅格布局GridRow
|
TypeScript
Scroll() {
GridRow() {
ForEach([0, 1, 2, 3, 4, 5, 6, 7], () => {
GridCol({ span: { sm: 12, md: 6, lg: 6 } }) {
Column() {
RepeatItemContent()
}
}
})
}
} |
3.3顶部布局
栅格布局GridRow
|
TypeScript
@State needWrap: boolean = true
build() {
GridRow() {
// 第一行布局
GridCol({ span: { sm: 12, md: 6, lg: 7 } }) {
Row() {
Text($r('app.string.recommended')).fontSize(24)
Blank()
Image($r('app.media.ic_public_more'))
.width(32)
.height(32)
.visibility(this.needWrap ? Visibility.Visible : Visibility.None)
}
.width('100%')
.alignItems(VerticalAlign.Center)
}
// 第二行布局
GridCol({ span: { sm: 12, md: 6, lg: 5 } }) {
Flex({ alignItems: ItemAlign.Center }) {
Search({ placeholder: '猜您喜欢: 万水千山' })
Image($r('app.media.audio_fm'))
.width(32)
.height(32)
Image($r('app.media.ic_public_more'))
.width(32)
.height(32)
.visibility(this.needWrap ? Visibility.None : Visibility.Visible)
}
}//控制显隐多余元素
}.onBreakpointChange((breakpoint: string) => {
if (breakpoint === 'sm') {
this.needWrap = true } else {
this.needWrap = false }
})
} |
3.复杂情况(判断手机的状态)
3.1折叠屏适配
|
TypeScript
// 当前折叠屏状态(若当前为折叠屏设备才有效)
@State curFoldStatus: display.FoldStatus = display.getFoldStatus(); if (display.isFoldable()) {
// 监听折叠屏状态变更,更新折叠态
display.on('foldStatusChange', (curFoldStatus: display.FoldStatus) => {
this.curFoldStatus = curFoldStatus;
})
}
build() {
// 折叠屏UI展示
if (display.isFoldable()) {
...
}
} else { // 非折叠屏UI展示
...
}
}
} |
讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。
所有评论(0)