Skip to content

Commit c28954b

Browse files
committed
Add documentation and test for triggeringView
1 parent 6de92e0 commit c28954b

File tree

6 files changed

+213
-30
lines changed

6 files changed

+213
-30
lines changed

README.md

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ $ npm install react-native-image-header-scroll-view --save
1818
## Basic Usage
1919

2020
```jsx
21-
import HeaderImageScrollView from 'react-native-image-header-scroll-view';
21+
import HeaderImageScrollView, { TriggeringView } from 'react-native-image-header-scroll-view';
2222

2323
// Inside of a component's render() method:
2424
render() {
@@ -31,7 +31,9 @@ render() {
3131
)}
3232
>
3333
<View style={{ height: 1000 }}>
34-
<Text>Scroll Me!</Text>
34+
<TriggeringView onHide={() => console.log('text hidden')}}>
35+
<Text>Scroll Me!</Text>
36+
</TriggeringView>
3537
</View>
3638
</HeaderImageScrollView>
3739
);
@@ -60,9 +62,29 @@ The `HeaderImageScrollView` handle also the following props. None is required :
6062
| Property | Type | Default | Description |
6163
| -------- | ---- | ------- | ----------- |
6264
| `renderForeground` | `function` | Empty view | Function which return the component to use at foreground. The component is render in front of the header and scroll with the ScrollView. It can return a title for example.|
65+
| `renderFixedForeground` | `function` | Empty view | Function which return the component to use as fixed foreground. The component is displayed with the header but not affected by the overlay. Perfect for navbar content.|
6366
| `foregroundParallaxRatio` | `number` | `1` | Ration for parallax effect of foreground when scrolling. If 2, the header goes up two times faster than the scroll |
6467
| `fadeOutForeground` | `bool` | `false` | If set, add a fade out effect on the foreground when scroll up |
6568

69+
70+
### TriggeringView
71+
72+
The module also export a TriggeringView component. It is a simple view witch accept callback called when it disappear
73+
or appear at the top of the ImageHeaderScrollView
74+
75+
All of the properties of `View` are supported.
76+
77+
78+
| Property | Type | Description |
79+
| -------- | ---- | ----------- |
80+
| `onBeginHidden` | `function` | Called when the component start to be hidden at the top of the scroll view. |
81+
| `onHide` | `function` | Called when the component is not displayed any more after scroll up |
82+
| `onBeginDisplayed` | `function` | Called when the component begin to be displayed again after scroll down |
83+
| `onDisplay` | `function` | Called when the component finished to be displayed again. |
84+
| `onTouchTop` | `function` | Called when the Top of the component touch the Top of the ScrollView. (`onDisplay` + `onBeginHidden`) |
85+
| `onTouchBottom` | `function` | Called when the Bottom of the component touch the Top of the ScrollView. (`onHide` + `onBeginDisplayed`) |
86+
87+
6688
## Other open-source modules by the folks at [BAM](http://github.com/bamlab)
6789

6890
* [generator-rn-toolbox](https://github.com/bamlab/generator-rn-toolbox)

src/ImageHeaderScrollView.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const styles = StyleSheet.create({
4040
left: 0,
4141
bottom: 0,
4242
zIndex: 101,
43-
}
43+
},
4444
});
4545

4646

@@ -52,6 +52,10 @@ class ImageHeaderScrollView extends Component {
5252
};
5353
}
5454

55+
getChildContext() {
56+
return { scrollY: this.state.scrollY };
57+
}
58+
5559
/*
5660
* Expose `ScrollView` API so this component is composable
5761
* with any component that expects a `ScrollView`.
@@ -72,9 +76,6 @@ class ImageHeaderScrollView extends Component {
7276
this.getScrollResponder().scrollTo(...args);
7377
}
7478

75-
getChildContext() {
76-
return { scrollY: this.state.scrollY };
77-
}
7879

7980
interpolateOnImageHeight(outputRange) {
8081
const headerScrollDistance = this.props.maxHeight - this.props.minHeight;

src/TriggeringView.js

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
11
import React, { Component } from 'react';
2-
import { View, Animated, StyleSheet } from 'react-native';
3-
4-
const styles = StyleSheet.create({
5-
fixed: {
6-
position: 'absolute',
7-
top: 0,
8-
},
9-
});
2+
import { View, Animated } from 'react-native';
3+
import _ from 'lodash';
104

115
class TriggeringView extends Component {
126

@@ -20,29 +14,34 @@ class TriggeringView extends Component {
2014
this.onScroll = this.onScroll.bind(this);
2115
}
2216

23-
onLayout(e) {
24-
this.layout = this.setState({
25-
layout: e.nativeEvent.layout,
26-
bottom: e.nativeEvent.layout.y + e.nativeEvent.layout.height,
27-
});
28-
}
29-
3017
componentWillMount() {
18+
if (!this.context.scrollY) {
19+
return;
20+
}
3121
this.listenerId = this.context.scrollY.addListener(this.onScroll);
3222
}
3323

3424
componentWillReceiveProps(nextProps, nextContext) {
25+
if (!this.context.scrollY) {
26+
return;
27+
}
3528
this.context.scrollY.removeListener(this.listenerId);
3629
nextContext.scrollY.addListener(this.onScroll);
3730
}
3831

32+
onLayout(e) {
33+
this.layout = this.setState({
34+
layout: e.nativeEvent.layout,
35+
bottom: e.nativeEvent.layout.y + e.nativeEvent.layout.height,
36+
});
37+
}
38+
3939
onScroll(e) {
4040
const value = e.value;
4141
if (!this.state.touched && value >= this.state.layout.y) {
42-
this.setState({ touched: true});
42+
this.setState({ touched: true });
4343
this.props.onBeginHidden();
4444
this.props.onTouchTop(true);
45-
4645
} else if (this.state.touched && value < this.state.layout.y) {
4746
this.setState({ touched: false });
4847
this.props.onDisplay();
@@ -61,13 +60,13 @@ class TriggeringView extends Component {
6160
}
6261

6362
render() {
64-
const {children, ...viewProps} = this.props;
63+
const viewProps = _.pick(this.props, _.keys(View.propTypes));
6564
return (
6665
<Animated.View
67-
onLayout={(e) => this.onLayout(e)}
66+
onLayout={e => this.onLayout(e)}
6867
{...viewProps}
6968
>
70-
{ children }
69+
{ this.props.children }
7170
</Animated.View>
7271
);
7372
}

src/__tests__/TriggeringView.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import React from 'react';
2+
import { Text } from 'react-native';
3+
import renderer from 'react-test-renderer';
4+
import ImageHeaderScrollView, { TriggeringView } from '../index.js';
5+
6+
describe('TriggeringView', () => {
7+
it('renders correctly by default', () => {
8+
const tree = renderer.create(
9+
<ImageHeaderScrollView>
10+
<TriggeringView />
11+
</ImageHeaderScrollView>,
12+
).toJSON();
13+
expect(tree).toMatchSnapshot();
14+
});
15+
16+
it('should dont\'t crash without ImageHeaderScrollView', () => {
17+
const tree = renderer.create(
18+
<TriggeringView />,
19+
).toJSON();
20+
expect(tree).toMatchSnapshot();
21+
});
22+
23+
it('should display children', () => {
24+
const tree = renderer.create(
25+
<TriggeringView>
26+
<Text> Hello world </Text>
27+
</TriggeringView>,
28+
).toJSON();
29+
expect(tree).toMatchSnapshot();
30+
});
31+
});
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
exports[`TriggeringView renders correctly by default 1`] = `
2+
<View
3+
style={
4+
Object {
5+
"flex": 1,
6+
}
7+
}>
8+
<ScrollView
9+
onScroll={[Function]}
10+
scrollEventThrottle={16}
11+
style={
12+
Array [
13+
Object {
14+
"flex": 1,
15+
},
16+
Object {
17+
"marginTop": 80,
18+
},
19+
]
20+
}>
21+
<View
22+
style={
23+
Object {
24+
"paddingTop": 45,
25+
}
26+
}>
27+
<View
28+
onLayout={[Function]} />
29+
</View>
30+
</ScrollView>
31+
<View
32+
style={
33+
Object {
34+
"height": 125,
35+
"left": 0,
36+
"overflow": "hidden",
37+
"position": "absolute",
38+
"right": 0,
39+
"top": 0,
40+
"transform": Array [
41+
Object {
42+
"scale": 1,
43+
},
44+
],
45+
}
46+
}>
47+
<View
48+
style={
49+
Object {
50+
"backgroundColor": "black",
51+
"bottom": 0,
52+
"left": 0,
53+
"opacity": 0,
54+
"position": "absolute",
55+
"right": 0,
56+
"top": 0,
57+
"zIndex": 100,
58+
}
59+
} />
60+
<View
61+
style={
62+
Object {
63+
"bottom": 0,
64+
"left": 0,
65+
"position": "absolute",
66+
"right": 0,
67+
"top": 0,
68+
"zIndex": 101,
69+
}
70+
}>
71+
<View />
72+
</View>
73+
<View />
74+
</View>
75+
<View
76+
style={
77+
Object {
78+
"height": 125,
79+
"left": 0,
80+
"opacity": 1,
81+
"overflow": "hidden",
82+
"position": "absolute",
83+
"right": 0,
84+
"top": 0,
85+
"transform": Array [
86+
Object {
87+
"translateY": 0,
88+
},
89+
],
90+
}
91+
}>
92+
<View />
93+
</View>
94+
</View>
95+
`;
96+
97+
exports[`TriggeringView should display children 1`] = `
98+
<View
99+
onLayout={[Function]}>
100+
<Text
101+
accessible={true}
102+
allowFontScaling={true}
103+
ellipsizeMode="tail">
104+
Hello world
105+
</Text>
106+
</View>
107+
`;
108+
109+
exports[`TriggeringView should dont't crash without ImageHeaderScrollView 1`] = `
110+
<View
111+
onLayout={[Function]} />
112+
`;

src/__tests__/__snapshots__/index.js.snap

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,19 @@ exports[`ImageHeaderScrollView renders correctly by default 1`] = `
99
onScroll={[Function]}
1010
scrollEventThrottle={16}
1111
style={
12-
Object {
13-
"flex": 1,
14-
}
12+
Array [
13+
Object {
14+
"flex": 1,
15+
},
16+
Object {
17+
"marginTop": 80,
18+
},
19+
]
1520
}>
1621
<View
1722
style={
1823
Object {
19-
"paddingTop": 125,
24+
"paddingTop": 45,
2025
}
2126
} />
2227
</ScrollView>
@@ -49,6 +54,19 @@ exports[`ImageHeaderScrollView renders correctly by default 1`] = `
4954
"zIndex": 100,
5055
}
5156
} />
57+
<View
58+
style={
59+
Object {
60+
"bottom": 0,
61+
"left": 0,
62+
"position": "absolute",
63+
"right": 0,
64+
"top": 0,
65+
"zIndex": 101,
66+
}
67+
}>
68+
<View />
69+
</View>
5270
<View />
5371
</View>
5472
<View

0 commit comments

Comments
 (0)