React Native基础入门之初步使用Flexbox布局


Posted in Javascript onJuly 02, 2018

前言

在上篇中,笔者分享了部分安装并调试React Native应用过程里的一点经验,如果还没有看过的同学请点击《React Native基础&入门教程:调试React Native应用的一小步》。

在本篇里,让我们一起来了解一下,什么是Flexbox布局,以及如何使用。

一、长度的单位

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

这个怎么理解呢?

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

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

React Native基础入门之初步使用Flexbox布局

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

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

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

React Native基础入门之初步使用Flexbox布局

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

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

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

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

React Native基础入门之初步使用Flexbox布局

图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>

显示如下:

React Native基础入门之初步使用Flexbox布局

图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个属性设置在容器上。

  • alignItems 指定item在侧轴上的对齐方式
  • alignContent 指定item在多条轴上的对齐方式
  • flexDirection 指定主轴方向
  • flexWrap 指定item在主轴方向如何换行
  • flexFlow flexDirection属性和flexWrap属性的简写形式
  • justifyContent 指定item在主轴上的分布方式

2.Flex Item

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

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

  • alignSelf 每个item可以单独设置对齐方式 覆盖Flex Container给设置的alignItems
  • order 指定item排列顺序 数字越小越靠前
  • flexGrow 指定item的拉伸比例
  • flexShrink 指定item的压缩比例
  • flexBasis 指定item在分配多余空间之前,占主轴的大小
  • 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'
},

React Native基础入门之初步使用Flexbox布局

图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'
}

React Native基础入门之初步使用Flexbox布局

图6. 默认的flex

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

defaultFlex: {
height: 300,
backgroundColor: '#ffe289',
display: 'flex',
justifyContent: 'space-between'
}

items就沿主轴分开了。

React Native基础入门之初步使用Flexbox布局

图7. justifyContent: 'space-between'

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

React Native基础入门之初步使用Flexbox布局

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

React Native基础入门之初步使用Flexbox布局

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

React Native基础入门之初步使用Flexbox布局

图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'
}

React Native基础入门之初步使用Flexbox布局

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

React Native基础入门之初步使用Flexbox布局

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

React Native基础入门之初步使用Flexbox布局

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

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

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

希望这是个不错的开始。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
javascript下判断一个元素是否存在的代码
Mar 05 Javascript
Jquery replace 字符替换实现代码
Dec 02 Javascript
js下拉框二级关联菜单效果代码具体实现
Aug 03 Javascript
js面向对象编程之如何实现方法重载
Jul 02 Javascript
JavaScript中的Function函数
Aug 27 Javascript
jqueryMobile使用示例分享
Jan 12 Javascript
Vue.Js中的$watch()方法总结
Mar 23 Javascript
js es6系列教程 - 基于new.target属性与es5改造es6的类语法
Sep 02 Javascript
解决webpack+Vue引入iView找不到字体文件的问题
Sep 28 Javascript
JQuery实现简单的复选框树形结构图示例【附源码下载】
Jul 16 jQuery
jQuery 选择器用法基础入门示例
Jan 04 jQuery
JavaScript 类的封装操作示例详解
May 16 Javascript
JavaScript设计模式之构造函数模式实例教程
Jul 02 #Javascript
vue-router 源码实现前端路由的两种方式
Jul 02 #Javascript
React Native基础入门之调试React Native应用的一小步
Jul 02 #Javascript
vue-router 源码之实现一个简单的 vue-router
Jul 02 #Javascript
JavaScript设计模式之单例模式简单实例教程
Jul 02 #Javascript
JavaScript设计模式之建造者模式实例教程
Jul 02 #Javascript
JS实现的JSON序列化操作简单示例
Jul 02 #Javascript
You might like
菜鸟学PHP之Smarty入门
2007/01/04 PHP
php IP及IP段进行访问限制的代码
2008/12/17 PHP
PHP 实现页面静态化的几种方法
2017/07/23 PHP
详解PHP 二维数组排序保持键名不变
2019/03/06 PHP
AJAX架构之Dojo篇
2007/04/10 Javascript
ie 处理 gif动画 的onload 事件的一个 bug
2007/04/12 Javascript
javascript eval和JSON之间的联系
2009/12/31 Javascript
40款非常棒的jQuery 插件和制作教程(系列一)
2011/10/26 Javascript
jQuery中odd选择器的定义和用法
2014/12/23 Javascript
jquery实现可关闭的倒计时广告特效代码
2015/09/02 Javascript
一种新的javascript对象创建方式Object.create()
2015/12/28 Javascript
jQuery选择器基础入门教程
2016/05/10 Javascript
javascript宿主对象之window.navigator详解
2016/09/07 Javascript
Bootstrap表单简单实现代码
2017/03/06 Javascript
vue利用v-for嵌套输出多层对象,分别输出到个表的方法
2018/09/07 Javascript
vue 组件开发原理与实现方法详解
2019/11/29 Javascript
vue 动态添加class,三个以上的条件做判断方式
2020/11/02 Javascript
python入门基础之用户输入与模块初认识
2016/11/14 Python
Python cookbook(数据结构与算法)将多个映射合并为单个映射的方法
2018/04/19 Python
python在每个字符后添加空格的实例
2018/05/07 Python
Python之数据序列化(json、pickle、shelve)详解
2019/08/30 Python
Python3+Flask安装使用教程详解
2021/02/16 Python
html5 Canvas绘制线条 closePath()实例代码
2012/05/10 HTML / CSS
利用Node实现HTML5离线存储的方法
2020/10/16 HTML / CSS
信息技术专业大学生个人的自我评价
2013/10/05 职场文书
会议开场欢迎词
2014/01/15 职场文书
缓刑人员思想汇报500字
2014/09/12 职场文书
简单租房协议书
2014/10/21 职场文书
个人年终总结开头
2015/03/06 职场文书
2015年学校管理工作总结
2015/07/20 职场文书
幼儿园老师新年寄语
2015/08/17 职场文书
有关保护环境的宣传标语100条
2019/08/07 职场文书
Python selenium模拟网页点击爬虫交管12123违章数据
2021/05/26 Python
使用CSS实现一个搜索引擎的原理解析
2021/09/25 HTML / CSS
浅谈Vue的computed计算属性
2022/03/21 Vue.js
微信小程序调用python模型
2022/04/21 Python