Singleline <TextInput> now has intrinsic size

Summary:
Singleline <TextInput> now has intrinsic size which is equal to size of placeholder.
And if <TextInput> does not have placeholder it still has intrinsic height.
So, we don't need to set the size up manually every single time anymore!

(Multiline <TextInput> already has this feature.)

Reviewed By: mmmulani

Differential Revision: D5069971

fbshipit-source-id: f65c1062a812259b66d287929314dc571dc1f3ee
This commit is contained in:
Valentin Shergin 2017-05-29 15:56:38 -07:00 committed by Facebook Github Bot
parent c98fc33ce5
commit ea9d6746df
4 changed files with 41 additions and 9 deletions

View File

@ -11,7 +11,7 @@
#import <React/RCTComponent.h>
@class RCTEventDispatcher;
@class RCTBridge;
@interface RCTTextField : UITextField
@ -25,6 +25,6 @@
@property (nonatomic, copy) RCTDirectEventBlock onSelectionChange;
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithBridge:(RCTBridge *)bridge NS_DESIGNATED_INITIALIZER;
@end

View File

@ -9,8 +9,10 @@
#import "RCTTextField.h"
#import <React/RCTBridge.h>
#import <React/RCTConvert.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTUIManager.h>
#import <React/RCTUtils.h>
#import <React/UIView+React.h>
@ -47,6 +49,7 @@
@implementation RCTTextField
{
RCTBridge *_bridge;
RCTEventDispatcher *_eventDispatcher;
NSInteger _nativeEventCount;
BOOL _submitted;
@ -56,17 +59,20 @@
RCTTextFieldDelegateProxy *_delegateProxy;
}
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
- (instancetype)initWithBridge:(RCTBridge *)bridge
{
if ((self = [super initWithFrame:CGRectZero])) {
RCTAssert(eventDispatcher, @"eventDispatcher is a required parameter");
_eventDispatcher = eventDispatcher;
if (self = [super initWithFrame:CGRectZero]) {
RCTAssertParam(bridge);
_bridge = bridge;
_eventDispatcher = bridge.eventDispatcher;
_blurOnSubmit = YES;
[self addTarget:self action:@selector(textFieldDidChange) forControlEvents:UIControlEventEditingChanged];
[self addTarget:self action:@selector(textFieldBeginEditing) forControlEvents:UIControlEventEditingDidBegin];
[self addTarget:self action:@selector(textFieldEndEditing) forControlEvents:UIControlEventEditingDidEnd];
[self addTarget:self action:@selector(textFieldSubmitEditing) forControlEvents:UIControlEventEditingDidEndOnExit];
[self addObserver:self forKeyPath:@"selectedTextRange" options:0 context:nil];
_blurOnSubmit = YES;
// We cannot use `self.delegate = self;` here because `UITextField` implements some of these delegate methods itself,
// so if we implement this delegate on self, we will override some of its behaviours.
@ -165,6 +171,7 @@ static void RCTUpdatePlaceholder(RCTTextField *self)
{
super.placeholder = placeholder;
RCTUpdatePlaceholder(self);
[self updateIntrinsicContentSize];
}
- (CGRect)caretRectForPosition:(UITextPosition *)position
@ -186,6 +193,8 @@ static void RCTUpdatePlaceholder(RCTTextField *self)
return [self textRectForBounds:bounds];
}
#pragma mark - Events
- (void)textFieldDidChange
{
_nativeEventCount++;
@ -293,6 +302,20 @@ static void RCTUpdatePlaceholder(RCTTextField *self)
[self reactFocusIfNeeded];
}
- (void)setFont:(UIFont *)font
{
[super setFont:font];
[self updateIntrinsicContentSize];
}
- (void)updateIntrinsicContentSize
{
NSString *text = self.placeholder ?: @"";
CGSize size = [text sizeWithAttributes:@{NSFontAttributeName: self.font}];
size = CGSizeMake(RCTCeilPixelValue(size.width), RCTCeilPixelValue(size.height));
[_bridge.uiManager setIntrinsicContentSize:size forView:self];
}
#pragma mark - UITextFieldDelegate (Proxied)
- (BOOL)shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string

View File

@ -30,7 +30,7 @@ RCT_EXPORT_MODULE()
- (UIView *)view
{
return [[RCTTextField alloc] initWithEventDispatcher:self.bridge.eventDispatcher];
return [[RCTTextField alloc] initWithBridge:self.bridge];
}
RCT_EXPORT_VIEW_PROPERTY(caretHidden, BOOL)

View File

@ -347,7 +347,6 @@ var styles = StyleSheet.create({
paddingBottom: 300,
},
default: {
height: 26,
borderWidth: 0.5,
borderColor: '#0f0f0f',
flex: 1,
@ -760,6 +759,16 @@ exports.examples = [
);
}
},
{
title: 'TextInput Intrinsic Size',
render: function() {
return (
<View style={{height: 50}}>
<TextInput style={{position: 'absolute', fontSize: 16, backgroundColor: '#eeeeee'}} placeholder="Placeholder defines intrinsic size" />
</View>
);
}
},
{
title: 'Auto-expanding',
render: function() {