Skip to content

Commit

Permalink
RCTTextInput: Common layout logic was moved to base class
Browse files Browse the repository at this point in the history
Summary:
Nothing really changed except that there is no code duplication in this part anymore.
More unification is coming!

Reviewed By: mmmulani

Differential Revision: D5144435

fbshipit-source-id: 390f795be3228907b254f8656783232013c36abe
  • Loading branch information
shergin authored and facebook-github-bot committed Jun 27, 2017
1 parent 3364488 commit a8c45ac
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 177 deletions.
1 change: 1 addition & 0 deletions Libraries/Text/RCTBackedTextInputViewProtocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
@property (nonatomic, strong, nullable) UIColor *placeholderColor;
@property (nonatomic, assign, readonly) BOOL textWasPasted;
@property (nonatomic, strong, nullable) UIFont *font;
@property (nonatomic, assign) UIEdgeInsets textContainerInset;

@end
2 changes: 0 additions & 2 deletions Libraries/Text/RCTTextField.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
@property (nonatomic, assign) BOOL blurOnSubmit;
@property (nonatomic, assign) NSInteger mostRecentEventCount;
@property (nonatomic, strong) NSNumber *maxLength;
@property (nonatomic, assign) UIEdgeInsets reactPaddingInsets;
@property (nonatomic, assign) UIEdgeInsets reactBorderInsets;

@property (nonatomic, copy) RCTDirectEventBlock onSelectionChange;

Expand Down
75 changes: 0 additions & 75 deletions Libraries/Text/RCTTextField.m
Original file line number Diff line number Diff line change
Expand Up @@ -87,22 +87,6 @@ - (void)sendKeyValueForString:(NSString *)string

#pragma mark - Properties

- (void)setReactPaddingInsets:(UIEdgeInsets)reactPaddingInsets
{
_reactPaddingInsets = reactPaddingInsets;
// We apply `paddingInsets` as `_textField`'s `textContainerInset`.
_textField.textContainerInset = reactPaddingInsets;
[self setNeedsLayout];
}

- (void)setReactBorderInsets:(UIEdgeInsets)reactBorderInsets
{
_reactBorderInsets = reactBorderInsets;
// We apply `borderInsets` as `_textView` layout offset.
_textField.frame = UIEdgeInsetsInsetRect(self.bounds, reactBorderInsets);
[self setNeedsLayout];
}

- (void)setSelection:(RCTTextSelection *)selection
{
if (!selection) {
Expand Down Expand Up @@ -240,65 +224,6 @@ - (void)sendSelectionEvent
}
}

#pragma mark - Content Size (in Yoga terms, without any insets)

- (CGSize)contentSize
{
// Returning value does NOT include border and padding insets.
CGSize contentSize = self.intrinsicContentSize;
UIEdgeInsets compoundInsets = self.reactCompoundInsets;
contentSize.width -= compoundInsets.left + compoundInsets.right;
contentSize.height -= compoundInsets.top + compoundInsets.bottom;
return contentSize;
}

- (void)invalidateContentSize
{
CGSize contentSize = self.contentSize;

if (CGSizeEqualToSize(_previousContentSize, contentSize)) {
return;
}
_previousContentSize = contentSize;

[_bridge.uiManager setIntrinsicContentSize:contentSize forView:self];
}

#pragma mark - Layout (in UIKit terms, with all insets)

- (CGSize)intrinsicContentSize
{
// Returning value DOES include border and padding insets.
CGSize size = _textField.intrinsicContentSize;
size.width += _reactBorderInsets.left + _reactBorderInsets.right;
size.height += _reactBorderInsets.top + _reactBorderInsets.bottom;
return size;
}

- (CGSize)sizeThatFits:(CGSize)size
{
CGFloat compoundHorizontalBorderInset = _reactBorderInsets.left + _reactBorderInsets.right;
CGFloat compoundVerticalBorderInset = _reactBorderInsets.top + _reactBorderInsets.bottom;

size.width -= compoundHorizontalBorderInset;
size.height -= compoundVerticalBorderInset;

// Note: `paddingInsets` already included in `_textView` size
// because it was applied as `textContainerInset`.
CGSize fittingSize = [_textField sizeThatFits:size];

fittingSize.width += compoundHorizontalBorderInset;
fittingSize.height += compoundVerticalBorderInset;

return fittingSize;
}

- (void)layoutSubviews
{
[super layoutSubviews];
[self invalidateContentSize];
}

#pragma mark - UITextFieldDelegate

- (BOOL)textField:(RCTTextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
Expand Down
8 changes: 8 additions & 0 deletions Libraries/Text/RCTTextInput.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,12 @@

@property (nonatomic, readonly) UIView<RCTBackedTextInputViewProtocol> *backedTextInputView;

@property (nonatomic, assign) UIEdgeInsets reactPaddingInsets;
@property (nonatomic, assign) UIEdgeInsets reactBorderInsets;
@property (nonatomic, assign, readonly) CGSize contentSize;

@property (nonatomic, copy) RCTDirectEventBlock onContentSizeChange;

- (void)invalidateContentSize;

@end
94 changes: 93 additions & 1 deletion Libraries/Text/RCTTextInput.m
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@
#import <React/RCTConvert.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTUtils.h>
#import <React/RCTUIManager.h>
#import <React/UIView+React.h>

@implementation RCTTextInput
@implementation RCTTextInput {
CGSize _previousContentSize;
}

- (instancetype)initWithBridge:(RCTBridge *)bridge
{
Expand All @@ -39,6 +42,95 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge
return nil;
}

#pragma mark - Properties

- (void)setReactPaddingInsets:(UIEdgeInsets)reactPaddingInsets
{
_reactPaddingInsets = reactPaddingInsets;
// We apply `paddingInsets` as `backedTextInputView`'s `textContainerInset`.
self.backedTextInputView.textContainerInset = reactPaddingInsets;
[self setNeedsLayout];
}

- (void)setReactBorderInsets:(UIEdgeInsets)reactBorderInsets
{
_reactBorderInsets = reactBorderInsets;
// We apply `borderInsets` as `backedTextInputView` layout offset.
self.backedTextInputView.frame = UIEdgeInsetsInsetRect(self.bounds, reactBorderInsets);
[self setNeedsLayout];
}

#pragma mark - Content Size (in Yoga terms, without any insets)

- (CGSize)contentSize
{
CGSize contentSize = self.intrinsicContentSize;
UIEdgeInsets compoundInsets = self.reactCompoundInsets;
contentSize.width -= compoundInsets.left + compoundInsets.right;
contentSize.height -= compoundInsets.top + compoundInsets.bottom;
// Returning value does NOT include border and padding insets.
return contentSize;
}

- (void)invalidateContentSize
{
// Updates `contentSize` property and notifies Yoga about the change, if necessary.
CGSize contentSize = self.contentSize;

if (CGSizeEqualToSize(_previousContentSize, contentSize)) {
return;
}
_previousContentSize = contentSize;

[_bridge.uiManager setIntrinsicContentSize:contentSize forView:self];

if (_onContentSizeChange) {
_onContentSizeChange(@{
@"contentSize": @{
@"height": @(contentSize.height),
@"width": @(contentSize.width),
},
@"target": self.reactTag,
});
}
}

#pragma mark - Layout (in UIKit terms, with all insets)

- (CGSize)intrinsicContentSize
{
CGSize size = self.backedTextInputView.intrinsicContentSize;
size.width += _reactBorderInsets.left + _reactBorderInsets.right;
size.height += _reactBorderInsets.top + _reactBorderInsets.bottom;
// Returning value DOES include border and padding insets.
return size;
}

- (CGSize)sizeThatFits:(CGSize)size
{
CGFloat compoundHorizontalBorderInset = _reactBorderInsets.left + _reactBorderInsets.right;
CGFloat compoundVerticalBorderInset = _reactBorderInsets.top + _reactBorderInsets.bottom;

size.width -= compoundHorizontalBorderInset;
size.height -= compoundVerticalBorderInset;

// Note: `paddingInsets` was already included in `backedTextInputView` size
// because it was applied as `textContainerInset`.
CGSize fittingSize = [self.backedTextInputView sizeThatFits:size];

fittingSize.width += compoundHorizontalBorderInset;
fittingSize.height += compoundVerticalBorderInset;

// Returning value DOES include border and padding insets.
return fittingSize;
}

- (void)layoutSubviews
{
[super layoutSubviews];
[self invalidateContentSize];
}

#pragma mark - Accessibility

- (UIView *)reactAccessibleView
Expand Down
4 changes: 0 additions & 4 deletions Libraries/Text/RCTTextView.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,8 @@
@property (nonatomic, strong) UIFont *font;
@property (nonatomic, assign) NSInteger mostRecentEventCount;
@property (nonatomic, strong) NSNumber *maxLength;
@property (nonatomic, assign, readonly) CGSize contentSize;
@property (nonatomic, assign) UIEdgeInsets reactPaddingInsets;
@property (nonatomic, assign) UIEdgeInsets reactBorderInsets;

@property (nonatomic, copy) RCTDirectEventBlock onChange;
@property (nonatomic, copy) RCTDirectEventBlock onContentSizeChange;
@property (nonatomic, copy) RCTDirectEventBlock onSelectionChange;
@property (nonatomic, copy) RCTDirectEventBlock onTextInput;
@property (nonatomic, copy) RCTDirectEventBlock onScroll;
Expand Down
87 changes: 0 additions & 87 deletions Libraries/Text/RCTTextView.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ @implementation RCTTextView
BOOL _blockTextShouldChange;
BOOL _nativeUpdatesInFlight;
NSInteger _nativeEventCount;

CGSize _previousContentSize;
}

