Skip to content

Commit 0f7477f

Browse files
aflanaganfacebook-github-bot-4
authored andcommitted
add flag to enable momentum scrolling on iOS
Summary: Expose a `decelerationNormalEnabled` flag on WebView, which, when enabled, will WebView's ScrollView's `decelerationRate` to `UIScrollViewDecelerationRateNormal`. This gives the WebView the same "momentum" style scrolling as other iOS views. This was discussed with ide in facebook#5447. Please let me know if there's anything I'm missing, or anything else you'd like to see in this pull request. Closes facebook#5527 Reviewed By: svcscm Differential Revision: D2870312 Pulled By: nicklockwood fb-gh-sync-id: 7dbfd06a349e3365a5df40c3bacf25a4fdb306cf
1 parent 4511993 commit 0f7477f

File tree

6 files changed

+62
-11
lines changed

6 files changed

+62
-11
lines changed

Examples/UIExplorer/ImageEditingExample.js

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ var {
3030
View,
3131
} = React;
3232

33-
var RCTScrollViewConsts = UIManager.RCTScrollView.Constants;
34-
3533
var PAGE_SIZE = 20;
3634

3735
type ImageOffset = {
@@ -249,17 +247,12 @@ class ImageCropper extends React.Component {
249247
}
250248

251249
render() {
252-
var decelerationRate =
253-
RCTScrollViewConsts && RCTScrollViewConsts.DecelerationRate ?
254-
RCTScrollViewConsts.DecelerationRate.Fast :
255-
0;
256-
257250
return (
258251
<ScrollView
259252
alwaysBounceVertical={true}
260253
automaticallyAdjustContentInsets={false}
261254
contentOffset={this._contentOffset}
262-
decelerationRate={decelerationRate}
255+
decelerationRate="fast"
263256
horizontal={true}
264257
maximumZoomScale={3.0}
265258
onMomentumScrollEnd={this._onScroll.bind(this)}

Examples/UIExplorer/WebViewExample.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ var WebViewExample = React.createClass({
9696
url={this.state.url}
9797
javaScriptEnabled={true}
9898
domStorageEnabled={true}
99+
decelerationRate="normal"
99100
onNavigationStateChange={this.onNavigationStateChange}
100101
onShouldStartLoadWithRequest={this.onShouldStartLoadWithRequest}
101102
startInLoadingState={true}

Libraries/Components/ScrollView/ScrollView.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ var invariant = require('invariant');
3232
var pointsDiffer = require('pointsDiffer');
3333
var requireNativeComponent = require('requireNativeComponent');
3434
var processColor = require('processColor');
35-
35+
var processDecelerationRate = require('processDecelerationRate');
3636
var PropTypes = React.PropTypes;
3737

3838
var SCROLLVIEW = 'ScrollView';
@@ -130,12 +130,18 @@ var ScrollView = React.createClass({
130130
contentContainerStyle: StyleSheetPropType(ViewStylePropTypes),
131131
/**
132132
* A floating-point number that determines how quickly the scroll view
133-
* decelerates after the user lifts their finger. Reasonable choices include
133+
* decelerates after the user lifts their finger. You may also use string
134+
* shortcuts `"normal"` and `"fast"` which match the underlying iOS settings
135+
* for `UIScrollViewDecelerationRateNormal` and
136+
* `UIScrollViewDecelerationRateFast` respectively.
134137
* - Normal: 0.998 (the default)
135138
* - Fast: 0.9
136139
* @platform ios
137140
*/
138-
decelerationRate: PropTypes.number,
141+
decelerationRate: PropTypes.oneOfType([
142+
PropTypes.oneOf(['fast', 'normal']),
143+
PropTypes.number,
144+
]),
139145
/**
140146
* When true, the scroll view's children are arranged horizontally in a row
141147
* instead of vertically in a column. The default value is false.
@@ -465,6 +471,11 @@ var ScrollView = React.createClass({
465471
function() { onRefreshStart && onRefreshStart(this.endRefreshing); }.bind(this);
466472
}
467473

474+
var { decelerationRate } = this.props;
475+
if (decelerationRate) {
476+
props.decelerationRate = processDecelerationRate(decelerationRate);
477+
}
478+
468479
var ScrollViewClass;
469480
if (Platform.OS === 'ios') {
470481
ScrollViewClass = RCTScrollView;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*
9+
* @providesModule processDecelerationRate
10+
*/
11+
'use strict';
12+
13+
var ScrollViewConsts = require('UIManager').RCTScrollView.Constants;
14+
15+
function processDecelerationRate(decelerationRate) {
16+
var ScrollViewDecelerationRateNormal = ScrollViewConsts && ScrollViewConsts.DecelerationRate.normal;
17+
var ScrollViewDecelerationRateFast = ScrollViewConsts && ScrollViewConsts.DecelerationRate.fast;
18+
19+
if (typeof decelerationRate === 'string') {
20+
if (decelerationRate === 'fast') {
21+
return ScrollViewDecelerationRateFast;
22+
} else if (decelerationRate === 'normal') {
23+
return ScrollViewDecelerationRateNormal;
24+
}
25+
}
26+
return decelerationRate;
27+
}
28+
29+
module.exports = processDecelerationRate;

Libraries/Components/WebView/WebView.ios.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ var StyleSheet = require('StyleSheet');
1818
var Text = require('Text');
1919
var UIManager = require('UIManager');
2020
var View = require('View');
21+
var ScrollView = require('ScrollView')
2122

23+
var processDecelerationRate = require('processDecelerationRate');
2224
var invariant = require('invariant');
2325
var keyMirror = require('keyMirror');
2426
var requireNativeComponent = require('requireNativeComponent');
@@ -117,6 +119,17 @@ var WebView = React.createClass({
117119
* @platform ios
118120
*/
119121
bounces: PropTypes.bool,
122+
/**
123+
* A floating-point number that determines how quickly the scroll view
124+
* decelerates after the user lifts their finger. You may also use string
125+
* shortcuts `"normal"` and `"fast"` which match the underlying iOS settings
126+
* for `UIScrollViewDecelerationRateNormal` and
127+
* `UIScrollViewDecelerationRateFast` respectively.
128+
* - Normal: 0.998
129+
* - Fast: 0.9 (the default for iOS WebView)
130+
* @platform ios
131+
*/
132+
decelerationRate: ScrollView.propTypes.decelerationRate,
120133
/**
121134
* @platform ios
122135
*/
@@ -228,6 +241,8 @@ var WebView = React.createClass({
228241
domStorageEnabled = this.props.domStorageEnabledAndroid;
229242
}
230243

244+
var decelerationRate = processDecelerationRate(this.props.decelerationRate);
245+
231246
var webView =
232247
<RCTWebView
233248
ref={RCT_WEBVIEW_REF}
@@ -238,6 +253,7 @@ var WebView = React.createClass({
238253
injectedJavaScript={this.props.injectedJavaScript}
239254
bounces={this.props.bounces}
240255
scrollEnabled={this.props.scrollEnabled}
256+
decelerationRate={decelerationRate}
241257
contentInset={this.props.contentInset}
242258
automaticallyAdjustContentInsets={this.props.automaticallyAdjustContentInsets}
243259
onLoadingStart={this.onLoadingStart}

React/Views/RCTWebViewManager.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ - (UIView *)view
3838
RCT_REMAP_VIEW_PROPERTY(bounces, _webView.scrollView.bounces, BOOL)
3939
RCT_REMAP_VIEW_PROPERTY(scrollEnabled, _webView.scrollView.scrollEnabled, BOOL)
4040
RCT_REMAP_VIEW_PROPERTY(scalesPageToFit, _webView.scalesPageToFit, BOOL)
41+
RCT_REMAP_VIEW_PROPERTY(decelerationRate, _webView.scrollView.decelerationRate, CGFloat)
4142
RCT_EXPORT_VIEW_PROPERTY(injectedJavaScript, NSString)
4243
RCT_EXPORT_VIEW_PROPERTY(contentInset, UIEdgeInsets)
4344
RCT_EXPORT_VIEW_PROPERTY(automaticallyAdjustContentInsets, BOOL)

0 commit comments

Comments
 (0)