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 条评论
登录 后参与评论

相关文章

来自专栏数据库新发现

关于shared pool的深入探讨(一)

http://www.eygle.com/internal/shared_pool-1.htm

15930
来自专栏知道一点点

【原创】bootstrap框架的学习 第五课

<h2>引导主体副本</h2> <p class="lead">这是一个演示引导主体副本用法的实例。</p>

9230
来自专栏小灰灰

Css学习手册之基本篇

Css学习手册之基本篇 每次写前端都是一个痛苦的过程,总是静不下来,彻底的研究下前端的技术,导致每次套页面都是直接采用一些封装好的控件,而有时对这些样式不满意时...

45060
来自专栏Android先生

Android开发人员初识前端

<em> 表示强调,<strong> 表示更强烈的强调。并且在浏览器中<em> 默认用斜体表示,<strong> 用粗体表示。两个标签相比,目前国内前端程序员更...

13730
来自专栏十月梦想

CSS边框

border-方向:width style color(border对应分别是宽度 样式 颜色中间空格隔开。)

9930
来自专栏九彩拼盘的叨叨叨

学习纲要:DOM

10520
来自专栏Android干货

自定义控件详解(七):drawText()

20730
来自专栏逸鹏说道

逆天通用水印支持Winform,WPF,Web,WP,Win10。支持位置选择(9个位置 ==》[X])

好几天没上QQ了,今天上了个QQ,,额....额...貌似消息还挺多,没及时回复的还请见谅~~刚好昨天无聊把水印这快封装出来了,支持图片水印,文字水印,索引图...

36660
来自专栏angularejs学习篇

marquee 标签的使用详情

64330
来自专栏前端说吧

css笔记 - 张鑫旭css课程笔记之 vertical-align 篇

元素vertical-align垂直对齐的位置与前后元素都没有关系 元素vertical-align垂直对齐的位置与行高line-height没有关系。 ver...

87320

扫码关注云+社区

领取腾讯云代金券