PedroBern / react-native-collapsible-tab-view

A cross-platform Collapsible Tab View component for React Native
MIT License
897 stars 175 forks source link

render custom tabbar #427

Open Jamal-ReachFirst opened 4 months ago

Jamal-ReachFirst commented 4 months ago

Existing code:

import React, { useRef, useState } from 'react';
import { View, StyleSheet, Animated,Text, TouchableOpacity } from 'react-native';
import LeavesHistory from './leavesHistory';
import PendingLeaves from './pendingLeaves';
import ApprovedLeaves from './approvedLeaves';
import { Layout } from 'constants/constants';
import { RFValue } from 'react-native-responsive-fontsize';
import { StackScreenProps } from '@react-navigation/stack';
import { MainStackParamList } from 'types/navigationTypes';
import { MaterialTopTabBarProps } from '@react-navigation/material-top-tabs';
import { Tabs, MaterialTabBar, MaterialTabItem, TabBarProps, TabProps } from 'react-native-collapsible-tab-view';
import { MaterialTabBarProps } from 'react-native-collapsible-tab-view';

const Header = ({}) => {
    //..........
}

type Props = StackScreenProps<MainStackParamList, 'App'>;

const App: React.FC<Props> = ({route, navigation}) => {
    return (
        <Tabs.Container
            containerStyle={styles.collapsibleContainer}
            initialTabName='History'
            renderHeader={() => <Header />}
            snapThreshold={.5}
            headerContainerStyle={styles.headerContainerStyle}
            renderTabBar={props => (
                <MaterialTabBar
                  {...props}
                  contentContainerStyle={styles.containerStyle}
                  tabStyle={styles.tabStyle}
                  inactiveColor={Layout.colors.black}
                  activeColor={Layout.colors.appColor}
                  labelStyle={styles.tabBarLabelStyle}
                  indicatorStyle={styles.tabbarIndicatorStyle}
                  TabItemComponent={props => (
                    <MaterialTabItem
                      {...props}
                      pressColor={Layout.colors.appColor}
                      labelStyle={props.labelStyle}
                      label={props.label}
                    />
                  )}
                />
            )}
        >
        <Tabs.Tab name="History" label={`History`}>
            <LeavesHistory />
        </Tabs.Tab>
        <Tabs.Tab name="History" label={`History`}>
            <PendingLeaves />
        </Tabs.Tab>
        <Tabs.Tab name="Approved" label={`Approved`}>
            <ApprovedLeaves />
        </Tabs.Tab>
        </Tabs.Container>
    )
}

const styles = StyleSheet.create({
  //......
})

export default App;

Instead of default material tabbar I want to render completely custom tabbar like we use in react-navigation material tabbar

Example:

import { Animated, View, TouchableOpacity } from 'react-native';
function MyTabBar({ state, descriptors, navigation, position }) {
  return (
    <View style={{ flexDirection: 'row' }}>
      {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,
            canPreventDefault: true,
          });

          if (!isFocused && !event.defaultPrevented) {
            navigation.navigate(route.name, route.params);
          }
        };

        const onLongPress = () => {
          navigation.emit({
            type: 'tabLongPress',
            target: route.key,
          });
        };

        const inputRange = state.routes.map((_, i) => i);
        const opacity = position.interpolate({
          inputRange,
          outputRange: inputRange.map(i => (i === index ? 1 : 0)),
        });

        return (
          <TouchableOpacity
            accessibilityRole="button"
            accessibilityState={isFocused ? { selected: true } : {}}
            accessibilityLabel={options.tabBarAccessibilityLabel}
            testID={options.tabBarTestID}
            onPress={onPress}
            onLongPress={onLongPress}
            style={{ flex: 1 }}
          >
            <Animated.Text style={{ opacity }}>
              {label}
            </Animated.Text>
          </TouchableOpacity>
        );
      })}
    </View>
  );
}

<Tabs.Container
            containerStyle={styles.collapsibleContainer}
            initialTabName='History'
            renderHeader={() => <Header />}
            snapThreshold={.5}
            headerContainerStyle={styles.headerContainerStyle}
            renderTabBar={props => <MyTabar {...props} />  // I want to implement this
        >
        <Tabs.Tab name="History" label={`History`}>
            <LeavesHistory />
        </Tabs.Tab>
        <Tabs.Tab name="History" label={`History`}>
            <PendingLeaves />
        </Tabs.Tab>
        <Tabs.Tab name="Approved" label={`Approved`}>
            <ApprovedLeaves />
        </Tabs.Tab>
        </Tabs.Container>
    )
}
coofzilla commented 3 months ago

what happens if you do this line:

renderTabBar={props => <MyTabar {...props} /> 

I ask because I want to do the same thing, was wondering if throws an error and how much work this would take 🤔

the main reason is because of this issue https://github.com/react-navigation/react-navigation/issues/11047. I want to keep using this library; but, it seems like the underlying tab navigator has a delay bug.