Skip to content

Commit ffba25c

Browse files
Yan Zhangfacebook-github-bot
Yan Zhang
authored andcommitted
add a hide-on-scroll feature to ScrollView
Summary: Add a stickyHeaderHiddenOnScroll option to keep the sticky header hidden during scrolling down, and only slide in when scrolling up Changelog: [General][Added] - Add a stickyHeaderHiddenOnScroll option to keep the sticky header hidden during scrolling down, and only slide in when scrolling up Reviewed By: JoshuaGross Differential Revision: D26900810 fbshipit-source-id: 6bfb1a4da07fff0763223d60836df187f9d95dd6
1 parent 311d2fb commit ffba25c

File tree

2 files changed

+32
-3
lines changed

2 files changed

+32
-3
lines changed

Libraries/Components/ScrollView/ScrollView.js

+6
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,11 @@ export type Props = $ReadOnly<{|
589589
* The default value is true.
590590
*/
591591
showsVerticalScrollIndicator?: ?boolean,
592+
/**
593+
* When true, Sticky header is hidden when scrolling down, and dock at the top
594+
* when scrolling up
595+
*/
596+
stickyHeaderHiddenOnScroll?: ?boolean,
592597
/**
593598
* An array of child indices determining which children get docked to the
594599
* top of the screen when scrolling. For example, passing
@@ -1642,6 +1647,7 @@ class ScrollView extends React.Component<Props, State> {
16421647
onLayout={event => this._onStickyHeaderLayout(index, event, key)}
16431648
scrollAnimatedValue={this._scrollAnimatedValue}
16441649
inverted={this.props.invertStickyHeaders}
1650+
hiddenOnScroll={this.props.stickyHeaderHiddenOnScroll}
16451651
scrollViewHeight={this.state.layoutHeight}>
16461652
{child}
16471653
</StickyHeaderComponent>

Libraries/Components/ScrollView/ScrollViewStickyHeader.js

+26-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
*/
1010

1111
import AnimatedImplementation from '../../Animated/AnimatedImplementation';
12+
import AnimatedAddition from '../../Animated/nodes/AnimatedAddition';
13+
import AnimatedDiffClamp from '../../Animated/nodes/AnimatedDiffClamp';
14+
import AnimatedNode from '../../Animated/nodes/AnimatedNode';
15+
1216
import * as React from 'react';
1317
import StyleSheet from '../../StyleSheet/StyleSheet';
1418
import View from '../View/View';
@@ -29,6 +33,7 @@ export type Props = {
2933
// The height of the parent ScrollView. Currently only set when inverted.
3034
scrollViewHeight: ?number,
3135
nativeID?: ?string,
36+
hiddenOnScroll?: ?boolean,
3237
...
3338
};
3439

@@ -50,7 +55,7 @@ class ScrollViewStickyHeader extends React.Component<Props, State> {
5055
translateY: null,
5156
};
5257

53-
_translateY: ?AnimatedImplementation.Interpolation = null;
58+
_translateY: ?AnimatedNode = null;
5459
_shouldRecreateTranslateY: boolean = true;
5560
_haveReceivedInitialZeroTranslateY: boolean = true;
5661
_ref: any; // TODO T53738161: flow type this, and the whole file
@@ -87,12 +92,15 @@ class ScrollViewStickyHeader extends React.Component<Props, State> {
8792
updateTranslateListener(
8893
translateY: AnimatedImplementation.Interpolation,
8994
isFabric: boolean,
95+
offset: AnimatedDiffClamp | null,
9096
) {
9197
if (this._translateY != null && this._animatedValueListenerId != null) {
9298
this._translateY.removeListener(this._animatedValueListenerId);
9399
}
100+
offset
101+
? (this._translateY = new AnimatedAddition(translateY, offset))
102+
: (this._translateY = translateY);
94103

95-
this._translateY = translateY;
96104
this._shouldRecreateTranslateY = false;
97105

98106
if (!isFabric) {
@@ -178,7 +186,6 @@ class ScrollViewStickyHeader extends React.Component<Props, State> {
178186
// eslint-disable-next-line dot-notation
179187
(this._ref && this._ref['_internalInstanceHandle']?.stateNode?.canonical)
180188
);
181-
182189
// Initially and in the case of updated props or layout, we
183190
// recreate this interpolated value. Otherwise, we do not recreate
184191
// when there are state changes.
@@ -259,6 +266,22 @@ class ScrollViewStickyHeader extends React.Component<Props, State> {
259266
outputRange,
260267
}),
261268
isFabric,
269+
this.props.hiddenOnScroll
270+
? new AnimatedDiffClamp(
271+
this.props.scrollAnimatedValue
272+
.interpolate({
273+
extrapolateLeft: 'clamp',
274+
inputRange: [layoutY, layoutY + 1],
275+
outputRange: ([0, 1]: Array<number>),
276+
})
277+
.interpolate({
278+
inputRange: [0, 1],
279+
outputRange: ([0, -1]: Array<number>),
280+
}),
281+
-this.state.layoutHeight,
282+
0,
283+
)
284+
: null,
262285
);
263286
}
264287

0 commit comments

Comments
 (0)