返回 导航

React / React Native

hangge.com

React Native - 实现一个简单的分页导航菜单(tab标签切换)

作者:hangge | 2017-09-06 08:10
分页菜单(分段菜单)在许多 App 上都会用到。大多数新闻 App,如网易新闻、今日头条等,顶部都有个导航菜单。这个导航菜单是一组标签的集合,每个标签表示一个新闻类别,我们点击这个标签后下面就会切换到对应的分页面。
下面我们使用 React Native 来实现一个简单的分页菜单功能。

1,效果图

(1)界面顶部的菜单栏中有 4 个标签,点击标签即可切换到对应的页面。
(2)当前选中的菜单标签背景为灰色,其他标签背景为白色。
             

2,样例代码

(1)菜单栏组件(NaviBar.js
import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  TouchableHighlight,
  Dimensions
} from 'react-native';

//获取设备的宽度和高度
var {
    height: deviceHeight,
    width: deviceWidth
} = Dimensions.get('window');

export default class NaviBar extends Component {
  componentWillMount() {
    //通过属性得知哪个导航按钮是当前的导航也,这个导航按钮将用灰色背景
    this.buttonColors = this.props.naviBarStatus.map(
      function(aNumber) {
        if (aNumber == 0) return 'white';
        return 'gray';
      }
    );
  }

  //四个按钮被按下时处理函数
  _naviTab0Pressed() {
    this.props.onNaviBarPress(0);
  }

  _naviTab1Pressed() {
    this.props.onNaviBarPress(1);
  }

  _naviTab2Pressed() {
    this.props.onNaviBarPress(2);
  }

  _naviTab3Pressed() {
    this.props.onNaviBarPress(3);
  }

  render() {
    return (
    //根View
    <View style={styles.naviRow}>
      <TouchableHighlight onPress={this._naviTab0Pressed.bind(this)}>
          <View style={[styles.button,{backgroundColor:this.buttonColors[0]}]}>
              <Text style={styles.textStyle1}>
                  栏目一
              </Text>
          </View>
      </TouchableHighlight>
      <TouchableHighlight onPress={this._naviTab1Pressed.bind(this)}>
          <View style={[styles.button,{backgroundColor:this.buttonColors[1]}]}>
              <Text style={styles.textStyle1}>
                  栏目二
              </Text>
          </View>
      </TouchableHighlight>
      <TouchableHighlight onPress={this._naviTab2Pressed.bind(this)}>
          <View style={[styles.button,{backgroundColor:this.buttonColors[2]}]}>
              <Text style={styles.textStyle1}>
                  栏目三
              </Text>
          </View>
      </TouchableHighlight>
      <TouchableHighlight onPress={this._naviTab3Pressed.bind(this)}>
          <View style={[styles.button,{backgroundColor:this.buttonColors[3]}]}>
              <Text style={styles.textStyle1}>
                  栏目四
              </Text>
          </View>
      </TouchableHighlight>
    </View>
    );
  }
}

//样式
const styles = StyleSheet.create({
  naviRow: {
      flexDirection: 'row'
  },
  button: {
      width: deviceWidth / 4, //导航栏每个标签宽度为屏幕1/4
      height: 45,
      justifyContent: 'center'
  },
  textStyle1: {
      fontSize: 20,
      textAlign: 'center'
  }
});

(2)页面1(Page1.jpg
每个分页面的顶部其实都放置了一个菜单栏组件,只不过菜单栏状态和菜单点击事件的处理逻辑有差异。
import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  View,
  Text
} from 'react-native';

import NaviBar from './NaviBar';

export default class Page1 extends Component {
  // 构造
    constructor(props) {
        super(props);
        // 初始状态
        this.onNaviBarPress = this.onNaviBarPress.bind(this);
        // 不同的Page,需要修改下面的这个数组, 通过数组控制导航栏条目显示状态
        this.naviStatus = [1, 0, 0, 0];
    }

    onNaviBarPress(aNumber) {
        //不同的page需要修改下面这个switch的处理逻辑
        switch (aNumber) {
            case 0:
                return;
            case 1:
                //通过replace切换
                this.props.navigator.replace({
                    name: 'Page2'
                });
                return;
            case 2:
                this.props.navigator.replace({
                    name: 'Page3'
                });
                return;
            case 3:
                this.props.navigator.replace({
                    name: 'Page4'
                });
                return;
        }
    }

    render() {
        return (
            <View style={styles.container}>
                <NaviBar naviBarStatus={this.naviStatus}
                         onNaviBarPress={this.onNaviBarPress}/>
                <View style={styles.whatLeft}/>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1
    },
    whatLeft: {  // 组件定义了一个上边框
        flex: 1,
        borderTopWidth: 1,
        borderColor: 'black',
        backgroundColor:'orange' //每个界面背景颜色不一样
    }
});

(3)页面2(Page2.jpg
下面高亮处显示的是 Page2 Page1 的差别,菜单栏状态和菜单点击事件的处理逻辑有差异,后面的 Page3Page4 也差不多,这里就不再列出相关代码了。
import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  View,
  Text
} from 'react-native';

import NaviBar from './NaviBar';

export default class Page1 extends Component {
  // 构造
    constructor(props) {
        super(props);
        // 初始状态
        this.onNaviBarPress = this.onNaviBarPress.bind(this);
        // 不同的Page,需要修改下面的这个数组, 通过数组控制导航栏条目显示状态
        this.naviStatus = [0, 1, 0, 0];
    }

    onNaviBarPress(aNumber) {
        //不同的page需要修改下面这个switch的处理逻辑
        switch (aNumber) {
            case 0:
                this.props.navigator.replace({
                    name: 'Page1'
                });
                return;
            case 1:
                return;
            case 2:
                this.props.navigator.replace({
                    name: 'Page3'
                });
                return;
            case 3:
                this.props.navigator.replace({
                    name: 'Page4'
                });
                return;
        }
    }

    render() {
        return (
            <View style={styles.container}>
                <NaviBar naviBarStatus={this.naviStatus}
                         onNaviBarPress={this.onNaviBarPress}/>
                <View style={styles.whatLeft}/>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1
    },
    whatLeft: {  // 组件定义了一个上边框
        flex: 1,
        borderTopWidth: 1,
        borderColor: 'black',
        backgroundColor:'green' //每个界面背景颜色不一样
    }
});

(4)主页视图(index.android.js
import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
} from 'react-native';

import { Navigator } from 'react-native-deprecated-custom-components';

import Page1 from './Page1';
import Page2 from './Page2';
import Page3 from './Page3';
import Page4 from './Page4';

//默认应用的容器组件
class App extends Component {

  //告知Navigator 模块切换时的效果
  configureScene() {
     return Navigator.SceneConfigs.FadeAndroid;
  }

  //根据传递的信息, 处理界面的切换
  renderScene(router, navigator) {
     switch (router.name) {
         case 'Page1':
             return <Page1 navigator={navigator}/>;
         case 'Page2':
             return <Page2 navigator={navigator}/>;
         case 'Page3':
             return <Page3 navigator={navigator}/>;
         case 'Page4':
             return <Page4 navigator={navigator}/>;
     }
  }

  render() {
     return (
         //根View
         <Navigator
             initialRoute={{name:'Page1'}}
             configureScene={this.configureScene}
             renderScene={this.renderScene}/>
     );
  }
}

AppRegistry.registerComponent('HelloWorld', () => App);
评论

全部评论(0)

回到顶部