3.3 StyleSheet与Flexbox布局


文档摘要

3.3 StyleSheet与Flexbox布局 本节摘要:RN 的布局只有一套答案:Flexbox。本节建立「主轴与交叉轴」的推导模型——先定方向、再定对齐、最后定伸缩,让任何布局都能按步骤推出来而不是试出来;同时讲清样式组织的工程纪律与双端默认值差异(方向默认值、单位语义、阴影与发丝线)。本节承接 3.2 的组件认知,是从「能显示」到「还原设计稿」的关键一跃。 从一张设计稿说起 设计评审会上,设计师把一张个人主页头部的设计稿投在屏幕上:头像在左,名字与签名垂直排列在头像右侧,底部三个统计数字横排等分。前端同学要在两端都把它还原出来。这个看似普通的任务,恰好覆盖 Flexbox 的全部核心概念——方向、对齐、伸缩。

3.3 StyleSheet与Flexbox布局

本节摘要:RN 的布局只有一套答案:Flexbox。本节建立「主轴与交叉轴」的推导模型——先定方向、再定对齐、最后定伸缩,让任何布局都能按步骤推出来而不是试出来;同时讲清样式组织的工程纪律与双端默认值差异(方向默认值、单位语义、阴影与发丝线)。本节承接 3.2 的组件认知,是从「能显示」到「还原设计稿」的关键一跃。

从一张设计稿说起

设计评审会上,设计师把一张个人主页头部的设计稿投在屏幕上:头像在左,名字与签名垂直排列在头像右侧,底部三个统计数字横排等分。前端同学要在两端都把它还原出来。这个看似普通的任务,恰好覆盖 Flexbox 的全部核心概念——方向、对齐、伸缩。RN 与 Web 最大的心智差异立刻出现:Web 的容器默认主轴是水平的,而 RN 出于移动竖屏的直觉,flexDirection 默认值是 column——竖直方向。无数从 Web 转来的布局 bug,根源都是这个默认值的惯性。所以本节的推导模型第一步永远是:先问主轴在哪。

主轴由 flexDirection 决定:row 是水平,column 是竖直;justifyContent 管的是「子项沿主轴怎么排」,alignItems 管「子项沿交叉轴怎么对」,flexWrap 决定放不下时换不换行。而伸缩由 flex 系数描述:给子项设 flex 为 1 且兄弟同级同值,则剩余空间被均分——设计稿里「三个统计数字横排等分」就是一行容器配三个 flex 等分的孩子。下面这张标注图把这套语言画清楚。

图:Flexbox 主轴与交叉轴标注

图:Flexbox 主轴与交叉轴标注

样式组织:StyleSheet 的工程纪律

布局语言之外,样式怎么组织决定项目的可维护性。基本纪律有三条。第一,静态样式一律收进 StyleSheet.create:它带来引用稳定性(样式对象不随渲染重建)、键名校验(写错属性名开发期就能发现)、以及集中可读(组件文件底部就是这页的「样式户口本」)。第二,动态值走样式数组:静态部分进 StyleSheet,随状态变化的少数属性用内联写在数组后面覆盖,例如选中态的边框色——既保住静态样式复用,又不让动态值污染户口本。第三,禁止魔法数字裸奔:间距、圆角、字号这类反复出现的值,收敛成设计令牌常量再引用,设计师改一版规范时你只需要改一处。

单位语义也要交代清楚:RN 的数字默认是密度无关像素,与屏幕物理密度解耦,两端观感一致,不需要也不应该再做像素换算。发丝线是另一个高频点:分隔线用 hairlineWidth 常量,它会取当前设备能渲染的最细线宽——写死 1 像素在高清屏上会显得粗笨,这正是「密度无关」原则的例外条款。

动手:还原那张设计稿

把开场的设计稿写成完整可运行的组件,注释标注每步的推导依据:

