Skip to content

Instantly share code, notes, and snippets.

@shengoo
Created March 23, 2018 16:26
Show Gist options
  • Save shengoo/d9f77764ae2e0b49927584e3e237ae95 to your computer and use it in GitHub Desktop.
Save shengoo/d9f77764ae2e0b49927584e3e237ae95 to your computer and use it in GitHub Desktop.
HeaderTransition
import React, {Component} from 'react';
import {
Animated,
Platform,
StatusBar,
StyleSheet,
Text,
View,
RefreshControl,
ScrollView,
Image,
} from 'react-native';
const HEADER_MAX_HEIGHT = 160;
const HEADER_MIN_HEIGHT = 64;
const HEADER_SCROLL_DISTANCE = HEADER_MAX_HEIGHT - HEADER_MIN_HEIGHT;
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
scrollY: new Animated.Value(
// iOS has negative initial scroll value because content inset...
Platform.OS === 'ios' ? -HEADER_MAX_HEIGHT : 0,
),
};
}
_renderScrollViewContent() {
const data = Array.from({length: 30});
return (
<View style={styles.scrollViewContent}>
{data.map((_, i) => (
<View key={i} style={styles.row}>
<Text>{i}</Text>
</View>
))}
</View>
);
}
render() {
// Because of content inset the scroll value will be negative on iOS so bring
// it back to 0.
const scrollY = Animated.add(
this.state.scrollY,
Platform.OS === 'ios' ? HEADER_MAX_HEIGHT : 0,
);
//
const headerTranslate = scrollY.interpolate({
inputRange: [0, HEADER_SCROLL_DISTANCE],
outputRange: [0, -HEADER_SCROLL_DISTANCE],
extrapolate: 'clamp',
});
const headerHeight = scrollY.interpolate({
inputRange: [0, HEADER_SCROLL_DISTANCE],
outputRange: [HEADER_MAX_HEIGHT, HEADER_MIN_HEIGHT],
extrapolate: 'clamp',
});
//图片变成透明的
const imageOpacity = scrollY.interpolate({
inputRange: [0, HEADER_SCROLL_DISTANCE],
outputRange: [1, 0],
extrapolate: 'clamp',
});
//图片跟随滚动,但是是滚动距离的一般
const imageTranslate = scrollY.interpolate({
inputRange: [0, HEADER_SCROLL_DISTANCE],
outputRange: [0, HEADER_SCROLL_DISTANCE / 2],
extrapolate: 'clamp',
});
//标题颜色
const titleColor = scrollY.interpolate({
inputRange: [0, HEADER_SCROLL_DISTANCE],
outputRange: ['#fff', '#000'],
extrapolate: 'clamp',
});
//头像大小
const avatarSize = scrollY.interpolate({
inputRange: [0, HEADER_SCROLL_DISTANCE],
outputRange: [80, 24],
extrapolate: 'clamp',
});
//头像圆角
const avatarBorderRadius = scrollY.interpolate({
inputRange: [0, HEADER_SCROLL_DISTANCE],
outputRange: [0, 12],
extrapolate: 'clamp',
});
//头像移动距离
const avatarTranslate = scrollY.interpolate({
inputRange: [0, HEADER_SCROLL_DISTANCE],
outputRange: [-80, 0],
extrapolate: 'clamp',
});
const titleTranslateX = scrollY.interpolate({
inputRange: [0, HEADER_SCROLL_DISTANCE],
outputRange: [-40, 0],
extrapolate: 'clamp',
});
return (
<View style={styles.fill}>
<StatusBar
barStyle="dark-content"
/>
<Animated.ScrollView
style={styles.fill}
scrollEventThrottle={1}
onScroll={Animated.event(
[{nativeEvent: {contentOffset: {y: this.state.scrollY}}}],
)}
contentInset={{
top: HEADER_MAX_HEIGHT,
}}
contentOffset={{
y: -HEADER_MAX_HEIGHT,
}}
>
{this._renderScrollViewContent()}
</Animated.ScrollView>
<Animated.View
style={[
styles.header,
{transform: [{translateY: headerTranslate}]},
]}
>
<Animated.Image
style={[
styles.backgroundImage,
{
opacity: imageOpacity,
transform: [{translateY: imageTranslate}],
},
]}
source={require('./assets/cat.jpg')}
/>
</Animated.View>
<Animated.View
style={[
styles.bar,
{
height: headerHeight,
},
]}
>
<Animated.Image style={[
{width: avatarSize, height: avatarSize, borderRadius: avatarBorderRadius,},
{
transform: [
{translateX: avatarTranslate},
],
},
]} source={require('./assets/avatar.jpg')}/>
<Animated.Text style={[
styles.title,
{
color: titleColor,
transform: [
{translateX: titleTranslateX},
// {translateY: titleTranslateY},
],
}
]}>My Name</Animated.Text>
</Animated.View>
</View>
);
}
}
const styles = StyleSheet.create({
fill: {
flex: 1,
},
content: {
flex: 1,
},
header: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
backgroundColor: '#f5f5f6',
overflow: 'hidden',
height: HEADER_MAX_HEIGHT,
},
backgroundImage: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
width: null,
height: HEADER_MAX_HEIGHT,
resizeMode: 'cover',
},
bar: {
// backgroundColor: 'transparent',
paddingTop: Platform.OS === 'ios' ? 20 : 0,
height: 44,
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
top: 0,
left: 0,
right: 0,
flexDirection: 'row',
borderBottomWidth: StyleSheet.hairlineWidth,
borderBottomColor: '#C6C7CB',
},
title: {
// color: 'white',
color: '#191A1C',
marginLeft: 8,
fontSize: 18,
},
scrollViewContent: {
// iOS uses content inset, which acts like padding.
paddingTop: Platform.OS !== 'ios' ? HEADER_MAX_HEIGHT : 0,
},
row: {
height: 40,
margin: 16,
backgroundColor: '#D3D3D3',
alignItems: 'center',
justifyContent: 'center',
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment