横向标签栏的滚动实现

05/1623 浏览开发心得 疑似 AI 合成内容
ScrollView { scrollX=true, scrollY=false, showScrollbar=false }
  │
  └─ Panel { flexDirection="row", gap=8, 不设 width }
        │
        ├─ Item  ← height="100%", aspectRatio=1, flexShrink=0
        ├─ Item  ← 同上
        ├─ Item  ← 总宽度超出 ScrollView → 触发横向滚动
        ├─ Item
        ├─ Item
        └─ Item
让内容溢出
福利活动页有六个标签:签到、每日特惠、积天好礼、基金商城、深渊金库、尊享。
六个正方形图标排成一行,总宽度远超手机屏幕宽度。
常规做法是缩小图标挤进一行,或者拆成两行。
前者看不清,后者浪费纵向空间。
横向滚动是第三种选择——图标保持正常大小,超出的部分允许滑动查看。
要让横向滚动生效,首先得让内容真的溢出容器。
这靠三层结构配合。
最外层是一个 UI.ScrollView,三个属性:scrollX = true 开启横向滚动,scrollY = false 关闭纵向滚动,showScrollbar = false 隐藏滚动条。
ScrollView 占满页面宽度,高度设为父容器的 12% 并附带 minHeight = 70 兜底。
flexShrink = 0 确保它不会被同级的内容区压缩——标签栏是导航控件,高度必须固定。
ScrollView 里面套一个 Panel 做行容器,flexDirection = "row" 横向排列子元素,gap = 8 控制间距,两端各留 10 像素的 padding。
关键是这个 Panel 没有设置 width。在 Flexbox 布局中,不设宽度意味着内容有多宽它就有多宽。
六个正方形标签加上间距和内边距,总宽度超出 ScrollView 的可视区域,行容器自然溢出,ScrollView 检测到子内容比自身宽,横向滚动就生效了。
如果给行容器设了 width = "100%",Flexbox 会试图把子元素压缩到容器宽度以内,滚动就不会触发。不设宽度、让子元素的固有尺寸撑开容器,这是横向滚动布局的标准写法。
子元素不可压缩
每个标签是一个 Panel,核心属性三个:height = "100%",aspectRatio = 1,flexShrink = 0。
height = "100%" 撑满行容器高度。
aspectRatio = 1 强制宽高比 1:1——高度确定了,宽度自动等于高度,得到一个正方形。
flexShrink = 0 禁止 Flexbox 压缩这个元素。
flexShrink = 0 是整个横向滚动能生效的关键。
Flexbox 的默认行为是当子元素总宽度超出容器时,按 flexShrink 比例压缩各个子元素以适配容器宽度。
如果标签的 flexShrink 不为零,六个标签会被压扁到刚好塞进一屏,滚动永远不会触发。
显式声明 flexShrink = 0 是一种防御式写法——确保标签在任何情况下都保持正方形,不会被 Flexbox 吞掉宽度。
小结
整个横向滚动只用了三层嵌套。
ScrollView 开 scrollX 负责滚动能力;行容器不设宽度,让子元素自然溢出;子元素用 aspectRatio 锁定尺寸、用 flexShrink = 0 拒绝压缩。
三者缺一不可——ScrollView 不开 scrollX 则溢出内容被裁切;行容器设了宽度则子元素被压进一屏;子元素允许压缩则总宽度不会超出容器。
同样的三层结构可以用在任何需要横向溢出滚动的场景——卡牌列表、装备栏、技能槽、关卡选择。
核心就两点:外层容器开启横向滚动,内层元素禁止压缩让总宽度超出容器。
3
2