一、长度的单位

在开始任何布局之前,让我们来首先需要知道,在写React Native组件样式时,长度的不带单位的,它表示“与设备像素密度无关的逻辑像素点”。

这个怎么理解呢?

我们知道,屏幕上一个发光的最小点,对应着一个pixel(像素)点。

假设下面三个矩形,代表三个屏幕大小一样的设备,但是,它们拥有的分辨率(resolution)不同:

图1.相同尺寸的设备 不同的分辨率

图上的每一个小格子,其实就代表了一个像素(pixel)。可以看到,一个像素点的大小,在这个三个物理尺寸一样但拥有不同分辨率的设备上,是不一样的。

如果我们以像素为单位来设置一个界面元素的大小,比如说2px的高度,那么这2px的长度上面的设备中就会是下面这个样子:

图2.不同分辨率下的2px实际高度

它们真实显示出的长度是不一样的。

我们想要一种长度单位,在同样物理尺寸大小的屏幕上(不论分辨率谁高谁低,只要物理尺寸大小一样即可),1个单位的长度所代表的物理尺寸是一样的。这种单位就应该是独立于分辨率的,把它起一个名字叫做 density-independent pixels,简称dp。这其实就是Android系统中所使用的长度单位。

举例来说,2dp宽,2dp高的内容,在不同分辨率但屏幕尺寸一样的设备上所显示出的物理大小是一样的。(一个题外话:有些Android开发者建议所有可点击的按钮,宽高都不应该少于48dp。)

图3. 2dp * 2dp大小的内容 在同样尺寸的屏幕中所占据的物理大小一致

Android中字体大小使用另外一个单位,叫做scale independent pixels,简称sp。这个单位和dp很类似,不过它通常是用在对字体大小的设置中。通过它设置的字体,可以根据系统字体大小的变化而变化。

pixel与dp存在一个公式:px = dp * (dpi/160)。

dpi表示dot per inch,是每英寸上的像素点,它也有个自己的计算公式,具体这里就不展开了。只需要知道我们之所以要使用一个独立于设备分辨率的单位,主要是为了让应用在不同分辨率的设备中,看起来一致。

在RN中,同样也拥有一个类似于dp的长度单位。如果我们想知道自己的屏幕以这种长度的计量下是多少单位,可以通过引入react-native包中的Dimensions拿到,同时还可以查看本机的像素比例是多少。

import {

Text,

View,

Dimensions,

PixelRatio

} from 'react-native';

const { height, width } = Dimensions.get('window');

const pxRatio = PixelRatio.get();

<View style={styles.container}>

<Text style={styles.welcome}>

{`width: ${width}, height: ${height}`}

</Text>

<Text style={styles.welcome}>

{`pixel radio: ${pxRatio}`}

</Text>

</View>

显示如下:

图4. 当前手机的屏幕信息

它反映出,当前手机屏幕的宽度占据360个单位,高度占据640个单位。像素比例是3,实际上这就是一个 1080 * 1920 像素的手机。其中1080 = width * pixelRadio, 1920 = height * pixelRatio

二、Flexbox布局

Flexbox布局,也就是弹性盒模型布局。也许有Android开发经验的朋友还对LinearLayout,RelativeLayout,FrameLayout等布局方法记忆犹新,但是对于更了解CSS的Web开发者而言,使用flexbox布局肯定会让他感受到更加顺手的开发体验。

RN中的flexbox布局,其实源于CSS中的flexbox(弹性盒子)布局规范。其实它在CSS中还处于Last Call Working Draft(最终征求意见稿)阶段,但是主流浏览器对它都有了良好的支持。在RN中,几乎完全借鉴了其中的布局语义,同时更没有浏览器兼容的烦恼,用起来是很方便的。RN中只是把CSS的属性用camelCase写法代替连字符写法。后面还还会看到,默认的flex方向也不同。

理解弹性盒模型布局,首先要知道四个最基本的概念:Flex Container(容器),Flex Item(项),Flex Direction(方向)和Axis(轴)。

1.Flex Container

就是包裹内容的容器,需要把它的display设置为‘flex’(或者'inline-flex')。

以下6个属性设置在容器上。

  1. alignItems 指定item在侧轴上的对齐方式

  2. alignContent 指定item在多条轴上的对齐方式

  3. flexDirection 指定主轴方向

  4. flexWrap 指定item在主轴方向如何换行

  5. flexFlow flexDirection属性和flexWrap属性的简写形式

  6. justifyContent 指定item在主轴上的分布方式

2.Flex Item

容器做直接包裹的元素。所谓弹性盒布局,通常想要布局的东西就是它们。

以下6个属性设置在项目上。

  1. alignSelf 每个item可以单独设置对齐方式 覆盖Flex Container给设置的alignItems

  2. order 指定item排列顺序 数字越小越靠前

  3. flexGrow 指定item的拉伸比例

  4. flexShrink 指定item的压缩比例

  5. flexBasis 指定item在分配多余空间之前,占主轴的大小

  6. flex flexGrow flexShrink flexBasis的简写

3.Flex Direction and Axis

在弹性盒子中,项目默认沿着main axis(主轴)排列,和主轴垂直的轴叫做cross axis,叫做侧轴,或者交叉轴。

在盒子中,排列项目又四个方向:水平的正反两个,垂直的正反两个。

结构代码:

<View>

<View style={styles.row}>

<Text style={styles.item}>1</Text>

<Text style={styles.item}>2</Text>

<Text style={styles.item}>3</Text>

</View>

<View style={styles.rowReverse}>

<Text style={styles.item}>1</Text>

<Text style={styles.item}>2</Text>

<Text style={styles.item}>3</Text>

</View>

<View style={styles.column}>

<Text style={styles.item}>1</Text>

<Text style={styles.item}>2</Text>

<Text style={styles.item}>3</Text>

</View>

<View style={styles.columnReverse}>

<Text style={styles.item}>1</Text>

<Text style={styles.item}>2</Text>

<Text style={styles.item}>3</Text>

</View>

</View>

样式代码:

row: {

backgroundColor: '#ffe289',

flexDirection: 'row'

},

rowReverse: {

flexDirection: 'row-reverse'

},

column: {

backgroundColor: '#ffe289',

flexDirection: 'column'

},

columnReverse: {

flexDirection: 'column-reverse'

},

图5. flexDirection

由于网上关于flex布局讲解的资源挺丰富的,读者可以参考最后给出的连接,或者自行上网搜索,CSS中的和RN是相通的。

这里主要分享个人在学习过程中,觉得容易引起混淆的两个小点。

首先,justify-content和align-content这两个属性,可能比较容易搞错它们作用的方向。

其中,justify-content是设置items沿着主轴上是如何分布的。align-content是设置items沿着侧轴如何对齐的。

还是拿之前的例子,默认情况下,flex的方向是column(这个与移动端与web页面不同,在web页面用CSS设置flex布局,默认的fiex-direction是row,即水平从左往右)。

在移动端,主轴默认是垂直方向,从上往下。让我们把它的高度设置高一点,放3个item在里面:

结构代码:

<View>

<View style={styles.defaultFlex}>

<Text style={styles.item}>1</Text>

<Text style={styles.item}>2</Text>

<Text style={styles.item}>3</Text>

</View>

</View>

样式代码:

defaultFlex: {

height: 300,

backgroundColor: '#ffe289',

display: 'flex'

}

图6. 默认的flex

justify-content设置items在主轴方向的如何分布,比如,如果我们加上justifyContent: 'space-between'

defaultFlex: {

height: 300,

backgroundColor: '#ffe289',

display: 'flex',

justifyContent: 'space-between'

}

items就沿主轴分开了。

图7. justifyContent: 'space-between'

如果我们设置alignItems: 'center',项目就沿侧轴(这里就是水平轴)居中了。注意这两个属性是可以同时起作用的。

图8. justifyContent: 'space-between' 以及 alignItems: 'center'

然后,值得指出的是,flex这个属性,其实是flexGrow, flexShrink, flexBasis(对应的CSS属性flex-grow, flex-shrink和flex-basis)三个属性的结合。

我们通常在移动端看到的flex:1这个设置,其实是对flex-grow的设置。后者的默认值为0。使用把flex-grow设置为正整数的方法,可以让item按比例分布,或者在其他item为固定大小时撑满剩余的盒子空间,就仿佛具有弹性一样。

结构代码:

<View style={styles.container}>

<View style={styles.flex1}></View>

<View style={styles.flex2}></View>

<View style={styles.flex3}></View>

</View>

样式代码:

container: {

flex: 1

},

flex1: {

// height: 99,

flexGrow: 1,

backgroundColor: 'orange',

},

flex2: {

flexGrow: 2,

backgroundColor: 'lightblue',

},

flex3: {

flexGrow: 3,

backgroundColor: 'green',

},

图9. 按比例分布

需要注意的是,如果父容器的尺寸为零(即没有设置宽高,或者没有设定flex),即使子组件如果使用了flex,也是无法显示的。

所以这里最外层的使用了flex布局的,flex:1,表示让它占据了垂直的整个空间。

三、小小实战演练

让我们来简单使用flex布局,对之前的例子稍加调整,实现一个头部,底部固定高度,中间内容占满剩下的屏幕的布局:

第一步,调整结构:

<View style={styles.container}>

<View style={styles.header}></View>

<View style={styles.body}></View>

<View style={styles.footer}></View>

</View>

调整样式:

container: {

flex: 1

},

header: {

height: 60,

backgroundColor: 'orange',

},

body: {

flexGrow: 1,

backgroundColor: 'lightblue',

},

footer: {

height: 60,

backgroundColor: 'green',

}

图10. 有头尾的布局

第二部,给header添加标题。

我们让头部的分成3部分,左边模拟一个返回按钮,中间显示标题文字,右边模拟一把小叉:

<View style={styles.header}>

<Text style={styles.back}>返回</Text>

<Text style={styles.title}>这是一个标题</Text>

<Text style={styles.exit}>×</Text>

</View>

需要把header的flexDirection设置为水平方向:

header: {

height: 60,

backgroundColor: 'orange',

flexDirection: 'row',

alignItems: 'center'

},

back: {

color: 'white',

marginLeft: 15

},

title: {

flexGrow: 1,

fontSize: 20,

color: 'white',

textAlign: 'center'

},

exit: {

marginRight: 20,

fontSize: 20,

color: 'white'

}

图11. header有了标题

第三步,我们可以把footer三等分,模拟成菜单的样子:

<View style={styles.footer}>

<Text style={styles.firstMenu}>添加</Text>

<Text style={styles.menu}>删除</Text>

<Text style={styles.menu}>修改</Text>

</View>

添加样式:

footer: {

height: 60,

backgroundColor: 'green',

flexDirection: 'row',

alignItems: 'center'

},

menu: {

flexGrow: 1,

textAlign: 'center',

borderColor: 'white',

borderLeftWidth: 1,

color: 'white'

},

firstMenu: {

flexGrow: 1,

textAlign: 'center',

color: 'white'

},

图12. footer三等分 模拟菜单

最后,让我们在body里也填入几个带按钮的输入框。

引入TextInput和Button组件,然后把它们分三组放入body中,

<View style={styles.body}>

<View style={styles.inputRow}>

<TextInput style={styles.textInput}></TextInput>

<Button style={styles.btn} onPress={() => {}} title="确定"></Button>

</View>

<View style={styles.inputRow}>

<TextInput style={styles.textInput}></TextInput>

<Button style={styles.btn} onPress={() => {}} title="非常确定"></Button>

</View>

<View style={styles.inputRow}>

<TextInput style={styles.textInput}></TextInput>

<Button style={styles.btn} onPress={() => {}} title="确定一定以及肯定"></Button>

</View>

</View>

添加样式:

body: {

flexGrow: 1,

backgroundColor: 'lightblue',

},

inputRow: {

flexDirection: 'row',

alignItems: 'center',

marginLeft: 10,

marginRight: 10

},

textInput: {

flex: 1

},

btn: {

minWidth: 60

}

flex布局的一个常用实践是,部分内容固定宽高,让剩下的内容自适应。

像上面这样,我们给Button有一个最小宽度,且TextInput的flexGrow为1,这样的做法可以实现,TextInput总是占满剩下的宽度,且可伸缩。

看了上面的例子,是否觉得在React Native中使用Flexbox布局也挺简单呢?

希望这是个不错的开始。

参考

优达学城的安卓入门课程 https://cla***oom.udacity.com/courses/ud837/lessons/4027328704/concepts/42075886740923

阙喜涛 React Native跨平台移动应用开发(第2版)

阮一峰 http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html

React Native官网 https://facebook.github.io/react-native/

转载于:https://blog.51cto.com/powertoolsteam/2135857

