,首先來看一下TabBar的效果和布局分析吧:
TabBar的外層為一個View(水平排布),內部為5個組合圖標,當選中時,切換相關頁面,TabBar按鈕呈現紅色,非選中時呈現白色,這些圖標也是已有UI切好的圖,所以邏輯處理比較簡單,主要控制好效果即可。
1.引入react-native-tab-navigator
我們可以在當前工程目錄下,使用npm i react-native-tab-navigator --save引入tab庫,目前最新版本為0.2.15
接着,我們在MainScreen類中將Tab控件import進來,具體代碼如下:
1 import TabNavigator from 'react-native-tab-navigator'; 2 3 export default class MainScreen extends Component { 4 render() { 5 return ( 6 <View style={{flex:1}}> 7 <Header /> 8 <TabNavigator> 9 10 </TabNavigator> 11 </View> 12 ); 13 } 14 }
2.TabNavigator的樣式設置
上面的代碼當中,TabNavigator繼承於View類,除了包括style的一些屬性可以和View控件一樣設置外,它還具有其他一些獨特的屬性,用於控制樣式
sceneStyle:場景樣式,即Tab頁容器的樣式,可按View的style設置
tabBarStyle:TabBar的樣式,基本也可按照普通的style寫法進行設置
tabBarShadowStyle:TabBar陰影的樣式,不過對於扁平化的設計,這個屬性應該用處不大
hidesTabTouch:bool類型,即是否隱藏Tab按鈕的按下效果
根據我們上面對TabBar樣式的分析,我們可以按照如下樣式,為TabNavigator指定tabBarStyle
1 const styles = StyleSheet.create({ 2 tab: { 3 height: 52, 4 backgroundColor: '#333333', 5 alignItems: 'center' 6 } 7 });
此時我們可以先運行在模擬器上看下效果
可以看到高度和背景色已經是我們想要的效果了,接下來,我們就可以着手構建Tab的Item了。
3.Item的構建
TabNavigator的Item就是我們所看到的5個Tab按鈕以及它們所對應的頁面,這些頁面在Android中可能以Fragment呈現,在iOS中可能以UIView呈現,而在React Native中,則是一個<View>,我們可以自己義,也可以直接放置其他控件。
這些Item在TabNavigator中,以<TabNavigator.Item>形式呈現,其可設置的相關屬性如下:
renderIcon: 必填項,即圖標,但為function類型,所以這里需要用到Arrow Function
renderSelectedIcon: 選中狀態的圖標,非必填,也是function類型
badgeText: 即Tab右上角的提示文字,可為String或Number,類似QQ中Tab右上角的消息提示,非必填
renderBadge: 提示角標渲染方式,function類型,類似render的使用,非必填
title: 標題,String類型,非必填
titleStyle: 標題樣式,style類型,非必填
selectedTitleStyle: 選中標題樣式,style類型,非必填
selected: bool型,是否選中狀態,可使用setState進行控制,默認false
onPress: function型,即點擊事件的回調函數,這里需要控制的是state,而切換頁面已經由控件本身幫我們實現好了
allowFontScaling: bool型,是否允許字體縮放,默認false
而對於我們所關心的頁面切換,在TabNavigator.Item中,可將其置於<TabNavigator.Item>{<View/>}</TabNavigator.Item>之中,即作為Item的子元素存在,這里請注意:如果添加了一個Item,必須為其添加一個View,否則將無法運行!
接着,我們將相關的圖標導入工程中,具體方法在上一篇博客中已經介紹,這里不再贅述。
為了代碼的簡潔,我們可以設計一個TabItem的渲染函數_renderTabItem
這個函數可以為我們創建Item,所以我們必須提供圖片資源(包括選中狀態)、Tag(區分Tab)、子元素View,那么函數代碼就可以寫成如下形式:
1 _renderTabItem(img, selectedImg, tag, childView) { 2 return ( 3 <TabNavigator.Item 4 selected={this.state.selectedTab === tag} 5 renderIcon={() => <Image style={styles.tabIcon} source={img}/>} 6 renderSelectedIcon={() => <Image style={styles.tabIcon} source={selectedImg}/>} 7 onPress={() => this.setState({ selectedTab: tag })}> 8 {childView} 9 </TabNavigator.Item> 10 ); 11 }
這里提醒大家:
如果使用本地圖片,即在<Image>中,source屬性內使用require的形式引用圖片,由於js本身的性質,不可以使用動態的require,而應該直接require后的圖片資源當做參數傳遞!而使用uri形式獲取在線資源不受影響
在上面的代碼中,由於TabBar控件的問題,我們可以在tabIcon樣式中,控制Icon的上邊距,以達到居中的效果,代碼如下:
1 tabIcon: { 2 width: 30, 3 height: 35, 4 resizeMode: 'stretch', 5 marginTop: 10 6 }
根據我們設計的函數,我們現在就可以方便地創建Tab了:
1 <TabNavigator hidesTabTouch={true} tabBarStyle={styles.tab}> 2 {this._renderTabItem(HOME_NORMAL, HOME_FOCUS, HOME, this._createChildView(HOME))} 3 {this._renderTabItem(CATEGORY_NORMAL, CATEGORY_FOCUS, CATEGORY, this._createChildView(CATEGORY))} 4 {this._renderTabItem(FAXIAN_NORMAL, FAXIAN_FOCUS, FAXIAN, this._createChildView(FAXIAN))} 5 {this._renderTabItem(CART_NORMAL, CART_FOCUS, CART, this._createChildView(CART))} 6 {this._renderTabItem(PERSONAL_NORMAL, PERSONAL_FOCUS, PERSONAL, this._createChildView(PERSONAL))} 7 </TabNavigator>
這里說明幾點:
1.特別注意:由於在onPress函數中調用了this.setState,所以必須在類的使用構造函數,並對state進行初始化:
1 constructor(props) { 2 super(props); 3 this.state = {selectedTab: HOME} 4 }
2._createChildView的僅僅為了區分Tab的切換,以后需要換成不同的View,這里給出代碼:
_createChildView(tag) { return ( <View style={{flex:1,backgroundColor:'#00baff',alignItems:'center',justifyContent:'center'}}> <Text style={{fontSize:22}}>{tag}</Text> </View> ) }
此時,我們的Tab也就基本構建完成了,我們可以在模擬器或真機上運行了!

看看效果,是不是還是比較滿意的呢?
源代碼及資源文件:https://github.com/yuanguozheng/JdApp
本次Commit:https://github.com/yuanguozheng/JdApp/commit/b661cd8767749bcf8512ea6564f4ac379adb5cf7