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 相关文章推荐
google地图的路线实现代码
Aug 20 Javascript
jQuery插件实现屏蔽单个元素使用户无法点击
Apr 12 Javascript
jQuery实现鼠标滑过点击事件音效试听
Aug 31 Javascript
详解JavaScript中的Unescape()和String() 函数
Nov 09 Javascript
JavaScript实现数据类型的相互转换
Mar 06 Javascript
Vue.js中用v-bind绑定class的注意事项
Dec 13 Javascript
Vue2.0 从零开始_环境搭建操作步骤
Jun 14 Javascript
js获取地址栏参数的两种方法
Jun 27 Javascript
JavaScript实现鼠标滚轮控制页面图片切换功能示例
Oct 14 Javascript
利用canvas中toDataURL()将图片转为dataURL(base64)的方法详解
Nov 20 Javascript
JavaScript中EventLoop介绍
Jan 22 Javascript
微信小程序动态添加view组件的实例代码
May 23 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报表之jpgraph柱状图实例代码
2011/08/22 PHP
php安全之直接用$获取值而不$_GET 字符转义
2012/06/03 PHP
PHP语法小结之基础和变量
2015/11/22 PHP
Zend Framework+smarty用法实例详解
2016/03/19 PHP
PHP  实现等比压缩图片尺寸和大小实例代码
2016/10/08 PHP
php中this关键字用法分析
2016/12/07 PHP
详谈php ip2long 出现负数的原因及解决方法
2017/04/05 PHP
JavaScript定义类的几种方式总结
2014/01/06 Javascript
JS清空多文本框、文本域示例代码
2014/02/24 Javascript
jQuery实现行文字链接提示效果的方法
2015/03/10 Javascript
JS禁用页面上所有控件的实现方法(附demo源码下载)
2015/12/17 Javascript
Javascript实现鼠标框选操作  不是点击选取
2016/04/14 Javascript
JavaScript常见JSON操作实例分析
2018/08/08 Javascript
基于layui框架响应式布局的一些使用详解
2019/09/16 Javascript
详解Vscode中使用Eslint终极配置大全
2019/11/08 Javascript
微信小程序select下拉框实现源码
2019/11/08 Javascript
vue路由传参的基本实现方式小结【三种方式】
2020/02/05 Javascript
jquery实现简单每周轮换的日历
2020/09/10 jQuery
小程序组件传值和引入sass的方法(使用vant Weapp组件库)
2020/11/24 Javascript
Python中几个比较常见的名词解释
2015/07/04 Python
利用Python爬取可用的代理IP
2016/08/18 Python
Python 迭代,for...in遍历,迭代原理与应用示例
2019/10/12 Python
一款纯css3实现的颜色渐变按钮的代码教程
2014/11/12 HTML / CSS
英国潮流网站:END.(全球免邮)
2017/01/16 全球购物
英国钻石公司:British Diamond Company
2020/02/16 全球购物
2014全国两会心得体会
2014/03/17 职场文书
求职者怎样写自荐信
2014/04/13 职场文书
作文评语大全
2014/04/23 职场文书
三八红旗手先进事迹材料
2014/05/13 职场文书
物流管理专业推荐信
2014/09/06 职场文书
标准大学生职业生涯规划书写作指南
2014/09/18 职场文书
2014年药剂科工作总结
2014/11/26 职场文书
自我检讨书怎么写
2015/05/07 职场文书
商标侵权律师函
2015/05/27 职场文书
浅谈 JavaScript 沙箱Sandbox
2021/11/02 Javascript
gtx1650怎么样 gtx1650显卡相当于什么级别
2022/04/08 数码科技