一起学ReactNative(2) Flex布局入坑手册

前言

网上面 关于Flex布局的文章 很多 有些也非常的详细
但是我觉得 学东西 还是得从实践触发 而不是光讲理论对不
今天来跟大家分享一下 自己在学习Flex布局中遇到的各种坑
如文章中有任何的错误 都可以直接联系我本人
或者在github上面提交问题
QQ:469373256

源码地址

https://github.com/fangkyi02/Demo

案例1(文本居中)

错误

import React, { Component } from 'react';
import {
  View,
  Text,
  StyleSheet,
} from 'react-native';

export default class TextAlign extends Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={{justifyContent:'center',alignItems:'center'}}>asdasd</Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
});

正确


import React, { Component } from 'react';
import {
  View,
  Text,
  StyleSheet,
} from 'react-native';

export default class TextAlign extends Component {
  render() {
    return (
      <View style={[styles.container,{justifyContent:'center',alignItems:'center'}]}>
        <Text >asdasd</Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
});

我想刚接触的人 一定有很多人这样尝试过吧 认为 我想实现一个Text那我就应该在Text这个style里面去做修改 但是实际结果却并非如此

其实Flex布局 你可以这样理解
对于改变控件布局形态的 都得写在父控件里面 比如居中 限宽 限高
对于改变自身子组件的样子 比如背景色 前景色 宽度 高度 等等的 都应该在子控件自身去完成

这样简单的分类一下 有没有清楚点呢?

看了上面的Text以后 你会发现 我并没有给我的Text限制宽高 但是的确是居中了 那么我们能否给View也尝试这样实现呢?来看一下接下来的案例

案例2(视图居中)

错误

import React, { Component } from 'react';
import {
  View,
  Text,
  StyleSheet,
} from 'react-native';

export default class ViewAlign extends Component {
  render() {
    return (
      <View style={styles.container}>
        <View style={{backgroundColor:'red'}}></View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent:'center',
    alignItems:'center'
  },
});

这个代码 是为了实现一个红色的View居中的效果 先看看 觉得代码有没有什么问题呢 静思三秒 然后继续往下看

正确

import React, { Component } from ‘react’;
import {
View,
Text,
StyleSheet,
} from ‘react-native’;

export default class ViewAlign extends Component {
render() {
return (



);
}
}

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent:’center’,
alignItems:’center’
},
});

不知道大家 有没有看出区别
为什么第一个不行 第二个加了一个宽高以后就可以了呢 我刚才的Text那边 不也没有写宽高的嘛 为啥就可以显示出来呢

这边跟大家说一下 一个View 你在不给定宽高跟flex的情况下 他是没有大小的一个空视图 所以你在这个时候 虽然给他指定了一个红色的背景 但是他也无法显示出来 哪怕你给他外面指定了一个居中
但是这里就会问了 为什么我刚才的Text没有指定宽高 依旧能显示出来呢
那是因为你的text的内容 就是宽高 你有了文本 有了内容 根据fontSize的这个值 你不就有了宽高了嘛

预标题

好 到目前为止 我们已经了解了 文本视图跟视图布局如何进行居中 也从中对于Flex有了一点了解 那么 我们就相对加深一下学习
还是实现居中的效果 不过 我们这次是要在tab里面去实现这个效果

再看源码之前 先自己脑补一下 应该如何实现 当然 如果你有更好的方式 也可以告诉我

案例3(Tab控件)

首先 我们假设 我们有5个TabItem
所以 我们在这边进行一下数据初始化
我这里随便输几个文字用来做Tab的标题

  constructor(props){
    super(props);
    this.data = [
      {text:'首页'},
      {text:'附近'},
      {text:'好友'},
      {text:'我的'},
      {text:'内容'},
    ]
  }

好 现在我们已经有了一个标题的数组了 接下来 我们就需要先创建一个tab的控件层
首先 我们要限制一下这个tab容器的高度 因为 你如果接下来要进行居中的话 你总不想看到你的这个tab是铺满整个屏幕的吧

   render() {
    return (
      <View style={styles.container}>
        {/* tab容器自身 */}
        <View style={styles.tabView}>
          {/* tab内容部分 */}
          <View style={styles.tabMainView}>
            {/* tabItem主体 */}
            {this._initRender()}
          </View>
          {/* tab滑动视图 用来处理tab按下以后的滑动 */}
          <View style={styles.slide}/>
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  tabView:{
    height:50,
  },
  tabMainView:{
    height:50-3,
    flexDirection:'row',
  },
  slide:{
    height:5,
    width:width/5,
    backgroundColor:'red'
  }
});

好 现在 一个tab容器已经呈现出来了 接下来 就是要为每个tab加上内容

  _initRender = () =>{
    return this.data.map((el,i)=>{
      return (
        // 单个的item控件
        <View style={styles.itemView}>
          {/* item主体内容 */}
            <View>
              <Text>{el.text}</Text>
            </View>
        </View>
      );
    })
  }

这里做一下解释
el 数组内容
i 数组内容位置
首先map从数组中 依次的枚举出 我在数组中填写的初始化标题数据
然后这个el的数据传递给了text文本 并且通过外部包裹的view变成一个组件视图
但是这里要注意 这里的map中return的数据 并没有立即返回 他是等整个数组循环完成以后 在做了返回

这里写图片描述
一个简单的tab就这样实现了 当然 这个只是最简单的tab
如果你想实现一些效果的话 可以这样实现 也非常简单

  _itemDown = (i) =>{
    this.setState({
      id:i
    });
  }
  _initRender = () =>{
    return this.data.map((el,i)=>{
      return (
        // 单个的item控件
        <View style={styles.itemView}>
          {/* item主体内容 */}
            <View>
              <TouchableOpacity onPress={this._itemDown.bind(this,i)}>
                <Text style={this.state.id==i?styles.itemTextFocus:styles.itemTextNoFocus}>{el.text}</Text>
              </TouchableOpacity>

            </View>
        </View>
      );
    })
  }

这里也很简单 根据this.state.id的值然后判断需要采取哪个styles
然后当你按下的时候 触发onPress的时候 然后设置你的state.id为i值
这个时候因为setState的关系 会导致整个页面刷新 然后又回到了刚才的判断this.state.id那边 来进行刷新渲染

记得 如果要使用这个方法来实现的话 最好将tab封装成一个子组件 不然像我这样直接进行setState会导致 下面的视图组件也进行重新的渲染

好了 来看一下结果吧

这里写图片描述

我的所有源码都已经上传到了github 你们有兴趣的话 可以自己去做修改 比如实现下面的滑块条效果
https://github.com/fangkyi02/Demo
如项目中有什么错误的地方 还望大家指正
QQ:469373256

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值