Skip to content

Commit

Permalink
iOS: Support inline view truncation (#21456)
Browse files Browse the repository at this point in the history
Summary:
If text is truncated and an inline view appears after the truncation point, the user should not see the inline view. Instead, we have a bug such that the inline view is always visible at the end of the visible text.

This commit fixes this by marking the inline view as hidden if it appears after the truncation point.

This appears to be a regression. React Native used to have logic similar to what this commit is adding: https://github.com/facebook/react-native/blob/1e2a924ba60001c6f0587c7561536f00b2922cbf/Libraries/Text/RCTShadowText.m#L186-L192

**Before fix**

Inline view (blue square) is visible even though it appears after the truncation point:

![image](https://user-images.githubusercontent.com/199935/46382038-d3a71200-c65d-11e8-8179-2ce4aad8d010.png)

The full text being rendered was:

```
<Text numberOfLines={1}>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit,
  sed do eiusmod tempor incididunt ut labore et dolore magna
  <View style={{width: 50, height: 50, backgroundColor: 'steelblue'}} />
</Text>
```

**After fix**

Inline view is properly truncated:

![image](https://user-images.githubusercontent.com/199935/46382067-fdf8cf80-c65d-11e8-84ea-e2b71c229dae.png)

**Test Plan**

Tested that the inline view is hidden if it appears after the truncation point when `numberOfLines` is 1 and 2. Similarly, verified that the inline view is visible if it appears before the truncation point.

**Release Notes**

[IOS] [BUGFIX] [Text] - Fix case where inline view is visible even though it should have been truncated

Adam Comella
Microsoft Corp.
Pull Request resolved: #21456

Differential Revision: D10182991

Pulled By: shergin

fbshipit-source-id: a5bddddb1bb8672b61d4feaa04013a92c8224155
  • Loading branch information
Adam Comella authored and facebook-github-bot committed Nov 20, 2018
1 parent 27cfba2 commit 70826db
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 2 deletions.
9 changes: 7 additions & 2 deletions Libraries/Text/Text/RCTTextShadowView.m
Expand Up @@ -290,6 +290,9 @@ - (void)layoutSubviewsWithContext:(RCTLayoutContext)layoutContext
RCTRoundPixelValue(attachmentSize.width), RCTRoundPixelValue(attachmentSize.width),
RCTRoundPixelValue(attachmentSize.height) RCTRoundPixelValue(attachmentSize.height)
}}; }};

NSRange truncatedGlyphRange = [layoutManager truncatedGlyphRangeInLineFragmentForGlyphAtIndex:range.location];
BOOL viewIsTruncated = NSIntersectionRange(range, truncatedGlyphRange).length != 0;


RCTLayoutContext localLayoutContext = layoutContext; RCTLayoutContext localLayoutContext = layoutContext;
localLayoutContext.absolutePosition.x += frame.origin.x; localLayoutContext.absolutePosition.x += frame.origin.x;
Expand All @@ -300,9 +303,11 @@ - (void)layoutSubviewsWithContext:(RCTLayoutContext)layoutContext
layoutDirection:self.layoutMetrics.layoutDirection layoutDirection:self.layoutMetrics.layoutDirection
layoutContext:localLayoutContext]; layoutContext:localLayoutContext];


// Reinforcing a proper frame origin for the Shadow View.
RCTLayoutMetrics localLayoutMetrics = shadowView.layoutMetrics; RCTLayoutMetrics localLayoutMetrics = shadowView.layoutMetrics;
localLayoutMetrics.frame.origin = frame.origin; localLayoutMetrics.frame.origin = frame.origin; // Reinforcing a proper frame origin for the Shadow View.
if (viewIsTruncated) {
localLayoutMetrics.displayType = RCTDisplayTypeNone;
}
[shadowView layoutWithMetrics:localLayoutMetrics layoutContext:localLayoutContext]; [shadowView layoutWithMetrics:localLayoutMetrics layoutContext:localLayoutContext];
} }
]; ];
Expand Down
7 changes: 7 additions & 0 deletions React/Modules/RCTUIManager.m
Expand Up @@ -488,6 +488,7 @@ - (RCTViewManagerUIBlock)uiBlockWithLayoutUpdateForRootView:(RCTRootShadowView *
UIUserInterfaceLayoutDirection layoutDirection; UIUserInterfaceLayoutDirection layoutDirection;
BOOL isNew; BOOL isNew;
BOOL parentIsNew; BOOL parentIsNew;
RCTDisplayType displayType;
} RCTFrameData; } RCTFrameData;


// Construct arrays then hand off to main thread // Construct arrays then hand off to main thread
Expand All @@ -505,6 +506,7 @@ - (RCTViewManagerUIBlock)uiBlockWithLayoutUpdateForRootView:(RCTRootShadowView *
layoutMetrics.layoutDirection, layoutMetrics.layoutDirection,
shadowView.isNewView, shadowView.isNewView,
shadowView.superview.isNewView, shadowView.superview.isNewView,
layoutMetrics.displayType
}; };
} }
} }
Expand Down Expand Up @@ -566,6 +568,7 @@ - (RCTViewManagerUIBlock)uiBlockWithLayoutUpdateForRootView:(RCTRootShadowView *
RCTLayoutAnimation *updatingLayoutAnimation = isNew ? nil : layoutAnimationGroup.updatingLayoutAnimation; RCTLayoutAnimation *updatingLayoutAnimation = isNew ? nil : layoutAnimationGroup.updatingLayoutAnimation;
BOOL shouldAnimateCreation = isNew && !frameData.parentIsNew; BOOL shouldAnimateCreation = isNew && !frameData.parentIsNew;
RCTLayoutAnimation *creatingLayoutAnimation = shouldAnimateCreation ? layoutAnimationGroup.creatingLayoutAnimation : nil; RCTLayoutAnimation *creatingLayoutAnimation = shouldAnimateCreation ? layoutAnimationGroup.creatingLayoutAnimation : nil;
BOOL isHidden = frameData.displayType == RCTDisplayTypeNone;


void (^completion)(BOOL) = ^(BOOL finished) { void (^completion)(BOOL) = ^(BOOL finished) {
completionsCalled++; completionsCalled++;
Expand All @@ -581,6 +584,10 @@ - (RCTViewManagerUIBlock)uiBlockWithLayoutUpdateForRootView:(RCTRootShadowView *
if (view.reactLayoutDirection != layoutDirection) { if (view.reactLayoutDirection != layoutDirection) {
view.reactLayoutDirection = layoutDirection; view.reactLayoutDirection = layoutDirection;
} }

if (view.isHidden != isHidden) {
view.hidden = isHidden;
}


if (creatingLayoutAnimation) { if (creatingLayoutAnimation) {


Expand Down

0 comments on commit 70826db

Please sign in to comment.