From 360b53d77fc2f747443de017c5c2944d79c0e638 Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Fri, 31 Jan 2020 21:53:46 -0800 Subject: [PATCH] Implement TextInput autoFocus natively on iOS (#27803) Summary: This implement the autoFocus functionality natively instead of calling the focus method from JS on mount. This is needed to properly fix the issue described in https://github.com/facebook/react-native/issues/27217, where when using native navigation (UINavigationController) text input focus needs to happen in the same frame transition starts or it leads to an animation bug in UIKit. My previous attempt fixed the problem only partially and the bug could still happen since there is no guaranty code executed in useEffect will end up in the same frame as the native view being created and attached. To fix this I added an autoFocus prop to the native component on iOS and in didAttachToWindow we focus the input if it is set. This makes sure the focus is set in the same frame as the view hierarchy containing the input is created. ## Changelog [iOS] [Fixed] - Add native support for TextInput autoFocus on iOS Pull Request resolved: https://github.com/facebook/react-native/pull/27803 Test Plan: - Tested that the UI glitch when transitionning to a screen with an input with autofocus no longer happens in my app. - Tested that autofocus still works in RNTester - Made sure that onFocus does get called and TextInputState is updated properly Differential Revision: D19673369 Pulled By: TheSavior fbshipit-source-id: 14d8486ac635901622ca667c0e61c75fb446e493 --- Libraries/Text/TextInput/RCTBaseTextInputView.h | 1 + Libraries/Text/TextInput/RCTBaseTextInputView.m | 9 ++++++++- Libraries/Text/TextInput/RCTBaseTextInputViewManager.m | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Libraries/Text/TextInput/RCTBaseTextInputView.h b/Libraries/Text/TextInput/RCTBaseTextInputView.h index 186f83d5e80782..99ccfa1e3a01f5 100644 --- a/Libraries/Text/TextInput/RCTBaseTextInputView.h +++ b/Libraries/Text/TextInput/RCTBaseTextInputView.h @@ -40,6 +40,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, copy, nullable) RCTDirectEventBlock onScroll; @property (nonatomic, assign) NSInteger mostRecentEventCount; +@property (nonatomic, assign) BOOL autoFocus; @property (nonatomic, assign) BOOL blurOnSubmit; @property (nonatomic, assign) BOOL selectTextOnFocus; @property (nonatomic, assign) BOOL clearTextOnFocus; diff --git a/Libraries/Text/TextInput/RCTBaseTextInputView.m b/Libraries/Text/TextInput/RCTBaseTextInputView.m index 5a15e8fe641e1a..6966dbd7f092f4 100644 --- a/Libraries/Text/TextInput/RCTBaseTextInputView.m +++ b/Libraries/Text/TextInput/RCTBaseTextInputView.m @@ -25,6 +25,7 @@ @implementation RCTBaseTextInputView { BOOL _hasInputAccesoryView; NSString *_Nullable _predictedText; NSInteger _nativeEventCount; + BOOL _didMoveToWindow; } - (instancetype)initWithBridge:(RCTBridge *)bridge @@ -522,7 +523,13 @@ - (void)reactBlur - (void)didMoveToWindow { - [self.backedTextInputView reactFocusIfNeeded]; + if (self.autoFocus && !_didMoveToWindow) { + [self.backedTextInputView reactFocus]; + } else { + [self.backedTextInputView reactFocusIfNeeded]; + } + + _didMoveToWindow = YES; } #pragma mark - Custom Input Accessory View diff --git a/Libraries/Text/TextInput/RCTBaseTextInputViewManager.m b/Libraries/Text/TextInput/RCTBaseTextInputViewManager.m index c48f712884116e..6b7b5ad5ea2f0d 100644 --- a/Libraries/Text/TextInput/RCTBaseTextInputViewManager.m +++ b/Libraries/Text/TextInput/RCTBaseTextInputViewManager.m @@ -48,6 +48,7 @@ @implementation RCTBaseTextInputViewManager RCT_REMAP_VIEW_PROPERTY(clearButtonMode, backedTextInputView.clearButtonMode, UITextFieldViewMode) RCT_REMAP_VIEW_PROPERTY(scrollEnabled, backedTextInputView.scrollEnabled, BOOL) RCT_REMAP_VIEW_PROPERTY(secureTextEntry, backedTextInputView.secureTextEntry, BOOL) +RCT_EXPORT_VIEW_PROPERTY(autoFocus, BOOL) RCT_EXPORT_VIEW_PROPERTY(blurOnSubmit, BOOL) RCT_EXPORT_VIEW_PROPERTY(clearTextOnFocus, BOOL) RCT_EXPORT_VIEW_PROPERTY(keyboardType, UIKeyboardType)