原文連接react
在React Native開發中,官方爲咱們提供的Tab控制器有兩種:TabBarIOS和ViewPagerAndroid。TabBarIOS,僅適用於IOS平臺
ViewPagerAndroid,僅適用於Android平臺(嚴格來說並不算,由於咱們還須要本身實現Tab)。在項目開發中,咱們優先選擇一些開源兼容性比較好的第三方庫,例如,react-navigation,以及本文即將說到的react-native-scrollable-tab-view(官方地址)。react-native-scrollable-tab-view不只能夠實現頂部的Tab切換,還能實現底部的切換。android
1, renderTabBar(Function:ReactComponent)git
TabBar的樣式,系統提供了兩種默認的,分別是DefaultTabBar和ScrollableTabBar。固然,咱們也能夠自定義一個,咱們會在下篇文章重點講解如何去自定義TabBar樣式。
注意:每一個被包含的子視圖須要使用tabLabel屬性,表示對應Tab顯示的文字。
DefaultTabBar:Tab會平分在水平方向的空間。
ScrollableTabBar:Tab能夠超過屏幕範圍,滾動能夠顯示。github
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欄沒有顏色)npm
render() { return ( <ScrollableTabView tabBarPosition='top' renderTabBar={() => <DefaultTabBar/>}> ... </ScrollableTabView> ); }
3, onChangeTab(Function)
Tab切換以後會觸發此方法,包含一個參數(Object類型),這個對象有兩個參數:
i:被選中的Tab的下標(從0開始)
ref:被選中的Tab對象(基本用不到)react-native
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來切換視圖。less
render() { return ( <ScrollableTabView locked={false} renderTabBar={() => <DefaultTabBar/>}> ... </ScrollableTabView> ); }
6, initialPage(Integer)
初始化時被選中的Tab下標,默認是0(即第一頁)。ide
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導航的效果。
相關代碼:
/** * 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/> ); } }
須要注意的是項目中用到了Navigator這個組件,在最新的版本中,系統標識Navigator已通過時被拋棄,因此咱們須要使用命令先按照相關的庫:
npm install --save react-native-deprecated-custom-components
而後在使用的界面中導入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('../p_w_picpath/tabbar_homepage.png'), require('../p_w_picpath/tabbar_mine.png'), ]const tabSelectedIcon = [ require('../p_w_picpath/tabbar_homepage_selected.png'), require('../p_w_picpath/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/> ); } }
附件:×××