ArkUI 沉浸式布局:别让状态栏把页面顶得难看
【摘要】 今天我们用一个小页面把沉浸式顶部讲清楚:背景可以铺进状态栏区域,但文字和按钮别跟着挤上去。 沉浸式布局最容易被误解成“把所有东西都顶到屏幕最上面”。这其实很危险。真正该上去的是背景、图片、色块这类装饰层;标题、按钮、正文这些可读内容,还是要留出安全距离。 第一块先看普通顶部布局。它规整、稳妥,适合大多数工具页。但如果设
ArkUI 沉浸式布局:别让状态栏把页面顶得难看
今天我们用一个小页面把沉浸式顶部讲清楚:背景可以铺进状态栏区域,但文字和按钮别跟着挤上去。
沉浸式布局最容易被误解成“把所有东西都顶到屏幕最上面”。这其实很危险。真正该上去的是背景、图片、色块这类装饰层;标题、按钮、正文这些可读内容,还是要留出安全距离。
第一块先看普通顶部布局。它规整、稳妥,适合大多数工具页。但如果设计稿希望顶部背景连到系统栏区域,这种写法会像被截了一刀。
第二块用 expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])。我们只放开顶部系统区域,让背景延伸上去。这里特意只处理 TOP,不把底部导航、键盘区域一起扯进来。
第三块用 safeAreaPadding(...) 做内容保护。背景可以沉浸,内容不能乱贴边。这个边界先想清楚,页面就不会为了“好看”牺牲可读性。
你自己做详情页或者首页 Banner 时,会更偏向普通顶部,还是沉浸式顶部?如果做沉浸式,你最担心的是适配问题,还是内容被遮住?
完整代码
class ImmersiveTip {
title: string
desc: string
color: string
constructor(title: string, desc: string, color: string) {
this.title = title
this.desc = desc
this.color = color
}
}
@Entry
@Component
struct ArkUIImmersiveLayoutDemo {
private tips: ImmersiveTip[] = [
new ImmersiveTip('背景可以进安全区', '让顶部色块或图片延伸上去,页面会更完整。', '#2563EB'),
new ImmersiveTip('文字不要贴边', '标题、按钮这类可读内容仍然要留出安全距离。', '#0F766E'),
new ImmersiveTip('只处理需要的边', '本篇只演示顶部,避免把底部导航和键盘混进来。', '#C2410C')
]
@Builder
sectionTitle(title: string, desc: string) {
Column({ space: 6 }) {
Text(title)
.fontSize(19)
.fontWeight(FontWeight.Bold)
.fontColor('#111827')
Text(desc)
.fontSize(13)
.fontColor('#6B7280')
.lineHeight(20)
}
.width('100%')
.alignItems(HorizontalAlign.Start)
}
@Builder
normalHeaderPreview() {
Column() {
Row() {
Text('普通顶部')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#111827')
Blank()
Text('安全区内')
.fontSize(12)
.fontColor('#6B7280')
}
.width('100%')
.height(58)
.padding({ left: 14, right: 14 })
.backgroundColor('#F3F4F6')
Column({ space: 8 }) {
Text('顶部背景从安全区下方开始')
.fontSize(15)
.fontWeight(FontWeight.Medium)
.fontColor('#374151')
Text('这种写法规整,但如果设计稿希望顶部色块铺到状态栏区域,视觉上会显得被截了一刀。')
.fontSize(13)
.fontColor('#6B7280')
.lineHeight(20)
}
.width('100%')
.padding(14)
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.borderRadius(14)
.backgroundColor('#FFFFFF')
.border({ width: 1, color: '#E5E7EB' })
}
@Builder
immersiveHeaderPreview() {
Column() {
Column({ space: 12 }) {
Text('沉浸式顶部')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.fontColor('#FFFFFF')
Text('背景延伸到顶部非安全区,内容再用留白保护起来。')
.fontSize(14)
.fontColor('#DBEAFE')
.lineHeight(22)
Row({ space: 8 }) {
Text('expandSafeArea')
.fontSize(12)
.fontColor('#0F172A')
.padding({ left: 10, right: 10, top: 6, bottom: 6 })
.borderRadius(14)
.backgroundColor('#BFDBFE')
Text('SafeAreaEdge.TOP')
.fontSize(12)
.fontColor('#0F172A')
.padding({ left: 10, right: 10, top: 6, bottom: 6 })
.borderRadius(14)
.backgroundColor('#A7F3D0')
}
}
.width('100%')
.height(188)
.padding({ left: 16, right: 16, top: 38, bottom: 18 })
.borderRadius({ topLeft: 14, topRight: 14 })
.backgroundColor('#1D4ED8')
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Start)
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
Column({ space: 8 }) {
Text('内容区继续正常排布')
.fontSize(15)
.fontWeight(FontWeight.Medium)
.fontColor('#111827')
Text('沉浸式不是让所有东西都顶上去,而是让背景更完整,内容仍然保持可读距离。')
.fontSize(13)
.fontColor('#6B7280')
.lineHeight(20)
}
.width('100%')
.padding(14)
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.borderRadius(14)
.backgroundColor('#FFFFFF')
.border({ width: 1, color: '#BFDBFE' })
}
@Builder
tipRow(item: ImmersiveTip) {
Row({ space: 12 }) {
Text(item.title.substring(0, 1))
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor('#FFFFFF')
.textAlign(TextAlign.Center)
.width(38)
.height(38)
.borderRadius(19)
.backgroundColor(item.color)
Column({ space: 4 }) {
Text(item.title)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor('#111827')
Text(item.desc)
.fontSize(13)
.fontColor('#4B5563')
.lineHeight(20)
}
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.padding(12)
.borderRadius(10)
.backgroundColor('#F8FAFC')
.border({ width: 1, color: '#E5E7EB' })
}
@Builder
protectedContentPreview() {
Column({ space: 12 }) {
Text('内容保护区')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#111827')
Text('safeAreaPadding 可以把安全区距离补回内容层。背景可以沉浸,文字和按钮不要硬贴系统区域。')
.fontSize(13)
.fontColor('#4B5563')
.lineHeight(20)
Column({ space: 10 }) {
ForEach(this.tips, (item: ImmersiveTip) => {
this.tipRow(item)
}, (item: ImmersiveTip) => item.title)
}
.width('100%')
}
.width('100%')
.padding({ left: 14, right: 14 })
.safeAreaPadding({ top: 12, bottom: 12 })
.borderRadius(14)
.backgroundColor('#ECFDF5')
.border({ width: 1, color: '#A7F3D0' })
.alignItems(HorizontalAlign.Start)
}
build() {
Scroll() {
Column({ space: 22 }) {
Column({ space: 8 }) {
Text('ArkUI 沉浸式布局')
.fontSize(28)
.fontWeight(FontWeight.Bold)
.fontColor('#111827')
Text('别让状态栏把页面顶得难看')
.fontSize(16)
.fontColor('#4B5563')
Text('沉浸式布局的重点不是把内容塞进系统区域,而是让背景延伸过去,再把真正要读的内容保护好。')
.fontSize(14)
.fontColor('#6B7280')
.lineHeight(22)
}
.width('100%')
.alignItems(HorizontalAlign.Start)
this.sectionTitle('普通顶部布局:规整,但容易被截断', '常规顶部从安全区下方开始,适合大多数工具页。')
this.normalHeaderPreview()
this.sectionTitle('沉浸式顶部:让背景先铺上去', 'expandSafeArea 只放开需要的边,这里只演示顶部系统区域。')
this.immersiveHeaderPreview()
this.sectionTitle('内容保护:背景可以上去,文字别跟着挤上去', 'safeAreaPadding 负责把可读内容和系统区域隔开。')
this.protectedContentPreview()
}
.width('100%')
.padding({ left: 18, right: 18, top: 22, bottom: 32 })
}
.width('100%')
.height('100%')
.backgroundColor('#FFFFFF')
}
}
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)