代码在这里:

https://github.com/future-challenger/petshop/tree/master/client/petshop/src/controller

回头看看RN的填坑之旅系列,发现一路写下来都是我在开发中遇到的问题如何解决的。兴之所至,不问顺序。于是出现一个问题,填坑系列和学习知识的顺序不是很一致。比如今天要说的布局问题。其实在一个app开发之前,就应该有所了解。否则的话每次看到的<View style={{flex: 1}} />代表的是什么呢?上来就是一个疑问。

在这个系列进行到一定程度的时候,我会花时间重新整理全系列的文章,让各位可以按照知识本来学习的顺序循序渐进的学习React Native的知识,避免在开发中遇到不应该遇到的问题。

正文开始。本文主要是介绍基础知识,但是不适用基础的代码。所以,如果你在看的时候有什么问题弄不清楚的话,随时查阅官网。那么问题是什么?三个View放在一个父View里显示出来会是设么样子的?这五个子View每次只要显示一个的话应该如何处理?

首先我们先来一点开胃小菜:

NavigationBar的布局

默认的情况下NavigationBar的左侧回退按钮看起来是这样的:

图中可见,按钮紧贴上沿。这个时候的布局是这样的:

	<TouchableHighlight
style={{backgroundColor: 'red', width: 50}}
onPress={() => {
if (index > 0) {
navigator.pop();
}
}}>
<Text style={{
marginLeft: 10,
backgroundColor: 'yellow'
}}>Back</Text>
</TouchableHighlight>

如何让NavigationBar的按钮竖直居中呢?不要想在TouchableHighlight上添加的样式可以起作用。只有在外层再包裹一层View才可以。并给外层的View设置样式,让其中的内容竖直居中才可以。

	<View style={{flex:1, justifyContent: 'center'}}>
<TouchableHighlight
style={{backgroundColor: 'red', width: 50}}
onPress={() => {
if (index > 0) {
navigator.pop();
}
}}>
<Text style={{
marginLeft: 10,
backgroundColor: 'yellow'
}}>Back</Text>
</TouchableHighlight>
</View>

开始填坑

下面要实现一个效果。我们已经有三个横向排列的,等宽度的View。对应的还有三个按钮,每一个按钮对应一个View。但是,不要三个View都显示出来。每次只显示一个。点一个按钮就显示出对应的View来。

Flex的方向

先来看看制造问题的代码重现:

  <View style={{flex: 1, marginTop: 64}}>
<View style={{flex: 1, backgroundColor: 'red'}}></View>
<View style={{flex: 1, backgroundColor: 'orange'}}></View>
<View style={{flex: 1, backgroundColor: 'yellow'}}></View>
</View>

看起来是这样的:

默认的,在一个View里的子View都是竖直依次排列的。

React Native使用Flexbox来实现布局的。Flexbox两个方向,一个是column,一个是row

  • column默认的flexbox方向,是竖直的,从上到下的方向。如上例的图片中截面里红、橙、黄三个颜色的view排列的方向。
  • row是横向的,从左到右的方向。

我们来看看flexbox在row方向的样子:

  <View style={{flex: 1, flexDirection: 'row', marginTop: 64}}>
<View style={{flex: 1, backgroundColor: 'red'}}></View>
<View style={{flex: 1, backgroundColor: 'orange'}}></View>
<View style={{flex: 1, backgroundColor: 'yellow'}}></View>
</View>

添加了按钮以后的界面看起来是这样的:

JustifyContent & AlignItems

在flow已经决定了子view排列的方向的时候。还需要进一步的调整子view的时候就会用到justifyContentalignItems

在和flow指定的方向同一方向上调整的时候使用justifyContent。flow指定的方向为主方向。要在次方向上指定子view如何排列就是用alignItems。如果flexDirection指定的是column(竖直方向),那么主方向就是竖直的,次方向就是水平的。

Flex的值

上面介绍了flex的方向,这里来说说flex的值。

在兄弟姐妹关系的View中,如果他们的flex都是1,那么他们评分父view的空间。如果,有一个flex的值是2,那么就是说这个子View的宽(高)是其他的兄弟姐妹的2倍。

在flex为0的时候,View的宽高就完全需要靠自己了。也就是这个view的宽和高需要设置具体的数值。系统不会替你计算。

