React Native基础&入门教程:初步使用Flexbox布局

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

一、长度的单位

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

这个怎么理解呢?

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

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

clip_image001

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

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

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

clip_image002

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

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

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

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

clip_image003

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

显示如下:

clip_image004

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

},

clip_image005

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

}

clip_image006

图6. 默认的flex

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

defaultFlex: {

height: 300,

backgroundColor: '#ffe289',

display: 'flex',

justifyContent: 'space-between'

}

items就沿主轴分开了。

clip_image007

图7. justifyContent: 'space-between'

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

clip_image008

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

},

clip_image009

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

}

clip_image010

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

}

clip_image011

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

},

clip_image012

图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

}

clip_image013

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

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

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

希望这是个不错的开始。

参考

优达学城的安卓入门课程 https://classroom.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/

原文发布时间为:2018年07月04日
原文作者:葡萄城技术团队

本文来源:开源中国 如需转载请联系原作者

目录
相关文章
|
6月前
|
开发框架 前端开发 JavaScript
探索前端开发中的跨平台框架React Native
本文将介绍前端开发中一种备受关注的跨平台框架React Native,通过比较原生应用与React Native的优缺点,探讨其在实际项目中的应用以及未来发展趋势。
103 2
|
6月前
|
开发框架 Dart 前端开发
【Flutter前端技术开发专栏】Flutter与React Native的对比与选择
【4月更文挑战第30天】对比 Flutter(Dart,强类型,Google支持,快速热重载,高性能渲染)与 React Native(JavaScript,庞大生态,热重载,依赖原生渲染),文章讨论了开发语言、生态系统、性能、开发体验、学习曲线、社区支持及项目选择因素。两者各有优势,选择取决于项目需求、团队技能和长期维护考虑。参考文献包括官方文档和性能比较文章。
243 0
【Flutter前端技术开发专栏】Flutter与React Native的对比与选择
|
3月前
|
前端开发
使用 React Router v6 进行布局
【8月更文挑战第27天】
42 1
|
4月前
|
前端开发 JavaScript Android开发
React Native跨平台开发实战
【7月更文挑战第21天】React Native为跨平台移动应用开发提供了一种高效且强大的解决方案。通过本文的学习,你应该能够掌握React Native的基本概念和实战步骤,并开始在你的项目中使用React Native进行开发。随着你对React Native的深入理解,你将能够利用其强大的功能来构建更加复杂和高效的移动应用。
|
5月前
|
前端开发 自动驾驶 程序员
鸿蒙? 车载?Flutter? React Native? 为什么我劝你三思,说点不一样的
本文探讨了在信息技术快速发展的背景下,开发者如何选择学习路径。作者提倡使用终局思维来规划职业发展,考虑技术的长远影响。终局思维注重长远目标、系统分析、反向规划和动态调整。以车载开发为例,预测未来智能汽车可能由语音助手主导,而非依赖平板界面。此外,作者建议不要过分投入打工状态,应思考创建自己的产品,如App,以实现技能补充和额外收入。选择对未来发展和自主性有益的技术,如Kotlin,比盲目追求热点更为重要。做减法和有标准的选择,能帮助减轻焦虑,实现更高效的成长。关注公众号“AntDream”获取更多相关内容。
135 1
|
6月前
|
开发框架 移动开发 前端开发
【Uniapp 专栏】Uniapp 与 React Native 的对比分析
【5月更文挑战第14天】Uniapp和React Native是热门的跨平台移动开发框架。Uniapp以其一套代码多端运行、丰富的组件生态和较低的学习曲线受到青睐,适合快速开发简单应用。React Native基于React,拥有活跃社区和优秀性能,适合复杂应用。React Native在性能上略胜一筹,尤其在需要接近原生体验的场景。Uniapp的官方组件弥补了社区资源不足。选择时需考虑开发效率、性能需求、团队技术栈和社区支持。
1889 1
【Uniapp 专栏】Uniapp 与 React Native 的对比分析
|
5月前
|
开发框架 前端开发 JavaScript
移动应用开发中的跨平台策略:Flutter与React Native的比较
在移动应用领域,跨平台解决方案已成为开发者追求高效、成本效益和广泛覆盖的关键。本文深入探讨了两种领先的跨平台框架——Flutter和React Native,从技术架构、性能、社区生态及实际应用案例四个维度进行全面对比分析。通过这一比较,旨在为移动应用开发者提供选择合适框架的参考依据,帮助他们根据项目需求做出明智的决策。
|
5月前
|
前端开发 iOS开发 Android开发
React Native跨平台开发实战:从零到一
学习React Native跨平台开发,首先安装Node.js和React Native CLI,设置Android/iOS环境。使用CLI创建项目,如`npx react-native init MyProject`。运行应用:`npx react-native run-android`或`run-ios`。编写组件,如在App.js中创建Hello World。添加样式,安装第三方库如react-native-vector-icons,使用react-navigation进行路由和导航。
111 2
|
6月前
|
前端开发 JavaScript Android开发
使用React Native开发跨平台移动应用的技术详解
【5月更文挑战第22天】本文详述了使用React Native开发跨平台移动应用的技术,该框架由Facebook推出,基于JavaScript,支持iOS和Android。React Native通过JNI/JSI实现JavaScript到原生代码的转换,提供高效性能和原生体验。其优势包括跨平台性、原生体验、开发速度及社区支持。开发流程涉及环境搭建、项目创建、编码、调试与测试,以及构建与发布。注意事项包括性能优化、平台适配、利用第三方库和持续学习。React Native为开发者构建高质量跨平台应用提供了便捷途径,未来潜力无限。
|
5月前
|
Dart 前端开发 JavaScript
探索移动应用开发中的跨平台解决方案:Flutter与React Native的比较
在移动应用开发领域,选择合适的跨平台解决方案是关键。本文将深入分析Flutter和React Native这两大主流框架,从性能、开发效率、社区支持等方面进行比较,帮助开发者做出明智的选择。
78 0
下一篇
无影云桌面