Uhney
Uhney

Reputation: 473

React Native - Changing the indicator width according to tab bar text width (react-native-tab-view)

I am using react-native-tab-view, and trying to change the indicator width. I would like indicator width to be the same with the tab text. But What I did is just the default. I have tried in many ways, but always it gave me the wrong result. The tab bar should be scrollable horizontally as well. Could you check which part I should change?

This is the expected result : enter image description here

ShowAllIndex Code :

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: colors.dark,
  },
});

const ShowAllIndex = () => {
  const { seller } = useSelector((s) => s.auth, shallowEqual);
  const [routes] = useState([
    { key: 'best', title: 'BEST' },
    { key: 'jacket', title: '아우터' },
    { key: 'pants', title: '바지' },
    { key: 'skirts', title: '스커트' },
    { key: 'topClothe', title: '원피스' },
    { key: 'one', title: '바지' },
    { key: 'two', title: '스커트' },
    { key: 'three', title: '상의' },
  ]);

  const renderScene = SceneMap({
    best: ShowAllMainRoutes,
    jacket: JacketRoutes,
    pants: PantsRoutes,
    skirts: SkirtsRoutes,
    topClothe: TopClotheRoutes,
    one: ShowAllMainRoutes,
    two: JacketRoutes,
    three: PantsRoutes,
  });

  return (
    <ScrollView style={[styles.container, { marginTop: Global() }]}>
      <CustomTabView
        routes={routes}
        renderScene={renderScene}
        scrollEnabled={true}
        tabStyle={{ width: 'auto' }}
        showAll={true}
      />
    </ScrollView>
  );
};

export default ShowAllIndex;

CustomTabView code :


const initialLayout = { width: Dimensions.get('window').width };

const CustomTabView = ({
  routes,
  renderScene,
  numberOfTabs,
  indicatorWidth,
  scrollEnabled = false,
  tabStyle,
  showAll,
  indicatorStyle,
}) => {
  const [index, setIndex] = useState(0);

  const renderTabBar = (props) => (
    <TabBar
      {...props}
      scrollEnabled={scrollEnabled}
      indicatorStyle={[
        indicatorStyle,
        {
          backgroundColor: colors.barbie_pink,
          height: 2.5,
          bottom: -1,
        },
      ]}
      style={[styles.tabBar]}
      renderLabel={({ route, focused }) => {
        return (
          <Text
            style={[styles.label, focused ? styles.activeLabel : styles.label]}
          >
            {route.title}
          </Text>
        );
      }}
      tabStyle={tabStyle}
    />
  );

  return (
    <TabView
      navigationState={{ index, routes }}
      renderScene={renderScene}
      renderTabBar={renderTabBar}
      onIndexChange={setIndex}
      initialLayout={initialLayout}
      style={[styles.container]}
    />
  );
};

const styles = StyleSheet.create({
  container: {
    backgroundColor: colors.dark,
  },
  scene: {
    flex: 1,
    marginTop: 5,
  },
  tabBar: {
    backgroundColor: 'transparent',
    shadowOpacity: 0,
    elevation: 0,
    borderBottomWidth: 0.5,
    borderColor: colors.very_light_pink_two,
    marginBottom: 5,
  },
  label: {
    color: colors.very_light_pink_four,
    fontSize: 14,
    lineHeight: 20.8,
    fontFamily: 'NotoSansCJKkr-Regular',
    letterSpacing: -0.35,
  },
  activeLabel: {
    color: colors.barbie_pink,
  },
});

Thank you for answers!

Upvotes: 4

Views: 9776

Answers (5)

             //use a TabViewScreen to design how you want the tab to look

    const TabViewScreen = ( props ) =>
    {
        const themeContext = React.useContext( ThemeContext );
        const theme = color; // Assuming color is your theme object from color.json


        //use a renderTabBar to design how you want each button  to look

        const renderTabBar = ( props ) => (
            <TabBar
                { ...props }
// Hide the active indicator
                indicatorStyle={ { backgroundColor: 'transparent' } }
// Make the TabBar transparent 
                style={ { backgroundColor: 'transparent' } } 
// use the rendaer label prop to design how you want the label to //look. for me i have a predefind button called BigButtons, but //you can use the normal view and style it the way you want. just //remember to make it look like a function and pass what you need. //here i am passing focussed and route.
                renderLabel={ ( { route, focused } ) => (
                    <BigButtons
                        width={ 100 }
                        title={ route.title }
                        isEnabled={ focused } // Use focused state to determine if the tab is active
                        checkUser={ () => props.jumpTo( route.key ) }
                        backgroundColor={ focused ? "red" : "yellow" }// Handle tab press
                    />
                ) }
            />
        );
    
        const [ index, setIndex ] = React.useState( 0 );
        const [ routes ] = React.useState( [
            { key: 'hotel', title: 'Hotel' },
            { key: 'hall', title: 'Hall' },
            { key: 'home', title: 'Home' },
        ] );
    
        return (
            <>
                <TabView
                    navigationState={ { index, routes } }
                    renderScene={ renderScene }
                    onIndexChange={ setIndex }
                    renderTabBar={ renderTabBar }
                />
            </>
        );
    };
    
    export default TabViewScreen;

Upvotes: -1

Wiharlley Yitzhak
Wiharlley Yitzhak

Reputation: 378

Just add:

screenOptions={{
                tabBarScrollEnabled: true,
                tabBarIndicatorContainerStyle: { marginBottom: 60 }, <---------
            }}

the position will automatically adjust to the top even if the margin is 2000 (for example)

Upvotes: -1

Mostav
Mostav

Reputation: 2612

Check this solution:

const TAB_MARGIN = 24;

<TabBar
...
scrollEnabled
renderIndicator={indicatorProps => {
          const width = indicatorProps.getTabWidth(this.state.index) - TAB_MARGIN
          return <TabBarIndicator {...indicatorProps} width={width} />
}}
indicatorStyle={{
      backgroundColor: '#333',
      height: 4,
      left: TAB_MARGIN / 2,
 }}
...
/>

Upvotes: 3

Erick Gutierrez
Erick Gutierrez

Reputation: 516

You can do the following:

<TabBar
  scrollEnabled                 //add this line to make it scrollable
  tabStyle={{width: 100}}      //and this one to change the tab width
/>

Upvotes: 1

Lawson
Lawson

Reputation: 36

I think the prop indicatorStyle in TabBar that can resolves you problem.

Upvotes: 0

Related Questions