Skip to content

Commit

Permalink
Scrollview updatedChildFrames data controlled by prop
Browse files Browse the repository at this point in the history
Summary: Optimize ScrollView by adding flag "DEPRECATED_sendUpdatedChildFrames" to gate whether updatedChildFrames data is computed and propagated on scroll events.  The frame data is used in ListView by the onChangeVisibleRows prop.  When this prop is not defined, unnecessary computation in ScrollView should not be performed.

Reviewed By: sahrens

Differential Revision: D5174898

fbshipit-source-id: e3eaed8760b76becf14dfeb00122bdebdaeae4ef
  • Loading branch information
John O'Leary authored and facebook-github-bot committed Jun 8, 2017
1 parent d062cc2 commit 62b20ce
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 8 deletions.
13 changes: 13 additions & 0 deletions Libraries/Components/ScrollView/ScrollView.js
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,15 @@ const ScrollView = React.createClass({
'always',
'never',
]),
/**
* When true, ScrollView will emit updateChildFrames data in scroll events,
* otherwise will not compute or emit child frame data. This only exists
* to support legacy issues, `onLayout` should be used instead to retrieve
* frame data.
* The default value is false.
* @platform ios
*/
DEPRECATED_sendUpdatedChildFrames: PropTypes.bool,
},

mixins: [ScrollResponder.Mixin],
Expand Down Expand Up @@ -682,6 +691,9 @@ const ScrollView = React.createClass({
this.props.alwaysBounceVertical :
!this.props.horizontal;

const DEPRECATED_sendUpdatedChildFrames =
!!this.props.DEPRECATED_sendUpdatedChildFrames;

const baseStyle = this.props.horizontal ? styles.baseHorizontal : styles.baseVertical;
const props = {
...this.props,
Expand Down Expand Up @@ -710,6 +722,7 @@ const ScrollView = React.createClass({
scrollEventThrottle: hasStickyHeaders ? 1 : this.props.scrollEventThrottle,
sendMomentumEvents: (this.props.onMomentumScrollBegin || this.props.onMomentumScrollEnd) ?
true : false,
DEPRECATED_sendUpdatedChildFrames,
};

const { decelerationRate } = this.props;
Expand Down
1 change: 1 addition & 0 deletions Libraries/Lists/ListView/ListView.js
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ var ListView = React.createClass({
ref: this._setScrollComponentRef,
onContentSizeChange: this._onContentSizeChange,
onLayout: this._onLayout,
DEPRECATED_sendUpdatedChildFrames: props.onChangeVisibleRows !== undefined,
}, header, bodyComponents, footer);
},

Expand Down
1 change: 1 addition & 0 deletions React/Views/RCTScrollView.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

@property (nonatomic, assign) UIEdgeInsets contentInset;
@property (nonatomic, assign) BOOL automaticallyAdjustContentInsets;
@property (nonatomic, assign) BOOL DEPRECATED_sendUpdatedChildFrames;
@property (nonatomic, assign) NSTimeInterval scrollEventThrottle;
@property (nonatomic, assign) BOOL centerContent;
@property (nonatomic, assign) int snapToInterval;
Expand Down
16 changes: 8 additions & 8 deletions React/Views/RCTScrollView.m
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ - (BOOL)canCoalesce
- (RCTScrollEvent *)coalesceWithEvent:(RCTScrollEvent *)newEvent
{
NSArray<NSDictionary *> *updatedChildFrames = [_userData[@"updatedChildFrames"] arrayByAddingObjectsFromArray:newEvent->_userData[@"updatedChildFrames"]];

if (updatedChildFrames) {
NSMutableDictionary *userData = [newEvent->_userData mutableCopy];
userData[@"updatedChildFrames"] = updatedChildFrames;
Expand Down Expand Up @@ -338,6 +337,7 @@ - (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
_scrollView.delegate = self;
_scrollView.delaysContentTouches = NO;
_automaticallyAdjustContentInsets = YES;
_DEPRECATED_sendUpdatedChildFrames = NO;
_contentInset = UIEdgeInsetsZero;
_contentSize = CGSizeZero;
_lastClippedToRect = CGRectNull;
Expand Down Expand Up @@ -587,9 +587,7 @@ - (void)removeScrollListener:(NSObject<UIScrollViewDelegate> *)scrollListener
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[self updateClippedSubviews];

NSTimeInterval now = CACurrentMediaTime();

/**
* TODO: this logic looks wrong, and it may be because it is. Currently, if _scrollEventThrottle
* is set to zero (the default), the "didScroll" event is only sent once per scroll, instead of repeatedly
Expand All @@ -599,16 +597,18 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView
if (_allowNextScrollNoMatterWhat ||
(_scrollEventThrottle > 0 && _scrollEventThrottle < (now - _lastScrollDispatchTime))) {

// Calculate changed frames
NSArray<NSDictionary *> *childFrames = [self calculateChildFramesData];

// Dispatch event
RCT_SEND_SCROLL_EVENT(onScroll, (@{@"updatedChildFrames": childFrames}));
if (_DEPRECATED_sendUpdatedChildFrames) {
// Calculate changed frames
RCT_SEND_SCROLL_EVENT(onScroll, (@{@"updatedChildFrames": [self calculateChildFramesData]}));
} else {
RCT_SEND_SCROLL_EVENT(onScroll, nil);
}

// Update dispatch time
_lastScrollDispatchTime = now;
_allowNextScrollNoMatterWhat = NO;
}

RCT_FORWARD_SCROLL_EVENT(scrollViewDidScroll:scrollView);
}

Expand Down
1 change: 1 addition & 0 deletions React/Views/RCTScrollViewManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ - (UIView *)view
RCT_EXPORT_VIEW_PROPERTY(onMomentumScrollBegin, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onMomentumScrollEnd, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onScrollAnimationEnd, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(DEPRECATED_sendUpdatedChildFrames, BOOL)

// overflow is used both in css-layout as well as by react-native. In css-layout
// we always want to treat overflow as scroll but depending on what the overflow
Expand Down

0 comments on commit 62b20ce

Please sign in to comment.