如果flow为-1,那么View的宽度和高度,由width和height决定。*在空间不够的情况下,view的宽度和高度会缩小到minWidthminHeight

看看我们要实现的效果和代码

效果:

实现代码:

export default class FlexDemo extends React.Component {
_onPress: (buttonIndex: number) => void; constructor(props) {
super(props);
this.state = {
view1Style: {flex: 1, width: 0}, // If flex is 1, width does not work.
view2Style: {flex: 0, width: 0},
view3Style: {flex: 0, width: 0}
}; this._onPress = this._onPress.bind(this);
} _onPress(buttonIndex) {
switch(buttonIndex) {
case 0:
this.setState({
view1Style: {flex: 1, width: 0}, // If flex is 1, width does not work.
view2Style: {flex: 0, width: 0},
view3Style: {flex: 0, width: 0}
});
break;
case 1:
this.setState({
view1Style: {flex: 0, width: 0}, // If flex is 1, width does not work.
view2Style: {flex: 1, width: 0},
view3Style: {flex: 0, width: 0}
});
break;
case 2:
this.setState({
view1Style: {flex: 0, width: 0}, // If flex is 1, width does not work.
view2Style: {flex: 0, width: 0},
view3Style: {flex: 1, width: 0}
});
break;
default:
this.setState({
view1Style: {flex: 1, width: 0}, // If flex is 1, width does not work.
view2Style: {flex: 0, width: 0},
view3Style: {flex: 0, width: 0}
});
break;
}
} render() {
return (
<View style={{flex: 1, flexDirection: 'row', marginTop: 64}}>
<View key="view1" style={[this.state.view1Style, {backgroundColor: 'red'}]}></View>
<View key="view2" style={[this.state.view2Style, {backgroundColor: 'orange'}]}></View>
<View key="view3" style={[this.state.view3Style, {backgroundColor: 'yellow'}]}></View> <View style={{
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
position: 'absolute',
height: 50,
left:0,
right: 0,
bottom: 0,
backgroundColor: 'black',
opacity: 0.6
}}>
<View style={{flex: 1, justifyContent:'center'}} key='b1'>
<TouchableOpacity
style={styles.button}
onPress={()=>this._onPress(0)}>
<Text style={styles.buttonText}>1</Text>
</TouchableOpacity>
</View>
<View style={{flex: 1, justifyContent: 'center'}} key='b2'>
<TouchableOpacity
style={styles.button}
onPress={()=>this._onPress(1)}>
<Text style={styles.buttonText}>2</Text>
</TouchableOpacity>
</View>
<View style={{flex: 1, justifyContent: 'center'}} key='b3'>
<TouchableOpacity
style={styles.button}
onPress={()=>this._onPress(2)}>
<Text style={styles.buttonText}>3</Text>
</TouchableOpacity>
</View>
</View>
</View>
);
}
};

实现原理:

如何去改变一个组件的外观布局?自然少不了setState方法。一开始,我们就把这几个子view的布局都放在state里。

在下面的三个按钮的点击事件中,设置不同的state,那么赤、橙和黄三个view就会发生变化。

前面提高flex的值为0的时候widthheight起作用,flex不为0的时候不起作用。这就是核心算法之所在了。在一开始让红色的view的flex为1。其他的view的flex为0,并且宽度也为0

之后每次点击了一个按钮的时候,对应的view的布局设置为flex等于1,其他的view的flex为0。这样就实现了上面的效果。

小小的练习

最后留一个练习题,上面的效果对于一个简单的View来说也可以使用conditional render来搞定。那么就请你做一个这样的练习。

最后

上面的讲解都是我遇到的问题的讲解。包含了一些flexbox布局的基础,但是更难理解一下。React Native的布局包括的东西还有很多。后续会在本文或者系列的其他的文章中讲解。

