【问题标题】:create a customized scrollable top Tab bar using react-navigation-tab?使用 react-navigation-tab 创建一个自定义的可滚动顶部标签栏?
【发布时间】:2020-06-19 21:16:13
【问题描述】:

我需要使用 react 导航标签和 tabBarComponent 创建一个自定义的可滚动顶部标签栏,而不使用任何其他第三方库。

const TopTabBar = createMaterialTopTabNavigator({
    Home: HomePage,
    Entertainment: EntertainmentNews,
    Business: BusinessStack,
    Music: MusicStack,
    Politics: PoliticsStack,
    Sports: SportsStack,
    Technology: TechnologyStack,
    WorldNews: WorldNewsStack
}, {
    tabBarComponent: (props) => <TopTabBarComponent {...props}/>
})

在这个带有标签栏的组件中,我可以创建顶部栏,但是在滑动屏幕时它不会滚动?

import React , { Component } from 'react'
import { Text, View, StyleSheet, FlatList, TouchableOpacity, Animated, Dimensions} from 'react-native'

interface Props {
    navigation?: any
}

interface State {
    //
}

export class TopTabBarComponent extends Component <Props, State>{
    flatListRef
    constructor(props: Props, state: State){
        super(props, state)
    }





    onPressItem = (index) => {
        const { navigation } = this.props
        navigation.navigate( this.props.navigation.state.routes[index].routeName )
        // this.onScrollIndex(index)
    }

    renderTopBar = (item, index) => {
        const routes = this.props.navigation.state.routes
        const activeIndex = this.props.navigation.state.index

            return (
                <TouchableOpacity style = {{
                     alignItems: 'center' ,  
                     height: 50, 
                     justifyContent: 'center', 
                     borderBottomWidth: activeIndex === index ?  2 : 0, 
                     borderColor: 'green', 
                     paddingHorizontal: 5
                     }} onPress = {() => this.onPressItem(index)}>  
                    <Text style = {{ fontSize: 20, color: 'blue'}}>{item.routeName}</Text>
                </TouchableOpacity>
            )
    }

    render() {
        // reactotron.log('this.props', this.props.navigation)
        console.warn('this.props.navigation.state.index', this.props.navigation.state.index)
        return(
            <View style = {{ marginHorizontal: 5}}>
                <FlatList
                    initialScrollIndex = { this.props.navigation.state.index }
                    ref = {(ref) => { this.flatListRef = ref}}
                    // style = {{ paddingHorizontal: 20}}
                    horizontal
                    showsHorizontalScrollIndicator = {false}
                    data = {this.props.navigation.state.routes}
                    renderItem = {({item , index}) => this.renderTopBar(item, index) }
                    ItemSeparatorComponent = {() => <View style = {{ paddingRight: 40}}/>}
                    />
            </View>
        )
    }

}

这是顶部标签栏组件代码?那么如何在屏幕滑动时让顶部选项卡自动滚动呢?

【问题讨论】:

    标签: react-native react-navigation react-native-flatlist react-navigation-v5 react-navigation-bottom-tab


    【解决方案1】:

    这是我为您的测试用例快速编辑的标签栏示例。

    function MyTabBar({ state, descriptors, navigation, position }) {
        const scrollViewRef = useRef(null)
    
        useEffect(() => {
            scrollViewRef.current.scrollTo({ x: state.index * 50, y: 0, animated: true })
        }, [state.index])
    
        return (
            <View style={styles.tabContainer}>
                <ScrollView ref={list => scrollViewRef.current = list} contentContainerStyle={{ flexDirection: 'row', alignItems: 'center'}} horizontal>
                    {state.routes.map((route, index) => {
                        const { options } = descriptors[route.key];
                        const label =
                            options.tabBarLabel !== undefined
                            ? options.tabBarLabel
                            : options.title !== undefined
                            ? options.title
                            : route.name;
    
                        const isFocused = state.index === index;
                        const onPress = () => {
                            const event = navigation.emit({
                            type: 'tabPress',
                            target: route.key,
                            });
    
                            if (!isFocused && !event.defaultPrevented) {
                            navigation.navigate(route.name);
                            }
                        };
    
                        const onLongPress = () => {
                            navigation.emit({
                            type: 'tabLongPress',
                            target: route.key,
                            });
                        };
    
                        let focusStyle = { }; //style object to append to the focussed tab
                        let tintColor = { };
                        let fontColor = { };
                        isFocused ? focusStyle = { backgroundColor: 'darkgray' } : focusStyle = { };
                        isFocused ? tintColor = { tintColor: 'black' } : tintColor = { tintColor: 'lightgray' }; // TODO: change this with proper fontColor codes
                        isFocused ? fontColor = { color: 'black' } : fontColor = { color: 'lightgray' };
                        //below controls the rendered tab
    
                            return (
                                <TouchableWithoutFeedback
                                    key={index}
                                    onPress={onPress}
                                    onLongPress={onLongPress}
                                    style={[styles.tabItem, focusStyle]}
                                >
                                        <View style={styles.tabIconContainer}>
                                            <LearnTabIcon title={route.name} color={tintColor} />
                                        </View>
                                        <Text style={[styles.labelStyle, fontColor]}>
                                            {label}
                                        </Text>
                                </TouchableWithoutFeedback>
                            );
                    })}
                </ScrollView>
    
                <View style={styles.tabBarIndicator}>
                    { state.routes.map((route, index) => {
                        const isFocused = state.index === index;
                        let selectedStyle = { };
                        isFocused ? selectedStyle = { backgroundColor: 'darkgray'} : { }; // TODO: change this coloring to actual color codes
                        return (
                            <View 
                                style={[styles.tabIndicators, selectedStyle]}
                                key={index}
                            >
                            </View>
                        );
                    })}
                </View>
            </View>
        );
      }
    

    我对所有内容都使用了功能组件,因此它看起来会有些不同,但在您的自定义选项卡栏中,在每个索引更改时抓取state.index,然后使用scrollToOffset 来控制滚动视图在屏幕上居中的位置。为了简单起见,我放了一个示例 50px 偏移比例。

    我也没有使用 TypeScript,但无论如何你似乎已经准备好了大部分样板。

    【讨论】:

    • 使用滚动视图之后的最后一个视图有什么用
    • 抱歉,这只是我的 TabBar 组件的一部分,用于显示状态指示器轨道。你不需要那个@rohitgarg
    • 当屏幕被滑动时,有什么方法可以为这个可滚动的标签栏设置动画吗?如果您知道任何方法,请帮助我。
    • scrollViewRef.current.scrollTo({ x: state.index * 50, y: 0, animated: true }) 使用animated: true 默认动画到指定的偏移量
    • 我想在滑动屏幕时显示动画。就像在屏幕上轻扫一点,我希望我的标签栏根据轻扫移动
    猜你喜欢
    • 1970-01-01
    • 2014-12-03
    • 2021-01-09
    • 1970-01-01
    • 2022-08-06
    • 1970-01-01
    • 2018-09-30
    • 2018-01-14
    • 1970-01-01
    相关资源
    最近更新 更多