React-native之Flexbox

1、关于Flexbox

在将flexbox引入css前,构建布局的各种css属性都比较粗糙,而且很容易出错。而flexbox通过抽象了很多属性来解决问题。字如其名flexbox的意思就是一个具有弹性的盒子模型。我们画个图:假设你有一个容器和它的子元素,它看起来可以是这样的。

image.png

Flexbox容器有二个轴,即(向上/向下)或(左/右)。

2、实操

我们直接上代码吧,这是一个js模块,而不是css模块。如果我们要声明rn的样式,我们需要去定义一个对象然后调用StyleSheet.create()最后抛出它在你的模块中。但是我们需要注意的是rn只支持驼峰命名

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',
  },
})

然后我们看到刚才我写了这样一段代码,这里其实就是根据你的移动端去选择样式。

...Platform.select({
  ios: { paddingTop: 20 },
  android: { paddingTop: StatusBar.currentHeight },
}),

ok,我们看一下在rn组件中如何使用

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>
  )
}

这些样式将通过样式属性分配给每个组件。我们来看看它的表现。

image.png

3、Styled-components样式组件库使用

Styled-components是一个css-in-js的库为我们的组件去提供样式,如我们去直接看看怎么使用吧。当然只是介绍一下,我们还是使用styleSheet

首先下载依赖

yarn add styled-components

然后我们写点代码

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;
';

使用

const App = () => {
return (
    <Box>
        <BoxText>I'm in a box</BoxText>
    </Box>
);

};

4、基础Flexbox

接下来主要讲一下rn中的几种常见布局和flexbox的实战

4.1、三栏布局

普通的从上到下的三栏布局。

image.png

你可以把view理解成div,text理解成p

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属性是决定了主轴的方向,上到下或者左到右,而alignItemjustifyContent属性决定了元素的排列和间隔。

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',
  },
})

而如果我们想让它左右两边填满那?就像这样

image.png

我们可以加入alignSelf这个属性,这个属性的意思是根据主轴flexDirection的方向,改变宽度或者高度(column改变的就是宽度,row改变的就是高度)去填充空白,动态计算高度或宽度。像这样就是会填满你屏幕的宽度。

  box: {
    height: 100,
    justifyContent: 'center',
    // 
    alignSelf: 'stretch',
    alignItems: 'center',
    backgroundColor: 'lightgray',
    borderWidth: 1,
    borderStyle: 'dashed',
    borderColor: 'darkslategray',
  },

当我们把手机横过去

image.png

我们稍微优化一下,正好也写一下横向的布局,上面的样式太抽象了写得。

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>
 )
}

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,
}

这个就是会拉伸至整个屏幕高度的横向布局

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',
  },
})

我们来看看它的表现

image.png

当我们把手机横过去

image.png

5、稍微复杂一点的flexBox

假设我们要实现这样一个效果,我们该如何实现?

image.png

在我们的意识中,整个布局有。那我们同样也可以抽象出colrow组件分别代表行列。我们直接上代码吧。

可以看到我们分别确定了colrow的方向和排列。

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

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

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

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,
}

box

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、总结

我们在这节里知道了rn中最常见的布局方式,需要同学们自己下去多练一下,还是比较简单的,有问题


溪抱鱼
6 声望0 粉丝

写有意思的代码,做有创造力的事情,站着赚钱。