React Native 系列(九) -- Tab標簽組件


前言

本系列是基於React Native版本號0.44.3寫的。很多的App都使用了Tab標簽組件,例如QQ微信等等,就是切換不同的選項,顯示不同的內容。那么這篇文章將介紹RN中的Tab標簽組件。

Tab標簽

什么是Tab標簽?(ps:我是這樣叫的),就拿微信來說吧,底部有4個選項卡,點擊不同的按鈕切換不同的內容。
RN中有兩個組件負責實現這樣的效果,它們是:

TabBarIOS

NavigatorIOS相似,看名字就知道該組件只適用於iOS,不能用於android

TabBarIOS 常用屬性

barTintColor string:標簽欄的背景顏色。 
style:樣式 
tintColor string: 當前被選中的標簽圖標的顏色。 unselectedItemTintColor string: 當前沒有被選中的標簽圖標的顏色。僅在iOS 10及以上版本有效 
translucent bool: 一個布爾值,決定標簽欄是否需要半透明化。

TabBarIOS.Item

  • 注意:TabBarIOS.Item必須包裝一個View,作為點擊選項卡,切換的view

TabBarIOS.Item 常用屬性

badge string, number :在圖標右上角顯示一個紅色的氣泡。
 
icon Image.propTypes.source :給當前標簽指定一個自定義的圖標。如果定義了systemIcon屬性, 這個屬性會被忽略。 

onPress function :當此標簽被選中時調用。你應該修改組件的狀態來使得selected={true}。 

selected bool :這個屬性決定了子視圖是否可見。如果你看到一個空白的頁面,很可能是沒有選中任何一個標簽。 

selectedIcon Image.propTypes.source :當標簽被選中的時候顯示的自定義圖標。如果定義了systemIcon屬性,這個屬性會被忽略。如果定義了icon而沒定義這個屬性,在選中的時候圖標會染上藍色。 

systemIcon enum('bookmarks', 'contacts', 'downloads', 'favorites', 'featured', 'history', 'more', 'most-recent', 'most-viewed', 'recents', 'search', 'top-rated') :一些預定義的系統圖標。注意如果你使用了此屬性,標題和自定義圖標都會被覆蓋為系統定義的值。 

title string :在圖標下面顯示的標題文字。如果定義了systemIcon屬性,這個屬性會被忽略

使用步驟

  1. 創建TabBar標簽: 使用下面行代碼,底部就會有一個條

    <TabBarIOS>
    </TabBarIOS>
    
  2. 添加選項卡

    <TabBarIOS.Item
            title='首頁'
            icon={{uri: 'tabbar_home_select' , scale: 3}}
    >
        <View style={{flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: 'red'}}>
            <Text>首頁</Text>
        </View>
    </TabBarIOS.Item>
    
  3. 監聽按鈕點擊,切換界面

    • 只要設置對應的tabBarItemselectedtrue,就會自動跳轉到對應界面
    • 注意:tabBarItemselected屬性不能寫死,可以定義個flag來標記當前選中的item
    • 監聽tabBarItem的點擊,修改selected屬性

實戰演練

先看效果圖:
圖1

我們在index.ios.js文件做修改,直接創建一個TabBarIOS組件:

render() {
    return (
        <TabBarIOS
            tintColor='orange'
            barTintColor='black'
        >
        </TabBarIOS>
    );
}

再創建三個選項卡(ps:3個選項卡創建方式類似,所以這里只貼出創建一個的代碼,),icon是圖片,關於圖片方面的知識,本文最后做一個總結吧:

<TabBarIOS.Item
        title='首頁'
        icon={{uri: 'tabbar_home_select' , scale: 3}}
        selected={true}
    >
        <View style={{flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: 'red'}}>
            <Text>首頁</Text>
        </View>

</TabBarIOS.Item>

監聽按鈕點擊,然后實現界面切換,我們需要定義一個flag記錄當前選中的,

constructor(props) {
    super(props);
    // 初始狀態
    this.state = {
        selectIndex:0,
    };
}

TabBarIOS.Item添加點擊事件:

<TabBarIOS.Item
    title='首頁'
    icon={{uri: 'tabbar_home_select' , scale: 3}}
    onPress={()=>{
        this.setState({
            selectIndex:0
        })
    }}
    selected={0==this.state.selectIndex}
>

