Quantcast
Viewing all articles
Browse latest Browse all 5930

React Native之react-native-scrollable-tab-view详解

在React Native开发中,官方为我们提供的Tab控制器有两种:TabBarIOS和ViewPagerAndroid。TabBarIOS,仅适用于IOS平台
ViewPagerAndroid,仅适用于Android平台(严格来讲并不算,因为我们还需要自己实现Tab)。在项目开发中,我们优先选择一些开源兼容性比较好的第三方库,例如,react-navigation,以及本文即将说到的react-native-scrollable-tab-view(官方地址)。react-native-scrollable-tab-view不仅可以实现顶部的Tab切换,还能实现底部的切换。
Image may be NSFW.
Clik here to view.
这里写图片描述
Image may be NSFW.
Clik here to view.
这里写图片描述

我们再来看一下官方的Demo。
Image may be NSFW.
Clik here to view.
这里写图片描述

属性及方法介绍

1, renderTabBar(Function:ReactComponent)

TabBar的样式,系统提供了两种默认的,分别是DefaultTabBar和ScrollableTabBar。当然,我们也可以自定义一个,我们会在下篇文章重点讲解如何去自定义TabBar样式。
注意:每个被包含的子视图需要使用tabLabel属性,表示对应Tab显示的文字。
DefaultTabBar:Tab会平分在水平方向的空间。
ScrollableTabBar:Tab可以超过屏幕范围,滚动可以显示。

render() {
  return (
    <ScrollableTabView
      renderTabBar={() => <DefaultTabBar/>}>
      <Text tabLabel='Tab1'/>
      <Text tabLabel='Tab2'/>
      <Text tabLabel='Tab3'/>
      <Text tabLabel='Tab4'/>
      <Text tabLabel='Tab5'/>
      <Text tabLabel='Tab6'/>
    </ScrollableTabView>
  );
}

2,tabBarPosition(String,默认值’top’)
top:位于屏幕顶部
bottom:位于屏幕底部
overlayTop:位于屏幕顶部,悬浮在内容视图之上(看颜色区分:视图有颜色,Tab栏没有颜色)
overlayBottom:位于屏幕底部,悬浮在内容视图之上(看颜色区分:视图有颜色,Tab栏没有颜色)

render() {
  return (
    <ScrollableTabView
      tabBarPosition='top'
      renderTabBar={() => <DefaultTabBar/>}>
      ...
    </ScrollableTabView>
  );
}

3, onChangeTab(Function)
Tab切换之后会触发此方法,包含一个参数(Object类型),这个对象有两个参数:
i:被选中的Tab的下标(从0开始)
ref:被选中的Tab对象(基本用不到)

render() {
  return (
    <ScrollableTabView
      renderTabBar={() => <DefaultTabBar/>}
      onChangeTab={(obj) => {
          console.log('index:' + obj.i);
        }
      }>
      ...
    </ScrollableTabView>
  );
}

4,onScroll(Function)
视图正在滑动的时候触发此方法,包含一个Float类型的数字,范围是[0, tab的数量-1]

render() {
  return (
    <ScrollableTabView
      renderTabBar={() => <DefaultTabBar/>}
      onScroll={(postion) => {  
          // float类型 [0, tab数量-1]  
          console.log('scroll position:' + postion);
        }
      }>
      ...
    </ScrollableTabView>
  );
}

5, locked(Bool,默认为false)
表示手指是否能拖动视图,默认为false(表示可以拖动)。设为true的话,我们只能“点击”Tab来切换视图。

render() {
  return (
    <ScrollableTabView
      locked={false}
      renderTabBar={() => <DefaultTabBar/>}>
      ...
    </ScrollableTabView>
  );
}

6, initialPage(Integer)
初始化时被选中的Tab下标,默认是0(即第一页)。

render() {
  return (
    <ScrollableTabView
      initialPage={1}
      renderTabBar={() => <DefaultTabBar/>}>
      ...
    </ScrollableTabView>
  );
}

7,page(Integer)
设置选中指定的Tab。

8,children(ReactComponents)
表示所有子视图的数组,比如下面的代码,children则是一个长度为6的数组,元素类型为Text。

render() {
  return (
    <ScrollableTabView
      renderTabBar={() => <DefaultTabBar/>}>
      <Text tabLabel='Tab1'/>
      <Text tabLabel='Tab2'/>
      <Text tabLabel='Tab3'/>
      <Text tabLabel='Tab4'/>
      <Text tabLabel='Tab5'/>
      <Text tabLabel='Tab6'/>
    </ScrollableTabView>
  );
}

