最后一部分,笔者分享了安装调试ReactNative应用过程中的一些心得。如果您还没有阅读,请点击《React Native基础&入门教程:调试React Native应用的一小步》。在本文中,让我们了解一下什么是Flexbox布局以及如何使用它。1.长度单位在开始任何布局之前,我们首先需要知道,在编写ReactNative组件样式时,没有单位的长度意味着“与设备像素密度无关的逻辑像素”。怎么理解呢?我们知道屏幕上一个发光最小的点对应一个像素(pixel)点。假设以下三个矩形代表三个屏幕尺寸相同但分辨率不同的设备:图1.尺寸相同但分辨率不同的设备图上的每个小格子实际上代表一个像素(pixel)。可以看出,在物理尺寸相同但分辨率不同的三台设备上,一个像素的大小是不同的。如果我们以像素为单位设置一个界面元素的大小,比如高度为2px,那么长度为2px以上的设备就会是这样的:图2.2px在不同分辨率下的实际高度它们实际显示的长度是不同的。我们想要一个长度单位。在相同物理尺寸的屏幕上(无论分辨率高低,只要物理尺寸相同),1个单位的长度所代表的物理尺寸是相同的。这种单位应该与分辨率无关,称为密度无关像素,简称dp。这其实就是Android系统中使用的长度单位。例如,宽度为2dp高度为2dp的内容在不同分辨率但屏幕尺寸相同的设备上显示时物理尺寸相同。(题外话:一些Android开发者建议所有可点击按钮的宽度和高度不应小于48dp。)图3.2dp*2dp内容在相同尺寸的屏幕上占据相同的物理尺寸。Android中的字体大小使用了另一种单位,叫做scaleindependentpixels,简称sp。这个单位和dp很像,不过一般用在字号设置上。它设置的字体会随着系统字体大小的变化而变化。pixel和dp之间有一个公式:px=dp*(dpi/160)。dpi表示dotperinch,也就是每英寸一个像素。它也有自己的计算公式,这里就不展开了。只需要知道,我们之所以使用与设备分辨率无关的单位,主要是为了让应用在不同分辨率的设备上看起来一致。在RN中,它也有一个类似于dp的长度单位。如果我们想知道我们的屏幕按照这个长度是多少个单位,我们可以通过react-native包中引入Dimensions来获取,同时我们也可以查看机器的像素比。import{ Text, View, Dimensions, PixelRatio}from'react-native';const{height,width}=Dimensions.get('window');constpxRatio=像素比率。得到(); {`宽度:${width},高度:${height}`} {`pixelradio:${pxRatio}`} 显示如下:图4.当前手机screen信息反映当前手机屏幕宽度为360单位,高度为640单位。像素比为3。其实这是一款1080x1920像素的手机。其中,1080=widthpixelRadio,1920=height*pixelRatio2.Flexbox布局Flexbox布局,即flexbox模型布局。可能有Android开发经验的朋友还记得LinearLayout、RelativeLayout、FrameLayout等布局方式,但是对于更懂CSS的Web开发者来说,使用flexbox布局肯定会让他感受到更舒服的开发体验。RN中的flexbox布局其实是来源于CSS中的flexbox(弹性盒)布局规范。其实它在CSS中还处于LastCallWorkingDraft阶段,但是主流浏览器已经很好的支持了。在RN中,几乎完全借鉴了布局语义,同时没有浏览器兼容性的困扰,使用起来非常方便。在RN中,CSS属性用驼峰式而不是连字符书写。正如您稍后将看到的,默认的弯曲方向也是不同的。要理解弹性盒模型的布局,首先要知道四个最基本的概念:FlexContainer(容器)、FlexItem(项目)、FlexDirection(方向)和Axis(轴)。1、FlexContainer是包装内容的容器,其显示需要设置为'flex'(或'inline-flex')。在容器上设置了以下6个属性。alignItems指定项目在侧轴上的对齐方式alignContent指定项目在多个轴上的对齐方式flexDirection指定主轴方向flexWrap指定项目如何在主轴方向换行flexFlowflexDirection属性的简写形式flexWrap属性justifyContent指定item在主轴上的分布方法二,FlexItem容器作为直接包裹的元素。所谓的flexbox布局,通常就是你想布局的东西。在项目上设置以下6个属性。alignSelf每个item可以单独设置覆盖FlexContainer的对齐方式来设置alignItemsorder指定item的顺序,数字越小越靠前flexGrow指定item的拉伸比例flexShrink指定item的压缩比例flexBasis指定item在分配多余空间之前占据主轴flex的size其实是flexGrowflexShrink的缩写flexBasis3.FlexDirectionandAxis在弹性盒子中,item默认是沿着mainaxis(主轴)排列的,与主轴垂直的轴称为横轴,称为侧轴,或横轴。在一个盒子里,物品的排列有四个方向:横向两个正反面,纵向两个正反面。结构代码:123123123123样式代码:row:{backgroundColor:'#ffe289',flexDirection:'row'},rowReverse:{flexDirection:'row-reverse'},column:{backgroundColor:'#ffe289',flexDirection:'column'},columnReverse:{flexDirection:'column-reverse'}图5.flexDirection由于网上关于flex布局的资源很多,读者可以参考文末给出的链接,或者搜索自己上网,CSSRN和RN是相通的。这里主要分享个人在学习过程中比较迷惑的两个小点。首先,justify-content和align-content这两个属性可能更容易混淆它们的动作方向。其中justify-content是设置item如何沿主轴分布。align-content设置项目如何沿侧轴对齐。还是拿前面的例子来说,默认情况下flex的方向是column(这点不同于移动端和网页,这里是通过css来设置网页的flex布局,默认的fiex-direction是row,即水平方向从左到右)。在移动端,主轴默认是垂直的,从上到下。让我们将它的高度设置得更高,并在其中放置3个项目:结构代码:1item}>23样式代码:defaultFlex:{height:300,backgroundColor:'#ffe289',显示:'flex'}图6.默认的flexjustify-content设置项目在主轴方向如何分布,例如,如果我们添加justifyContent:'space-between'defaultFlex:{height:300,backgroundColor:'#ffe289',display:'flex',justifyContent:'space-between'}项目沿主轴分开。图7.justifyContent:'space-between'如果我们设置alignItems:'center',项目将沿侧轴(在本例中为水平轴)居中。请注意,这两个属性可以同时起作用。图8.justifyContent:'space-between'andalignItems:'center'然后,值得指出的是,flex的属性实际上是flexGrow、flexShrink、flexBasis(对应的CSS属性flex-grow、flex-shrink和flex-基础)三个属性的组合。我们平时在移动端看到的flex:1设置,其实就是对flex-grow的设置。后者的默认值为0。使用设置flex-grow为正整数的方法,可以让item按比例分布,或者在其他item大小固定的情况下,填充剩余的box空间,就好像它是弹性的一样。结构代码:样式代码: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,也就是说占据了整个垂直空间。3.一个小练习让我们简单地使用flex布局,稍微调整一下前面的例子,实现一个有头部的布局,底部固定高度,中间的内容占据屏幕的其余部分:Step1,调整结构:调整样式:container:{flex:1},header:{height:60,backgroundColor:'orange',},body:{flexGrow:1,backgroundColor:'lightblue',},footer:{height:60,backgroundColor:'green',}图10.带有头部和尾部的布局第二步是向头部添加标题。我们把header分成3部分,左边模拟一个返回按钮,中间显示标题文字,右边模拟一个小叉子:返回这是一个标题×你需要设置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.标题有一个标题第三个步骤,我们可以把footer分成三份,模拟成一个菜单的样子:}>删除修改添加样式:footer:{height:60,backgroundColor:'green',flexDirection:'row',alignItems:'中心'},菜单:{flexGrow:1,textAlign:'center',borderColor:'white',borderLeftWidth:1,color:'white'},firstMenu:{flexGrow:1,textAlign:'center',color:'white'},图12.footertrisectionsimulationmenu最后让我们在正文中也填入几个带有按钮的输入框引入TextInput和Button组件,分三组放入body中,{}}title="OK">{}}title="非常确定">{}}title="sureandsure">添加样式:body:{flexGrow:1,backgroundColor:'lightblue',},inputRow:{flexDirection:'row',alignItems:'center',marginLeft:10,marginRight:10},textInput:{flex:1},btn:{minWidth:60}flex布局的一个常见做法是固定部分内容的宽高,其余内容自适应。像上面,我们有一个button为Button的最小宽度,TextInput的flexGrow为1,这个方法就可以实现,TextInput一直占据剩余的宽度,并且是可伸缩的。看完上面的例子,是不是觉得在ReactNative中使用Flexbox布局很简单呢?希望这是一个好的开始。移动应用开发利器:SpreadJS纯前端表单控件和WijmoJS纯前端控件集,为您的移动应用带来更灵活的操作体验和更好的外观风格。欢迎下载。延伸阅读:纯干货分享:如何在React框架中使用SpreadJS