我們會發現,創建3個TabBarIOS.Item的代碼是一樣的,避免寫重復代碼,我們可以抽取出來:

_renderTabBarItem(title, iconName, selected, bgColor, badgeNumber){
    return (
        <TabBarIOS.Item
            title={title}
            icon={{uri: iconName, scale: 3}}
            onPress={()=>{
                this.setState({
                    selectIndex: selected
                })
            }}
            badge={badgeNumber}
            selected={this.state.selectIndex === selected}
        >
            <View style={{flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: bgColor}}>
                <Text>{title}</Text>
            </View>
        </TabBarIOS.Item>
    );
}

然后我們整個創建標簽Tab的代碼就應該是這樣:

render() {
    return (
        <TabBarIOS
            tintColor='orange'
            barTintColor='black'
        >
            {this._renderTabBarItem("首頁", 'tabbar_my_select', 0, 'red', null)}
            {this._renderTabBarItem("消息", 'tabbar_my_select', 1, 'yellow', 2)}
            {this._renderTabBarItem("我的", 'tabbar_my_select', 2, 'cyan', null)}

        </TabBarIOS>
    );
}

TabNavigator

本系列上篇文章中,介紹到React Navigation組件中包含了TabNavigator。所以接下來的講解是在引入了React Navigation的基礎之上的。

常用屬性

screen:和導航的功能是一樣的,對應界面名稱,可以在其他頁面通過這個screen傳值和跳轉。  
      
navigationOptions:配置TabNavigator的一些屬性  
{  
    title:標題,會同時設置導航條和標簽欄的title  
    tabBarVisible:是否隱藏標簽欄。默認不隱藏(true)  
    tabBarIcon:設置標簽欄的圖標。需要給每個都設置  
    tabBarLabel:設置標簽欄的title。推薦  
}


tabBarPosition:設置tabbar的位置,iOS默認在底部,安卓默認在頂部。(屬性值:'top','bottom')  
      
swipeEnabled:是否允許在標簽之間進行滑動  
      
animationEnabled:是否在更改標簽時顯示動畫  
      
lazy:是否根據需要懶惰呈現標簽,而不是提前,意思是在app打開的時候將底部標簽欄全部加載,默認false,推薦為true  
      
trueinitialRouteName: 設置默認的頁面組件  
      
backBehavior:按 back 鍵是否跳轉到第一個Tab(首頁), none 為不跳轉  
      
tabBarOptions:配置標簽欄的一些屬性iOS屬性  
      
activeTintColor:label和icon的前景色 活躍狀態下  
      
activeBackgroundColor:label和icon的背景色 活躍狀態下  
      
inactiveTintColor:label和icon的前景色 不活躍狀態下  
      
inactiveBackgroundColor:label和icon的背景色 不活躍狀態下  
      
showLabel:是否顯示label,默認開啟 style:tabbar的樣式  
      
labelStyle:label的樣式安卓屬性  
      
activeTintColor:label和icon的前景色 活躍狀態下  
      
inactiveTintColor:label和icon的前景色 不活躍狀態下  
      
showIcon:是否顯示圖標,默認關閉  
      
showLabel:是否顯示label,默認開啟 style:tabbar的樣式  
      
labelStyle:label的樣式 upperCaseLabel:是否使標簽大寫,默認為true  
      
pressColor:material漣漪效果的顏色(安卓版本需要大於5.0)  
      
pressOpacity:按壓標簽的透明度變化(安卓版本需要小於5.0)  
      
scrollEnabled:是否啟用可滾動選項卡 tabStyle:tab的樣式  
      
indicatorStyle:標簽指示器的樣式對象(選項卡底部的行)。安卓底部會多出一條線,可以將height設置為0來暫時解決這個問題  
      
labelStyle:label的樣式  
      
iconStyle:圖標樣式  

實戰演練

我們創建App.js,然后在index.ios.js文件引用該組件:

import App from './App'
export default class RNDemoTwo extends Component {
    render() {
        return (
            <App/>
        );
    }
}

現在來配置下App.js文件:

import {TabNavigator} from 'react-navigation'
import HelloViewCompnent from './HelloViewComponent'
import DetailComponent from './DetailComponent'
import ThreeComponent from './Three'
import CustTabBarItem from "./TabBarItem"


