Skip to content

Commit

Permalink
Merge pull request #90 from redacademy/yk-feature-dynamic-header
Browse files Browse the repository at this point in the history
Add a dynamic header feature
  • Loading branch information
siddharthparmar7 authored Dec 16, 2019
2 parents 11e1496 + 9f50db7 commit 0e8fbad
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 9 deletions.
61 changes: 58 additions & 3 deletions client/js/screens/Home/Home.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, {Component} from 'react';
import {ScrollView as NavScrollView} from 'react-navigation';
import {
Animated,
Image,
ImageBackground,
Text,
Expand All @@ -9,6 +10,7 @@ import {
Button,
View,
} from 'react-native';
import {VibrancyView} from '@react-native-community/blur';
import CategoryList from '../../components/CategoryList';
import CityPicker from '../../components/CityPicker';
import CardEventSmall from '../../components/CardEventSmall';
Expand All @@ -19,13 +21,16 @@ import {removeViewer} from '../../config/models';
import styles from './styles';
import PropTypes from 'prop-types';

const AnimatedNavScrollView = Animated.createAnimatedComponent(NavScrollView);
class Home extends Component {
constructor(props) {
super(props);

this.state = {
showPicker: false,
citySelected: null,
isAnimated: false,
headerAnimation: new Animated.ValueXY({x: 0, y: -props.headerHeight}),
};
}

Expand Down Expand Up @@ -53,16 +58,48 @@ class Home extends Component {
this.setState({showPicker: false});
};

onScroll = e => {
const offset = e.nativeEvent.contentOffset;

if (offset.y > this.props.headerHeight && !this.state.isAnimated) {
this.setState({isAnimated: true});
this.animateHeader();
} else if (offset.y <= this.props.headerHeight && this.state.isAnimated) {
this.setState({
isAnimated: false,
});

this.animateHeader();
}
};

animateHeader = () => {
Animated.timing(this.state.headerAnimation, {
duration: 500,
toValue: this.state.isAnimated
? {x: 0, y: -this.props.headerHeight}
: {x: 1, y: 0},
}).start();
};

render() {
const {navigation, detectOffsetTop, eventInfo} = this.props;
const {navigation, collapsible, eventInfo} = this.props;
const {paddingHeight, animatedY} = collapsible;

const cityImage = CITY_LIST.filter(
city => city.name === this.state.citySelected,
)[0];

return (
<>
<NavScrollView>
<AnimatedNavScrollView
scrollEventThrottle={32}
onScroll={Animated.event([{nativeEvent: {contentOffset: {y: 0}}}], {
useNativeDriver: true,
listener: this.onScroll,
})}
_mustAddThis={animatedY}
scrollIndicatorInsets={{top: paddingHeight}}>
<ImageBackground
source={cityImage && cityImage.image}
style={styles.imgCity}>
Expand Down Expand Up @@ -192,7 +229,23 @@ class Home extends Component {
title="Log out"
/>
</View>
</NavScrollView>
</AnimatedNavScrollView>

<Animated.View
style={{
position: 'absolute',
opacity: this.state.headerAnimation.x,
top: this.state.headerAnimation.y,
height: paddingHeight,
...styles.hiddenHeaderWrapper,
}}>
<VibrancyView
blurType="dark"
blurAmount={2}
style={styles.hiddenHeader}
/>
</Animated.View>

{this.state.showPicker && (
<CityPicker
hidePicker={this.hidePicker}
Expand All @@ -211,4 +264,6 @@ Home.propTypes = {
navigation: PropTypes.object.isRequired,
userInfo: PropTypes.object,
eventInfo: PropTypes.object,
collapsible: PropTypes.object,
headerHeight: PropTypes.number,
};
39 changes: 33 additions & 6 deletions client/js/screens/Home/HomeContainer.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,52 @@
import React, {Component} from 'react';
import {compose} from 'recompose';
import {graphql, Query} from 'react-apollo';
import {graphql} from 'react-apollo';
import {
QUERY_USER,
QUERY_ALL_EVENTS,
QUERY_EVENT_THIS_WEEK,
} from '../../apollo/queries';
import {StatusBar, Text, View, LayoutAnimation} from 'react-native';
import {VibrancyView} from '@react-native-community/blur';
import {withCollapsible} from 'react-navigation-collapsible';
import {StatusBar, View} from 'react-native';
import Home from './Home';
import {getParamFromParent} from '../../lib/paramFromParent';
import {calculateRatingScore} from '../../lib/calculateRatingScore';
import PropTypes from 'prop-types';

class HomeContainer extends Component {
static navigationOptions = props => {
constructor(props) {
super(props);

this.state = {
headerHeight: 88,
};
}

componentDidMount() {
this.setState({headerHeight: this.props.collapsible.paddingHeight});
}

static navigationOptions = ({navigation, navigationOptions}) => {
return {
headerTransparent: true,
headerStyle: {
backgroundColor: 'transparent',
},
headerBackground: () => {
return <StatusBar barStyle="light-content" />;
},
};
};

render() {
const {navigation, userInfo, allEvents, eventThisWeek} = this.props;
const {
navigation,
userInfo,
allEvents,
eventThisWeek,
collapsible,
} = this.props;

const popularEvents = allEvents && allEvents.events;

const filteredPopularEvents =
Expand All @@ -42,6 +67,8 @@ class HomeContainer extends Component {
thisWeek: eventThisWeek.events,
popular: filteredPopularEvents,
}}
collapsible={collapsible}
headerHeight={this.state.headerHeight}
/>
);
}
Expand Down Expand Up @@ -83,7 +110,7 @@ export default compose(
};
},
}),
)(HomeContainer);
)(withCollapsible(HomeContainer, {iOSCollapsedColor: 'transparent'}));

HomeContainer.propTypes = {
navigation: PropTypes.object.isRequired,
Expand Down
7 changes: 7 additions & 0 deletions client/js/screens/Home/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ const styles = StyleSheet.create({
...THEME.typography.size.default,
color: THEME.colors.grey,
},
hiddenHeaderWrapper: {
width: '100%',
},
hiddenHeader: {
width: '100%',
height: '100%',
},
});

export default styles;

0 comments on commit 0e8fbad

Please sign in to comment.