React-native-tab-view: How can I use renderIndicator, please help

Created on 18 Jul 2019  ·  9Comments  ·  Source: satya164/react-native-tab-view

I'm trying to custom indicator like the picture below but I have a problem is the indicator lose animation and it doesn't work when I press on the second tab :'( , what should I do now ? please help

66909187_1357794867718535_6060456621413236736_n

bug

Most helpful comment

renderIndicator is a prop on TabBar. You're passing it to TabView

All 9 comments

@vinhnvfabbi you can custom renderIndicator to make exactly the same what you want.
If you need a tab width, you can use this function to get it getTabWidth

Example: https://github.com/react-native-community/react-native-tab-view/blob/master/example/src/CustomIndicatorExample.tsx#L162

I'm trying to custom indicator like the picture below but I have a problem is the indicator lose animation and it doesn't work when I press on the second tab :'( , what should I do now ? please help

66909187_1357794867718535_6060456621413236736_n

can you share your code,really like it

I'm trying to custom indicator like the picture below but I have a problem is the indicator lose animation and it doesn't work when I press on the second tab :'( , what should I do now ? please help
66909187_1357794867718535_6060456621413236736_n

can you share your code,really like it

you can check this https://github.com/BunHouth/RNTabExample/blob/feature/indicator-gradient/Home.js#L41

it similar to that images

I'm trying to custom indicator like the picture below but I have a problem is the indicator lose animation and it doesn't work when I press on the second tab :'( , what should I do now ? please help
66909187_1357794867718535_6060456621413236736_n

can you share your code,really like it

you can check this https://github.com/BunHouth/RNTabExample/blob/feature/indicator-gradient/Home.js#L41

it similar to that images

thanks very much!

I'm trying to custom indicator like the picture below but I have a problem is the indicator lose animation and it doesn't work when I press on the second tab :'( , what should I do now ? please help
66909187_1357794867718535_6060456621413236736_n

can you share your code,really like it

you can check this https://github.com/BunHouth/RNTabExample/blob/feature/indicator-gradient/Home.js#L41

it similar to that images

import React, { Component, useEffect, useRef } from 'react';
import { StyleSheet, Dimensions, Animated, Text, View } from 'react-native';
import { TabView, SceneMap, TabBar } from 'react-native-tab-view';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import LinearGradient from "react-native-linear-gradient";
import MyApplication from '../../components/MyApplication';
import Shop from '../../components/Shop';
import _ from "lodash";
import { ButtonGroup } from 'react-native-elements'

const styles = StyleSheet.create({
tabView: {
backgroundColor: 'white',
},
tabbar: {
backgroundColor: 'white',
overflow: 'hidden',
// height: 50,
marginBottom: 10,
elevation: 0,
shadowColor: 'white',
shadowOpacity: 0,
shadowRadius: StyleSheet.hairlineWidth,
shadowOffset: {
height: 0,
width: 0,
},
marginLeft: 10
},
tabStyle: {
flexDirection: 'row',
color: '#263238',
width: 'auto',
// borderWidth: 1,
// borderColor: 'black',
// borderRadius: 50,
// paddingLeft: 20,
// paddingRight: 20,
},
labelStyle: {
color: '#263238',
fontSize: 16,
},
// indicatorStyle: {
// backgroundColor: 'black'
// },
fn: {
position: 'absolute',
right: 0,
top: 0,
flexDirection: 'row'
}
});

const TabIndicator = props => {
const { width, tabWidth, index } = props;
const marginLeftRef = useRef(new Animated.Value(index ? tabWidth : 0))
.current;
useEffect(() => {
Animated.timing(marginLeftRef, {
toValue: tabWidth,
duration: 400
}).start();
}, [tabWidth]);

return (
    <Animated.View
        style={{
            justifyContent: "flex-end",
            alignItems: "center",
            flex: 1,
            width: width,
            marginLeft: marginLeftRef
        }}
    >
        <LinearGradient
            start={{ x: 0, y: 0 }}
            end={{ x: 1, y: 0 }}
            colors={["#50b0ea", "#80a2ed", "#a797f2", "#e981f4"]}
            style={{ height: 2, width: "100%" }}
        />
    </Animated.View>
);

}

class Application extends Component {

constructor(props) {
    super(props)
    this.state = {
        index: 0,
        routes: [
            {
                key: 'MyApplication',
                title: 'My App',
                icon: 'view-compact-outline',
                color: [244, 67, 54]
            },
            {
                key: 'Shop',
                title: 'Store',
                icon: 'store',
                color: [244, 67, 54]
            },
        ],
    }
}

renderIndicator = ({ getTabWidth }) => {
    const tabWidth = _.sum([...Array(this.state.index).keys()].map(i => getTabWidth(i)));

    return (
        <TabIndicator
            width={getTabWidth(this.state.index)}
            tabWidth={tabWidth}
            index={this.state.index}
        />
    );
}


renderScene = SceneMap({
    MyApplication,
    Shop
});

renderIcon = ({ route, color, size }) => (
    <Icon
        type='material-community'
        name={route.icon}
        size={25}
        color='#263238'
    />
);

renderLabel = ({ route, focused, color }) => (
    <Text
        style={styles.labelStyle}>
        {route.title}
    </Text>
)

renderTabBar = props => (
    <TabBar
        {...props}
        renderIcon={this.renderIcon}
        style={styles.tabbar}
        labelStyle={styles.labelStyle}
        tabStyle={styles.tabStyle}
        indicatorStyle={styles.indicatorStyle}
    />
);

render() {
    const { selectedIndex } = this.state
    return (
        <TabView
            style={styles.tabView}
            lazy
            navigationState={this.state}
            renderScene={this.renderScene}
            renderTabBar={this.renderTabBar}
            renderIndicator={this.renderIndicator}
            onIndexChange={index => this.setState({ index })}
        // initialLayout={{ width: Dimensions.get('window').width }}
        />
    );
}

}