9,tabBarUnderlineStyle(style)
设置DefaultTabBar和ScrollableTabBarTab选中时下方横线的颜 色。
10.,tabBarBackgroundColor(String)
设置整个Tab这一栏的背景颜色
11,tabBarActiveTextColor(String)
设置选中Tab的文字颜色。
12,tabBarInactiveTextColor(String)
设置未选中Tab的文字颜色。
13,contentProps(Object)
这里要稍微说下react-native-scrollable-tab-view的实现,其实在Android平台底层用的是ViewPagerAndroid,iOS平台用的是ScrollView。这个属性的意义是:比如我们设置了某个属性,最后这个属性会被应用在ScrollView/ViewPagerAndroid,这样会覆盖库里面默认的,通常官方不建议我们去使用。
14,scrollWithoutAnimation(Bool,默认为false)
设置“点击”Tab时,视图切换是否有动画,默认为false(即:有动画效果)。

render() {
  return (
    <ScrollableTabView
      scrollWithoutAnimation={true}
      renderTabBar={() => <DefaultTabBar/>}>
      ...
    </ScrollableTabView>
  );
}

顶部导航示例

顶部导航的代码是比较简单的。例如,我们实现上图的新闻Tab导航的效果。
Image may be NSFW.
Clik here to view.
这里写图片描述

相关代码:

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

 import React, { Component } from 'react';
 import ScrollableTabView, {DefaultTabBar,ScrollableTabBar} from 'react-native-scrollable-tab-view';
 import {
   AppRegistry,
   StyleSheet,
   Text,
   Image,
   View
 } from 'react-native';

var Dimensions = require('Dimensions');
var ScreenWidth = Dimensions.get('window').width;

class TabTopView extends Component {
    render() {
        return (
            <ScrollableTabView
                style={styles.container}
                renderTabBar={() => <DefaultTabBar />}
                tabBarUnderlineStyle={styles.lineStyle}
                tabBarActiveTextColor='#FF0000'>

                <Text style={styles.textStyle} tabLabel='娱乐'>娱乐</Text>
                <Text style={styles.textStyle} tabLabel='科技'>科技</Text>
                <Text style={styles.textStyle} tabLabel='军事'>军事</Text>
                <Text style={styles.textStyle} tabLabel='体育'>体育</Text>
            </ScrollableTabView>
        );
    }
    }


 const styles = StyleSheet.create({
     container: {
         flex: 1,
         marginTop: 20
     },
     lineStyle: {
         width:ScreenWidth/4,
         height: 2,
         backgroundColor: '#FF0000',
     },
     textStyle: {
         flex: 1,
         fontSize:20,
         marginTop:20,
         textAlign:'center',
     },

 });

export default TabTopView;

然后在index.ios.js或index.android.js中导入组件。

export default class RNDemo extends Component {
    render() {
        return (
            <TabBottomView/>
        );
    }
}

底部Tab切换示例

Image may be NSFW.
Clik here to view.
这里写图片描述

需要注意的是项目中用到了Navigator这个组件,在最新的版本中,系统标识Navigator已经过时被抛弃,所以我们需要使用命令先按照相关的库:

npm install --save react-native-deprecated-custom-components

Image may be NSFW.
Clik here to view.
这里写图片描述

然后在使用的界面中导入Navigator。

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

好了其他的不再说明,直接上代码:
TabBottomView.js

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

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

import TabBarView from './TabBarView'
import TabDefaultView from './TabDefaultView'

import {
    AppRegistry,
    StyleSheet,
    Text,
    Image,
    View,
    AlertIOS,
    StatusBar,
} from 'react-native';



var Dimensions = require('Dimensions');
var ScreenWidth = Dimensions.get('window').width;

class TabBottomView extends Component {

    counter = 0;
    configureScene = route => {
        if (route.sceneConfig) return route.sceneConfig

        return {
            ...Navigator.SceneConfigs.PushFromRight,
            gestures: {}    // 禁用左滑返回手势
        }
    }

    renderScene = (route, navigator) => {
        let Component = route.component
        return <Component navigator={navigator}{...route.passProps}/>
    }

    inc = () => {
        ++this.counter;
    };

    dec = () => {
        --this.counter;
    };

    OnChangeText = v => {
        try {
            this.counter = parseInt(v);
        } catch (err) {
        }

    };

