iOS: Add onScroll event to TextInput

Summary:
Corresponding Android PR: https://github.com/facebook/react-native/pull/11001

This adds an onScroll event to TextInput which is useful when a multiline TextInput has so much content that it is scrollable.

**Test plan (required)**

Verified the event works properly in a test app. Also, my team uses this event in our app.

Adam Comella
Microsoft Corp.
Closes https://github.com/facebook/react-native/pull/11002

Differential Revision: D4203565

Pulled By: ericvicenti

fbshipit-source-id: 7cb5e10325c3b03c6b395cce0f1bacb0528db40a
This commit is contained in:
Adam Comella
2016-11-22 11:52:18 -08:00
committed by Facebook Github Bot
parent 145692a940
commit c609aee733
4 changed files with 46 additions and 0 deletions

View File

@@ -364,6 +364,12 @@ const TextInput = React.createClass({
* Invoked on mount and layout changes with `{x, y, width, height}`.
*/
onLayout: PropTypes.func,
/**
* Invoked on content scroll with `{ nativeEvent: { contentOffset: { x, y } } }`.
* May also contain other properties from ScrollEvent but on Android contentSize
* is not provided for performance reasons.
*/
onScroll: PropTypes.func,
/**
* The string that will be rendered before text input has been entered.
*/
@@ -652,6 +658,7 @@ const TextInput = React.createClass({
onSelectionChangeShouldSetResponder={emptyFunction.thatReturnsTrue}
text={this._getText()}
dataDetectorTypes={this.props.dataDetectorTypes}
onScroll={this._onScroll}
/>;
}
@@ -811,6 +818,10 @@ const TextInput = React.createClass({
_onTextInput: function(event: Event) {
this.props.onTextInput && this.props.onTextInput(event);
},
_onScroll: function(event: Event) {
this.props.onScroll && this.props.onScroll(event);
},
});
var styles = StyleSheet.create({

View File

@@ -32,6 +32,7 @@
@property (nonatomic, copy) RCTDirectEventBlock onContentSizeChange;
@property (nonatomic, copy) RCTDirectEventBlock onSelectionChange;
@property (nonatomic, copy) RCTDirectEventBlock onTextInput;
@property (nonatomic, copy) RCTDirectEventBlock onScroll;
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER;

View File

@@ -106,6 +106,7 @@
#if !TARGET_OS_TV
_scrollView.scrollsToTop = NO;
#endif
_scrollView.delegate = self;
[_scrollView addSubview:_textView];
[self addSubview:_scrollView];
@@ -141,6 +142,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
}
}
- (void)dealloc
{
_scrollView.delegate = nil;
}
- (void)removeReactSubview:(UIView *)subview
{
[super removeReactSubview:subview];
@@ -694,4 +700,31 @@ static BOOL findMismatch(NSString *first, NSString *second, NSRange *firstRange,
return [UIColor colorWithRed:0.0/255.0 green:0.0/255.0 blue:0.098/255.0 alpha:0.22];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (_onScroll) {
_onScroll(@{
@"contentOffset": @{
@"x": @(scrollView.contentOffset.x),
@"y": @(scrollView.contentOffset.y)
},
@"contentInset": @{
@"top": @(_scrollView.contentInset.top),
@"left": @(_scrollView.contentInset.left),
@"bottom": @(_scrollView.contentInset.bottom),
@"right": @(_scrollView.contentInset.right)
},
@"contentSize": @{
@"width": @(_scrollView.contentSize.width),
@"height": @(_scrollView.contentSize.height)
},
@"layoutMeasurement": @{
@"width": @(_scrollView.frame.size.width),
@"height": @(_scrollView.frame.size.height)
},
@"zoomScale": @(_scrollView.zoomScale ?: 1),
});
}
}
@end

View File

@@ -38,6 +38,7 @@ RCT_EXPORT_VIEW_PROPERTY(maxLength, NSNumber)
RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onContentSizeChange, RCTBubblingEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onSelectionChange, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onScroll, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onTextInput, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(placeholder, NSString)
RCT_EXPORT_VIEW_PROPERTY(placeholderTextColor, UIColor)