mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-24 12:25:59 +08:00
Implements onKeyPress
Summary: - When a key is pressed, it's `key value` is passed as an argument to the callback handler. - For `Enter` and `Backspace` keys, I'm using their `key value` as defined [here](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key#Key_values). As per JonasJonny & brentvatne's [suggestion](https://github.com/facebook/react-native/issues/1882#issuecomment-123485883). - Example ```javascript _handleKeyPress: function(e) { console.log(e.nativeEvent.key); }, render: function() { return ( <View style={styles.container}> <TextInput style={{width: 150, height: 25, borderWidth: 0.5}} onKeyPress={this._handleKeyPress} /> <TextInput style={{width: 150, height: 100, borderWidth: 0.5}} onKeyPress={this._handleKeyPress} multiline={true} /> </View> ); } ``` - Implements [shouldChangeCharactersInRange](https://developer.apple.com/library/prerelease/ios/documentat Closes https://github.com/facebook/react-native/pull/2082 Reviewed By: javache Differential Revision: D2280460 Pulled By: nicklockwood fb-gh-sync-id: 1f824f80649043dc2520c089e2531d428d799405
This commit is contained in:
committed by
facebook-github-bot-6
parent
6539b26810
commit
6c7c845145
@@ -20,8 +20,11 @@
|
||||
@property (nonatomic, strong) UIColor *placeholderTextColor;
|
||||
@property (nonatomic, assign) NSInteger mostRecentEventCount;
|
||||
@property (nonatomic, strong) NSNumber *maxLength;
|
||||
@property (nonatomic, assign) BOOL textWasPasted;
|
||||
|
||||
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (void)textFieldDidChange;
|
||||
- (void)sendKeyValueForString:(NSString *)string;
|
||||
|
||||
@end
|
||||
|
||||
@@ -39,6 +39,23 @@
|
||||
RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
|
||||
RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
|
||||
|
||||
- (void)sendKeyValueForString:(NSString *)string
|
||||
{
|
||||
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeKeyPress
|
||||
reactTag:self.reactTag
|
||||
text:nil
|
||||
key:string
|
||||
eventCount:_nativeEventCount];
|
||||
}
|
||||
|
||||
// This method is overriden for `onKeyPress`. The manager
|
||||
// will not send a keyPress for text that was pasted.
|
||||
- (void)paste:(id)sender
|
||||
{
|
||||
_textWasPasted = YES;
|
||||
[super paste:sender];
|
||||
}
|
||||
|
||||
- (void)setText:(NSString *)text
|
||||
{
|
||||
NSInteger eventLag = _nativeEventCount - _mostRecentEventCount;
|
||||
@@ -134,6 +151,7 @@ static void RCTUpdatePlaceholder(RCTTextField *self)
|
||||
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeChange
|
||||
reactTag:self.reactTag
|
||||
text:self.text
|
||||
key:nil
|
||||
eventCount:_nativeEventCount];
|
||||
}
|
||||
|
||||
@@ -142,6 +160,7 @@ static void RCTUpdatePlaceholder(RCTTextField *self)
|
||||
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeEnd
|
||||
reactTag:self.reactTag
|
||||
text:self.text
|
||||
key:nil
|
||||
eventCount:_nativeEventCount];
|
||||
}
|
||||
- (void)textFieldSubmitEditing
|
||||
@@ -149,6 +168,7 @@ static void RCTUpdatePlaceholder(RCTTextField *self)
|
||||
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeSubmit
|
||||
reactTag:self.reactTag
|
||||
text:self.text
|
||||
key:nil
|
||||
eventCount:_nativeEventCount];
|
||||
}
|
||||
|
||||
@@ -162,6 +182,7 @@ static void RCTUpdatePlaceholder(RCTTextField *self)
|
||||
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeFocus
|
||||
reactTag:self.reactTag
|
||||
text:self.text
|
||||
key:nil
|
||||
eventCount:_nativeEventCount];
|
||||
}
|
||||
|
||||
@@ -181,6 +202,7 @@ static void RCTUpdatePlaceholder(RCTTextField *self)
|
||||
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeBlur
|
||||
reactTag:self.reactTag
|
||||
text:self.text
|
||||
key:nil
|
||||
eventCount:_nativeEventCount];
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -31,6 +31,13 @@ RCT_EXPORT_MODULE()
|
||||
|
||||
- (BOOL)textField:(RCTTextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
|
||||
{
|
||||
// Only allow single keypresses for onKeyPress, pasted text will not be sent.
|
||||
if (textField.textWasPasted) {
|
||||
textField.textWasPasted = NO;
|
||||
} else {
|
||||
[textField sendKeyValueForString:string];
|
||||
}
|
||||
|
||||
if (textField.maxLength == nil || [string isEqualToString:@"\n"]) { // Make sure forms can be submitted via return
|
||||
return YES;
|
||||
}
|
||||
@@ -54,6 +61,14 @@ RCT_EXPORT_MODULE()
|
||||
}
|
||||
}
|
||||
|
||||
// This method allows us to detect a `Backspace` keyPress
|
||||
// even when there is no more text in the TextField
|
||||
- (BOOL)keyboardInputShouldDelete:(RCTTextField *)textField
|
||||
{
|
||||
[self textField:textField shouldChangeCharactersInRange:NSMakeRange(0, 0) replacementString:@""];
|
||||
return YES;
|
||||
}
|
||||
|
||||
RCT_EXPORT_VIEW_PROPERTY(caretHidden, BOOL)
|
||||
RCT_EXPORT_VIEW_PROPERTY(autoCorrect, BOOL)
|
||||
RCT_REMAP_VIEW_PROPERTY(editable, enabled, BOOL)
|
||||
|
||||
@@ -14,6 +14,22 @@
|
||||
#import "RCTUtils.h"
|
||||
#import "UIView+React.h"
|
||||
|
||||
@interface RCTUITextView : UITextView
|
||||
|
||||
@property (nonatomic, assign) BOOL textWasPasted;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTUITextView
|
||||
|
||||
- (void)paste:(id)sender
|
||||
{
|
||||
_textWasPasted = YES;
|
||||
[super paste:sender];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTTextView
|
||||
{
|
||||
RCTEventDispatcher *_eventDispatcher;
|
||||
@@ -33,7 +49,7 @@
|
||||
_eventDispatcher = eventDispatcher;
|
||||
_placeholderTextColor = [self defaultPlaceholderTextColor];
|
||||
|
||||
_textView = [[UITextView alloc] initWithFrame:self.bounds];
|
||||
_textView = [[RCTUITextView alloc] initWithFrame:self.bounds];
|
||||
_textView.backgroundColor = [UIColor clearColor];
|
||||
_textView.scrollsToTop = NO;
|
||||
_textView.delegate = self;
|
||||
@@ -56,15 +72,15 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
|
||||
// first focused.
|
||||
UIEdgeInsets adjustedFrameInset = UIEdgeInsetsZero;
|
||||
adjustedFrameInset.left = _contentInset.left - 5;
|
||||
|
||||
|
||||
UIEdgeInsets adjustedTextContainerInset = _contentInset;
|
||||
adjustedTextContainerInset.top += 5;
|
||||
adjustedTextContainerInset.left = 0;
|
||||
|
||||
|
||||
CGRect frame = UIEdgeInsetsInsetRect(self.bounds, adjustedFrameInset);
|
||||
_textView.frame = frame;
|
||||
_placeholderView.frame = frame;
|
||||
|
||||
|
||||
_textView.textContainerInset = adjustedTextContainerInset;
|
||||
_placeholderView.textContainerInset = adjustedTextContainerInset;
|
||||
}
|
||||
@@ -138,8 +154,18 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
|
||||
return _textView.text;
|
||||
}
|
||||
|
||||
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
|
||||
- (BOOL)textView:(RCTUITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
|
||||
{
|
||||
if (textView.textWasPasted) {
|
||||
textView.textWasPasted = NO;
|
||||
} else {
|
||||
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeKeyPress
|
||||
reactTag:self.reactTag
|
||||
text:nil
|
||||
key:text
|
||||
eventCount:_nativeEventCount];
|
||||
}
|
||||
|
||||
if (_maxLength == nil) {
|
||||
return YES;
|
||||
}
|
||||
@@ -215,6 +241,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
|
||||
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeFocus
|
||||
reactTag:self.reactTag
|
||||
text:textView.text
|
||||
key:nil
|
||||
eventCount:_nativeEventCount];
|
||||
}
|
||||
|
||||
@@ -225,6 +252,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
|
||||
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeChange
|
||||
reactTag:self.reactTag
|
||||
text:textView.text
|
||||
key:nil
|
||||
eventCount:_nativeEventCount];
|
||||
|
||||
}
|
||||
@@ -234,6 +262,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
|
||||
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeEnd
|
||||
reactTag:self.reactTag
|
||||
text:textView.text
|
||||
key:nil
|
||||
eventCount:_nativeEventCount];
|
||||
}
|
||||
|
||||
@@ -253,6 +282,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
|
||||
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeBlur
|
||||
reactTag:self.reactTag
|
||||
text:_textView.text
|
||||
key:nil
|
||||
eventCount:_nativeEventCount];
|
||||
}
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user