本文总结:
我们学到了 React Native 的 Flexbox 布局,它让写样式变得更方便啦!😊 Flexbox 就像一个有弹性的盒子,有主轴和交叉轴(行或列)。
在 RN 里写样式要用 StyleSheet.create
对象,属性名是驼峰命名。
文章还介绍了如何用 Platform.select
给不同平台写样式,以及使用 styled-components 这个库的简单例子(虽然我们主要还是用 StyleSheet)。
文章还通过三栏布局 和横向布局 的例子,展示了 flexDirection
, alignItems
, justifyContent
和 alignSelf
这些属性的用法。
特别喜欢 alignSelf: 'stretch'
能让元素填充空间的技巧!👍
最后,通过抽象出 Row
和 Col
组件,我看到了如何用 Flexbox 实现更复杂的嵌套布局。感觉 Flexbox 真的让布局变得灵活多了!🚀
1、关于Flexbox
在将flexbox
引入css
前,构建布局的各种css
属性都比较粗糙,而且很容易出错。而flexbox
通过抽象了很多属性来解决问题。字如其名flexbox
的意思就是一个具有弹性的盒子模型。我们画个图:假设你有一个容器和它的子元素,它看起来可以是这样的。
Flexbox
容器有二个轴,即列
(向上/向下)或行
(左/右)。
2、实操
我们直接上代码吧,这是一个js
模块,而不是css
模块。如果我们要声明rn
的样式,我们需要去定义一个对象然后调用StyleSheet.create()
最后抛出它在你的模块中。但是我们需要注意的是rn
只支持驼峰命名
。
JavaScript
import { Platform, StyleSheet, StatusBar } from 'react-native'
export default StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'ghostwhite',
...Platform.select({
ios: { paddingTop: 20 },
android: { paddingTop: StatusBar.currentHeight },
}),
},
box: {
width: 100,
height: 100,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'lightgray',
},
boxText: {
color: 'darkslategray',
fontWeight: 'bold',
},
})
然后我们看到刚才我写了这样一段代码,这里其实就是根据你的移动端去选择样式。
JavaScript
...Platform.select({
ios: { paddingTop: 20 },
android: { paddingTop: StatusBar.currentHeight },
}),
ok,我们看一下在rn
组件中如何使用
JavaScript
import { Text, View } from 'react-native'
import styles from './styles'
export default function App() {
return (
<View style={styles.container}>
<View style={styles.box}>
<Text style={styles.boxText}>I'm in a box</Text>
</View>
</View>
)
}
这些样式将通过样式属性分配给每个组件。我们来看看它的表现。
3、Styled-components样式组件库使用
Styled-components
是一个css-in-js
的库为我们的组件去提供样式,如我们去直接看看怎么使用吧。当然只是介绍一下,我们还是使用styleSheet
。
首先下载依赖
JavaScript
yarn add styled-components
然后我们写点代码
JavaScript
import styled from "styled-components/native";
const Box = styled.View'
width: 100px;
height: 100px;
justify-content: center;
align-items: center;
background-color: lightgray;
';
const BoxText = styled.Text'
color: darkslategray;
font-weight: bold;
';
使用
JavaScript
const App = () => {
return (
<Box>
<BoxText>I'm in a box</BoxText>
</Box>
);
};
4、基础Flexbox
接下来主要讲一下rn
中的几种常见布局和flexbox
的实战
4.1、三栏布局
普通的从上到下的三栏布局。
你可以把view
理解成div
,text
理解成p
。
JavaScript
import { Text, View } from 'react-native'
import styles from './styles'
export default function App() {
return (
<View style={styles.container}>
<View style={styles.box}>
<Text style={styles.boxText}>#1</Text>
</View>
<View style={styles.box}>
<Text style={styles.boxText}>#2</Text>
</View>
<View style={styles.box}>
<Text style={styles.boxText}>#3</Text>
</View>
</View>
)
}
flexDirection
属性是决定了主轴的方向,上到下或者左到右,而alignItem
和justifyContent
属性决定了元素的排列和间隔。
PHP
import { Platform, StyleSheet, StatusBar } from 'react-native'
export default StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'space-around',
backgroundColor: 'ghostwhite',
...Platform.select({
ios: { paddingTop: 20 },
android: { paddingTop: StatusBar.currentHeight },
}),
},
box: {
width: 300,
height: 100,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'lightgray',
borderWidth: 1,
borderStyle: 'dashed',
borderColor: 'darkslategray',
},
boxText: {
color: 'darkslategray',
fontWeight: 'bold',
},
})
而如果我们想让它左右两边填满那?就像这样
我们可以加入alignSelf
这个属性,这个属性的意思是根据主轴flexDirection
的方向,改变宽度或者高度(column改变的就是宽度,row改变的就是高度)去填充空白,动态计算高度或宽度。像这样就是会填满你屏幕的宽度。
JavaScript
box: {
height: 100,
justifyContent: 'center',
//
alignSelf: 'stretch',
alignItems: 'center',
backgroundColor: 'lightgray',
borderWidth: 1,
borderStyle: 'dashed',
borderColor: 'darkslategray',
},
当我们把手机横过去
我们稍微优化一下,正好也写一下横向的布局,上面的样式太`抽象`了写得。
JavaScript
import { Text, View, StatusBar } from 'react-native'
import styles from './styles'
import Box from './Box'
export default function App() {
return (
<View style={styles.container}>
<Box>#1</Box>
<Box>#2</Box>
</View>
)
}
JavaScript
import { PropTypes } from 'prop-types'
import { View, Text } from 'react-native'
import styles from './styles'
export default function Box({ children }) {
return (
<View style={styles.box}>
<Text style={styles.boxText}>{children}</Text>
</View>
)
}
Box.propTypes = {
children: PropTypes.node.isRequired,
}
这个就是会拉伸至整个屏幕高度的横向布局
PHP
import { Platform, StyleSheet, StatusBar } from 'react-native'
export default StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
backgroundColor: 'ghostwhite',
alignItems: 'center',
justifyContent: 'space-around',
...Platform.select({
ios: { paddingTop: 20 },
android: { paddingTop: StatusBar.currentHeight },
}),
},
box: {
width: 100,
justifyContent: 'center',
alignSelf: 'stretch',
alignItems: 'center',
backgroundColor: 'lightgray',
borderWidth: 1,
borderStyle: 'dashed',
borderColor: 'darkslategray',
},
boxText: {
color: 'darkslategray',
fontWeight: 'bold',
},
})
我们来看看它的表现
当我们把手机横过去
5、稍微复杂一点的flexBox
假设我们要实现这样一个效果,我们该如何实现?
在我们的意识中,整个布局有行
、列
。那我们同样也可以抽象出col
、row
组件分别代表行列。我们直接上代码吧。
可以看到我们分别确定了col
、row
的方向和排列。
JavaScript
import { Platform, StyleSheet, StatusBar } from 'react-native'
export default StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
backgroundColor: 'ghostwhite',
alignItems: 'center',
justifyContent: 'space-around',
...Platform.select({
ios: { paddingTop: 40 },
android: { paddingTop: StatusBar.currentHeight },
}),
},
box: {
height: 100,
width: 100,
justifyContent: 'center',
alignItems: 'center',
borderWidth: 1,
borderStyle: 'dashed',
borderColor: 'darkslategray',
backgroundColor: 'lightgray',
},
boxText: {
color: 'darkslategray',
fontWeight: 'bold',
},
row: {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-around',
alignSelf: 'stretch',
},
column: {
flex: 1,
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'space-around',
alignSelf: 'stretch',
},
})
组件部分
app
JavaScript
import { View, StatusBar } from 'react-native'
import styles from './styles'
import Row from './Row'
import Col from './Col'
import Box from './Box'
export default function App() {
return (
<View style={styles.container}>
<StatusBar hidden={false} />
<Row>
<Col>
<Box>#1</Box>
<Box>#2</Box>
</Col>
<Col>
<Box>#3</Box>
<Box>#4</Box>
</Col>
</Row>
<Row>
<Col>
<Box>#5</Box>
<Box>#6</Box>
</Col>
<Col>
<Box>#7</Box>
<Box>#8</Box>
</Col>
</Row>
<Row>
<Col>
<Box>#9</Box>
<Box>#10</Box>
</Col>
<Col>
<Box>#11</Box>
<Box>#12</Box>
</Col>
</Row>
</View>
)
}
col
JavaScript
import PropTypes from 'prop-types'
import { View } from 'react-native'
import styles from './styles'
export default function Column({ children }) {
return <View style={styles.column}>{children}</View>
}
Column.propTypes = {
children: PropTypes.node.isRequired,
}
row
JavaScript
import PropTypes from 'prop-types'
import { View } from 'react-native'
import styles from './styles'
export default function Row({ children }) {
return <View style={styles.row}>{children}</View>
}
Row.propTypes = {
children: PropTypes.node.isRequired,
}
JavaScript
import React from 'react'
import PropTypes from 'prop-types'
import { View, Text } from 'react-native'
import styles from './styles'
export default function Box({ children }) {
return (
<View style={styles.box}>
<Text style={styles.boxText}>{children}</Text>
</View>
)
}
Box.propTypes = {
children: PropTypes.node.isRequired,
}
6、总结
欢迎加入群聊,我们一起讨论一些更有趣的技术、商业、闲聊。