Permalink
Browse files

Support `<TextInput keyboardType="numeric" returnKeyType="done" />` o…

…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:
#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 2b1795c5add2e1442878a884d6dcd8f0ec5c1572
@@ -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
@@ -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;

This comment has been minimized.

Show comment
Hide comment
@dariocravero

dariocravero Jul 21, 2017

should this support go, next, search and send too?

@dariocravero

dariocravero Jul 21, 2017

should this support go, next, search and send too?

This comment has been minimized.

Show comment
Hide comment
@shergin

shergin Jul 22, 2017

Contributor

Goooooood question. Do you need this functionality? The main problem here is i18n; UIBarButtonSystemItemDone automatically provides us "Done" button.

@shergin

shergin Jul 22, 2017

Contributor

Goooooood question. Do you need this functionality? The main problem here is i18n; UIBarButtonSystemItemDone automatically provides us "Done" button.

This comment has been minimized.

Show comment
Hide comment
@dariocravero

dariocravero Jul 22, 2017

Hi @shergin, thanks for asking. Yes, we do, for next.
I understand where you're coming from though, I was reading on https://developer.apple.com/documentation/uikit/uibarbuttonsystemitem?language=objc and can't seem to find one that would suit neither next nor go. There's one for search though.

I wonder, is there a way to access those i18n system values? After all, next and go are being translated in the keyboard already. The other solutions that I can see are either keeping some internal i18n records for this or asking the user to provide that text.

What're your thoughts on that?

@dariocravero

dariocravero Jul 22, 2017

Hi @shergin, thanks for asking. Yes, we do, for next.
I understand where you're coming from though, I was reading on https://developer.apple.com/documentation/uikit/uibarbuttonsystemitem?language=objc and can't seem to find one that would suit neither next nor go. There's one for search though.

I wonder, is there a way to access those i18n system values? After all, next and go are being translated in the keyboard already. The other solutions that I can see are either keeping some internal i18n records for this or asking the user to provide that text.

What're your thoughts on that?

This comment has been minimized.

Show comment
Hide comment
@shergin

shergin Aug 2, 2017

Contributor

Yeah. AFAIK, there is no way to access i18n values inside the system keyboard. We can easily wrap these strings into NSLocalizedStrings which makes them localizable using standard iOS approach. Probably this is good idea.

And moreover, if we do this, we will have to introduce a way to opt-out this feature (because current done exclusivity also works as opt-in trigger).

If you (or someone else) have strong feeling that we need this fuctionality... I would love to review your PR! 😄

@shergin

shergin Aug 2, 2017

Contributor

Yeah. AFAIK, there is no way to access i18n values inside the system keyboard. We can easily wrap these strings into NSLocalizedStrings which makes them localizable using standard iOS approach. Probably this is good idea.

And moreover, if we do this, we will have to introduce a way to opt-out this feature (because current done exclusivity also works as opt-in trigger).

If you (or someone else) have strong feeling that we need this fuctionality... I would love to review your PR! 😄

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
@@ -239,6 +239,7 @@ class BlurOnSubmitExample extends React.Component {
ref="4"
style={styles.default}
keyboardType="numeric"
returnKeyType="done"

This comment has been minimized.

Show comment
Hide comment
@MikeFvv

MikeFvv Oct 27, 2017

thank you very much , I need this

@MikeFvv

MikeFvv Oct 27, 2017

thank you very much , I need this

This comment has been minimized.

Show comment
Hide comment
@shergin

shergin Oct 27, 2017

Contributor

❤️

@shergin

shergin Oct 27, 2017

Contributor

❤️

placeholder="blurOnSubmit = false"
blurOnSubmit={false}
onSubmitEditing={() => this.focusNextField('5')}

8 comments on commit 2b1795c

@fabriziogiordano

This comment has been minimized.

Show comment
Hide comment
@fabriziogiordano

fabriziogiordano Jun 28, 2017

It would be nice to add this new feature in the official documentation.

fabriziogiordano replied Jun 28, 2017

It would be nice to add this new feature in the official documentation.

@sidrees00

This comment has been minimized.

Show comment
Hide comment
@sidrees00

sidrees00 Jul 6, 2017

Will this work on react-native version 0.45.1? I don't have the referenced files in my node_modules/react-native folder.

sidrees00 replied Jul 6, 2017

Will this work on react-native version 0.45.1? I don't have the referenced files in my node_modules/react-native folder.

@leandro-a-silva

This comment has been minimized.

Show comment
Hide comment
@leandro-a-silva

leandro-a-silva Aug 2, 2017

Very well! Thanks!!!

leandro-a-silva replied Aug 2, 2017

Very well! Thanks!!!

@douglasjunior

This comment has been minimized.

Show comment
Hide comment
@douglasjunior

douglasjunior Sep 1, 2017

This commit brought a problem when use a custom ToolBar, like IQKeyboardManager.

Is there any way to disable this feature?

douglasjunior replied Sep 1, 2017

This commit brought a problem when use a custom ToolBar, like IQKeyboardManager.

Is there any way to disable this feature?

@shergin

This comment has been minimized.

Show comment
Hide comment
@shergin

shergin Sep 1, 2017

Contributor

@douglasjunior Can you change returnKeyType for your <TextInput>s?

Contributor

shergin replied Sep 1, 2017

@douglasjunior Can you change returnKeyType for your <TextInput>s?

@shergin

This comment has been minimized.

Show comment
Hide comment
@shergin

shergin Sep 1, 2017

Contributor

@douglasjunior Oh, I see what you mean. RN uses self.textInputAccessoryView == nil as a flag to know should we rebuild/reset textInputAccessoryView or not, but that library also modifies this.
Technically, it can be fixed by having additional variable which will store the fact that textInputAccessoryView was constructed by RN.
I would love to see PR. 😄

Contributor

shergin replied Sep 1, 2017

@douglasjunior Oh, I see what you mean. RN uses self.textInputAccessoryView == nil as a flag to know should we rebuild/reset textInputAccessoryView or not, but that library also modifies this.
Technically, it can be fixed by having additional variable which will store the fact that textInputAccessoryView was constructed by RN.
I would love to see PR. 😄

@douglasjunior

This comment has been minimized.

Show comment
Hide comment
@douglasjunior

douglasjunior Sep 2, 2017

@shergin thanks. I'll try it.

But I think that if a textInputAccessoryView already exists, the RN should not replace it. What do you think?

douglasjunior replied Sep 2, 2017

@shergin thanks. I'll try it.

But I think that if a textInputAccessoryView already exists, the RN should not replace it. What do you think?

@douglasjunior

This comment has been minimized.

Show comment
Hide comment
@douglasjunior

douglasjunior replied Oct 2, 2017

Created #16071

Please sign in to comment.