satya164 / react-native-tab-view

A cross-platform Tab View component for React Native
MIT License
5.13k stars 1.07k forks source link

How can I use renderIndicator, please help #848

Closed vinhnvfabbi closed 5 years ago

vinhnvfabbi commented 5 years ago

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

BunHouth commented 5 years ago

@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

wowtrxqn commented 5 years ago

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

BunHouth commented 5 years ago

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

wowtrxqn commented 5 years ago

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!

wowtrxqn commented 5 years ago

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?

BunHouth commented 5 years ago

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?

wowtrxqn commented 5 years ago

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

satya164 commented 5 years ago

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

wowtrxqn commented 5 years ago

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

it worked,thanks boss