Skip to content

Commit 62e588b

Browse files
fred2028Facebook Github Bot 4
authored andcommitted
Fix Android flash and iOS juttering
Summary: Before: - Android had the slideout row flash upon render due to it being rendered first - iOS had the left side of each row load first, then rerender to show entire row when `scrollViewWidth` is available Reason: - Android was loading the slideout view first without an opacity check - iOS was loading the swipeable view with width 0 first then stretching to `scrollViewWidth` when it was available via `onLayout` Fix: Render swipeable view with `flex: 1` then render slideout view Reviewed By: fkgozali Differential Revision: D3321466 fbshipit-source-id: 92a3b5e22034e06d05986ddb8c348796bafbbf34
1 parent 8301978 commit 62e588b

1 file changed

Lines changed: 23 additions & 42 deletions

File tree

Libraries/Experimental/SwipeableRow/SwipeableRow.js

Lines changed: 23 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
const Animated = require('Animated');
2727
const PanResponder = require('PanResponder');
28-
const Platform = require('Platform');
2928
const React = require('React');
3029
const StyleSheet = require('StyleSheet');
3130
const View = require('View');
@@ -49,11 +48,7 @@ const SwipeableRow = React.createClass({
4948

5049
propTypes: {
5150
isOpen: PropTypes.bool,
52-
/**
53-
* Left position of the maximum open swipe. If unspecified, swipe will open
54-
* fully to the left
55-
*/
56-
maxSwipeDistance: PropTypes.number,
51+
maxSwipeDistance: PropTypes.number.isRequired,
5752
onOpen: PropTypes.func,
5853
onSwipeEnd: PropTypes.func.isRequired,
5954
onSwipeStart: PropTypes.func.isRequired,
@@ -79,17 +74,13 @@ const SwipeableRow = React.createClass({
7974
* component A to be transparent until component B is loaded.
8075
*/
8176
isSwipeableViewRendered: false,
82-
/**
83-
* scrollViewWidth can change based on orientation, thus it's stored as a
84-
* state variable. This means all styles depending on it will be inline
85-
*/
86-
scrollViewWidth: 0,
8777
};
8878
},
8979

9080
getDefaultProps(): Object {
9181
return {
9282
isOpen: false,
83+
maxSwipeDistance: 0,
9384
onSwipeEnd: emptyFunction,
9485
onSwipeStart: emptyFunction,
9586
swipeThreshold: 30,
@@ -122,43 +113,42 @@ const SwipeableRow = React.createClass({
122113
},
123114

124115
render(): ReactElement {
125-
const slideoutStyle = [styles.slideOutContainer];
126-
if (Platform.OS === 'ios') {
127-
slideoutStyle.push({opacity: this.state.isSwipeableViewRendered ? 1 : 0});
128-
}
129-
130116
// The view hidden behind the main view
131-
const slideOutView = (
132-
<View style={slideoutStyle}>
133-
{this.props.slideoutView}
134-
</View>
135-
);
117+
let slideOutView;
118+
if (this.state.isSwipeableViewRendered) {
119+
slideOutView = (
120+
<View style={styles.slideOutContainer}>
121+
{this.props.slideoutView}
122+
</View>
123+
);
124+
}
136125

137-
// The swipable item
126+
// The swipeable item
138127
const swipeableView = (
139128
<Animated.View
140129
onLayout={this._onSwipeableViewLayout}
141-
style={{
142-
transform: [{translateX: this.state.currentLeft}],
143-
width: this.state.scrollViewWidth,
144-
}}>
130+
style={[
131+
styles.swipeableContainer,
132+
{
133+
transform: [{translateX: this.state.currentLeft}],
134+
},
135+
]}>
145136
{this.props.children}
146137
</Animated.View>
147138
);
148139

149140
return (
150141
<View
151142
{...this._panResponder.panHandlers}
152-
style={styles.container}
153-
onLayout={this._onLayoutChange}>
143+
style={styles.container}>
154144
{slideOutView}
155145
{swipeableView}
156146
</View>
157147
);
158148
},
159149

160150
_onSwipeableViewLayout(event: Object): void {
161-
if (!this._isSwipeableViewRendered && this.state.scrollViewWidth !== 0) {
151+
if (!this.state.isSwipeableViewRendered) {
162152
this.setState({
163153
isSwipeableViewRendered: true,
164154
});
@@ -198,10 +188,7 @@ const SwipeableRow = React.createClass({
198188
},
199189

200190
_animateToOpenPosition(): void {
201-
const toValue = this.props.maxSwipeDistance
202-
? -this.props.maxSwipeDistance
203-
: -this.state.scrollViewWidth;
204-
this._animateTo(toValue);
191+
this._animateTo(-this.props.maxSwipeDistance);
205192
},
206193

207194
_animateToClosedPosition(): void {
@@ -235,15 +222,6 @@ const SwipeableRow = React.createClass({
235222

236223
this.props.onSwipeEnd();
237224
},
238-
239-
_onLayoutChange(event: Object): void {
240-
const width = event.nativeEvent.layout.width;
241-
if (width && width !== this.state.scrollViewWidth) {
242-
this.setState({
243-
scrollViewWidth: width,
244-
});
245-
}
246-
},
247225
});
248226

249227
const styles = StyleSheet.create({
@@ -259,6 +237,9 @@ const styles = StyleSheet.create({
259237
right: 0,
260238
top: 0,
261239
},
240+
swipeableContainer: {
241+
flex: 1,
242+
},
262243
});
263244

264245
module.exports = SwipeableRow;

0 commit comments

Comments
 (0)