前言
接觸過ReactNative(以下簡稱RN)的大概都知道,react-navigation提供了兩種開箱即用的導航欄元件
分別是這樣的
儘管官方提供了導航欄的開箱即用方案,但是實際開發裡面,我們會遇到各種各樣的導航欄,各種各樣的動效,所以以上可能無法滿足我們的開發需求,我們就需要定製化的去做我們導航欄
例如我們UI給我的導航欄樣式
我的內心: 這他麼中間凸起的我怎麼做,老子只是一個小前端,app很渣啊啊啊
藉助可愛的google,我找到了解決方法
就是
TabBarComponent
這個api在文件資料很少,所以想要知道怎麼用只能通過網路上的資源了
其中深受這篇文案的啟發
這位外國友人(話說reactnative在國外似乎還有點火),藉助動畫庫react-native-pose
,完成了這樣的效果
雖然是英文部落格,但是配合翻譯基本閱讀無障礙,藉助他的部落格,我完成了ReactNative的自定義導航欄,效果如下
自定義底部導航欄
- 自定義底部導航欄是基於
createBottomTabNavigator
,所以我們使用這個api來建立底部導航欄- 指定
createBottomTabNavigator
的tabBarComponent- tabBarComponent內部進行底部導航欄的編寫
增加底部導航器
import React from 'react'
import { createBottomTabNavigator } from 'react-navigation'
import Icon from '../Common/Icon' // 自定義圖示庫
import TabBar from '../Common/TabBar' // tabBarComponent 自定義元件
// 頁面
import Category from '../View/TabBar/Category/Category'
import Main from '../View/TabBar/Main/Main'
import My from '../View/TabBar/My/My'
import OrderList from '../View/TabBar/OrderList/OrderList'
import OnlineDoctor from '../View/TabBar/OnlineDoctor/OnlineDoctor'
export default createBottomTabNavigator(
{
// 首頁:
one: {
screen: Main,
navigationOptions: () => {
return {
tabBarIcon: ({ tintColor }) => {
var soureImge
if (tintColor == '#CBCBCB') {
soureImge = 'main'
} else {
soureImge = 'mainActive'
}
return <Icon name={soureImge} size={26} color={tintColor} />
}
}
}
},
//分類:
two: {
screen: Category,
navigationOptions: {
tabBarIcon: ({ tintColor }) => {
var soureImge
if (tintColor == '#CBCBCB') {
soureImge = 'Category'
} else {
soureImge = 'CategoryActive'
}
return <Icon name={soureImge} size={26} color={tintColor} />
}
}
},
//問診:
three: {
screen: OnlineDoctor,
navigationOptions: {
tabBarIcon: ({ tintColor }) => {
var soureImge
if (tintColor == '#CBCBCB') {
soureImge = 'onLine'
} else {
soureImge = 'onLineActive'
}
return <Icon name={soureImge} size={48} color={tintColor} />
}
}
},
// 購物籃:
four: {
screen: OrderList,
navigationOptions: {
tabBarIcon: ({ tintColor }) => {
var soureImge
if (tintColor == '#CBCBCB') {
soureImge = 'OrderList'
} else {
soureImge = 'OrderListActive'
}
return <Icon name={soureImge} size={26} color={tintColor} />
}
}
},
//我的:
five: {
screen: My,
navigationOptions: () => {
return {
tabBarIcon: ({ tintColor }) => {
var soureImge
if (tintColor == '#CBCBCB') {
soureImge = 'My'
} else {
soureImge = 'MyActive'
}
return <Icon name={soureImge} size={26} color={tintColor} />
}
}
}
}
},
{
initialRouteName: 'one', // 初始化頁面
tabBarComponent: TabBar,
tabBarOptions: {
activeTintColor: '#F34C56',
inactiveTintColor: '#CBCBCB'
}
}
)
複製程式碼
工具函式
圖示沒有使用圖示庫,直接搞一個圖示庫比較得心應手
../Common/Icon.js
import React from 'react'
import { Image } from 'react-native'
import { TabIcon } from './Image'
const Icon = ({ name, style, size }) => {
const icon = TabIcon[name]
return (
<Image
source={icon}
style={[{ width: size, height: size }, style]}
/>
)
}
export default Icon
複製程式碼
而對於圖片則進行統一管理
../Common/Image.js
/**
* 所有的圖片資源都從這裡統一管理
*/
// 底部導航欄的圖片資源
export const TabIcon = {
main: require('..'),
mainActive: require('..'),
Category: require('..'),
CategoryActive: require('..'),
onLine: require('..'),
onLineActive: require('..'),
OrderList: require('..'),
OrderListActive: require('..'),
My: require('..'),
MyActive: require('..'),
}
複製程式碼
自定義底部導航器
萬事俱備,下面就是自定義底部導航器了,就和定義React
元件一樣
import React from 'react'
import {
View,
Text,
StyleSheet,
TouchableOpacity,
TouchableNativeFeedback,
Dimensions
} from 'react-native'
import posed from 'react-native-pose' // react-native 動畫庫
const Scaler = posed.View({ // 定義點選縮放
active: { scale: 1 },
inactive: { scale: 0.9 }
})
const TabBar = props => {
const {
renderIcon,
getLabelText,
activeTintColor,
inactiveTintColor,
onTabPress,
onTabLongPress,
getAccessibilityLabel,
navigation
} = props
const { routes, index: activeRouteIndex } = navigation.state
return (
<Scaler style={Styles.container}>
{routes.map((route, routeIndex) => {
const isRouteActive = routeIndex === activeRouteIndex
const tintColor = isRouteActive ? activeTintColor : inactiveTintColor
return (
<TouchableNativeFeedback
key={routeIndex}
style={Styles.tabButton}
onPress={() => {
onTabPress({ route })
}}
onLongPress={() => {
onTabLongPress({ route })
}}
accessibilityLabel={getAccessibilityLabel({ route })}
>
{route.key == 'three' ? ( // 對特殊圖示進行特殊處理
<Scaler
style={Styles.scalerOnline}
pose={isRouteActive ? 'active' : 'inactive'}
>
{renderIcon({ route, focused: isRouteActive, tintColor })}
<Text style={Styles.iconText}>{getLabelText({ route })}</Text>
</Scaler>
) : ( // 普通圖示普通處理
<Scaler
style={Styles.scaler}
pose={isRouteActive ? 'active' : 'inactive'}
>
{renderIcon({ route, focused: isRouteActive, tintColor })}
<Text style={Styles.iconText}>{getLabelText({ route })}</Text>
</Scaler>
)}
</TouchableNativeFeedback>
)
})}
</Scaler>
)
}
const Styles = StyleSheet.create({
container: {
flexDirection: 'row',
height: 53,
borderWidth: 1,
borderRadius: 1,
borderColor: '#EEEEEE',
shadowOffset: { width: 5, height: 10 },
shadowOpacity: 0.75,
elevation: 1
},
tabButton: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
spotLight: {
width: tabWidth,
height: '100%',
justifyContent: 'center',
alignItems: 'center'
},
spotLightInner: {
width: 48,
height: 48,
backgroundColor: '#ee0000',
borderRadius: 24
},
scaler: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
scalerOnline: {
flex: 1,
alignItems: 'center',
justifyContent: 'flex-end',
},
iconText: {
fontSize: 12,
lineHeight: 20
}
})
export default TabBar
複製程式碼
最後實現的效果就是
如果你也有這樣的需求,可以看看老外發布的那篇部落格
Let's Create A Custom Animated Tab Bar With React Native
最後: 快要過年了,祝大家新年快樂