const SimpleApp = TabNavigator({
    Home: {
        screen: HelloViewCompnent,
        navigationOptions: ({navigation}) => ({
            tabBarVisible: true,
            tabBarLabel: '首頁',
            tabBarIcon: ({focused, tintColor})=>(
                <CustTabBarItem
                    tintColor={tintColor}
                    focused={focused}
                    selectImage={{uri: 'tabbar_home_select'}}
                    normalImage={{uri: 'tabbar_home'}}
                />
            ),
        })
    },

    Detail: {
        screen: DetailComponent,
        navigationOptions: ({navigation}) => ({
            tabBarLabel: '消息',
            tabBarIcon: ({focused, tintColor})=>(
                <CustTabBarItem
                    tintColor={tintColor}
                    focused={focused}
                    selectImage={{uri: 'tabbar_licai_select'}}
                    normalImage={{uri: 'tabbar_licai'}}
                />
            ),
        })
    },

    Three: {
        screen: ThreeComponent,
        navigationOptions: ({navigation}) => ({
            tabBarLabel: '我的',
            tabBarIcon: ({focused, tintColor})=>(
                <CustTabBarItem
                    tintColor={tintColor}
                    focused={focused}
                    selectImage={{uri: 'tabbar_my_select'}}
                    normalImage={{uri: 'tabbar_my'}}
                />
            ),
        })
    }
},{
    tabBarPosition:'bottom',
    swipeEnabled:false,
    animationEnabled:false,
    lazy:true,
    tabBarOptions:{
        activeTintColor:'red',
        inactiveTintColor:'black',
        style:{backgroundColor:'#fff',},
        labelStyle: {
            fontSize: 16, // 文字大小
        },
    }
})

export default SimpleApp

可以看到我們導入了三個頁面組件,一個CustTabBarItem
三個頁面組件很簡單,都類似,由於篇幅原因,只貼出一個就行了:

export default class HelloViewCompnent extends Component {

    render() {
        return (
            <View style={styles.container}>
                <Text style={styles.welcome}>
                    首頁
                </Text>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: 'white',
    },
    welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
});

最后,就是我們的TabBarItem.js文件了:

export default class TabBarItem extends Component {
    render(){
        return (
            <Image source={this.props.focused ? this.props.selectImage : this.props.normalImage}
            style={{tintColor: this.props.tintColor, width: 25, height: 25}}/>
        );
    }
}

保存代碼,運行項目,不出意外,應該和使用TabBarIOS是一樣的效果。

關於Image組件

由於這里我們都使用到<Image/>組件,這里就稍微講一下。

  • Image:用於加載圖片,可加載網絡圖片,也可以加載本地圖片

  • Image常用屬性

    source {uri: string}, number : 設置Image圖片資源 
    blurRadius number:讓圖片模糊 
    defaultSource {uri: string, width: number, height:number, scale: number}, number 占位圖片,在讀取圖片時默認顯示的加載提示圖片 
     
    resizeMode enum('cover', 'contain', 'stretch', 'repeat', 
    

'center') 決定圖片尺寸大小。

cover: 在保持圖片寬高比的前提下縮放圖片,直到寬度和高度都大於等於容器視圖的尺寸(如果容器有padding內襯的話,則相應減去)。譯注:這樣圖片完全覆蓋甚至超出容器,容器中不留任何空白。 

contain: 在保持圖片寬高比的前提下縮放圖片,直到寬度和高度都小於等於容器視圖的尺寸(如果容器有padding內襯的話,則相應減去)。譯注:這樣圖片完全被包裹在容器中,容器中可能留有空白 

stretch: 拉伸圖片且不維持寬高比,直到寬高都剛好填滿容器。
repeat: 重復平鋪圖片直到填滿容器。圖片會維持原始尺寸。僅iOS可用。 
center: 居中不拉伸。
```
  • 本地圖片存放位置

      1. 直接放在RN項目中
      1. 可以放在ios項目中,放到images.xcassets文件中
      1. 可以放在android項目中(安卓中圖片文字不能以數字開頭,也不能有大寫字母)
  • 如何加載本地圖片

    • RN中加載資源:require(文件路徑),用於加載RN中的資源,不管是圖片,還是json都是一樣的
    • uri:指定一個資源路徑,就會自動加載
    • uri加載注意:通過uri加載資源,必須設置圖片尺寸,否則不顯示
    • 如果網絡加載http圖片,iOS默認不支持,需要開啟App Transport

致謝

如果發現有錯誤的地方,歡迎各位指出,謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM