From 6adba409e6256fd2dcc27a4272edcedae89927af 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 c61279893f0ad0..e01bd43b67c6e9 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 @@ -519,7 +520,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 3d289464bd15c7..beaedda782d582 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)