专栏首页向治洪react-native 之布局总结

react-native 之布局总结

前言

之前我们讲了很多react-native的基础控件,为了方便大家的理解,我们来对react-native的布局做一个总结,观看本节知识,你将看到。

  • 宽度单位和像素密度
  • flex的布局
  • 图片布局
  • 绝对定位和相对定位
  • padding和margin的区别和应用场合
  • 文本元素

宽度单位和像素密度

我们知道在Android中是用设备像素来作为单位的(后面又出现了百分比这么 一个概念),ios中后面也有了Auto Layout和1倍图,二倍图等概念(xib+storyboard)。然而react的宽度不支持百分比,那么React怎么提供尺寸的呢?PixelRatio,PixelRatio及像素密度,可以看看官方的介绍。

 var image = getImage({
   width: 200 * PixelRatio.get(),
   height: 100 * PixelRatio.get()
 });
 <Image source={image} style={{width: 200, height: 100}} />

flex的布局

我们知道一个div如果不设置宽度,默认的会占用100%的宽度, 为了验证100%这个问题, 做三个实验:

  1. 根节点上方一个View, 不设置宽度
  2. 固定宽度的元素上设置一个View, 不设置宽度
  3. flex的元素上放一个View宽度, 不设置宽度
 <Text style={[styles.text, styles.header]}>
      根节点上放一个元素,不设置宽度
  </Text>        

  <View style={{height: 20, backgroundColor: '#333333'}} />

  <Text style={[styles.text, styles.header]}>
      固定宽度的元素上放一个View,不设置宽度
  </Text> 

  <View style={{width: 100}}>
    <View style={{height: 20, backgroundColor: '#333333'}} />
  </View>

  <Text style={[styles.text, styles.header]}>
      flex的元素上放一个View,不设置宽度
  </Text> 

  <View style={{flexDirection: 'row'}}>
    <View style={{flex: 1}}>
      <View style={{height: 20, backgroundColor: '#333333'}} />
    </View>
    <View style={{flex: 1}}/>
  </View>

来看一下运行的结果:

水平垂直居中

css 里边经常会将一个文本或者图片水平垂直居中,如果使用过css 的flexbox当然知道使用alignItems 和 justifyContent ,那如果用React Native如何实现呢?

<Text style={[styles.text, styles.header]}>
        水平居中
    </Text>

    <View style={{height: 100, backgroundColor: '#333333', alignItems: 'center'}}>
      <View style={{backgroundColor: '#fefefe', width: 30, height: 30, borderRadius: 15}}/>
    </View>

     <Text style={[styles.text, styles.header]}>
        垂直居中
    </Text>
    <View style={{height: 100, backgroundColor: '#333333', justifyContent: 'center'}}>
      <View style={{backgroundColor: '#fefefe', width: 30, height: 30, borderRadius: 15}}/>
    </View>

    <Text style={[styles.text, styles.header]}>
        水平垂直居中
    </Text>
    <View style={{height: 100, backgroundColor: '#333333', alignItems: 'center', justifyContent: 'center'}}>
      <View style={{backgroundColor: '#fefefe', width: 30, height: 30, borderRadius: 15}}/>
    </View>

网格布局

通常页面不是很复杂的时候,我们可以使用flex布局等分做到网格,复杂的那么就要用ListView实现,或者第三方控件。

等分的网格

<View style={styles.flexContainer}>
      <View style={styles.cell}>
        <Text style={styles.welcome}>
          cell1
        </Text>
      </View>
      <View style={styles.cell}>
        <Text style={styles.welcome}>
          cell2
        </Text>
      </View>
      <View style={styles.cell}>
        <Text style={styles.welcome}>
          cell3
        </Text>
      </View>
    </View>

    styles = {
        flexContainer: {
            // 容器需要添加direction才能变成让子元素flex
            flexDirection: 'row'
        },
        cell: {
            flex: 1,
            height: 50,
            backgroundColor: '#aaaaaa'
        },
        welcome: {
            fontSize: 20,
            textAlign: 'center',
            margin: 10
        },
    }

另一种方式可以参照我之前的实现: React Native实现九宫格效果

图片布局

<Text style={styles.welcome}> 100px height </Text>
  <Image style={{height: 100}} source={{uri: 'http://gtms03.alicdn.com/tps/i3/TB1Kcs5GXXXXXbMXVXXutsrNFXX-608-370.png'}} />

100px 高度, 可以看到图片适应100高度和全屏宽度,背景居中适应未拉伸但是被截断也就是cover。

  <Text style={styles.welcome}> 100px height with resizeMode contain </Text>
  <View style={[{flex: 1, backgroundColor: '#fe0000'}]}>
      <Image style={{flex: 1, height: 100, resizeMode: Image.resizeMode.contain}} source={{uri: 'http://gtms03.alicdn.com/tps/i3/TB1Kcs5GXXXXXbMXVXXutsrNFXX-608-370.png'}} />
  </View>

contain 模式容器完全容纳图片,图片自适应宽高。

  <Text style={styles.welcome}> 100px height with resizeMode cover </Text>
  <View style={[{flex: 1, backgroundColor: '#fe0000'}]}>
      <Image style={{flex: 1, height: 100, resizeMode: Image.resizeMode.cover}} source={{uri: 'http://gtms03.alicdn.com/tps/i3/TB1Kcs5GXXXXXbMXVXXutsrNFXX-608-370.png'}} />
  </View>

stretch模式图片被拉伸适应屏幕

 <Text style={styles.welcome}> set height to image container </Text>
  <View style={[{flex: 1, backgroundColor: '#fe0000', height: 100}]}>
      <Image style={{flex: 1}} source={{uri: 'http://gtms03.alicdn.com/tps/i3/TB1Kcs5GXXXXXbMXVXXutsrNFXX-608-370.png'}} />
  </View>

绝对定位和相对定位

<View style={{flex: 1, height: 100, backgroundColor: '#333333'}}>
    <View style={[styles.circle, {position: 'absolute', top: 50, left: 180}]}>
    </View>
  </View>
  styles = {
    circle: {
    backgroundColor: '#fe0000',
    borderRadius: 10,
    width: 20,
    height: 20
    }
  }

和css的标准不同的是, 元素容器不用设置position:’absolute|relative’ 。

<View style={{flex: 1, height: 100, backgroundColor: '#333333'}}>
    <View style={[styles.circle, {position: 'relative', top: 50, left: 50, marginLeft: 50}]}>
    </View>
  </View>

padding和margin

我们知道在css中区分inline元素和block元素,既然react-native实现了一个超级小的css subset。那我们就来实验一下padding和margin在inline和非inline元素上的padding和margin的使用情况。 padding

 <Text style={[styles.text, styles.header]}>
    在正常的View上设置padding 
  </Text>

  <View style={{padding: 30, backgroundColor: '#333333'}}>
    <Text style={[styles.text, {color: '#fefefe'}]}> Text Element</Text>
  </View>

  <Text style={[styles.text, styles.header]}>
    在文本元素上设置padding
  </Text>
  <View style={{padding: 0, backgroundColor: '#333333'}}>
    <Text style={[styles.text, {backgroundColor: '#fe0000', padding: 30}]}>
      text 元素上设置paddinga
    </Text>
  </View>

margin

 <Text style={[styles.text, styles.header]}>
    在正常的View上设置margin 
  </Text>

  <View style={{backgroundColor: '#333333'}}>
    <View style={{backgroundColor: '#fefefe', width: 30, height: 30, margin: 30}}/>
  </View>

  <Text style={[styles.text, styles.header]}>
    在文本元素上设置margin
  </Text>
  <View style={{backgroundColor: '#333333'}}>
    <Text style={[styles.text, {backgroundColor: '#fe0000', margin: 30}]}>
      text 元素上设置margin
    </Text>
    <Text style={[styles.text, {backgroundColor: '#fe0000', margin: 30}]}>
      text 元素上设置margin
    </Text>
  </View>

文本元素

先看看文字有哪些支持的style属性:

 Attributes.style = {
    color string
    containerBackgroundColor string
    fontFamily string
    fontSize number
    fontStyle enum('normal', 'italic')
    fontWeight enum("normal", 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900')
    lineHeight number
    textAlign enum("auto", 'left', 'right', 'center')
    writingDirection enum("auto", 'ltr', 'rtl')
  }

Text的样式继承

实际上React-native里边是没有样式继承这种说法的, 但是对于Text元素里边的Text元素是可以继承的。到底是继承的最外层的Text的值呢,还是继承父亲Text的值呢?肯定是继承父亲Text的值。

 <Text style={[styles.text, styles.header]}>
      文本样式继承
  </Text>

  <View style={{backgroundColor: '#333333', padding: 10}}>
    <Text style={{color: 'white'}}>
      <Text style={{color: 'red'}} onPress={this.onPressTitle}>
         文本元素{'\n'}
        <Text>我是white还是red呢?{'\n'} </Text>
      </Text>
      <Text>我应该是white的</Text>
    </Text>
  </View>

总结

针对上面的实例,我们做一个总结。

  • react 宽度基于pt为单位, 可以通过Dimensions 来获取宽高,PixelRatio 获取密度。
  • 基于flex的布局: view默认宽度为100% 水平居中用alignItems, 垂直居中用justifyContent 基于flex能够实现现有的网格系统需求,且网格能够各种嵌套无bug
  • 图片布局 通过Image.resizeMode来适配图片布局,包括contain, cover, stretch 三种模式 默认不设置模式等于cover模式 contain模式自适应宽高,给出高度值即可 cover铺满容器,但是会做截取 stretch铺满容器,拉伸
  • 绝对定位和相对定位 定位相对于父元素,父元素不用设置position也行 padding 设置在Text元素上的时候会存在bug。所有padding变成了marginBottom
  • 文本元素 文字必须放在Text元素里边 Text元素可以相互嵌套,且存在样式继承关系 numberOfLines 需要放在最外层的Text元素上,且虽然截取了文字但是还是会占用空间

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • React Native之ScrollView控件详解

    概述 ScrollView在Android和ios原生开发中都比较常见,是一个 滚动视图控件。在RN开发中,系统也给我们提供了这么一个控件。不过在RN开发中 ,...

    xiangzhihong
  • React Native控件只TextInput

    TextInput是一个允许用户在应用中通过键盘输入文本的基本组件。本组件的属性提供了多种特性的配置,譬如自动完成、自动大小写、占位文字,以及多种不同的键盘类型...

    xiangzhihong
  • React Native 实现基于react-native-tab-navigator库Tab切换封装

    react-native-tab-navigator是一款Tab切换的库,细心的读者可能注意到了对于TabNavigator.Item选项卡部分,代码功能上基本...

    xiangzhihong
  • 【React Native 安卓开发】----(View实战之仿携程)【第三篇】

    如图:我们可以想到先做三个View 这三个View使用FlexBox平分,flex都为1,这里的flex其实就相当于安卓里面的weight权重的概念。

    先知先觉
  • Eureka+SpringBoot2.X结合Security注册中心安全验证

    Arebirth
  • 英语和汉语谁更高效?17大主流语言测试结果:没有优劣之分,带宽都是每秒39bit

    首先,不同语种的说话速度差异很大。有研究证明,意大利人语速最快,每秒能说9个音节;而德国人语速最慢,每秒只能说5~6个音节。

    量子位
  • 谷歌推出“Federated Learning”,一种全新的机器学习模式

    传统机器学习方法,需要把训练数据集中于某一台机器或是单个数据中心里。谷歌等云服务巨头还建设了规模庞大的云计算基础设施,来对数据进行处理。现在,为利用移动设备上的...

    BestSDK
  • 开发 | 分布式机器学习时代即将来临?谷歌推出“Federated Learning”

    传统机器学习方法,需要把训练数据集中于某一台机器或是单个数据中心里。谷歌等云服务巨头还建设了规模庞大的云计算基础设施,来对数据进行处理。现在,为利用移动设备上的...

    AI科技评论
  • 手机里跑个 AI 模型 | 谷歌 Federated Learning 联盟学习

    各位数据大咖,还记得自己的跑模型的心路历程么?我想大家都在经历着下面的一个或多个阶段: 论文答辩前夕,把自己敲进去的三千多条数据放进SAS中,哗的一下模型出来了...

    数说君
  • 分布式机器学习时代即将来临?谷歌推出“Federated Learning”

    传统机器学习方法,需要把训练数据集中于某一台机器或是单个数据中心里。谷歌等云服务巨头还建设了规模庞大的云计算基础设施,来对数据进行处理。现在,为利用移动设备上的...

    AI研习社

扫码关注云+社区

领取腾讯云代金券