создать настраиваемую прокручиваемую верхнюю панель вкладок с помощью response-navigation-tab?

Мне нужно создать настраиваемую прокручиваемую верхнюю панель вкладок с помощью вкладок навигации и 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>
        )
    }

}

Это код компонента верхней вкладки? Итак, как я могу сделать так, чтобы верхняя вкладка автоматически прокручивалась при смахивании экранов?




Ответы (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, чтобы контролировать, где прокрутка центрируется на экране. Для простоты я добавил образец шкалы смещения 50 пикселей.

Я также не использовал TypeScript, но у вас, похоже, уже есть готовая к работе большая часть кода.

person SKeney    schedule 19.06.2020
comment
какой смысл использовать последнее представление, которое находится после просмотра прокрутки - person rohit garg; 20.06.2020
comment
Извините, это было частью моего компонента TabBar, чтобы показать дорожку индикатора состояния. Тебе это не нужно @rohitgarg - person SKeney; 20.06.2020
comment
Есть ли способ оживить эту прокручиваемую панель вкладок при смахивании по экрану? Если вы знаете какой-либо способ, пожалуйста, помогите мне. - person rohit garg; 21.06.2020
comment
scrollViewRef.current.scrollTo({ x: state.index * 50, y: 0, animated: true }) при использовании animated: true по умолчанию будет анимироваться с заданным смещением. - person SKeney; 21.06.2020
comment
Я хочу показывать анимацию, когда провожу пальцем по экрану. Например, если провести немного по экрану, я хочу, чтобы моя панель вкладок двигалась в соответствии с этим смахиванием - person rohit garg; 21.06.2020
comment
Есть ли какое-либо событие, которое срабатывает при считывании в createMaterialTopTabNavigator - person rohit garg; 21.06.2020
comment
Я использовал materialTopTabNavigator с указанным выше настраиваемым компонентом навигатора вкладок, и по умолчанию он имеет возможность прокрутки. - person SKeney; 21.06.2020
comment
Моя панель вкладок также прокручивается. Но он прокручивается после того, как страница полностью перенесена на другой экран. Я хочу показать анимацию при смахивании. Если я проведу пальцем по экрану на 10%, я хочу, чтобы моя верхняя панель вкладок прокручивалась на 10%. - person rohit garg; 21.06.2020
comment
Вам нужно будет настроить какую-то собственную анимацию. Я бы заглянул в Animated библиотеку из react-native и / или react-native-reanimated - person SKeney; 21.06.2020