在某些情況下,預設的react-navigation的tab bar無法滿足開發者的要求。這個時候就需要自定義一個tab bar了。本文就基於react-navigtion v2來演示如何實現一個自定義tab bar。
這裡主要處理的是再android裡,當介面中有輸入框,喚起軟鍵盤的時候位於底部的tab bar也會浮動到鍵盤的上方。這顯然不是我們需要的。所以,需要用自定義的tab bar來解決這個問題。
Keyboard模組
問題是,有鍵盤的時候tabbar會被頂起來,鍵盤消失的時候tab bar也會恢復到正常的位置。 那麼處理這個問題的最好辦法就是,當鍵盤喚起的時候讓tab bar不可見,當鍵盤消失當時候再讓tab bar顯示出來。
這就需要用到Keyboard
了。
import { Keyboard } from 'react-native';
複製程式碼
Keyboard
模組專門用來處理鍵盤事件。通過這個模組我們就可以得知鍵盤要喚起,還是要消失。
import React, { Component } from 'react';
import { Keyboard, TextInput } from 'react-native';
class Example extends Component {
componentDidMount () {
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._keyboardDidShow);
this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this._keyboardDidHide);
}
componentWillUnmount () {
this.keyboardDidShowListener.remove();
this.keyboardDidHideListener.remove();
}
_keyboardDidShow () {
alert('Keyboard Shown');
}
_keyboardDidHide () {
alert('Keyboard Hidden');
}
render() {
return (
<TextInput
onSubmitEditing={Keyboard.dismiss}
/>
);
}
}
複製程式碼
在componentDidMount
的時候繫結鍵盤的兩個事件:
- keyboardDidShow, 鍵盤即將出現
- keyboardDidHide, 鍵盤即將隱藏
通過Keyboard
模組繫結了這兩個事件之後就可以在繫結的回撥裡讓tab bar顯示和隱藏了。
自定義tab bar
在react-navigation v2中,要實現自定義的tab bar非常簡單:
import {
createBottomTabNavigator,
createStackNavigator,
} from 'react-navigation';
class DetailsScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Details!</Text>
</View>
);
}
}
class HomeScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
{/* other code from before here */}
<Button
title="Go to Details"
onPress={() => this.props.navigation.navigate('Details')}
/>
</View>
);
}
}
class SettingsScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
{/* other code from before here */}
<Button
title="Go to Details"
onPress={() => this.props.navigation.navigate('Details')}
/>
</View>
);
}
}
const HomeStack = createStackNavigator({
Home: HomeScreen,
Details: DetailsScreen,
});
const SettingsStack = createStackNavigator({
Settings: SettingsScreen,
Details: DetailsScreen,
});
export default createBottomTabNavigator(
{
Home: HomeStack,
Settings: SettingsStack,
},
{
/* Other configuration remains unchanged */
}
);
複製程式碼
這裡建立了一個每一個tab項都是一個stack navigator的tab bar。這裡當然使用的是預設的tab bar。方法createBottomTabNavigator
會返回一個在底部的tab bar。
我們來新增一個自定義的tab bar:
// ...略...
export default createBottomTabNavigator(
{
Home: HomeStack,
Settings: SettingsStack,
},
{
tabBarComponent: CustomTabComponent,
}
);
複製程式碼
CustomTabView
就是自定義的tab bar。
當程式執行起來以後,react-navigation會把tab bar所需要的內容(tab的label、icon、navigate到什麼地方等都通過prop的方式傳進來)。但是,我們這裡並不打算做其他的定製,所以可以通過一個簡單的方式把這些tab bar的item都繪製出來。
這就需要用到react-navigation-tabs
。這個包提供了tab bar的所有預設的實現。包括上面提到的props的解析都有。看下程式碼:
import React from 'react';
import { Keyboard } from 'react-native';
import { BottomTabBar } from 'react-navigation-tabs';
type Prop = {};
type State = { visible: boolean };
export default class CustomTabComponent extends React.Component<Prop, State> {
state: State = { visible: true };
componentDidMount() {
this.kbShowListener = Keyboard.addListener('keyboardDidShow', this.keyboardWillShow);
this.kbHideListener = Keyboard.addListener('keyboardDidHide', this.keyboardWillHide);
}
keyboardWillShow = () => {
console.log('keyboardwillshow');
this.setState({ visible: false });
};
keyboardWillHide = () => {
console.log('keyboardwillhide');
this.setState({ visible: true });
};
componentWillUnmount() {
this.kbShowListener.remove();
this.kbHideListener.remove();
}
render() {
return this.state.visible && <BottomTabBar {...this.props} />;
}
}
複製程式碼
在keyboard顯示的時候隱藏tab bar:
keyboardWillShow = () => {
this.setState({ visible: false });
};
複製程式碼
在鍵盤隱藏的時候顯示tab bar:
keyboardWillHide = () => {
this.setState({ visible: true });
};
複製程式碼
顯示出全部的tab item:
render() {
return this.state.visible && <BottomTabBar {...this.props} />;
}
複製程式碼
最後
處理軟鍵盤導致的tab bar上浮這個問題就完美解決了。其他的很多時候軟鍵盤的出現都會導致類似的問題。基本上都可以通過繫結Keyboard
模組的方式來解決。
對於tab bar本身有定製需要的,則可以通過自定義tab bar實現。正好本文解決了軟鍵盤對tab bar的影響,也開是了一個解決自定義tab bar的門。有深度定義tab bar的同學,就需要解析從react-navigation傳過來的props了。