React Native布局与Flexbox #
概述 #
React Native 使用 Flexbox(弹性盒模型)作为主要的布局系统。Flexbox 提供了一种高效的方式来排列、对齐和分配容器中元素的空间。
Flexbox 基础 #
主轴与交叉轴 #
在 Flexbox 中,有两个重要的概念:
- 主轴(Main Axis):元素排列的方向
- 交叉轴(Cross Axis):与主轴垂直的方向
text
flexDirection: 'row' flexDirection: 'column'
┌─────────────────────┐ ┌─────────────────────┐
│ ┌───┐ ┌───┐ ┌───┐ │ │ ┌─────────────────┐ │
│ │ 1 │ │ 2 │ │ 3 │ │ │ │ 1 │ │
│ └───┘ └───┘ └───┘ │ │ └─────────────────┘ │
│ ←── 主轴 ──→ │ │ ┌─────────────────┐ │
│ ↓ 交叉轴 │ │ │ 2 │ │
└─────────────────────┘ │ └─────────────────┘ │
│ ┌─────────────────┐ │
│ │ 3 │ │
│ └─────────────────┘ │
│ ↑ 主轴 │
│ ← 交叉轴 → │
└─────────────────────┘
flexDirection #
决定主轴方向,即子元素的排列方向。
column(默认) #
垂直方向,从上到下:
tsx
const ColumnExample = () => {
return (
<View style={styles.container}>
<View style={styles.box1} />
<View style={styles.box2} />
<View style={styles.box3} />
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
backgroundColor: '#f5f5f5',
},
box1: {height: 100, backgroundColor: '#FF6B6B'},
box2: {height: 100, backgroundColor: '#4ECDC4'},
box3: {height: 100, backgroundColor: '#45B7D1'},
});
row #
水平方向,从左到右:
tsx
const RowExample = () => {
return (
<View style={styles.container}>
<View style={styles.box1} />
<View style={styles.box2} />
<View style={styles.box3} />
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
backgroundColor: '#f5f5f5',
},
box1: {width: 100, backgroundColor: '#FF6B6B'},
box2: {width: 100, backgroundColor: '#4ECDC4'},
box3: {width: 100, backgroundColor: '#45B7D1'},
});
反向方向 #
column-reverse:从下到上row-reverse:从右到左
justifyContent #
定义子元素在主轴上的对齐方式。
tsx
const JustifyContentExample = () => {
return (
<ScrollView>
<Text>flex-start</Text>
<View style={[styles.row, styles.flexStart]}>
<View style={styles.box} />
<View style={styles.box} />
<View style={styles.box} />
</View>
<Text>center</Text>
<View style={[styles.row, styles.center]}>
<View style={styles.box} />
<View style={styles.box} />
<View style={styles.box} />
</View>
<Text>flex-end</Text>
<View style={[styles.row, styles.flexEnd]}>
<View style={styles.box} />
<View style={styles.box} />
<View style={styles.box} />
</View>
<Text>space-between</Text>
<View style={[styles.row, styles.spaceBetween]}>
<View style={styles.box} />
<View style={styles.box} />
<View style={styles.box} />
</View>
<Text>space-around</Text>
<View style={[styles.row, styles.spaceAround]}>
<View style={styles.box} />
<View style={styles.box} />
<View style={styles.box} />
</View>
<Text>space-evenly</Text>
<View style={[styles.row, styles.spaceEvenly]}>
<View style={styles.box} />
<View style={styles.box} />
<View style={styles.box} />
</View>
</ScrollView>
);
};
const styles = StyleSheet.create({
row: {
flexDirection: 'row',
height: 100,
backgroundColor: '#f5f5f5',
marginBottom: 20,
},
box: {
width: 50,
backgroundColor: '#007AFF',
},
flexStart: {justifyContent: 'flex-start'},
center: {justifyContent: 'center'},
flexEnd: {justifyContent: 'flex-end'},
spaceBetween: {justifyContent: 'space-between'},
spaceAround: {justifyContent: 'space-around'},
spaceEvenly: {justifyContent: 'space-evenly'},
});
对齐方式对比 #
| 值 | 效果 |
|---|---|
| flex-start | 从起点开始排列 |
| center | 居中排列 |
| flex-end | 从终点开始排列 |
| space-between | 两端对齐,中间平分 |
| space-around | 每个元素两侧间隔相等 |
| space-evenly | 所有间隔完全相等 |
alignItems #
定义子元素在交叉轴上的对齐方式。
tsx
const AlignItemsExample = () => {
return (
<ScrollView>
<Text>flex-start</Text>
<View style={[styles.row, styles.alignStart]}>
<View style={[styles.box, {height: 50}]} />
<View style={[styles.box, {height: 80}]} />
<View style={[styles.box, {height: 60}]} />
</View>
<Text>center</Text>
<View style={[styles.row, styles.alignCenter]}>
<View style={[styles.box, {height: 50}]} />
<View style={[styles.box, {height: 80}]} />
<View style={[styles.box, {height: 60}]} />
</View>
<Text>flex-end</Text>
<View style={[styles.row, styles.alignEnd]}>
<View style={[styles.box, {height: 50}]} />
<View style={[styles.box, {height: 80}]} />
<View style={[styles.box, {height: 60}]} />
</View>
<Text>stretch</Text>
<View style={[styles.row, styles.alignStretch]}>
<View style={styles.boxNoHeight} />
<View style={styles.boxNoHeight} />
<View style={styles.boxNoHeight} />
</View>
</ScrollView>
);
};
const styles = StyleSheet.create({
row: {
flexDirection: 'row',
height: 120,
backgroundColor: '#f5f5f5',
marginBottom: 20,
},
box: {
width: 50,
backgroundColor: '#007AFF',
},
boxNoHeight: {
width: 50,
backgroundColor: '#007AFF',
},
alignStart: {alignItems: 'flex-start'},
alignCenter: {alignItems: 'center'},
alignEnd: {alignItems: 'flex-end'},
alignStretch: {alignItems: 'stretch'},
});
flex 属性 #
flex: 1 #
让元素填充剩余空间:
tsx
const FlexExample = () => {
return (
<View style={styles.container}>
<View style={styles.header}>
<Text>Header</Text>
</View>
<View style={styles.content}>
<Text>Content - fills remaining space</Text>
</View>
<View style={styles.footer}>
<Text>Footer</Text>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5',
},
header: {
height: 60,
backgroundColor: '#007AFF',
justifyContent: 'center',
alignItems: 'center',
},
content: {
flex: 1,
backgroundColor: '#fff',
justifyContent: 'center',
alignItems: 'center',
},
footer: {
height: 60,
backgroundColor: '#333',
justifyContent: 'center',
alignItems: 'center',
},
});
flex 比例 #
多个元素按比例分配空间:
tsx
const FlexRatioExample = () => {
return (
<View style={styles.container}>
<View style={[styles.box, {flex: 1}]}>
<Text>flex: 1</Text>
</View>
<View style={[styles.box, {flex: 2}]}>
<Text>flex: 2</Text>
</View>
<View style={[styles.box, {flex: 1}]}>
<Text>flex: 1</Text>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
backgroundColor: '#f5f5f5',
},
box: {
backgroundColor: '#007AFF',
justifyContent: 'center',
alignItems: 'center',
margin: 2,
},
});
flexGrow, flexShrink, flexBasis #
tsx
const styles = StyleSheet.create({
grow: {
flexGrow: 1,
},
shrink: {
flexShrink: 1,
},
basis: {
flexBasis: 100,
},
});
flexWrap #
控制元素是否换行。
nowrap(默认) #
不换行,元素可能溢出:
tsx
const NoWrapExample = () => {
return (
<View style={styles.container}>
{[1, 2, 3, 4, 5, 6].map(i => (
<View key={i} style={styles.box}>
<Text>{i}</Text>
</View>
))}
</View>
);
};
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
flexWrap: 'nowrap',
backgroundColor: '#f5f5f5',
},
box: {
width: 80,
height: 80,
backgroundColor: '#007AFF',
margin: 4,
justifyContent: 'center',
alignItems: 'center',
},
});
wrap #
换行显示:
tsx
const WrapExample = () => {
return (
<View style={[styles.container, {flexWrap: 'wrap'}]}>
{/* 同上 */}
</View>
);
};
alignSelf #
允许单个元素覆盖父容器的 alignItems 设置:
tsx
const AlignSelfExample = () => {
return (
<View style={[styles.container, {alignItems: 'center'}]}>
<View style={[styles.box, {alignSelf: 'flex-start'}]}>
<Text>flex-start</Text>
</View>
<View style={styles.box}>
<Text>center (inherited)</Text>
</View>
<View style={[styles.box, {alignSelf: 'flex-end'}]}>
<Text>flex-end</Text>
</View>
<View style={[styles.box, {alignSelf: 'stretch'}]}>
<Text>stretch</Text>
</View>
</View>
);
};
实用布局模式 #
居中布局 #
tsx
const CenterLayout = () => {
return (
<View style={styles.container}>
<View style={styles.centered}>
<Text>Centered Content</Text>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
centered: {
padding: 20,
backgroundColor: '#007AFF',
},
});
等分布局 #
tsx
const EqualDistribution = () => {
return (
<View style={styles.row}>
{[1, 2, 3, 4].map(i => (
<View key={i} style={styles.equalItem}>
<Text>{i}</Text>
</View>
))}
</View>
);
};
const styles = StyleSheet.create({
row: {
flexDirection: 'row',
},
equalItem: {
flex: 1,
height: 50,
backgroundColor: '#007AFF',
margin: 2,
justifyContent: 'center',
alignItems: 'center',
},
});
固定侧边栏 #
tsx
const SidebarLayout = () => {
return (
<View style={styles.container}>
<View style={styles.sidebar}>
<Text>Sidebar</Text>
</View>
<View style={styles.content}>
<Text>Main Content</Text>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
},
sidebar: {
width: 200,
backgroundColor: '#333',
},
content: {
flex: 1,
backgroundColor: '#fff',
},
});
底部固定 #
tsx
const BottomFixedLayout = () => {
return (
<View style={styles.container}>
<ScrollView style={styles.content}>
<Text>Scrollable content...</Text>
</ScrollView>
<View style={styles.footer}>
<TouchableOpacity style={styles.button}>
<Text style={styles.buttonText}>Submit</Text>
</TouchableOpacity>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
content: {
flex: 1,
},
footer: {
padding: 16,
backgroundColor: '#fff',
borderTopWidth: 1,
borderTopColor: '#eee',
},
button: {
backgroundColor: '#007AFF',
padding: 16,
borderRadius: 8,
alignItems: 'center',
},
buttonText: {
color: '#fff',
fontSize: 16,
fontWeight: '600',
},
});
卡片网格 #
tsx
const CardGrid = () => {
const data = Array.from({length: 6}, (_, i) => i + 1);
return (
<View style={styles.container}>
{data.map(item => (
<View key={item} style={styles.card}>
<Text>Card {item}</Text>
</View>
))}
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
padding: 8,
},
card: {
width: '50%',
padding: 8,
},
cardInner: {
backgroundColor: '#fff',
borderRadius: 8,
padding: 16,
height: 150,
shadowColor: '#000',
shadowOffset: {width: 0, height: 2},
shadowOpacity: 0.1,
shadowRadius: 4,
elevation: 3,
},
});
常见问题 #
为什么 flex: 1 不生效? #
确保父容器有确定的尺寸:
tsx
const WrongExample = () => {
return (
<View>
<View style={{flex: 1}}> {/* 不会生效,父容器没有高度 */}
<Text>Content</Text>
</View>
</View>
);
};
const CorrectExample = () => {
return (
<View style={{flex: 1}}> {/* 父容器有确定高度 */}
<View style={{flex: 1}}>
<Text>Content</Text>
</View>
</View>
);
};
如何实现固定宽高比? #
tsx
const AspectRatioBox = () => {
const [width, setWidth] = useState(0);
return (
<View
style={styles.container}
onLayout={e => setWidth(e.nativeEvent.layout.width)}>
<View style={[styles.box, {height: width * 0.75}]}>
<Text>16:9 Aspect Ratio</Text>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
padding: 16,
},
box: {
backgroundColor: '#007AFF',
justifyContent: 'center',
alignItems: 'center',
},
});
总结 #
Flexbox 是 React Native 的核心布局系统:
- flexDirection:决定主轴方向
- justifyContent:主轴对齐
- alignItems:交叉轴对齐
- flex:弹性比例
- flexWrap:换行控制
- alignSelf:单独对齐
掌握 Flexbox 可以轻松实现各种复杂的布局需求。
继续学习 事件处理,了解触摸事件和手势处理。
最后更新:2026-03-28