Skip to content

Commit

Permalink
ios changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Szymon20000 committed Mar 8, 2023
1 parent 543a010 commit 9239ee6
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 15 deletions.
2 changes: 2 additions & 0 deletions Libraries/Components/TextInput/RCTTextInputViewConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ const RCTTextInputViewConfig = {
placeholder: true,
autoCorrect: true,
multiline: true,
numberOfLines: true,
maximumNumberOfLines: true,
textContentType: true,
maxLength: true,
autoCapitalize: true,
Expand Down
10 changes: 8 additions & 2 deletions Libraries/Components/TextInput/TextInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,6 @@ type AndroidProps = $ReadOnly<{|
/**
* Sets the number of lines for a `TextInput`. Use it with multiline set to
* `true` to be able to fill the lines.
* @platform android
*/
numberOfLines?: ?number,

Expand All @@ -532,10 +531,14 @@ type AndroidProps = $ReadOnly<{|
/**
* Sets the number of rows for a `TextInput`. Use it with multiline set to
* `true` to be able to fill the lines.
* @platform android
*/
rows?: ?number,

/**
* Sets the maximum number of lines the TextInput can have.
*/
maximumNumberOfLines?: ?number,

/**
* When `false`, it will prevent the soft keyboard from showing when the field is focused.
* Defaults to `true`.
Expand Down Expand Up @@ -1085,6 +1088,8 @@ function InternalTextInput(props: Props): React.Node {
accessibilityState,
id,
tabIndex,
rows,
numberOfLines,
...otherProps
} = props;

Expand Down Expand Up @@ -1462,6 +1467,7 @@ function InternalTextInput(props: Props): React.Node {
focusable={tabIndex !== undefined ? !tabIndex : focusable}
mostRecentEventCount={mostRecentEventCount}
nativeID={id ?? props.nativeID}
numberOfLines={props.rows ?? props.numberOfLines}
onBlur={_onBlur}
onKeyPressSync={props.unstable_onKeyPressSync}
onChange={_onChange}
Expand Down
2 changes: 1 addition & 1 deletion Libraries/Text/Text/RCTTextViewManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ @implementation RCTTextViewManager {

RCT_EXPORT_MODULE(RCTText)

RCT_REMAP_SHADOW_PROPERTY(numberOfLines, maximumNumberOfLines, NSInteger)
RCT_EXPORT_SHADOW_PROPERTY(maximumNumberOfLines, NSInteger)
RCT_REMAP_SHADOW_PROPERTY(ellipsizeMode, lineBreakMode, NSLineBreakMode)
RCT_REMAP_SHADOW_PROPERTY(adjustsFontSizeToFit, adjustsFontSizeToFit, BOOL)
RCT_REMAP_SHADOW_PROPERTY(minimumFontScale, minimumFontScale, CGFloat)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

#import <React/RCTMultilineTextInputView.h>
#import <React/RCTMultilineTextInputViewManager.h>
#import <React/RCTUITextView.h>
#import <React/RCTBaseTextInputShadowView.h>

@implementation RCTMultilineTextInputViewManager

Expand All @@ -17,8 +19,21 @@ - (UIView *)view
return [[RCTMultilineTextInputView alloc] initWithBridge:self.bridge];
}

- (RCTShadowView *)shadowView
{
RCTBaseTextInputShadowView *shadowView = (RCTBaseTextInputShadowView *)[super shadowView];

shadowView.maximumNumberOfLines = 0;
shadowView.exactNumberOfLines = 0;

return shadowView;
}

#pragma mark - Multiline <TextInput> (aka TextView) specific properties

RCT_REMAP_VIEW_PROPERTY(dataDetectorTypes, backedTextInputView.dataDetectorTypes, UIDataDetectorTypes)

RCT_EXPORT_SHADOW_PROPERTY(maximumNumberOfLines, NSInteger)
RCT_REMAP_SHADOW_PROPERTY(numberOfLines, exactNumberOfLines, NSInteger)

@end
1 change: 1 addition & 0 deletions Libraries/Text/TextInput/RCTBaseTextInputShadowView.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, copy, nullable) NSString *text;
@property (nonatomic, copy, nullable) NSString *placeholder;
@property (nonatomic, assign) NSInteger maximumNumberOfLines;
@property (nonatomic, assign) NSInteger exactNumberOfLines;
@property (nonatomic, copy, nullable) RCTDirectEventBlock onContentSizeChange;

- (void)uiManagerWillPerformMounting;
Expand Down
17 changes: 16 additions & 1 deletion Libraries/Text/TextInput/RCTBaseTextInputShadowView.m
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,22 @@ - (NSAttributedString *)measurableAttributedText

- (CGSize)sizeThatFitsMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximumSize
{
NSAttributedString *attributedText = [self measurableAttributedText];
NSMutableAttributedString *attributedText = [[self measurableAttributedText] mutableCopy];

/*
* The block below is responsible for setting the exact height of the view in lines
* Unfortunatelly, iOS doesn't export any easy way to do it. So we set maximumNumberOfLines
* prop and then add random lines at the front. However, they are only used for layout
* so they are not visible on the screen.
*/
if (self.exactNumberOfLines) {
NSMutableString *newLines = [NSMutableString stringWithCapacity: self.exactNumberOfLines];
for (NSUInteger i = 0UL; i < self.exactNumberOfLines; ++i) {
[newLines appendString:@"\n"];
}
[attributedText insertAttributedString:[[NSAttributedString alloc] initWithString:newLines attributes:self.textAttributes.effectiveTextAttributes] atIndex:0];
_maximumNumberOfLines = self.exactNumberOfLines;
}

if (!_textStorage) {
_textContainer = [NSTextContainer new];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ - (RCTShadowView *)shadowView
RCTBaseTextInputShadowView *shadowView = (RCTBaseTextInputShadowView *)[super shadowView];

shadowView.maximumNumberOfLines = 1;
shadowView.exactNumberOfLines = 0;

return shadowView;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,26 +170,50 @@ - (LinesMeasurements)getLinesForAttributedString:(facebook::react::AttributedStr
return paragraphLines;
}

- (NSTextStorage *)_textStorageAndLayoutManagerWithAttributesString:(NSAttributedString *)attributedString
- (NSTextStorage *)_textStorageAndLayoutManagerWithAttributesString:(NSAttributedString *)inputAttributedString
paragraphAttributes:(ParagraphAttributes)paragraphAttributes
size:(CGSize)size
{
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:size];

textContainer.lineFragmentPadding = 0.0; // Note, the default value is 5.
textContainer.lineBreakMode = paragraphAttributes.maximumNumberOfLines > 0
? RCTNSLineBreakModeFromEllipsizeMode(paragraphAttributes.ellipsizeMode)
: NSLineBreakByClipping;
textContainer.maximumNumberOfLines = paragraphAttributes.maximumNumberOfLines;

NSMutableAttributedString *attributedString = [ inputAttributedString mutableCopy];

/*
* The block below is responsible for setting the exact height of the view in lines
* Unfortunatelly, iOS doesn't export any easy way to do it. So we set maximumNumberOfLines
* prop and then add random lines at the front. However, they are only used for layout
* so they are not visible on the screen. This method is used for drawing only for Paragraph component
* but we set exact height in lines only on TextInput that doesn't use it.
*/
if (paragraphAttributes.numberOfLines) {
paragraphAttributes.maximumNumberOfLines = paragraphAttributes.numberOfLines;
NSMutableString *newLines = [NSMutableString stringWithCapacity: paragraphAttributes.numberOfLines];
for (NSUInteger i = 0UL; i < paragraphAttributes.numberOfLines; ++i) {
// K is added on purpose. New line seems to be not enough for NTtextContainer
[newLines appendString:@"K\n"];
}
NSDictionary<NSAttributedStringKey, id> * attributesOfFirstCharacter = [inputAttributedString attributesAtIndex:0 effectiveRange:NULL];


[attributedString insertAttributedString:[[NSAttributedString alloc] initWithString:newLines attributes:attributesOfFirstCharacter] atIndex:0];
}

NSTextContainer *textContainer = [NSTextContainer new];

NSLayoutManager *layoutManager = [NSLayoutManager new];
layoutManager.usesFontLeading = NO;
[layoutManager addTextContainer:textContainer];

NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedString];

NSTextStorage *textStorage = [NSTextStorage new];
[textStorage addLayoutManager:layoutManager];

textContainer.lineFragmentPadding = 0.0; // Note, the default value is 5.
textContainer.lineBreakMode = paragraphAttributes.maximumNumberOfLines > 0
? RCTNSLineBreakModeFromEllipsizeMode(paragraphAttributes.ellipsizeMode)
: NSLineBreakByClipping;
textContainer.size = size;
textContainer.maximumNumberOfLines = paragraphAttributes.maximumNumberOfLines;

[textStorage replaceCharactersInRange:(NSRange){0, textStorage.length} withAttributedString:attributedString];

if (paragraphAttributes.adjustsFontSizeToFit) {
CGFloat minimumFontSize = !isnan(paragraphAttributes.minimumFontSize) ? paragraphAttributes.minimumFontSize : 4.0;
CGFloat maximumFontSize = !isnan(paragraphAttributes.maximumFontSize) ? paragraphAttributes.maximumFontSize : 96.0;
Expand Down

0 comments on commit 9239ee6

Please sign in to comment.