Toggle secureTextEntry cursor spacing (#23524)

Summary:
This is a fix for #5859, based on the feedback in #18587. Instead of using `didSetProps` it uses a setter. I will also note that setting to `nil` no longer works (crashes) so setting it to a blank string then back to the original works fine.

[iOS] [Fixed] - Toggling secureTextEntry correctly places cursor.
Pull Request resolved: https://github.com/facebook/react-native/pull/23524

Differential Revision: D14143028

Pulled By: cpojer

fbshipit-source-id: 5f3203d56b1329eb7359465f8ab50eb4f4fa5507
This commit is contained in:
Eric Lewis 2019-02-21 23:47:05 -08:00 committed by Mike Grabowski
parent 8e5eb6389f
commit c1392c2ff3
4 changed files with 45 additions and 2 deletions

View File

@ -43,6 +43,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, assign) BOOL blurOnSubmit;
@property (nonatomic, assign) BOOL selectTextOnFocus;
@property (nonatomic, assign) BOOL clearTextOnFocus;
@property (nonatomic, assign) BOOL secureTextEntry;
@property (nonatomic, copy) RCTTextSelection *selection;
@property (nonatomic, strong, nullable) NSNumber *maxLength;
@property (nonatomic, copy) NSAttributedString *attributedText;

View File

@ -283,6 +283,24 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
}
}
- (BOOL)secureTextEntry {
return self.backedTextInputView.secureTextEntry;
}
- (void)setSecureTextEntry:(BOOL)secureTextEntry {
UIView<RCTBackedTextInputViewProtocol> *textInputView = self.backedTextInputView;
if (textInputView.secureTextEntry != secureTextEntry) {
textInputView.secureTextEntry = secureTextEntry;
// Fix #5859, see https://stackoverflow.com/questions/14220187/uitextfield-has-trailing-whitespace-after-securetextentry-toggle/22537788#22537788
NSAttributedString *originalText = [textInputView.attributedText copy];
self.backedTextInputView.attributedText = [NSAttributedString new];
self.backedTextInputView.attributedText = originalText;
}
}
#pragma mark - RCTBackedTextInputDelegate
- (BOOL)textInputShouldBeginEditing

View File

@ -43,12 +43,12 @@ RCT_REMAP_VIEW_PROPERTY(keyboardAppearance, backedTextInputView.keyboardAppearan
RCT_REMAP_VIEW_PROPERTY(placeholder, backedTextInputView.placeholder, NSString)
RCT_REMAP_VIEW_PROPERTY(placeholderTextColor, backedTextInputView.placeholderColor, UIColor)
RCT_REMAP_VIEW_PROPERTY(returnKeyType, backedTextInputView.returnKeyType, UIReturnKeyType)
RCT_REMAP_VIEW_PROPERTY(secureTextEntry, backedTextInputView.secureTextEntry, BOOL)
RCT_REMAP_VIEW_PROPERTY(selectionColor, backedTextInputView.tintColor, UIColor)
RCT_REMAP_VIEW_PROPERTY(spellCheck, backedTextInputView.spellCheckingType, UITextSpellCheckingType)
RCT_REMAP_VIEW_PROPERTY(caretHidden, backedTextInputView.caretHidden, BOOL)
RCT_REMAP_VIEW_PROPERTY(clearButtonMode, backedTextInputView.clearButtonMode, UITextFieldViewMode)
RCT_REMAP_VIEW_PROPERTY(scrollEnabled, backedTextInputView.scrollEnabled, BOOL)
RCT_EXPORT_VIEW_PROPERTY(secureTextEntry, BOOL)
RCT_EXPORT_VIEW_PROPERTY(blurOnSubmit, BOOL)
RCT_EXPORT_VIEW_PROPERTY(clearTextOnFocus, BOOL)
RCT_EXPORT_VIEW_PROPERTY(keyboardType, UIKeyboardType)

View File

@ -212,7 +212,11 @@ class SecureEntryExample extends React.Component<$FlowFixMeProps, any> {
* comment and run Flow. */
constructor(props) {
super(props);
this.state = {text: ''};
this.state = {
text: '',
password: '',
isSecureTextEntry: true,
};
}
render() {
return (
@ -225,6 +229,26 @@ class SecureEntryExample extends React.Component<$FlowFixMeProps, any> {
value={this.state.text}
/>
<Text>Current text is: {this.state.text}</Text>
<View
style={{
flex: 1,
flexDirection: 'row',
}}>
<TextInput
style={styles.default}
defaultValue="cde"
onChangeText={text => this.setState({password: text})}
secureTextEntry={this.state.isSecureTextEntry}
value={this.state.password}
/>
<Switch
onValueChange={value => {
this.setState({isSecureTextEntry: value});
}}
style={{marginLeft: 4}}
value={this.state.isSecureTextEntry}
/>
</View>
</View>
);
}