React Native填坑之旅--布局篇

简介:

代码在这里:
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的左侧回退按钮看起来是这样的:

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>

看起来是这样的:

column layout

默认的,在一个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>

layout row

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

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的布局包括的东西还有很多。后续会在本文或者系列的其他的文章中讲解。

欢迎加群互相学习,共同进步。QQ群:iOS: 58099570 | Android: 572064792 | Nodejs:329118122 做人要厚道,转载请注明出处!



















本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sunshine-anycall/p/5983172.html ,如需转载请自行联系原作者

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

热门文章

最新文章