React Native基础入门教程:初步使用Flexbox布局相关推荐

  1. 最新Android基础入门教程目录(完结版)

    第一章:环境搭建与开发相关(已完结 10/10) https://blog.csdn.net/coder_pig/article/details/50000773 Android基础入门教程--1.1 ...

  2. 2015年最新Android基础入门教程目录(完结版)

    2015年最新Android基础入门教程目录(完结版) 标签(空格分隔): Android基础入门教程 前言: 关于<2015年最新Android基础入门教程目录>终于在今天落下了帷幕,全 ...

  3. java adt入门教程_Android基础入门教程目录

    第一章:环境搭建与开发相关(已完结 10/10) https://blog.csdn.net/coder_pig/article/details/50000773 Android基础入门教程--1.1 ...

  4. 菜鸟窝Android百度云视频,菜鸟窝React Native 视频系列教程

    菜鸟窝React Native 视频系列教程 交流QQ群:276960232 Hi,我是RichardCao,现任新美大酒店旅游事业群的Android Developer.15年加入饿了么即时配送BU ...

  5. React Native小白入门学习路径——五

    React Native小白入门学习路径--五 序 "哦天呐!" 这句话成了我在实验室的口头禅, 老师可能觉得我们都是大神吧,都还在看着基础就给布置了那么多任务:写一个RN的TDD ...

  6. React 全家桶入门教程 01

    React 全家桶入门教程 01 前面是基础课程(难度小,略过),后面是案例 目的 巩固react基础知识,查漏补缺(熟悉的部分快进) 学习相关的库的使用 https://study.163.com/ ...

  7. Python基础入门教程:Day21-30/Web前端概述

    Python基础入门教程:Web前端概述 说明:本文使用的部分插图来自 Jon Duckett 先生的*HTML and CSS: Design and Build Websites*一书,这是一本非 ...

  8. Android基础入门教程——8.3.5 Paint API之—— Xfermode与PorterDuff详解(二)

    Android基础入门教程--8.3.5 Paint API之-- Xfermode与PorterDuff详解(二) 标签(空格分隔): Android基础入门教程 本节引言: 上一节,我们学习了Xf ...

  9. Android基础入门教程——8.3.14 Paint几个枚举-常量值以及ShadowLayer阴影效果

    Android基础入门教程--8.3.14 Paint几个枚举/常量值以及ShadowLayer阴影效果 标签(空格分隔): Android基础入门教程 本节引言: 在Android基础入门教程--8 ...

最新文章

  1. 安利10款效率工具,打造windows超强生产力
  2. 解决 java “错误:编码GBK 的不可映射字符”
  3. Activity的四种launchMode
  4. 放弃OpenStack?恐怕还不到时候
  5. hdu 5563 Clarke and five-pointed star (枚举)
  6. 计算机学院张旭豪,饿了么收购百度外卖,可以看出张旭豪硕士研究生是有多厉害!...
  7. ubuntu 任务栏监视器_从系统任务栏监视Google服务
  8. 如果生活中没有数学,那么。。。
  9. b 树查找时间复杂度_心里没点 B 树。。。
  10. php 获取 body json,从PHP中的JSON POST读取HTTP请求正文的问题
  11. 【网络信息安全】鉴别和密钥分配协议
  12. V-Play入门手册3-如何编写高效的代码?
  13. 浏览器提取已安装扩展教程
  14. python爬取b站弹幕并进行数据分析_【Python3爬虫】我爬取了七万条弹幕,看看RNG和SKT打得怎么样...
  15. 安卓手机超频CPU(无修饰CPU控制)
  16. 基于双向流固耦合的Fluent dynamic mesh 学习笔记
  17. 反汇编工具OD(OllyDebug)
  18. archlinux音量管理
  19. 零基础转行学编程技术难吗?
  20. Unity3D中UGUI的RectTransform对齐方式详解

热门文章

  1. Android软件开发需要学什么
  2. Ubuntu 下 Git 服务器的安装和初级配置
  3. python命名空间特性_Python命名空间与作用域
  4. 问题 | Spare BA 中的Eigen运行错误
  5. html预览不出效果是怎么回事,为何HTML文件直接双击打不开 要用浏览器才能打开 之前双击还能打开显示效果的...
  6. 采用CreateThread()创建多线程程序
  7. 机器学习性能评估指标汇总
  8. 工业用微型计算机(28)-dos和bios功能调用(2)-int 21h
  9. python3精要(34)-import工作原理
  10. python3精要(2)-python运行过程,模块,内置对象