export default Application;

not work ,is any mistake?

I'm trying to custom indicator like the picture below but I have a problem is the indicator lose animation and it doesn't work when I press on the second tab :'( , what should I do now ? please help
66909187_1357794867718535_6060456621413236736_n

can you share your code,really like it

you can check this https://github.com/BunHouth/RNTabExample/blob/feature/indicator-gradient/Home.js#L41
it similar to that images

import React, { Component, useEffect, useRef } from 'react';
import { StyleSheet, Dimensions, Animated, Text, View } from 'react-native';
import { TabView, SceneMap, TabBar } from 'react-native-tab-view';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import LinearGradient from "react-native-linear-gradient";
import MyApplication from '../../components/MyApplication';
import Shop from '../../components/Shop';
import _ from "lodash";
import { ButtonGroup } from 'react-native-elements'

const styles = StyleSheet.create({
tabView: {
backgroundColor: 'white',
},
tabbar: {
backgroundColor: 'white',
overflow: 'hidden',
// height: 50,
marginBottom: 10,
elevation: 0,
shadowColor: 'white',
shadowOpacity: 0,
shadowRadius: StyleSheet.hairlineWidth,
shadowOffset: {
height: 0,
width: 0,
},
marginLeft: 10
},
tabStyle: {
flexDirection: 'row',
color: '#263238',
width: 'auto',
// borderWidth: 1,
// borderColor: 'black',
// borderRadius: 50,
// paddingLeft: 20,
// paddingRight: 20,
},
labelStyle: {
color: '#263238',
fontSize: 16,
},
// indicatorStyle: {
// backgroundColor: 'black'
// },
fn: {
position: 'absolute',
right: 0,
top: 0,
flexDirection: 'row'
}
});

const TabIndicator = props => {
const { width, tabWidth, index } = props;
const marginLeftRef = useRef(new Animated.Value(index ? tabWidth : 0))
.current;
useEffect(() => {
Animated.timing(marginLeftRef, {
toValue: tabWidth,
duration: 400
}).start();
}, [tabWidth]);

return (
    <Animated.View
        style={{
            justifyContent: "flex-end",
            alignItems: "center",
            flex: 1,
            width: width,
            marginLeft: marginLeftRef
        }}
    >
        <LinearGradient
            start={{ x: 0, y: 0 }}
            end={{ x: 1, y: 0 }}
            colors={["#50b0ea", "#80a2ed", "#a797f2", "#e981f4"]}
            style={{ height: 2, width: "100%" }}
        />
    </Animated.View>
);

}

class Application extends Component {

constructor(props) {
    super(props)
    this.state = {
        index: 0,
        routes: [
            {
                key: 'MyApplication',
                title: 'My App',
                icon: 'view-compact-outline',
                color: [244, 67, 54]
            },
            {
                key: 'Shop',
                title: 'Store',
                icon: 'store',
                color: [244, 67, 54]
            },
        ],
    }
}

renderIndicator = ({ getTabWidth }) => {
    const tabWidth = _.sum([...Array(this.state.index).keys()].map(i => getTabWidth(i)));

    return (
        <TabIndicator
            width={getTabWidth(this.state.index)}
            tabWidth={tabWidth}
            index={this.state.index}
        />
    );
}


renderScene = SceneMap({
    MyApplication,
    Shop
});

renderIcon = ({ route, color, size }) => (
    <Icon
        type='material-community'
        name={route.icon}
        size={25}
        color='#263238'
    />
);

renderLabel = ({ route, focused, color }) => (
    <Text
        style={styles.labelStyle}>
        {route.title}
    </Text>
)

renderTabBar = props => (
    <TabBar
        {...props}
        renderIcon={this.renderIcon}
        style={styles.tabbar}
        labelStyle={styles.labelStyle}
        tabStyle={styles.tabStyle}
        indicatorStyle={styles.indicatorStyle}
    />
);

render() {
    const { selectedIndex } = this.state
    return (
        <TabView
            style={styles.tabView}
            lazy
            navigationState={this.state}
            renderScene={this.renderScene}
            renderTabBar={this.renderTabBar}
            renderIndicator={this.renderIndicator}
            onIndexChange={index => this.setState({ index })}
        // initialLayout={{ width: Dimensions.get('window').width }}
        />
    );
}

}