React Native填坑之旅--布局篇的更多相关文章

  1. React Native填坑之旅--Flow篇(番外)

    flow不是React Native必会的技能,但是作为正式的产品开发优势很有必要掌握的技能之一.所以,算是RN填坑之旅系列的番外篇. Flow是一个静态的检查类型检查工具,设计之初的目的就是为了可以 ...

  2. React Native填坑之旅--Navigation篇

    React Native的导航有两种,一种是iOS和Android通用的叫做Navigator,一种是支持iOS的叫做NavigatorIOS.我们这里只讨论通用的Navigator.会了Naviga ...

  3. React Native填坑之旅--ListView篇

    列表显示数据,基本什么应用都是必须.今天就来从浅到深的看看React Native的ListView怎么使用.笔者写作的时候RN版本是0.34. 最简单的 //@flow import React f ...

  4. React Native填坑之旅--Button篇

    从React过来,发现React Native(以下简称RN)居然没有Button.隔壁的iOS是有UIButton的,隔壁的隔壁的Android里也是有的.没有Button,就没有点击效果啊.这还真 ...

  5. React Native填坑之旅--LayoutAnimation篇

    比较精细的动画可以用Animated来控制.但是,在一些简单的界面切换.更新的时候所做的动画里再去计算开始值.结束值和插值器如何运作绝对是浪费时间. RN正好给我们提供了LayoutAnimation ...

  6. React Native填坑之旅--与Native通信之iOS篇

    终于开始新一篇的填坑之旅了.RN厉害的一个地方就是RN可以和Native组件通信.这个Native组件包括native的库和自定义视图,我们今天主要设计的内容是native库方面的只是.自定义视图的使 ...

  7. React Native填坑之旅--组件生命周期

    这次我们来填React Native生命周期的坑.这一点非常重要,需要有一个清晰的认识.如果你了解Android或者iOS的话,你会非常熟悉我们今天要说的的内容. 基本上一个React Native的 ...

  8. React Native填坑之旅--重新认识RN

    如同黑夜里的一道光一样,就这么知道了F8. F8是每年一次Facebook每年一次的开发者大会.每次大会都会release相应的APP,iOS.Android都有.之前都是用Native开发的,但是2 ...

  9. React Native填坑之旅--动画

    动画是提高用户体验不可缺少的一个元素.恰如其分的动画可以让用户更明确的感知当前的操作是什么. 无疑在使用React Native开发应用的时候也需要动画.这就需要知道RN都给我们提供了那些动画,和每个 ...

随机推荐

  1. User mode and kernel mode

    [User mode and kernel mode] 参考:https://msdn.microsoft.com/en-us/library/windows/hardware/ff554836(v= ...

  2. Android Studio使用百度地图示例BaiduMapsApiASDemo

    Android Studio使用百度地图示例BaiduMapsApiASDemo 用自己AVD下的debug.keystore替换掉项目中的debug.keystore 生成自己的签名 同样的方法生成 ...

  3. NTKO控件在阅读PDF时,显示DEMO的问题

    NTKO控件在阅读PDF时,显示DEMO的问题, 原因是加载了以前的DEMO版本的控件.解决办法是: 在命令行中执行命令: regsvr32 /u NtkoOleDocAll.DLL 卸载老版本的控件 ...

  4. fedora23 tweak tool不工作解决方案

    在启动器中打开 优化工具 失败 在终端中开启显示 Traceback (most recent call last): File "/usr/bin/gnome-tweak-tool&quo ...

  5. Android控件Gridview实现仿支付宝首页,Fragment底部按钮切换和登录圆形头像

    此案例主要讲的是Android控件Gridview(九宫格)完美实现仿支付宝首页,包含添加和删除功能:Fragment底部按钮切换的效果,包含四个模块,登录页面圆形头像等,一个小项目的初始布局. 效果 ...

  6. C++的一些小的知识点

    1.初始化: 对于内置类型 ]; // 10个未初始化int ](); // 10个值初始化为0的int 对于自定义类型: 只要一调用new,那么编译器不仅仅给它分配内存,还调用它的默认构造函数初始化 ...

  7. C语言获取时间

    转载:http://www.cnblogs.com/fzhe/archive/2012/11/06/2757858.html C语言获取系统时间的几种方式   C语言中如何获取时间?精度如何? 1 使 ...

  8. windows7内核驱动开发试验环境配置

    首先配置环境参照这个: http://blog.csdn.net/qing666888/article/details/50858272 然后在win10里可能由于没有做测试签名因此一直没有成功加载驱 ...

  9. position与z-index的关系

    .simulationgame .gameranking .rankinginfo{ width:140px; margin:0 auto; font-family:Arial, Microsoft ...

  10. python:爬虫

    模块: (1)url管理器:对url进行管理 (2)网页下载器(urllib2):将需要爬取的url指定的网页以字符串的形式下载下来 (3)网页解释器(BeautifulSoup):解析 利用urll ...