Support `<TextInput keyboardType="numeric" returnKeyType="done" />` on iOS

Summary:
Standard only-numeric (number pad) keyboard on iOS does not have any "Done" or "Enter" button, and this is often very badly hurt user experience.
Usually it can be solved by implementing custom `inputAccessoryView`, but RN does not have built-in support for customizing it.
So, this commit introduced limited support only for "Done" button (returnKeyType="done") and it should suite very well for the vast majority of use cases.
This is highly requested feature, see more details here:
https://github.com/facebook/react-native/issues/1190

Reviewed By: mmmulani

Differential Revision: D5268020

fbshipit-source-id: 90bd5bffac6aaa1fb7c5c2ac539b35b04d45918f
This commit is contained in:
Valentin Shergin 2017-06-27 16:05:11 -07:00 committed by Facebook Github Bot
parent 1081b21f3e
commit 2b1795c5ad
3 changed files with 62 additions and 0 deletions

View File

@ -18,5 +18,6 @@
@property (nonatomic, assign, readonly) BOOL textWasPasted;
@property (nonatomic, strong, nullable) UIFont *font;
@property (nonatomic, assign) UIEdgeInsets textContainerInset;
@property (nonatomic, strong, nullable) UIView *inputAccessoryView;
@end

View File

@ -155,4 +155,64 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
[self.backedTextInputView reactFocusIfNeeded];
}
#pragma mark - Custom Input Accessory View
- (void)didSetProps:(NSArray<NSString *> *)changedProps
{
[self invalidateInputAccessoryView];
}
- (void)invalidateInputAccessoryView
{
#if !TARGET_OS_TV
UIView<RCTBackedTextInputViewProtocol> *textInputView = self.backedTextInputView;
UIKeyboardType keyboardType = textInputView.keyboardType;
// These keyboard types (all are number pads) don't have a "Done" button by default,
// so we create an `inputAccessoryView` with this button for them.
BOOL shouldHaveInputAccesoryView =
(
keyboardType == UIKeyboardTypeNumberPad ||
keyboardType == UIKeyboardTypePhonePad ||
keyboardType == UIKeyboardTypeDecimalPad ||
keyboardType == UIKeyboardTypeASCIICapableNumberPad
) &&
textInputView.returnKeyType == UIReturnKeyDone;
BOOL hasInputAccesoryView = textInputView.inputAccessoryView != nil;
if (hasInputAccesoryView == shouldHaveInputAccesoryView) {
return;
}
if (shouldHaveInputAccesoryView) {
UIToolbar *toolbarView = [[UIToolbar alloc] init];
[toolbarView sizeToFit];
UIBarButtonItem *flexibleSpace =
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:nil
action:nil];
UIBarButtonItem *doneButton =
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self
action:@selector(handleInputAccessoryDoneButton)];
toolbarView.items = @[flexibleSpace, doneButton];
textInputView.inputAccessoryView = toolbarView;
}
else {
textInputView.inputAccessoryView = nil;
}
// We have to call `reloadInputViews` for focused text inputs to update an accessory view.
if (textInputView.isFirstResponder) {
[textInputView reloadInputViews];
}
#endif
}
- (void)handleInputAccessoryDoneButton
{
[self.backedTextInputView endEditing:YES];
}
@end

View File

@ -239,6 +239,7 @@ class BlurOnSubmitExample extends React.Component {
ref="4"
style={styles.default}
keyboardType="numeric"
returnKeyType="done"
placeholder="blurOnSubmit = false"
blurOnSubmit={false}
onSubmitEditing={() => this.focusNextField('5')}