import React from 'react'; import { View, Text, Image, StyleSheet, Platform } from 'react-native'; // 复用 3.2 节沉淀的阴影语义:一级浮起 const levelOneShadow = Platform.select({ ios: { shadowColor: '#000', shadowOpacity: 0.1, shadowRadius: 6, shadowOffset: { width: 0, height: 2 } }, android: { elevation: 3 }, default: {}, }); export function ProfileHeader({ avatar, name, bio, followers, likes, posts }) { return ( <View style={styles.wrap}> {/* 上半区:水平主轴,头像固定宽,文字区 flex 伸缩占满剩余 */} <View style={styles.topRow}> <Image source={{ uri: avatar }} style={styles.avatar} /> <View style={styles.nameCol}> <Text style={styles.name}>{name}</Text> <Text style={styles.bio}>{bio}</Text> </View> </View> {/* 下半区:水平主轴,三个统计项 flex 等分 */} <View style={styles.statsRow}> <Text style={styles.stat}>{followers}</Text> <Text style={styles.stat}>{likes}</Text> <Text style={styles.stat}>{posts}</Text> </View> </View> ); } const styles = StyleSheet.create({ wrap: { margin: 16, padding: 16, borderRadius: 12, backgroundColor: '#fff', ...levelOneShadow }, topRow: { flexDirection: 'row', alignItems: 'center' }, avatar: { width: 56, height: 56, borderRadius: 28, marginRight: 12 }, nameCol: { flex: 1, justifyContent: 'center' }, name: { fontSize: 17, fontWeight: '600', color: '#2c3e50' }, bio: { fontSize: 13, color: '#7a8a99', marginTop: 2 }, statsRow: { flexDirection: 'row', marginTop: 14, paddingTop: 12, borderTopWidth: StyleSheet.hairlineWidth, borderTopColor: '#e4eaf0' }, stat: { flex: 1, textAlign: 'center', fontSize: 14, color: '#34495e' }, });

其中 levelOneShadow 是 3.2 节沉淀的阴影语义对象——布局与差异管理在这里完成会师。逐段回看推导:上半区主轴水平(row),名字区 flex 1 吃掉剩余宽度;下半区主轴水平,三个统计文字各 flex 1 实现等分;分隔线用发丝线常量。没有一处尺寸是试出来的。

完整案例:三栏等高布局的推导

背景:某内容页需要「左图、中标题摘要、右按钮」的三栏列表项,且要求三栏垂直居中、中栏自适应宽度、按钮不被压缩。操作:主轴设 row,交叉轴对齐设 center 解决垂直居中;中栏 flex 1 占据剩余空间,同时配合最小宽度防止极窄;按钮设固定内边距且 flexShrink 为 0,声明「我不可被压缩」;图片固定尺寸。结果:从短标题到两行长标题、再到超长无空格串,三种数据下布局都稳定——长文本被中栏自动截断省略而不是把按钮挤出屏幕。解读:等高与居中来自交叉轴对齐,压缩策略来自 flex 三兄弟(flexGrow、flexShrink、flexBasis)的显式声明——「谁可伸展、谁可压缩、谁按兵不动」三问答完,布局就收敛了。变式:若设计改为「按钮要贴底」,交叉轴对齐改 alignSelf 逐项覆盖即可,整行其他子项不受牵连。这个案例可以当成模板背下来,列表项布局九成是它的变体。

本节要点回顾

  • RN 默认主轴是竖直的:从 Web 转来的第一课,先改 row 直觉;
  • 推导三步法:主轴方向、双轴对齐、伸缩策略,按序回答不试错;
  • flex 三兄弟显式表态:谁可长、谁可缩、谁固定,压缩事故多源于没表态;
  • StyleSheet 三纪律:静态进 create、动态走数组、令牌禁魔法数字;
  • 单位密度无关:数字即密度无关像素,发丝线用 hairlineWidth 常量。

静态的界面立起来了,下一节让它动起来:手势如何跟手,动画如何不卡,两套动画方案各适合什么场景。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U