export default Application;

not work ,is any mistake?

can you just show the error? did you able to run my example?

I'm trying to custom indicator like the picture below but I have a problem is the indicator lose animation and it doesn't work when I press on the second tab :'( , what should I do now ? please help
66909187_1357794867718535_6060456621413236736_n

can you share your code,really like it

you can check this https://github.com/BunHouth/RNTabExample/blob/feature/indicator-gradient/Home.js#L41
it similar to that images

import React, { Component, useEffect, useRef } from 'react';
import { StyleSheet, Dimensions, Animated, Text, View } from 'react-native';
import { TabView, SceneMap, TabBar } from 'react-native-tab-view';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import LinearGradient from "react-native-linear-gradient";
import MyApplication from '../../components/MyApplication';
import Shop from '../../components/Shop';
import _ from "lodash";
import { ButtonGroup } from 'react-native-elements'
const styles = StyleSheet.create({
tabView: {
backgroundColor: 'white',
},
tabbar: {
backgroundColor: 'white',
overflow: 'hidden',
// height: 50,
marginBottom: 10,
elevation: 0,
shadowColor: 'white',
shadowOpacity: 0,
shadowRadius: StyleSheet.hairlineWidth,
shadowOffset: {
height: 0,
width: 0,
},
marginLeft: 10
},
tabStyle: {
flexDirection: 'row',
color: '#263238',
width: 'auto',
// borderWidth: 1,
// borderColor: 'black',
// borderRadius: 50,
// paddingLeft: 20,
// paddingRight: 20,
},
labelStyle: {
color: '#263238',
fontSize: 16,
},
// indicatorStyle: {
// backgroundColor: 'black'
// },
fn: {
position: 'absolute',
right: 0,
top: 0,
flexDirection: 'row'
}
});
const TabIndicator = props => {
const { width, tabWidth, index } = props;
const marginLeftRef = useRef(new Animated.Value(index ? tabWidth : 0))
.current;
useEffect(() => {
Animated.timing(marginLeftRef, {
toValue: tabWidth,
duration: 400
}).start();
}, [tabWidth]);

return (
    <Animated.View
        style={{
            justifyContent: "flex-end",
            alignItems: "center",
            flex: 1,
            width: width,
            marginLeft: marginLeftRef
        }}
    >
        <LinearGradient
            start={{ x: 0, y: 0 }}
            end={{ x: 1, y: 0 }}
            colors={["#50b0ea", "#80a2ed", "#a797f2", "#e981f4"]}
            style={{ height: 2, width: "100%" }}
        />
    </Animated.View>
);

}
class Application extends Component {

constructor(props) {
    super(props)
    this.state = {
        index: 0,
        routes: [
            {
                key: 'MyApplication',
                title: 'My App',
                icon: 'view-compact-outline',
                color: [244, 67, 54]
            },
            {
                key: 'Shop',
                title: 'Store',
                icon: 'store',
                color: [244, 67, 54]
            },
        ],
    }
}

renderIndicator = ({ getTabWidth }) => {
    const tabWidth = _.sum([...Array(this.state.index).keys()].map(i => getTabWidth(i)));

    return (
        <TabIndicator
            width={getTabWidth(this.state.index)}
            tabWidth={tabWidth}
            index={this.state.index}
        />
    );
}


renderScene = SceneMap({
    MyApplication,
    Shop
});

renderIcon = ({ route, color, size }) => (
    <Icon
        type='material-community'
        name={route.icon}
        size={25}
        color='#263238'
    />
);

renderLabel = ({ route, focused, color }) => (
    <Text
        style={styles.labelStyle}>
        {route.title}
    </Text>
)

renderTabBar = props => (
    <TabBar
        {...props}
        renderIcon={this.renderIcon}
        style={styles.tabbar}
        labelStyle={styles.labelStyle}
        tabStyle={styles.tabStyle}
        indicatorStyle={styles.indicatorStyle}
    />
);

render() {
    const { selectedIndex } = this.state
    return (
        <TabView
            style={styles.tabView}
            lazy
            navigationState={this.state}
            renderScene={this.renderScene}
            renderTabBar={this.renderTabBar}
            renderIndicator={this.renderIndicator}
            onIndexChange={index => this.setState({ index })}
        // initialLayout={{ width: Dimensions.get('window').width }}
        />
    );
}

}
export default Application;
not work ,is any mistake?

can you just show the error? did you able to run my example?

no effect ,the final view is default effect,i can't find where wrong
1212333

renderIndicator is a prop on TabBar. You're passing it to TabView

renderIndicator is a prop on TabBar. You're passing it to TabView

it worked,thanks boss

Was this page helpful?
0 / 5 - 0 ratings

Related issues

QuentinBrosse picture QuentinBrosse  ·  4Comments

glennvgastel picture glennvgastel  ·  3Comments

KingAmo picture KingAmo  ·  3Comments

lubomyr picture lubomyr  ·  3Comments

AndriiUhryn picture AndriiUhryn  ·  3Comments