-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
118 lines (106 loc) · 3.36 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import React, {Component} from 'react';
import {ScrollView, StyleSheet, View, Animated, Dimensions} from 'react-native';
import PropTypes from 'prop-types';
const { width: SCREEN_WIDTH } = Dimensions.get('screen')
export default class Collapsable extends Component {
constructor(props) {
super(props);
this.state = {
scrollY: new Animated.Value(0),
}
}
render() {
const {
content,
collapsedHeader,
expandedHeader,
collapsedHeight,
expandedHeight,
containerStyle,
scrollContainerStyle,
headerContainerStyle,
} = this.props;
const HEADER_EXPANDED_HEIGHT = expandedHeight;
const HEADER_COLLAPSED_HEIGHT = collapsedHeight;
const headerHeight = this.state.scrollY.interpolate({
inputRange: [0, HEADER_EXPANDED_HEIGHT - HEADER_COLLAPSED_HEIGHT],
outputRange: [HEADER_EXPANDED_HEIGHT, HEADER_COLLAPSED_HEIGHT],
extrapolate: 'clamp',
});
const collapsedHeaderOpacity = this.state.scrollY.interpolate({
inputRange: [0, HEADER_EXPANDED_HEIGHT - HEADER_COLLAPSED_HEIGHT],
outputRange: [0.5, 1],
extrapolate: 'clamp',
});
const expandedHeaderOpacity = this.state.scrollY.interpolate({
inputRange: [0, HEADER_EXPANDED_HEIGHT - HEADER_COLLAPSED_HEIGHT],
outputRange: [1, 0],
extrapolate: 'clamp',
});
return (
<View style={[styles.container, containerStyle]}>
<Animated.View style={[styles.header, headerContainerStyle, { height: headerHeight }]}>
<Animated.View style={{ height: headerHeight, opacity: expandedHeaderOpacity}}>
{expandedHeader()}
</Animated.View>
</Animated.View>
<ScrollView
contentContainerStyle={[styles.scrollContainer, scrollContainerStyle, { paddingTop: HEADER_EXPANDED_HEIGHT + 10, zIndex: 1 }]}
onScroll={Animated.event([{
nativeEvent: {
contentOffset: {
y: this.state.scrollY,
}
}
}])}
showsVerticalScrollIndicator={false}
scrollEventThrottle={16}
>
{content()}
</ScrollView>
<Animated.View style={{
position: 'absolute',
width: SCREEN_WIDTH,
height: HEADER_COLLAPSED_HEIGHT,
opacity: collapsedHeaderOpacity,
transform: [{
translateY: this.state.scrollY.interpolate({
inputRange: [0, HEADER_EXPANDED_HEIGHT - HEADER_COLLAPSED_HEIGHT],
outputRange: [-HEADER_COLLAPSED_HEIGHT, 0],
extrapolate: 'clamp',
})
}],
zIndex: 9999,
}}
>
{collapsedHeader()}
</Animated.View>
</View>
);
}
}
Collapsable.props = {
containerStyle: PropTypes.style,
scrollContainerStyle: PropTypes.style,
headerContainerStyle: PropTypes.style,
content: PropTypes.any.isRequired,
collapsedHeader: PropTypes.any.isRequired,
expandedHeader: PropTypes.any.isRequired,
collapsedHeight: PropTypes.number.isRequired,
expandedHeight: PropTypes.number.isRequired,
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
scrollContainer: {
padding: 16,
},
header: {
position: 'absolute',
width: SCREEN_WIDTH,
top: 0,
left: 0,
zIndex: 9998
},
});