资讯详情

资讯详情

HarmonyOS 短屏适配:页面高度不够时,按钮为什么会“消失“【鸿蒙心迹】

你好欢迎来到我的博客我是【菜鸟学鸿蒙】我是一名在路上的移动端开发者正从传统“小码农”转向鸿蒙原生开发的进阶之旅。为了把学习过的知识沉淀下来也为了和更多同路人互相启发我决定把探索 HarmonyOS 的过程都记录在这里。️主要方向ArkTS 语言基础、HarmonyOS 原生应用Stage 模型、UIAbility/ServiceAbility、分布式能力与软总线、元服务/卡片、应用签名与上架、性能与内存优化、项目实战以及 Android → 鸿蒙的迁移踩坑与复盘。内容节奏从基础到实战——小示例拆解框架认知、专项优化手记、实战项目拆包、面试题思考与复盘让每篇都有可落地的代码与方法论。 我相信写作是把知识内化的过程分享是让生态更繁荣的方式。如果你也想拥抱鸿蒙、热爱成长欢迎关注我一起交流进步摘要页面在竖屏手机上显示正常切到横屏或在折叠屏小屏态下就看不到底部按钮——这是开发阶段很容易漏掉的问题。宽度方向的适配已经有大量资料但高度方向溢出导致操作按钮不可见排查起来要绕一个弯原因值得专门说一次。一、短屏是一个真实的开发场景所谓短屏并不是某一种特定的设备形态而是指在当前运行状态下页面的可用高度明显小于设计时的预期。出现这种状况的情况有几类横屏状态。手机横置后屏幕的宽高对换高度会急剧缩小。一块分辨率为 2400×1080 的设备横屏后可用高度大约只有原来的 45%。折叠屏小屏态。折叠屏在外屏或折叠状态下屏幕比例接近方形高度偏小。字体变大以后。用户在设置中调大系统字号会导致页面内文本组件撑开更多高度原本刚好放得下的内容变大之后就超出了屏幕范围。多任务分屏。应用在分屏模式下获得的窗口高度远低于全屏。这几种场景有一个共同的结果页面总高度不变但可用高度缩水布局里位置靠下的组件就会被顶出视口。二、固定高度页面会出什么问题先看一种常见的写法// 问题示例整页使用 Column 固定高度排列EntryComponentstruct FixedLayoutPage{build(){Column(){// 标题区固定高度Row(){Text(填写信息).fontSize(20).fontWeight(FontWeight.Medium)}.width(100%).height(56).padding({left:16,right:16})// 内容区也写了固定高度Column(){TextInput({placeholder:请输入姓名}).height(48).margin({top:16})TextInput({placeholder:请输入手机号}).height(48).margin({top:12})TextInput({placeholder:请输入邮箱}).height(48).margin({top:12})TextInput({placeholder:请输入地址}).height(48).margin({top:12})TextInput({placeholder:备注信息选填}).height(48).margin({top:12})}.width(100%).height(400)// ← 固定了高度.padding({left:16,right:16})// 底部按钮区Button(提交).width(100%).height(48).margin({top:24,left:16,right:16})}.width(100%).height(100%)}}这段代码在竖屏 6.7 英寸手机上可能完全正常按钮清晰可见。但在横屏状态或折叠屏小屏态下内容区的固定高度 400vp 加上标题区 56vp 再加上按钮 48vp总计已经超过可用高度底部按钮就被推到屏幕外面去了。问题的根本不是按钮出了什么错而是内容区占用了固定的像素数量无法根据实际窗口高度收缩。三、标题区、内容区、底部操作区如何划分在需要垂直铺满整个页面的场景中官方推荐的思路是将页面划分为三个区域各自承担不同的职责区域高度策略说明标题区Header固定高度品牌标识、页面标题、导航按钮高度相对稳定内容区Content弹性拉伸内部可滚动表单、列表、详情内容随窗口高度自适应底部操作区Footer固定高度始终贴底确认、提交、跳转等关键按钮这三个区域共同组成一个撑满整个页面的 Column。其中内容区承担了弹性的责任不管当前窗口高度如何变化它都自动占用标题区和底部操作区剩下来的空间不多也不少。四、内容区改造成可滚动结构让内容区弹性拉伸并支持内部滚动核心用到两个机制layoutWeight属性根据 ArkUI 官方说明layoutWeight用于设置组件在父容器主轴方向上的权重父容器会在分配完其他固定尺寸子组件的空间后将剩余空间按权重分配给设置了layoutWeight的子组件。这正是内容区弹性拉伸所需要的能力。Scroll组件当内部内容高度超出Scroll容器本身的高度时用户可以通过手势滚动查看完整内容而不会撑开容器本身。下面是改造后的结构// 改造后三段式页面结构内容区可滚动EntryComponentstruct AdaptiveLayoutPage{build(){Column(){// ① 标题区固定高度不参与弹性分配Row(){Text(填写信息).fontSize(20).fontWeight(FontWeight.Medium)}.width(100%).height(56).padding({left:16,right:16}).backgroundColor(#F5F5F5)// ② 内容区用 layoutWeight(1) 占用剩余空间// 内部使用 Scroll 包裹内容超出时可滚动Scroll(){Column(){TextInput({placeholder:请输入姓名}).height(48).width(100%).margin({top:16})TextInput({placeholder:请输入手机号}).height(48).width(100%).margin({top:12})TextInput({placeholder:请输入邮箱}).height(48).width(100%).margin({top:12})TextInput({placeholder:请输入地址}).height(48).width(100%).margin({top:12})TextInput({placeholder:备注信息选填}).height(48).width(100%).margin({top:12,bottom:16})}.width(100%).padding({left:16,right:16})}.width(100%).layoutWeight(1)// ← 核心占用标题区和底部操作区之外的全部剩余高度.scrollable(ScrollDirection.Vertical).scrollBar(BarState.Auto)// ③ 底部操作区固定高度不参与弹性分配始终可见Column(){Button(提交).width(100%).height(48).type(ButtonType.Capsule)}.width(100%).padding({left:16,right:16,top:12,bottom:12}).backgroundColor(Color.White)}.width(100%).height(100%)// 整个页面撑满窗口}}五、关键操作按钮如何保持可见改造后底部操作区之所以始终可见原因是它和标题区一样都没有设置layoutWeight在父容器 Column 的布局计算中它们会先被分配固定高度。剩余的空间才由设置了layoutWeight(1)的 Scroll 区域独占。这个逻辑可以用一句话概括固定的先走剩下的全给 Scroll。无论窗口高度是 800vp 还是 320vp底部操作区都稳稳占据自己的 72vp48vp 按钮 12vp 上下内边距不会被内容区挤掉。一个值得关注的细节是底部操作区不应该写在 Scroll 的内部。如果把按钮放进了 Scroll 里面它会随内容一起滚动用户可能需要拖动到底部才能看到按钮这在高度特别小的短屏场景下体验非常差。六、字体变化后再验证一次用户字号调大是另一类容易忽略的短屏诱因。系统字号变大后TextInput 的占位符文本、标签文字都会变大但如果组件本身设置了固定高度如height(48)内容可能出现截断如果没有固定高度组件会自然撑开导致内容区整体变高。两种情况都会带来问题固定高度文字被截断显示异常不固定高度内容区总高度增加在小屏下溢出更严重处理方法是对于内容区内的表单组件高度可以设置一个合理的最小值而非绝对固定值或者干脆不设置高度让组件根据内容自然撑开。因为内容区的外层已经是 Scroll即使总高度超出 Scroll 的容器高度用户也可以通过滚动访问全部内容底部按钮不受影响。对于标题区和底部操作区固定高度是合理的但内部文字尽量使用maxFontScale做限制避免在极大字号下出现布局异常。这部分能力在 ArkUIText组件的字体相关属性中有说明实际项目中建议在对应 SDK 版本中核实属性可用性。七、横屏状态为什么也是短屏测试场景横屏是最容易复现短屏问题的手段因为不需要折叠屏任何手机都可以操作。在 HarmonyOS 应用开发中如果module.json5里abilities的orientation配置为unspecified或user_rotation应用就会响应设备旋转进入横屏。此时窗口的宽高互换高度急剧降低。测试时可以关注以下几点进入横屏后页面底部按钮是否仍然可见不需要滚动就能直接点击进入横屏后内容区是否可以正常滚动不会卡住从横屏切回竖屏布局是否正常恢复没有残留异常。如果应用需要感知窗口尺寸变化例如在宽度增大时切换双栏布局可以通过window.on(windowSizeChange, callback)监听窗口尺寸变化事件在回调中根据新的窗口尺寸更新状态变量触发 ArkUI 的响应式重绘。// 监听窗口尺寸变化示例根据官方接口定义组织import{window}fromkit.ArkUI// 在 UIAbility 的 onWindowStageCreate 或页面的 aboutToAppear 中注册windowInstance.on(windowSizeChange,(size:window.Size){// size.width 和 size.height 单位为 px// 使用 vp 换算时需要结合屏幕密度console.info(窗口尺寸变化宽${size.width}高${size.height})})八、几个值得单独注意的地方layoutWeight生效有前提。它只在直接父容器是 Row 或 Column 时生效且父容器必须有明确的尺寸比如height(100%)或固定高度。如果父容器高度是auto即由子组件撑开layoutWeight无从分配剩余空间效果会失效。Scroll 的直接子组件只能有一个。Scroll组件只接受一个直接子组件。如果需要在可滚动区域内放置多个并列的内容块需要用一个 Column 或 Row 包裹后再放进 Scroll而不是直接在 Scroll 里并列写多个组件。不要在 Scroll 内的子组件上设置height(100%)。Scroll 内部的子组件高度设置为100%在某些情况下会导致滚动失效因为子组件高度等于 Scroll 容器高度不存在可滚动的溢出内容。子组件应该由自身内容决定高度或者设置比 Scroll 容器高的固定高度。底部安全区域。在使用全面屏或异形屏设备时底部可能有系统手势条的安全区域直接把按钮放在页面底部可能和手势条重叠。可以在底部操作区加padding({ bottom: ... })并结合安全区域相关设置处理具体配置方式参考官方文档中关于沉浸式窗口和避让区的说明。九、页面高度适配排查清单当遇到页面在某些设备或状态下底部内容不可见时按以下顺序排查确认页面根容器高度— 根 Column 或其他容器是否设置了height(100%)没有的话整个布局无法撑满窗口检查内容区有没有固定高度— 固定高度是短屏溢出的最常见原因改为layoutWeight(1)确认 Scroll 是否包裹了内容区— 仅靠layoutWeight让内容区弹性收缩还不够内容多时仍需滚动检查底部按钮是否在 Scroll 外部— 在 Scroll 内部的按钮会随内容滚动消失切换到横屏验证— 最快的短屏复现方式调大系统字号再验证— 字体变化会改变实际内容高度要单独测试一次检查 layoutWeight 的父容器是否有明确高度— 父容器高度 auto 会导致 layoutWeight 失效底部安全区域— 确认按钮是否因为手势条区域被遮挡。开发经验总结页面高度适配的核心是固定高度区域标题、底部操作先分配剩余空间全部交给可滚动的内容区用layoutWeight(1)加Scroll组合来实现。横屏是成本最低的短屏测试手段不需要折叠屏设备任何手机都可以直接验证。layoutWeight有生效前提父容器必须有明确尺寸且是 Row 或 Column这一点比layoutWeight本身更值得注意。字体变大引发的高度溢出和短屏本质上是同一个问题统一用可滚动的内容区来应对。底部操作区必须放在 Scroll 外部这是保证关键按钮始终可见的前提。如果你正在处理类似的页面结构可以重点观察一下项目里所有使用固定高度内容区 底部操作按钮组合的页面在横屏模式下逐个检查一遍这类问题通常集中在表单页、详情页和设置页。 写在最后如果你觉得这篇文章对你有帮助或者有任何想法、建议欢迎在评论区留言交流你的每一个点赞 、收藏 ⭐、关注 ❤️都是我持续更新的最大动力我是一个在代码世界里不断摸索的小码农愿我们都能在成长的路上越走越远越学越强感谢你的阅读我们下篇文章再见✍️ 作者菜鸟不学编程 本文原创转载请注明出处。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →