Skip to content

Commit

Permalink
Support <TextInput keyboardType="numeric" returnKeyType="done" /> o…
Browse files Browse the repository at this point in the history
…n 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:
facebook#1190

Reviewed By: mmmulani

Differential Revision: D5268020

fbshipit-source-id: 90bd5bffac6aaa1fb7c5c2ac539b35b04d45918f
  • Loading branch information
shergin authored and facebook-github-bot committed Jun 27, 2017
1 parent 1081b21 commit 2b1795c
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 0 deletions.
1 change: 1 addition & 0 deletions Libraries/Text/RCTBackedTextInputViewProtocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
60 changes: 60 additions & 0 deletions Libraries/Text/RCTTextInput.m
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,64 @@ - (void)didMoveToWindow
[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
1 change: 1 addition & 0 deletions RNTester/js/TextInputExample.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')}
Expand Down

0 comments on commit 2b1795c

Please sign in to comment.