Skip to content

Instantly share code, notes, and snippets.

@JohnProg
Forked from andigu/TabParallax.js
Created February 4, 2018 13:15
Show Gist options
  • Save JohnProg/9a2875b5a1d4b5fe7fa566f9a328d0a2 to your computer and use it in GitHub Desktop.
Save JohnProg/9a2875b5a1d4b5fe7fa566f9a328d0a2 to your computer and use it in GitHub Desktop.

Revisions

  1. @andigu andigu revised this gist Sep 12, 2017. 1 changed file with 55 additions and 39 deletions.
    94 changes: 55 additions & 39 deletions TabParallax.js
    Original file line number Diff line number Diff line change
    @@ -1,11 +1,11 @@
    import React, {Component} from "react";
    import {Animated, Dimensions, Text, TouchableOpacity, View} from "react-native";
    import {Animated, Dimensions, Platform, Text, TouchableOpacity, View} from "react-native";
    import {Body, Header, List, ListItem as Item, ScrollableTab, Tab, TabHeading, Tabs, Title} from "native-base";
    import LinearGradient from "react-native-linear-gradient";

    const {width: SCREEN_WIDTH} = Dimensions.get("window");
    const IMAGE_HEIGHT = 250;
    const HEADER_HEIGHT = 64;
    const HEADER_HEIGHT = Platform.OS === "ios" ? 64 : 50;
    const SCROLL_HEIGHT = IMAGE_HEIGHT - HEADER_HEIGHT;
    const THEME_COLOR = "rgba(85,186,255, 1)";
    const FADED_THEME_COLOR = "rgba(85,186,255, 0.8)";
    @@ -41,8 +41,18 @@ export class ParallaxDemo extends Component {
    inputRange: [0, SCROLL_HEIGHT],
    outputRange: [1, 0],
    });
    tabContent = (
    <List>{new Array(20).fill(null).map((_, i) => <Item key={i}><Text>Item {i}</Text></Item>)}</List>);
    tabContent = (x, i) => <View style={{height: this.state.height}}>
    <List onLayout={({nativeEvent: {layout: {height}}}) => {
    this.heights[i] = height;
    if (this.state.activeTab === i) this.setState({height})
    }}>
    {new Array(x).fill(null).map((_, i) => <Item key={i}><Text>Item {i}</Text></Item>)}
    </List></View>;
    heights = [500, 500];
    state = {
    activeTab: 0,
    height: 500
    };

    constructor(props) {
    super(props);
    @@ -75,51 +85,57 @@ export class ParallaxDemo extends Component {
    <Animated.Image
    source={{uri: "https://upload.wikimedia.org/wikipedia/commons/c/c5/Moraine_Lake_17092005.jpg"}}
    style={{height: IMAGE_HEIGHT, width: "100%", opacity: this.imgOpacity}}>
    {/*gradient*/}
    <LinearGradient
    colors={["rgba(255,255,255,0.9)", "rgba(255,255,255,0.35)", "rgba(255,255,255,0)"]}
    locations={[0, 0.25, 1]}
    style={{position: "absolute", height: "100%", width: "100%"}}/>
    </Animated.Image>
    </Animated.View>
    <Tabs renderTabBar={(props) => <Animated.View
    style={{transform: [{translateY: this.tabY}], zIndex: 1, width: "100%", backgroundColor: "white"}}>
    <ScrollableTab {...props}
    renderTab={(name, page, active, onPress, onLayout) => (
    <TouchableOpacity key={page}
    onPress={() => onPress(page)}
    onLayout={onLayout}
    activeOpacity={0.4}>
    <Animated.View
    style={{
    flex: 1,
    height: 100,
    backgroundColor: this.tabBg
    }}>
    <TabHeading scrollable
    style={{
    backgroundColor: "transparent",
    width: SCREEN_WIDTH / 2
    }}
    active={active}>
    <Animated.Text style={{
    fontWeight: active ? "bold" : "normal",
    color: this.textColor,
    fontSize: 14
    <Tabs
    prerenderingSiblingsNumber={3}
    onChangeTab={({i}) => {
    this.setState({height: this.heights[i], activeTab: i})
    }}
    renderTabBar={(props) => <Animated.View
    style={{transform: [{translateY: this.tabY}], zIndex: 1, width: "100%", backgroundColor: "white"}}>
    <ScrollableTab {...props}
    renderTab={(name, page, active, onPress, onLayout) => (
    <TouchableOpacity key={page}
    onPress={() => onPress(page)}
    onLayout={onLayout}
    activeOpacity={0.4}>
    <Animated.View
    style={{
    flex: 1,
    height: 100,
    backgroundColor: this.tabBg
    }}>
    {name}
    </Animated.Text>
    </TabHeading>
    </Animated.View>
    </TouchableOpacity>
    )}
    underlineStyle={{backgroundColor: this.textColor}}/>
    </Animated.View>
    }>
    <TabHeading scrollable
    style={{
    backgroundColor: "transparent",
    width: SCREEN_WIDTH / 2
    }}
    active={active}>
    <Animated.Text style={{
    fontWeight: active ? "bold" : "normal",
    color: this.textColor,
    fontSize: 14
    }}>
    {name}
    </Animated.Text>
    </TabHeading>
    </Animated.View>
    </TouchableOpacity>
    )}
    underlineStyle={{backgroundColor: this.textColor}}/>
    </Animated.View>
    }>
    <Tab heading="Tab 1">
    {this.tabContent}
    {this.tabContent(30, 0)}
    </Tab>
    <Tab heading="Tab 2">
    {this.tabContent}
    {this.tabContent(15, 1)}
    </Tab>
    </Tabs>
    </Animated.ScrollView>
  2. @andigu andigu revised this gist Aug 16, 2017. 1 changed file with 19 additions and 9 deletions.
    28 changes: 19 additions & 9 deletions TabParallax.js
    Original file line number Diff line number Diff line change
    @@ -7,20 +7,20 @@ const {width: SCREEN_WIDTH} = Dimensions.get("window");
    const IMAGE_HEIGHT = 250;
    const HEADER_HEIGHT = 64;
    const SCROLL_HEIGHT = IMAGE_HEIGHT - HEADER_HEIGHT;
    const COLOR = "rgba(85,186,255, 1)";
    const FADED_COLOR = "rgba(85,186,255, 0.8)";
    const THEME_COLOR = "rgba(85,186,255, 1)";
    const FADED_THEME_COLOR = "rgba(85,186,255, 0.8)";

    export class ParallaxDemo extends Component {
    nScroll = new Animated.Value(0);
    scroll = new Animated.Value(0);
    textColor = this.scroll.interpolate({
    inputRange: [0, SCROLL_HEIGHT / 5, SCROLL_HEIGHT],
    outputRange: [COLOR, FADED_COLOR, "white"],
    outputRange: [THEME_COLOR, FADED_THEME_COLOR, "white"],
    extrapolate: "clamp"
    });
    tabBg = this.scroll.interpolate({
    inputRange: [0, SCROLL_HEIGHT],
    outputRange: ["white", COLOR],
    outputRange: ["white", THEME_COLOR],
    extrapolate: "clamp"
    });
    tabY = this.nScroll.interpolate({
    @@ -29,7 +29,7 @@ export class ParallaxDemo extends Component {
    });
    headerBg = this.scroll.interpolate({
    inputRange: [0, SCROLL_HEIGHT, SCROLL_HEIGHT + 1],
    outputRange: ["transparent", "transparent", COLOR],
    outputRange: ["transparent", "transparent", THEME_COLOR],
    extrapolate: "clamp"
    });
    imgScale = this.nScroll.interpolate({
    @@ -70,7 +70,7 @@ export class ParallaxDemo extends Component {
    style={{zIndex: 0}}>
    <Animated.View style={{
    transform: [{translateY: Animated.multiply(this.nScroll, 0.65)}, {scale: this.imgScale}],
    backgroundColor: COLOR
    backgroundColor: THEME_COLOR
    }}>
    <Animated.Image
    source={{uri: "https://upload.wikimedia.org/wikipedia/commons/c/c5/Moraine_Lake_17092005.jpg"}}
    @@ -85,11 +85,21 @@ export class ParallaxDemo extends Component {
    style={{transform: [{translateY: this.tabY}], zIndex: 1, width: "100%", backgroundColor: "white"}}>
    <ScrollableTab {...props}
    renderTab={(name, page, active, onPress, onLayout) => (
    <TouchableOpacity key={page} onPress={() => onPress(page)} onLayout={onLayout}
    <TouchableOpacity key={page}
    onPress={() => onPress(page)}
    onLayout={onLayout}
    activeOpacity={0.4}>
    <Animated.View style={{flex: 1, height: 100, backgroundColor: this.tabBg}}>
    <Animated.View
    style={{
    flex: 1,
    height: 100,
    backgroundColor: this.tabBg
    }}>
    <TabHeading scrollable
    style={{backgroundColor: "transparent", width: SCREEN_WIDTH / 2}}
    style={{
    backgroundColor: "transparent",
    width: SCREEN_WIDTH / 2
    }}
    active={active}>
    <Animated.Text style={{
    fontWeight: active ? "bold" : "normal",
  3. @andigu andigu revised this gist Aug 16, 2017. 1 changed file with 110 additions and 111 deletions.
    221 changes: 110 additions & 111 deletions TabParallax.js
    Original file line number Diff line number Diff line change
    @@ -1,120 +1,119 @@
    import React, {Component} from "react";
    import {Animated, Dimensions} from "react-native";
    import {Body, Button, Container, Header, Icon, Left, Right, ScrollableTab, Tab, Tabs, Text, Title, View} from "native-base";
    import {Animated, Dimensions, Text, TouchableOpacity, View} from "react-native";
    import {Body, Header, List, ListItem as Item, ScrollableTab, Tab, TabHeading, Tabs, Title} from "native-base";
    import LinearGradient from "react-native-linear-gradient";

    const {width: SCREEN_WIDTH, height: SCREEN_HEIGHT} = Dimensions.get("window");
    const {width: SCREEN_WIDTH} = Dimensions.get("window");
    const IMAGE_HEIGHT = 250;
    const HEADER_HEIGHT = 64;
    const MIN_TAB_VIEW_HEIGHT = SCREEN_HEIGHT - IMAGE_HEIGHT;
    const tabProps = {
    tabStyle: {backgroundColor: "transparent", width: SCREEN_WIDTH / 2},
    activeTabStyle: {backgroundColor: "transparent", width: SCREEN_WIDTH / 2}
    };
    const SCROLL_HEIGHT = IMAGE_HEIGHT - HEADER_HEIGHT;
    const COLOR = "rgba(85,186,255, 1)";
    const FADED_COLOR = "rgba(85,186,255, 0.8)";

    export class App extends Component {
    nativeScroll;
    scroll;
    export class ParallaxDemo extends Component {
    nScroll = new Animated.Value(0);
    scroll = new Animated.Value(0);
    textColor = this.scroll.interpolate({
    inputRange: [0, SCROLL_HEIGHT / 5, SCROLL_HEIGHT],
    outputRange: [COLOR, FADED_COLOR, "white"],
    extrapolate: "clamp"
    });
    tabBg = this.scroll.interpolate({
    inputRange: [0, SCROLL_HEIGHT],
    outputRange: ["white", COLOR],
    extrapolate: "clamp"
    });
    tabY = this.nScroll.interpolate({
    inputRange: [0, SCROLL_HEIGHT, SCROLL_HEIGHT + 1],
    outputRange: [0, 0, 1]
    });
    headerBg = this.scroll.interpolate({
    inputRange: [0, SCROLL_HEIGHT, SCROLL_HEIGHT + 1],
    outputRange: ["transparent", "transparent", COLOR],
    extrapolate: "clamp"
    });
    imgScale = this.nScroll.interpolate({
    inputRange: [-25, 0],
    outputRange: [1.1, 1],
    extrapolateRight: "clamp"
    });
    imgOpacity = this.nScroll.interpolate({
    inputRange: [0, SCROLL_HEIGHT],
    outputRange: [1, 0],
    });
    tabContent = (
    <List>{new Array(20).fill(null).map((_, i) => <Item key={i}><Text>Item {i}</Text></Item>)}</List>);

    constructor(props) {
    super(props);
    this.nativeScroll = new Animated.Value(0);
    this.scroll = new Animated.Value(0);
    this.nativeScroll.addListener(Animated.event([{value: this.scroll}], {useNativeDriver: false}));
    }
    constructor(props) {
    super(props);
    this.nScroll.addListener(Animated.event([{value: this.scroll}], {useNativeDriver: false}));
    }

    render() {
    const tabScroll = this.nativeScroll.interpolate({
    inputRange: [0, IMAGE_HEIGHT - HEADER_HEIGHT, IMAGE_HEIGHT - HEADER_HEIGHT + 1],
    outputRange: [0, 0, 1]
    });
    const headerColor = this.scroll.interpolate({
    inputRange: [0, IMAGE_HEIGHT - HEADER_HEIGHT],
    outputRange: ["rgba(255,255,255,0)", "rgba(255,255,255,1)"]
    });
    const imageScale = this.nativeScroll.interpolate({
    inputRange: [-25, 0],
    outputRange: [1.1, 1],
    extrapolateRight: "clamp"
    });
    return (
    <Container>
    <Animated.View
    style={{
    position: "absolute",
    width: "100%",
    height: HEADER_HEIGHT,
    backgroundColor: headerColor,
    zIndex: 1,
    }}>
    <Header style={{backgroundColor: "transparent"}} hasTabs>
    <Left>
    <Button transparent>
    <Icon name='arrow-back'/>
    </Button>
    </Left>
    <Body>
    <Title>
    Hello
    </Title>
    </Body>
    <Right/>
    </Header>
    </Animated.View>
    <Animated.ScrollView
    scrollEventThrottle={5}
    showsVerticalScrollIndicator={false}
    onScroll={Animated.event([{
    nativeEvent: {
    contentOffset: {
    y: this.nativeScroll
    }
    }
    }], {useNativeDriver: true})} style={{zIndex: 0}}>
    <Animated.Image source={{uri: "https://facebook.github.io/react-native/img/opengraph.png"}}
    style={{
    height: IMAGE_HEIGHT,
    width: "100%",
    transform: [{translateY: Animated.multiply(this.nativeScroll, 0.5)}, {scale: imageScale}]
    }}>
    <LinearGradient
    colors={["rgba(255,255,255,0.8)", "rgba(255,255,255,0.3)", "rgba(255,255,255,0)"]}
    locations={[0, 0.3, 1]}
    style={{
    position: "absolute",
    top: 0,
    bottom: 0,
    left: 0,
    right: 0
    }}/>
    </Animated.Image>
    <Tabs renderTabBar={(props) => {
    return <Animated.View
    style={{
    transform: [{translateY: tabScroll}],
    zIndex: 1,
    width: "100%", backgroundColor: "white"
    }}>
    <ScrollableTab {...props}/>
    </Animated.View>
    }}>
    <Tab heading="Tab 1" {...tabProps}>
    <View style={{minHeight: MIN_TAB_VIEW_HEIGHT}}>
    <Text>
    Lorem ipsum dolor sit amet, ...
    </Text>
    </View>
    </Tab>
    <Tab heading="Tab 2" {...tabProps}>
    <View style={{minHeight: MIN_TAB_VIEW_HEIGHT}}>
    <Text>
    Tab 2
    </Text>
    </View>
    </Tab>
    </Tabs>
    </Animated.ScrollView>
    </Container>
    )
    }
    render() {
    return (
    <View>
    <Animated.View style={{position: "absolute", width: "100%", backgroundColor: this.headerBg, zIndex: 1}}>
    <Header style={{backgroundColor: "transparent"}} hasTabs>
    <Body>
    <Title>
    <Animated.Text style={{color: this.textColor, fontWeight: "bold"}}>
    Tab Parallax
    </Animated.Text>
    </Title>
    </Body>
    </Header>
    </Animated.View>
    <Animated.ScrollView
    scrollEventThrottle={5}
    showsVerticalScrollIndicator={false}
    onScroll={Animated.event([{nativeEvent: {contentOffset: {y: this.nScroll}}}], {useNativeDriver: true})}
    style={{zIndex: 0}}>
    <Animated.View style={{
    transform: [{translateY: Animated.multiply(this.nScroll, 0.65)}, {scale: this.imgScale}],
    backgroundColor: COLOR
    }}>
    <Animated.Image
    source={{uri: "https://upload.wikimedia.org/wikipedia/commons/c/c5/Moraine_Lake_17092005.jpg"}}
    style={{height: IMAGE_HEIGHT, width: "100%", opacity: this.imgOpacity}}>
    <LinearGradient
    colors={["rgba(255,255,255,0.9)", "rgba(255,255,255,0.35)", "rgba(255,255,255,0)"]}
    locations={[0, 0.25, 1]}
    style={{position: "absolute", height: "100%", width: "100%"}}/>
    </Animated.Image>
    </Animated.View>
    <Tabs renderTabBar={(props) => <Animated.View
    style={{transform: [{translateY: this.tabY}], zIndex: 1, width: "100%", backgroundColor: "white"}}>
    <ScrollableTab {...props}
    renderTab={(name, page, active, onPress, onLayout) => (
    <TouchableOpacity key={page} onPress={() => onPress(page)} onLayout={onLayout}
    activeOpacity={0.4}>
    <Animated.View style={{flex: 1, height: 100, backgroundColor: this.tabBg}}>
    <TabHeading scrollable
    style={{backgroundColor: "transparent", width: SCREEN_WIDTH / 2}}
    active={active}>
    <Animated.Text style={{
    fontWeight: active ? "bold" : "normal",
    color: this.textColor,
    fontSize: 14
    }}>
    {name}
    </Animated.Text>
    </TabHeading>
    </Animated.View>
    </TouchableOpacity>
    )}
    underlineStyle={{backgroundColor: this.textColor}}/>
    </Animated.View>
    }>
    <Tab heading="Tab 1">
    {this.tabContent}
    </Tab>
    <Tab heading="Tab 2">
    {this.tabContent}
    </Tab>
    </Tabs>
    </Animated.ScrollView>
    </View>
    )
    }
    }
  4. @andigu andigu revised this gist Aug 15, 2017. 1 changed file with 1 addition and 35 deletions.
    36 changes: 1 addition & 35 deletions TabParallax.js
    Original file line number Diff line number Diff line change
    @@ -101,41 +101,7 @@ export class App extends Component {
    <Tab heading="Tab 1" {...tabProps}>
    <View style={{minHeight: MIN_TAB_VIEW_HEIGHT}}>
    <Text>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin et nibh sem. Maecenas
    et lectus sodales, egestas justo eu, mattis neque. Suspendisse id ex risus. In sed
    pretium ipsum, tempor iaculis velit. Nulla tristique convallis auctor. Etiam aliquam
    sodales velit, non porta arcu ultricies eu. Suspendisse accumsan ante a est vehicula
    convallis. Phasellus eget orci laoreet, fringilla libero sit amet, maximus massa. In
    at blandit quam, vitae volutpat dui. Integer semper interdum sem a feugiat. In vel
    lectus sed mi efficitur suscipit. Nam molestie sapien sem, vitae luctus massa
    rhoncus nec. Curabitur viverra tristique sem, eu lobortis augue pellentesque sed.
    Sed eget tortor ut odio finibus sodales et in ante. Aenean eu felis sapien.
    Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis
    egestas. Nulla id nunc lectus. Ut in fermentum justo. Mauris aliquam ultrices
    mauris, id ullamcorper ipsum porta non. Mauris eleifend nunc quis erat hendrerit,
    vitae tincidunt justo tristique. Etiam ultrices ac lorem id pretium.
    Aenean fermentum eget velit eget aliquet. Sed ut cursus leo, quis finibus neque.
    Integer at nisi viverra arcu euismod aliquam. Aliquam a fermentum felis. Phasellus
    tristique a mi non accumsan. Morbi porttitor metus in diam lobortis suscipit. Ut
    molestie, ante quis rutrum tristique, nisi tortor consectetur est, ut rhoncus nibh
    nisi ac sem. Cras ultricies condimentum neque a pellentesque. Vivamus quis sapien
    faucibus nisi suscipit aliquet eget tempus ex. Mauris nec erat eros. Sed hendrerit
    rutrum eros, et tempus neque. Duis nisl velit, feugiat et dui eu, condimentum
    consectetur metus. Quisque sed tellus nulla. Donec eget ante feugiat, luctus risus
    non, aliquam tortor. Curabitur maximus condimentum metus, aliquam viverra lectus
    interdum at.
    Nunc sollicitudin est eget ullamcorper imperdiet. Aliquam cursus dapibus tempus.
    Donec ultricies egestas egestas. Mauris id lacus accumsan arcu dignissim ullamcorper
    nec vitae purus. Morbi finibus scelerisque scelerisque. Praesent at velit nec eros
    porta luctus. Donec tincidunt iaculis scelerisque.
    Sed id vehicula odio, non condimentum mi. Cras lectus mauris, auctor vitae sem ut,
    imperdiet venenatis mi. Mauris rutrum id sem vitae vehicula. Donec sed malesuada
    metus, in accumsan tortor. Praesent vehicula diam at odio sagittis bibendum. Sed
    condimentum volutpat tempor. Nullam non eros sed libero finibus blandit eget eu
    tortor. Maecenas hendrerit elit et massa blandit tincidunt. Sed iaculis commodo
    laoreet. Vivamus id consectetur tortor. Aliquam a sem elit. Curabitur nec
    condimentum mi. Etiam auctor commodo libero vitae volutpat. In dictum lobortis odio
    et volutpat.
    Lorem ipsum dolor sit amet, ...
    </Text>
    </View>
    </Tab>
  5. @andigu andigu revised this gist Aug 12, 2017. 1 changed file with 81 additions and 12 deletions.
    93 changes: 81 additions & 12 deletions TabParallax.js
    Original file line number Diff line number Diff line change
    @@ -1,30 +1,50 @@
    import React, {Component} from "react";
    import {Animated, Dimensions, Platform} from "react-native";
    import {Animated, Dimensions} from "react-native";
    import {Body, Button, Container, Header, Icon, Left, Right, ScrollableTab, Tab, Tabs, Text, Title, View} from "native-base";
    import LinearGradient from "react-native-linear-gradient";

    const {width: SCREEN_WIDTH} = Dimensions.get("window");
    const {width: SCREEN_WIDTH, height: SCREEN_HEIGHT} = Dimensions.get("window");
    const IMAGE_HEIGHT = 250;
    const HEADER_HEIGHT = Platform.OS === "ios" ? 64 : 56;
    const MIN_TAB_VIEW_HEIGHT = 1000;
    const HEADER_HEIGHT = 64;
    const MIN_TAB_VIEW_HEIGHT = SCREEN_HEIGHT - IMAGE_HEIGHT;
    const tabProps = {
    tabStyle: {width: SCREEN_WIDTH / 2, backgroundColor: "white"},
    activeTabStyle: {width: SCREEN_WIDTH / 2, backgroundColor: "white"},
    tabStyle: {backgroundColor: "transparent", width: SCREEN_WIDTH / 2},
    activeTabStyle: {backgroundColor: "transparent", width: SCREEN_WIDTH / 2}
    };

    export class App extends Component {
    nativeScroll;
    scroll;

    constructor(props) {
    super(props);
    this.nativeScroll = new Animated.Value(0);
    this.scroll = new Animated.Value(0);
    this.nativeScroll.addListener(Animated.event([{value: this.scroll}], {useNativeDriver: false}));
    }

    render() {
    const tabScroll = this.nativeScroll.interpolate({
    inputRange: [0, IMAGE_HEIGHT - HEADER_HEIGHT, IMAGE_HEIGHT - HEADER_HEIGHT + 1],
    outputRange: [0, 0, 1]
    });
    const headerColor = this.scroll.interpolate({
    inputRange: [0, IMAGE_HEIGHT - HEADER_HEIGHT],
    outputRange: ["rgba(255,255,255,0)", "rgba(255,255,255,1)"]
    });
    const imageScale = this.nativeScroll.interpolate({
    inputRange: [-25, 0],
    outputRange: [1.1, 1],
    extrapolateRight: "clamp"
    });
    return (
    <Container>
    <Animated.View
    style={{
    position: "absolute",
    width: "100%",
    height: HEADER_HEIGHT,
    backgroundColor: headerColor,
    zIndex: 1,
    }}>
    <Header style={{backgroundColor: "transparent"}} hasTabs>
    @@ -34,7 +54,7 @@ export class App extends Component {
    </Button>
    </Left>
    <Body>
    <Title style={{color: "black"}}>
    <Title>
    Hello
    </Title>
    </Body>
    @@ -44,11 +64,18 @@ export class App extends Component {
    <Animated.ScrollView
    scrollEventThrottle={5}
    showsVerticalScrollIndicator={false}
    style={{zIndex: 0}}>
    <Animated.Image source={{uri: "https://www.novoda.com/blog/content/images/2016/06/reactive-nativingitup-png-800x600_q96.png"}}
    onScroll={Animated.event([{
    nativeEvent: {
    contentOffset: {
    y: this.nativeScroll
    }
    }
    }], {useNativeDriver: true})} style={{zIndex: 0}}>
    <Animated.Image source={{uri: "https://facebook.github.io/react-native/img/opengraph.png"}}
    style={{
    height: IMAGE_HEIGHT,
    width: "100%",
    transform: [{translateY: Animated.multiply(this.nativeScroll, 0.5)}, {scale: imageScale}]
    }}>
    <LinearGradient
    colors={["rgba(255,255,255,0.8)", "rgba(255,255,255,0.3)", "rgba(255,255,255,0)"]}
    @@ -61,12 +88,54 @@ export class App extends Component {
    right: 0
    }}/>
    </Animated.Image>
    <Tabs>
    <Tabs renderTabBar={(props) => {
    return <Animated.View
    style={{
    transform: [{translateY: tabScroll}],
    zIndex: 1,
    width: "100%", backgroundColor: "white"
    }}>
    <ScrollableTab {...props}/>
    </Animated.View>
    }}>
    <Tab heading="Tab 1" {...tabProps}>
    <View style={{minHeight: MIN_TAB_VIEW_HEIGHT}}>
    <Text>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum nec justo fringilla est mattis lacinia. Suspendisse sollicitudin suscipit lobortis. Etiam nec ante mi. Ut porta rutrum velit, a ullamcorper ligula. Praesent ut venenatis turpis. Maecenas id pulvinar lacus. Morbi consectetur imperdiet risus et luctus. In accumsan risus sit amet purus tempus maximus. Curabitur vel tristique dui, eget venenatis magna. Etiam semper enim mi, vel luctus felis dignissim id. Vestibulum feugiat hendrerit gravida. Vestibulum est ligula, aliquam eu sem vitae, gravida luctus enim.
    Vestibulum vel consectetur magna. Nulla sapien lorem, congue id consequat eu, finibus non quam. Donec consectetur imperdiet enim vel semper. Donec consequat accumsan ipsum, in tempus odio efficitur ac. Vestibulum arcu neque, ultricies vitae euismod ac, hendrerit quis leo. Phasellus aliquet diam quis posuere pulvinar. Nam turpis urna, bibendum eget faucibus ut, condimentum id purus. Nulla ac tellus ut massa malesuada ultrices id vel metus. Aenean lectus nulla, tincidunt id facilisis nec, consectetur non mi. Nam in nisi vitae lacus consectetur sodales quis aliquam ex.
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin et nibh sem. Maecenas
    et lectus sodales, egestas justo eu, mattis neque. Suspendisse id ex risus. In sed
    pretium ipsum, tempor iaculis velit. Nulla tristique convallis auctor. Etiam aliquam
    sodales velit, non porta arcu ultricies eu. Suspendisse accumsan ante a est vehicula
    convallis. Phasellus eget orci laoreet, fringilla libero sit amet, maximus massa. In
    at blandit quam, vitae volutpat dui. Integer semper interdum sem a feugiat. In vel
    lectus sed mi efficitur suscipit. Nam molestie sapien sem, vitae luctus massa
    rhoncus nec. Curabitur viverra tristique sem, eu lobortis augue pellentesque sed.
    Sed eget tortor ut odio finibus sodales et in ante. Aenean eu felis sapien.
    Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis
    egestas. Nulla id nunc lectus. Ut in fermentum justo. Mauris aliquam ultrices
    mauris, id ullamcorper ipsum porta non. Mauris eleifend nunc quis erat hendrerit,
    vitae tincidunt justo tristique. Etiam ultrices ac lorem id pretium.
    Aenean fermentum eget velit eget aliquet. Sed ut cursus leo, quis finibus neque.
    Integer at nisi viverra arcu euismod aliquam. Aliquam a fermentum felis. Phasellus
    tristique a mi non accumsan. Morbi porttitor metus in diam lobortis suscipit. Ut
    molestie, ante quis rutrum tristique, nisi tortor consectetur est, ut rhoncus nibh
    nisi ac sem. Cras ultricies condimentum neque a pellentesque. Vivamus quis sapien
    faucibus nisi suscipit aliquet eget tempus ex. Mauris nec erat eros. Sed hendrerit
    rutrum eros, et tempus neque. Duis nisl velit, feugiat et dui eu, condimentum
    consectetur metus. Quisque sed tellus nulla. Donec eget ante feugiat, luctus risus
    non, aliquam tortor. Curabitur maximus condimentum metus, aliquam viverra lectus
    interdum at.
    Nunc sollicitudin est eget ullamcorper imperdiet. Aliquam cursus dapibus tempus.
    Donec ultricies egestas egestas. Mauris id lacus accumsan arcu dignissim ullamcorper
    nec vitae purus. Morbi finibus scelerisque scelerisque. Praesent at velit nec eros
    porta luctus. Donec tincidunt iaculis scelerisque.
    Sed id vehicula odio, non condimentum mi. Cras lectus mauris, auctor vitae sem ut,
    imperdiet venenatis mi. Mauris rutrum id sem vitae vehicula. Donec sed malesuada
    metus, in accumsan tortor. Praesent vehicula diam at odio sagittis bibendum. Sed
    condimentum volutpat tempor. Nullam non eros sed libero finibus blandit eget eu
    tortor. Maecenas hendrerit elit et massa blandit tincidunt. Sed iaculis commodo
    laoreet. Vivamus id consectetur tortor. Aliquam a sem elit. Curabitur nec
    condimentum mi. Etiam auctor commodo libero vitae volutpat. In dictum lobortis odio
    et volutpat.
    </Text>
    </View>
    </Tab>
  6. @andigu andigu created this gist Aug 12, 2017.
    85 changes: 85 additions & 0 deletions TabParallax.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,85 @@
    import React, {Component} from "react";
    import {Animated, Dimensions, Platform} from "react-native";
    import {Body, Button, Container, Header, Icon, Left, Right, ScrollableTab, Tab, Tabs, Text, Title, View} from "native-base";
    import LinearGradient from "react-native-linear-gradient";

    const {width: SCREEN_WIDTH} = Dimensions.get("window");
    const IMAGE_HEIGHT = 250;
    const HEADER_HEIGHT = Platform.OS === "ios" ? 64 : 56;
    const MIN_TAB_VIEW_HEIGHT = 1000;
    const tabProps = {
    tabStyle: {width: SCREEN_WIDTH / 2, backgroundColor: "white"},
    activeTabStyle: {width: SCREEN_WIDTH / 2, backgroundColor: "white"},
    };

    export class App extends Component {
    constructor(props) {
    super(props);
    }

    render() {
    return (
    <Container>
    <Animated.View
    style={{
    position: "absolute",
    width: "100%",
    height: HEADER_HEIGHT,
    zIndex: 1,
    }}>
    <Header style={{backgroundColor: "transparent"}} hasTabs>
    <Left>
    <Button transparent>
    <Icon name='arrow-back'/>
    </Button>
    </Left>
    <Body>
    <Title style={{color: "black"}}>
    Hello
    </Title>
    </Body>
    <Right/>
    </Header>
    </Animated.View>
    <Animated.ScrollView
    scrollEventThrottle={5}
    showsVerticalScrollIndicator={false}
    style={{zIndex: 0}}>
    <Animated.Image source={{uri: "https://www.novoda.com/blog/content/images/2016/06/reactive-nativingitup-png-800x600_q96.png"}}
    style={{
    height: IMAGE_HEIGHT,
    width: "100%",
    }}>
    <LinearGradient
    colors={["rgba(255,255,255,0.8)", "rgba(255,255,255,0.3)", "rgba(255,255,255,0)"]}
    locations={[0, 0.3, 1]}
    style={{
    position: "absolute",
    top: 0,
    bottom: 0,
    left: 0,
    right: 0
    }}/>
    </Animated.Image>
    <Tabs>
    <Tab heading="Tab 1" {...tabProps}>
    <View style={{minHeight: MIN_TAB_VIEW_HEIGHT}}>
    <Text>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum nec justo fringilla est mattis lacinia. Suspendisse sollicitudin suscipit lobortis. Etiam nec ante mi. Ut porta rutrum velit, a ullamcorper ligula. Praesent ut venenatis turpis. Maecenas id pulvinar lacus. Morbi consectetur imperdiet risus et luctus. In accumsan risus sit amet purus tempus maximus. Curabitur vel tristique dui, eget venenatis magna. Etiam semper enim mi, vel luctus felis dignissim id. Vestibulum feugiat hendrerit gravida. Vestibulum est ligula, aliquam eu sem vitae, gravida luctus enim.
    Vestibulum vel consectetur magna. Nulla sapien lorem, congue id consequat eu, finibus non quam. Donec consectetur imperdiet enim vel semper. Donec consequat accumsan ipsum, in tempus odio efficitur ac. Vestibulum arcu neque, ultricies vitae euismod ac, hendrerit quis leo. Phasellus aliquet diam quis posuere pulvinar. Nam turpis urna, bibendum eget faucibus ut, condimentum id purus. Nulla ac tellus ut massa malesuada ultrices id vel metus. Aenean lectus nulla, tincidunt id facilisis nec, consectetur non mi. Nam in nisi vitae lacus consectetur sodales quis aliquam ex.
    </Text>
    </View>
    </Tab>
    <Tab heading="Tab 2" {...tabProps}>
    <View style={{minHeight: MIN_TAB_VIEW_HEIGHT}}>
    <Text>
    Tab 2
    </Text>
    </View>
    </Tab>
    </Tabs>
    </Animated.ScrollView>
    </Container>
    )
    }
    }