Skip to content

Instantly share code, notes, and snippets.

@omeileo
Last active August 26, 2018 23:54
Show Gist options
  • Save omeileo/3166be5ea9007a253ebadfbeef0e1143 to your computer and use it in GitHub Desktop.
Save omeileo/3166be5ea9007a253ebadfbeef0e1143 to your computer and use it in GitHub Desktop.
Floating Animating Header with Scrolling Content (React Native)
import React, { Component } from 'react'
import { Animated, ScrollView, StyleSheet, View } from 'react-native'
const HEADER_MAX_HEIGHT = 350
const HEADER_MIN_HEIGHT = 175
const SEARCH_AREA_HEIGHT = 100
const SEARCH_AREA_MAX_TOP = HEADER_MAX_HEIGHT - (SEARCH_AREA_HEIGHT / 2)
const SEARCH_AREA_MIN_TOP = 120
export default class App extends Component {
constructor () {
super()
this.state = { animatedHeaderValue: new Animated.Value(0) }
}
render () {
const animatedHeaderHeight = this.state.animatedHeaderValue.interpolate({
inputRange: [0, (HEADER_MAX_HEIGHT - HEADER_MIN_HEIGHT)],
outputRange: [HEADER_MAX_HEIGHT, HEADER_MIN_HEIGHT],
extrapolate: 'clamp'
})
const animatedHeaderZindex = this.state.animatedHeaderValue.interpolate({
inputRange: [0, (HEADER_MAX_HEIGHT - HEADER_MIN_HEIGHT)],
outputRange: [0, 1],
extrapolate: 'clamp'
})
const animatedSearchPosition = this.state.animatedHeaderValue.interpolate({
inputRange: [0, (HEADER_MAX_HEIGHT - HEADER_MIN_HEIGHT)],
outputRange: [SEARCH_AREA_MAX_TOP, SEARCH_AREA_MIN_TOP],
extrapolate: 'clamp'
})
const onScroll = () => {
return Animated.event([{ nativeEvent: {contentOffset: { y: this.state.animatedHeaderValue }} }])
}
return (
<View style={styles.container}>
<Animated.View style={[styles.header, {height: animatedHeaderHeight, zIndex: animatedHeaderZindex}]}></Animated.View>
<Animated.View style={[styles.searchArea, {top: animatedSearchPosition}]}/>
<ScrollView style={styles.scrollView} onScroll={onScroll()} scrollEventThrottle={16} showsVerticalScrollIndicator={false}>
<View style={[styles.lists]}>
<View style={styles.listItem}/>
<View style={styles.listItem}/>
<View style={styles.listItem}/>
<View style={styles.listItem}/>
<View style={styles.listItem}/>
<View style={styles.listItem}/>
<View style={styles.listItem}/>
<View style={styles.listItem}/>
<View style={styles.listItem}/>
<View style={styles.listItem}/>
<View style={styles.listItem}/>
<View style={styles.listItem}/>
<View style={styles.listItem}/>
<View style={styles.listItem}/>
<View style={styles.listItem}/>
</View>
</ScrollView>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},
header: {
width: '100%',
backgroundColor: 'orange',
position: 'absolute',
top: 0,
left: 0,
right: 0
},
scrollView: {
flex: 1,
paddingHorizontal: 15
},
searchArea: {
position: 'absolute',
height: SEARCH_AREA_HEIGHT,
marginHorizontal: 15,
left: 0,
right: 0,
zIndex: 1,
backgroundColor: 'blue'
},
lists: {
marginTop: 430
},
listItem: {
height: 60,
marginBottom: 5,
backgroundColor: 'green'
}
})
@omeileo
Copy link
Author

omeileo commented Aug 26, 2018

floating animating header

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment