在本章中,我们将学习如何为顶部标签导航器添加自定义渐变背景,并实现根据滚动位置动态改变背景色的效果。
一、隐藏首页标题栏
我们将在首页标签页时隐藏顶部标题栏。
1. 更新 HomeTabs.tsx
在 navigator/HomeTabs.tsx 中,使用 headerTransparent 属性隐藏标题栏:
<Tab.Navigator
tabBar={(props) => <TopTabBarWrapper {...props} />}
sceneContainerStyle={styles.sceneContainer}
>
...
</Tab.Navigator>;
const styles = StyleSheet.create({
sceneContainer: {
backgroundColor: 'transparent',
},
});
2. 更新导航逻辑
在 src/navigator/index.tsx 中,设置标题栏的显示状态:
function getHeaderTitle(routeName: string) {
switch (routeName) {
case 'HomeTabs':
return '';
case 'Listen':
return '我听';
case 'Found':
return '发现';
case 'Account':
return '账户';
default:
return '首页';
}
}
class App extends React.Component {
setOptions = () => {
const { navigation, route } = this.props;
const routeName = route.state
? route.state.routes[route.state.index].name
: route.params
? route.params.screen
: 'HomeTabs';
navigation.setOptions({
headerTitle: getHeaderTitle(routeName),
headerTransparent: routeName === 'HomeTabs',
});
};
componentDidMount() {
this.setOptions();
}
componentDidUpdate() {
this.setOptions();
}
render() {
return (
<Navigator />
);
}
}
二、自定义顶部标签栏
1. 引入 MaterialTopTabBar
在 pages/views/TopTabBarWrapper.tsx 中,自定义顶部标签栏:
import React from 'react';
import { View, Text, StyleSheet, TouchableOpacity, Platform } from 'react-native';
import { MaterialTopTabBarProps } from '@react-navigation/material-top-tabs';
import LinearGradient from 'react-native-linear-gradient';
import { getStatusBarHeight } from 'react-native-iphone-x-helper';
interface IProps extends MaterialTopTabBarProps {
gradientVisible: boolean;
linearColors: string[];
}
const TopTabBarWrapper: React.FC<IProps> = (props) => {
const { gradientVisible, linearColors } = props;
return (
<View style={styles.container}>
<LinearGradient
colors={gradientVisible ? linearColors : ['#fff', '#fff']}
style={styles.gradient}
/>
<View style={styles.topTabBarView}>
<MaterialTopTabBar {...props} labelStyle={styles.labelStyle} />
<TouchableOpacity style={styles.categoryBtn}>
<Text style={styles.text}>分类</Text>
</TouchableOpacity>
</View>
<View style={styles.bottom}>
<TouchableOpacity style={styles.searchBtn}>
<Text style={styles.text}>搜索按钮</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.historyBtn}>
<Text style={styles.text}>历史记录</Text>
</TouchableOpacity>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
paddingTop: getStatusBarHeight(),
},
gradient: {
...StyleSheet.absoluteFillObject,
height: 260,
},
topTabBarView: {
flexDirection: 'row',
alignItems: 'center',
},
labelStyle: {
fontWeight: 'bold',
},
categoryBtn: {
paddingHorizontal: 8,
borderLeftColor: '#eee',
borderLeftWidth: StyleSheet.hairlineWidth,
},
bottom: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
paddingVertical: 7,
paddingHorizontal: 15,
},
searchBtn: {
flex: 1,
justifyContent: 'center',
paddingLeft: 12,
height: 30,
borderRadius: 15,
backgroundColor: 'rgba(0, 0, 0, 0.1)',
},
historyBtn: {
marginLeft: 24,
},
text: {
color: '#fff',
},
});
export default TopTabBarWrapper;
2. 集成渐变背景
在 pages/Home/Carousel.tsx 中,将轮播图切换的索引保存到 Dva 仓库:
export interface HomeModelState {
carousels: ICarousel[];
activeCarouselIndex: number;
}
export interface HomeModelType {
namespace: 'home';
state: HomeModelState;
effects: {
fetchCarousels: Effect;
};
reducers: {
setState: Reducer<HomeModelState>;
};
}
const homeModel: HomeModelType = {
namespace: 'home',
state: {
carousels: [],
activeCarouselIndex: 0,
},
effects: {
*fetchCarousels({ payload }, { call, put }) {
const { data } = yield call(axios.get, CAROUSEL_URL);
yield put({
type: 'setState',
payload: {
carousels: data,
activeCarouselIndex: 0,
},
});
},
},
reducers: {
setState(state, { payload }) {
return {
...state,
...payload,
};
},
},
};
在 pages/Home/Carousel.tsx 中,将轮播图的索引保存到 Dva 仓库:
<Carousel
data={carouselList}
renderItem={this.renderItem}
sliderWidth={sliderWidth}
itemWidth={itemWidth}
hasParallaxImages
loop
autoPlay
onSnapToItem={(index) => this.setState({ activeCarouselIndex: index })}
/>
3. 动态渐变背景
在 pages/views/TopTabBarWrapper.tsx 中,根据轮播图的索引动态更新渐变背景:
const TopTabBarWrapper: React.FC<IProps> = (props) => {
const { gradientVisible, linearColors } = props;
return (
<View style={styles.container}>
<LinearGradient
colors={gradientVisible ? linearColors : ['#fff', '#fff']}
style={styles.gradient}
/>
...
</View>
);
};
三、总结
在本章中,我们为顶部标签导航器添加了自定义渐变背景,并实现了根据滚动位置动态改变背景色的效果。这包括以下步骤:
- 隐藏首页标题栏。
- 自定义顶部标签栏,添加渐变背景和额外的交互按钮。
- 使用 Dva 管理状态,根据轮播图的切换动态更新渐变颜色。
- 根据滚动位置动态显示或隐藏渐变背景。
下一章,我们将继续学习更多高级功能。