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
This commit is contained in:
parent
830197847a
commit
62e588bece
|
@ -25,7 +25,6 @@
|
|||
|
||||
const Animated = require('Animated');
|
||||
const PanResponder = require('PanResponder');
|
||||
const Platform = require('Platform');
|
||||
const React = require('React');
|
||||
const StyleSheet = require('StyleSheet');
|
||||
const View = require('View');
|
||||
|
@ -49,11 +48,7 @@ const SwipeableRow = React.createClass({
|
|||
|
||||
propTypes: {
|
||||
isOpen: PropTypes.bool,
|
||||
/**
|
||||
* Left position of the maximum open swipe. If unspecified, swipe will open
|
||||
* fully to the left
|
||||
*/
|
||||
maxSwipeDistance: PropTypes.number,
|
||||
maxSwipeDistance: PropTypes.number.isRequired,
|
||||
onOpen: PropTypes.func,
|
||||
onSwipeEnd: PropTypes.func.isRequired,
|
||||
onSwipeStart: PropTypes.func.isRequired,
|
||||
|
@ -79,17 +74,13 @@ const SwipeableRow = React.createClass({
|
|||
* component A to be transparent until component B is loaded.
|
||||
*/
|
||||
isSwipeableViewRendered: false,
|
||||
/**
|
||||
* scrollViewWidth can change based on orientation, thus it's stored as a
|
||||
* state variable. This means all styles depending on it will be inline
|
||||
*/
|
||||
scrollViewWidth: 0,
|
||||
};
|
||||
},
|
||||
|
||||
getDefaultProps(): Object {
|
||||
return {
|
||||
isOpen: false,
|
||||
maxSwipeDistance: 0,
|
||||
onSwipeEnd: emptyFunction,
|
||||
onSwipeStart: emptyFunction,
|
||||
swipeThreshold: 30,
|
||||
|
@ -122,26 +113,26 @@ const SwipeableRow = React.createClass({
|
|||
},
|
||||
|
||||
render(): ReactElement {
|
||||
const slideoutStyle = [styles.slideOutContainer];
|
||||
if (Platform.OS === 'ios') {
|
||||
slideoutStyle.push({opacity: this.state.isSwipeableViewRendered ? 1 : 0});
|
||||
// The view hidden behind the main view
|
||||
let slideOutView;
|
||||
if (this.state.isSwipeableViewRendered) {
|
||||
slideOutView = (
|
||||
<View style={styles.slideOutContainer}>
|
||||
{this.props.slideoutView}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
// The view hidden behind the main view
|
||||
const slideOutView = (
|
||||
<View style={slideoutStyle}>
|
||||
{this.props.slideoutView}
|
||||
</View>
|
||||
);
|
||||
|
||||
// The swipable item
|
||||
// The swipeable item
|
||||
const swipeableView = (
|
||||
<Animated.View
|
||||
onLayout={this._onSwipeableViewLayout}
|
||||
style={{
|
||||
transform: [{translateX: this.state.currentLeft}],
|
||||
width: this.state.scrollViewWidth,
|
||||
}}>
|
||||
style={[
|
||||
styles.swipeableContainer,
|
||||
{
|
||||
transform: [{translateX: this.state.currentLeft}],
|
||||
},
|
||||
]}>
|
||||
{this.props.children}
|
||||
</Animated.View>
|
||||
);
|
||||
|
@ -149,8 +140,7 @@ const SwipeableRow = React.createClass({
|
|||
return (
|
||||
<View
|
||||
{...this._panResponder.panHandlers}
|
||||
style={styles.container}
|
||||
onLayout={this._onLayoutChange}>
|
||||
style={styles.container}>
|
||||
{slideOutView}
|
||||
{swipeableView}
|
||||
</View>
|
||||
|
@ -158,7 +148,7 @@ const SwipeableRow = React.createClass({
|
|||
},
|
||||
|
||||
_onSwipeableViewLayout(event: Object): void {
|
||||
if (!this._isSwipeableViewRendered && this.state.scrollViewWidth !== 0) {
|
||||
if (!this.state.isSwipeableViewRendered) {
|
||||
this.setState({
|
||||
isSwipeableViewRendered: true,
|
||||
});
|
||||
|
@ -198,10 +188,7 @@ const SwipeableRow = React.createClass({
|
|||
},
|
||||
|
||||
_animateToOpenPosition(): void {
|
||||
const toValue = this.props.maxSwipeDistance
|
||||
? -this.props.maxSwipeDistance
|
||||
: -this.state.scrollViewWidth;
|
||||
this._animateTo(toValue);
|
||||
this._animateTo(-this.props.maxSwipeDistance);
|
||||
},
|
||||
|
||||
_animateToClosedPosition(): void {
|
||||
|
@ -235,15 +222,6 @@ const SwipeableRow = React.createClass({
|
|||
|
||||
this.props.onSwipeEnd();
|
||||
},
|
||||
|
||||
_onLayoutChange(event: Object): void {
|
||||
const width = event.nativeEvent.layout.width;
|
||||
if (width && width !== this.state.scrollViewWidth) {
|
||||
this.setState({
|
||||
scrollViewWidth: width,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
|
@ -259,6 +237,9 @@ const styles = StyleSheet.create({
|
|||
right: 0,
|
||||
top: 0,
|
||||
},
|
||||
swipeableContainer: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = SwipeableRow;
|
||||
|
|
Loading…
Reference in New Issue