    OnClickText = (title) => {
        alert('title=' + title);
    }

    render() {
        const initialPage = TabDefaultView;
        const initialPageName = 'TabBarView';

        return (
            <View style={styles.container}>
                <StatusBar barStyle={'light-content'}/>
                <Navigator
                    initialRoute={{name: initialPageName, component: initialPage}}
                    configureScene={this.configureScene}
                    renderScene={this.renderScene}/>
            </View>

        );
    }
}


const styles = StyleSheet.create({
    container: {
        flex: 1,
        marginTop: 20
    },


});

export default TabBottomView;

TabBottomView设计到的两个自定义View:
TabBarView.js

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow TextInput自动提示输入
 */

import React, {Component} from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    TouchableOpacity,
    Image,
    TextInput,
    View
}
from
'react-native';


class TabBarView extends Component {

    static propType = {
        goToPage    : React.PropTypes.func,
        activeTab   : React.PropTypes.number,
        tabs        : React.PropTypes.array,

        tabNames    : React.PropTypes.array,
        tabIconNames: React.PropTypes.array,
        selectedTabIconNames: React.PropTypes.array
    };

    componentDidMount() {
        this.props.scrollValue.addListener(this.setAnimationValue);
    }

    setAnimationValue({value}) {
        console.log(value);
    }

    render() {
        return (
            <View style={styles.tabs}>
                {this.props.tabs.map((tab, i) => {
                    let color = this.props.activeTab === i ? 'green' : 'gray';
                    let icon = this.props.activeTab == i ? this.props.selectedTabIconNames[i] : this.props.tabIconNames[i];
                    return (
                        <TouchableOpacity
                            key={i}
                            activeOpacity={0.8}
                            style={styles.tab}
                            onPress={()=>this.props.goToPage(i)}>
                            <View style={styles.tabItem}>
                                <Image
                                    style={styles.icon}
                                    source={icon}/>
                                <Text style={{color: color, fontSize: 12}}>
                                    {this.props.tabNames[i]}
                                </Text>
                            </View>
                        </TouchableOpacity>
                    )
                })}
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: '#ffffff',
        marginTop: 20
    },
    tabs: {
        flexDirection: 'row',
        height: 49,
        borderTopColor: '#d9d9d9',
        borderTopWidth:2
    },
    tab: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
    },
    tabItem: {
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'space-around'
    },
    icon: {
        width: 26,
        height: 26,
        marginBottom: 2
    }
});

export default TabBarView;

TabDefaultView.js(默认界面)

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow TextInput自动提示输入
 */

import React, {Component} from 'react';
import TabBarView from './TabBarView'
import ScrollableTabView, {DefaultTabBar, ScrollableTabBar} from 'react-native-scrollable-tab-view';
import HomeScreen from '../widght/HomeScreen';
import MineScreen from '../widght/MineScreen';

import {
    AppRegistry,
    StyleSheet,
    Text,
    TouchableOpacity,
    Image,
    TextInput,
    StatusBar,
    View
}from 'react-native';

const tabTitles = ['首页', '我的']
//Tab图标
const tabIcon = [
    require('../image/tabbar_homepage.png'),
    require('../image/tabbar_mine.png'),
]
const tabSelectedIcon = [
    require('../image/tabbar_homepage_selected.png'),
    require('../image/tabbar_mine_selected.png'),
]

class TabDefaultView extends Component {

    onChangeTabs = ({i}) => 'light-content';

    render() {
        return (
            <ScrollableTabView
                renderTabBar={() =>
                    <TabBarView
                        tabNames={tabTitles}
                        tabIconNames={tabIcon}
                        selectedTabIconNames={tabSelectedIcon}/>
                }
                tabBarPosition='bottom'
                locked
                scrollWithoutAnimationz
                onChangeTab={this.onChangeTabs}>

                <HomeScreen tabLabel="Home" navigator={this.props.navigator}/>
                <MineScreen tabLabel="Mine" navigator={this.props.navigator}/>

            </ScrollableTabView>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: '#ffffff',
        marginTop: 20
    },
    value:{
        paddingHorizontal:10,
        paddingVertical:8,
        width:100,
        marginLeft:120,
    }
});

export default TabDefaultView;

最后在index.ios.js或index.android.js中导入组件。


export default class RNDemo extends Component {
    render() {
        return (
            <TabBottomView/>
        );
    }
}

附件:源码下载

作者:xiangzhihong8 发表于2017/5/25 16:40:29 原文链接
阅读:208 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>