- (instancetype)initWithBridge:(RCTBridge *)bridge
Expand Down Expand Up @@ -205,22 +203,6 @@ - (void)setFont:(UIFont *)font
[self setNeedsLayout];
}

- (void)setReactPaddingInsets:(UIEdgeInsets)reactPaddingInsets
{
_reactPaddingInsets = reactPaddingInsets;
// We apply `paddingInsets` as `_textView`'s `textContainerInset`.
_textView.textContainerInset = reactPaddingInsets;
[self setNeedsLayout];
}

- (void)setReactBorderInsets:(UIEdgeInsets)reactBorderInsets
{
_reactBorderInsets = reactBorderInsets;
// We apply `borderInsets` as `_textView` layout offset.
_textView.frame = UIEdgeInsetsInsetRect(self.bounds, reactBorderInsets);
[self setNeedsLayout];
}

- (void)setSelection:(RCTTextSelection *)selection
{
if (!selection) {
Expand Down Expand Up @@ -509,75 +491,6 @@ - (void)textViewDidEndEditing:(UITextView *)textView
eventCount:_nativeEventCount];
}

#pragma mark - Content Size (in Yoga terms, without any insets)

- (CGSize)contentSize
{
// Returning value does NOT include border and padding insets.
CGSize contentSize = self.intrinsicContentSize;
UIEdgeInsets compoundInsets = self.reactCompoundInsets;
contentSize.width -= compoundInsets.left + compoundInsets.right;
contentSize.height -= compoundInsets.top + compoundInsets.bottom;
return contentSize;
}

- (void)invalidateContentSize
{
CGSize contentSize = self.contentSize;

if (CGSizeEqualToSize(_previousContentSize, contentSize)) {
return;
}
_previousContentSize = contentSize;

[_bridge.uiManager setIntrinsicContentSize:contentSize forView:self];

if (_onContentSizeChange) {
_onContentSizeChange(@{
@"contentSize": @{
@"height": @(contentSize.height),
@"width": @(contentSize.width),
},
@"target": self.reactTag,
});
}
}

#pragma mark - Layout (in UIKit terms, with all insets)

- (CGSize)intrinsicContentSize
{
// Calling `sizeThatFits:` is probably more expensive method to compute
// content size compare to direct access `_textView.contentSize` property,
// but seems `sizeThatFits:` returns more reliable and consistent result.
// Returning value DOES include border and padding insets.
return [self sizeThatFits:CGSizeMake(self.bounds.size.width, INFINITY)];
}

- (CGSize)sizeThatFits:(CGSize)size
{
CGFloat compoundHorizontalBorderInset = _reactBorderInsets.left + _reactBorderInsets.right;
CGFloat compoundVerticalBorderInset = _reactBorderInsets.top + _reactBorderInsets.bottom;

size.width -= compoundHorizontalBorderInset;
size.height -= compoundVerticalBorderInset;

// Note: `paddingInsets` already included in `_textView` size
// because it was applied as `textContainerInset`.
CGSize fittingSize = [_textView sizeThatFits:size];

fittingSize.width += compoundHorizontalBorderInset;
fittingSize.height += compoundVerticalBorderInset;

return fittingSize;
}

- (void)layoutSubviews
{
[super layoutSubviews];
[self invalidateContentSize];
}

#pragma mark - UIScrollViewDelegate

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
Expand Down
2 changes: 2 additions & 0 deletions Libraries/Text/RCTUITextView.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, copy, nullable) NSString *placeholder;
@property (nonatomic, strong, nullable) UIColor *placeholderColor;

@property (nonatomic, assign) CGFloat preferredMaxLayoutWidth;

@end

NS_ASSUME_NONNULL_END
Loading

0 comments on commit a8c45ac

Please sign in to comment.