Skip to content

Commit c2a7a50

Browse files
committed
Update title & opacity of title+navbar
- Change title to accept string/component - Added `alwaysShowTitle` & `alwaysShowNavBar` property - Added status bar to display same color as navBarColor - Change default `extraScrollHeight` to 30 - Change default `headerMaxHeight` to 170
1 parent fbbaf04 commit c2a7a50

File tree

3 files changed

+114
-71
lines changed

3 files changed

+114
-71
lines changed

README.md

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,26 @@
1515
$ npm i react-native-parallax-header --save
1616
```
1717
## Demo
18+
### iPhone X or XS (Using `alwaysShowTitle={false}` & `alwaysShowNavBar={false}`)
19+
![iPhone X](https://i.gyazo.com/24343e2127b8e479a52f4bc5853ef457.gif)
20+
1821
### iPhone X or XS
19-
![iPhone X (Image)](http://g.recordit.co/iWW0MOia6i.gif)
20-
![iPhone X (Color)](http://g.recordit.co/vDfanKwzy0.gif)
22+
![iPhone X](https://i.gyazo.com/b24881b191ce5a69e7de14b7d0bb688e.gif)
2123

2224
### iPhone 8
23-
![iPhone 8 (Image)](http://g.recordit.co/g7zcxrsKD6.gif)
24-
![iPhone 8 (Color)](http://g.recordit.co/3JYXSvjFAM.gif)
25+
![iPhone 8](https://i.gyazo.com/eebeff28c7df7b0233fabb9cf2a9c5dc.gif)
2526

2627
## Example
2728
```jsx
2829
import Icon from 'react-native-vector-icons/MaterialIcons';
2930
import ReactNativeParallaxHeader from 'react-native-parallax-header';
3031

31-
const IS_IPHONE_X = SCREEN_HEIGHT === || SCREEN_HEIGHT === 896;
32+
const IS_IPHONE_X = SCREEN_HEIGHT === 812 || SCREEN_HEIGHT === 896;
3233
const STATUS_BAR_HEIGHT = Platform.OS === 'ios' ? (IS_IPHONE_X ? 44 : 20) : 0;
33-
const HEADER_HEIGHT = Platform.OS === 'ios' ? (IS_IPHONE_X ? 88 : 64) : 45;
34+
const HEADER_HEIGHT = Platform.OS === 'ios' ? (IS_IPHONE_X ? 88 : 64) : 64;
3435
const NAV_BAR_HEIGHT = HEADER_HEIGHT - STATUS_BAR_HEIGHT;
3536

36-
const viewImages = {
37+
const images = {
3738
background: require('../../../img/test.jpg'),
3839
};
3940

@@ -53,12 +54,6 @@ const styles = StyleSheet.create({
5354
flexDirection: 'row',
5455
backgroundColor: Colors.transparent,
5556
},
56-
innerContainer: {
57-
flex: 1,
58-
justifyContent: 'center',
59-
alignItems: 'center',
60-
margin: 10,
61-
},
6257
titleStyle: {
6358
color: Colors.white,
6459
fontWeight: 'bold',
@@ -90,7 +85,7 @@ render() {
9085
navbarColor={Colors.primary}
9186
title="Parallax Header ~"
9287
titleStyle={styles.titleStyle}
93-
backgroundImage={viewImages.background}
88+
backgroundImage={images.background}
9489
backgroundImageScale={1.2}
9590
renderNavBar={this.renderNavBar}
9691
renderContent={this.renderContent}
@@ -107,15 +102,17 @@ render() {
107102
| -------- | ---- | -------- | ----------- | ------- |
108103
| `renderNavBar` | `func` | No | This renders the nav bar component | Empty `<View />` |
109104
| `renderContent` | `func` | **YES** | This renders the scroll view content | - |
110-
| `headerMaxHeight` | `number` | No | This is the header maximum height | Default to `200` |
105+
| `headerMaxHeight` | `number` | No | This is the header maximum height | Default to `170` |
111106
| `headerMinHeight` | `number` | No | This is the header minimum height | Default to common ios & android navbar height (have support for iPhone X too :p) |
112107
| `backgroundImage` | `image source` | No | This renders the background image of the header (**if specified, background color will not take effect**) | Default is `null` |
113108
| `backgroundImageScale` | `number` | No | This is the image scale - either enlarge or shrink (after scrolling to bottom & exceed the headerMaxHeight) | Default is `1.5` |
114109
| `backgroundColor` | `string` | No | This is the color of the parallax background (before scrolling up), **will not be used if `backgroundImage` is specified** | Default color is `#303F9F` |
115-
| `extraScrollHeight` | `number` | No | This is the extra scroll height (after scrolling to bottom & exceed the headerMaxHeight) | Default is `50` |
110+
| `extraScrollHeight` | `number` | No | This is the extra scroll height (after scrolling to bottom & exceed the headerMaxHeight) | Default is `30` |
116111
| `navbarColor` | `string` | No | This is the background color of the navbar (after scroll up) | Default color is `#3498db` |
117-
| `title` | `string` | No | This is the title to be display in the header | Default is empty string `‘’` |
112+
| `title` | `any` | No | This is the title to be display in the header, can be string or component | Default to null |
118113
| `titleStyle` | `style` | No | This is the title style to override default font size/color | Default to `color: ‘white’ `text and `fontSize: 16` |
119114
| `scrollEventThrottle` | `number` | No | This is the scroll event throttle | Default is `16` |
120115
| `contentContainerStyle` | `style` | No | This is the contentContainerStyle style to override default `<ScrollView>` contentContainerStyle style | Default to null |
121116
| `contentStyle` | `style` | No | This is the inner content style to override default `<View>` style inside `<ScrollView>` component | Default to null |
117+
| `alwaysShowTitle` | `bool` | No | This is to determine whether show or hide the title after scroll | Default to `true` |
118+
| `alwaysShowNavBar` | `bool` | No | This is to determine whether show or hide the navBar before scroll | Default to `true` |

index.js

Lines changed: 99 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
Text,
88
View,
99
Dimensions,
10+
StatusBar,
1011
} from 'react-native';
1112

1213
const {
@@ -15,12 +16,12 @@ const {
1516

1617
const IS_IPHONE_X = SCREEN_HEIGHT === 812 || SCREEN_HEIGHT === 896;
1718
const STATUS_BAR_HEIGHT = Platform.OS === 'ios' ? (IS_IPHONE_X ? 44 : 20) : 0;
18-
const NAV_BAR_HEIGHT = Platform.OS === 'ios' ? (IS_IPHONE_X ? 88 : 64) : 45;
19+
const NAV_BAR_HEIGHT = Platform.OS === 'ios' ? (IS_IPHONE_X ? 88 : 64) : 64;
1920

2021
const SCROLL_EVENT_THROTTLE = 16;
21-
const DEFAULT_HEADER_MAX_HEIGHT = 200;
22+
const DEFAULT_HEADER_MAX_HEIGHT = 170;
2223
const DEFAULT_HEADER_MIN_HEIGHT = NAV_BAR_HEIGHT;
23-
const DEFAULT_EXTRA_SCROLL_HEIGHT = 50;
24+
const DEFAULT_EXTRA_SCROLL_HEIGHT = 30;
2425
const DEFAULT_BACKGROUND_IMAGE_SCALE = 1.5;
2526

2627
const DEFAULT_NAVBAR_COLOR = '#3498db';
@@ -114,91 +115,77 @@ class RNParallax extends Component {
114115
}
115116

116117
getHeaderHeight() {
117-
return this.state.scrollY.interpolate({
118+
const { scrollY } = this.state;
119+
return scrollY.interpolate({
118120
inputRange: this.getInputRange(),
119121
outputRange: [this.getHeaderMaxHeight() + this.getExtraScrollHeight(), this.getHeaderMaxHeight(), this.getHeaderMinHeight()],
120122
extrapolate: 'clamp',
121123
});
122124
}
123125

124126
getNavBarOpacity() {
125-
return this.state.scrollY.interpolate({
127+
const { scrollY } = this.state;
128+
return scrollY.interpolate({
126129
inputRange: this.getInputRange(),
127130
outputRange: [0, 1, 1],
128131
extrapolate: 'clamp',
129132
});
130133
}
131134

135+
getNavBarForegroundOpacity() {
136+
const { scrollY } = this.state;
137+
const { alwaysShowNavBar } = this.props;
138+
return scrollY.interpolate({
139+
inputRange: this.getInputRange(),
140+
outputRange: [alwaysShowNavBar ? 1 : 0, alwaysShowNavBar ? 1 : 0, 1],
141+
extrapolate: 'clamp',
142+
});
143+
}
144+
132145
getImageOpacity() {
133-
return this.state.scrollY.interpolate({
146+
const { scrollY } = this.state;
147+
return scrollY.interpolate({
134148
inputRange: this.getInputRange(),
135149
outputRange: [1, 1, 0],
136150
extrapolate: 'clamp',
137151
});
138152
}
139153

140154
getImageTranslate() {
141-
return this.state.scrollY.interpolate({
155+
const { scrollY } = this.state;
156+
return scrollY.interpolate({
142157
inputRange: this.getInputRange(),
143158
outputRange: [0, 0, -50],
144159
extrapolate: 'clamp',
145160
});
146161
}
147162

148163
getImageScale() {
149-
return this.state.scrollY.interpolate({
164+
const { scrollY } = this.state;
165+
return scrollY.interpolate({
150166
inputRange: this.getInputRange(),
151167
outputRange: [this.getBackgroundImageScale(), 1, 1],
152168
extrapolate: 'clamp',
153169
});
154170
}
155171

156-
getTitleTranslate() {
157-
return this.state.scrollY.interpolate({
172+
getTitleTranslateY() {
173+
const { scrollY } = this.state;
174+
return scrollY.interpolate({
158175
inputRange: this.getInputRange(),
159176
outputRange: [5, 0, 0],
160177
extrapolate: 'clamp',
161178
});
162179
}
163180

164-
renderHeaderTitle() {
165-
const { title, titleStyle } = this.props;
166-
const titleTranslate = this.getTitleTranslate();
167-
168-
return (
169-
<Animated.View
170-
style={[
171-
styles.headerTitle,
172-
{
173-
transform: [
174-
{ translateY: titleTranslate },
175-
],
176-
height: this.getHeaderHeight(),
177-
},
178-
]}
179-
>
180-
<Text style={[styles.headerText, titleStyle]}>
181-
{title}
182-
</Text>
183-
</Animated.View>
184-
);
185-
}
186-
187-
renderHeaderForeground() {
188-
const { renderNavBar } = this.props;
189-
190-
return (
191-
<Animated.View
192-
style={[
193-
styles.bar,
194-
{
195-
height: this.getHeaderMinHeight(),
196-
},
197-
]}
198-
>
199-
{renderNavBar()}
200-
</Animated.View>
201-
);
181+
getTitleOpacity() {
182+
const { scrollY } = this.state;
183+
const { alwaysShowTitle } = this.props;
184+
return scrollY.interpolate({
185+
inputRange: this.getInputRange(),
186+
outputRange: [1, 1, alwaysShowTitle ? 1 : 0],
187+
extrapolate: 'clamp',
188+
});
202189
}
203190

204191
renderBackgroundImage() {
@@ -280,15 +267,66 @@ class RNParallax extends Component {
280267
);
281268
}
282269

283-
renderScrollView() {
284-
const { renderContent, scrollEventThrottle, contentContainerStyle, containerStyle } = this.props;
270+
renderHeaderTitle() {
271+
const { title, titleStyle } = this.props;
272+
const titleTranslateY = this.getTitleTranslateY();
273+
const titleOpacity = this.getTitleOpacity();
285274

275+
return (
276+
<Animated.View
277+
style={[
278+
styles.headerTitle,
279+
{
280+
transform: [
281+
{ translateY: titleTranslateY },
282+
],
283+
height: this.getHeaderHeight(),
284+
opacity: titleOpacity,
285+
},
286+
]}
287+
>
288+
{typeof title === 'string'
289+
&& (
290+
<Text style={[styles.headerText, titleStyle]}>
291+
{title}
292+
</Text>
293+
)
294+
}
295+
{typeof title !== 'string' && title}
296+
</Animated.View>
297+
);
298+
}
299+
300+
renderHeaderForeground() {
301+
const { renderNavBar } = this.props;
302+
const navBarOpacity = this.getNavBarForegroundOpacity();
303+
304+
return (
305+
<Animated.View
306+
style={[
307+
styles.bar,
308+
{
309+
height: this.getHeaderMinHeight(),
310+
opacity: navBarOpacity,
311+
},
312+
]}
313+
>
314+
{renderNavBar()}
315+
</Animated.View>
316+
);
317+
}
318+
319+
renderScrollView() {
320+
const {
321+
renderContent, scrollEventThrottle, contentContainerStyle, containerStyle,
322+
} = this.props;
323+
const { scrollY } = this.state;
286324
return (
287325
<Animated.ScrollView
288326
style={styles.scrollView}
289327
scrollEventThrottle={scrollEventThrottle}
290328
onScroll={Animated.event(
291-
[{ nativeEvent: { contentOffset: { y: this.state.scrollY } } }],
329+
[{ nativeEvent: { contentOffset: { y: scrollY } } }],
292330
)}
293331
contentContainerStyle={contentContainerStyle}
294332
>
@@ -300,8 +338,12 @@ class RNParallax extends Component {
300338
}
301339

302340
render() {
341+
const { navbarColor } = this.props;
303342
return (
304343
<View style={styles.container}>
344+
<StatusBar
345+
backgroundColor={navbarColor}
346+
/>
305347
{this.renderScrollView()}
306348
{this.renderNavbarBackground()}
307349
{this.renderHeaderBackground()}
@@ -318,7 +360,7 @@ RNParallax.propTypes = {
318360
backgroundColor: PropTypes.string,
319361
backgroundImage: PropTypes.any,
320362
navbarColor: PropTypes.string,
321-
title: PropTypes.string,
363+
title: PropTypes.any,
322364
titleStyle: PropTypes.any,
323365
headerMaxHeight: PropTypes.number,
324366
headerMinHeight: PropTypes.number,
@@ -327,14 +369,16 @@ RNParallax.propTypes = {
327369
backgroundImageScale: PropTypes.number,
328370
contentContainerStyle: PropTypes.any,
329371
containerStyle: PropTypes.any,
372+
alwaysShowTitle: PropTypes.bool,
373+
alwaysShowNavBar: PropTypes.bool,
330374
};
331375

332376
RNParallax.defaultProps = {
333377
renderNavBar: () => <View />,
334378
navbarColor: DEFAULT_NAVBAR_COLOR,
335379
backgroundColor: DEFAULT_BACKGROUND_COLOR,
336380
backgroundImage: null,
337-
title: '',
381+
title: null,
338382
titleStyle: styles.headerText,
339383
headerMaxHeight: DEFAULT_HEADER_MAX_HEIGHT,
340384
headerMinHeight: DEFAULT_HEADER_MIN_HEIGHT,
@@ -343,6 +387,8 @@ RNParallax.defaultProps = {
343387
backgroundImageScale: DEFAULT_BACKGROUND_IMAGE_SCALE,
344388
contentContainerStyle: null,
345389
containerStyle: null,
390+
alwaysShowTitle: true,
391+
alwaysShowNavBar: true,
346392
};
347393

348394
export default RNParallax;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-native-parallax-header",
3-
"version": "1.0.7",
3+
"version": "1.1.0",
44
"description": "A react native scroll view component with Parallax header :p",
55
"main": "index.js",
66
"scripts": {

0 commit comments

Comments
 (0)