facebook / react-native

A framework for building native applications using React
https://reactnative.dev
MIT License
119.27k stars 24.35k forks source link

[iOS] <Image> or <View> is to be nested within <Text> as child of <Text> the layout overlap #9059

Closed ymmuse closed 8 years ago

ymmuse commented 8 years ago

When i set the lineHeight of Text that is to be nested within Text as child of Text, I get the layout overlap. Here is my code:

class nestedImage extends Component {
  render() {
    return (
       <Text style={{lineHeight: 30}}>
          hello{'\n'}
            <Text>
            <View style={{width: 300, height: 100, backgroundColor: 'steelblue'}} />{'\n'}world
            </Text>
        </Text>
    );
  }
}

5e7e5ff0-27f6-4451-aaab-104de0788a67

Actually, If i remove the child Text that is a parent of View, I can get correct layout, but between the text 'hello' and View lineHeight is incorrect, And the lineHight change to the View Height.

class nestedImage extends Component {
  render() {
    return (
       <Text style={{lineHeight: 30}}>
          hello{'\n'}
            {/*<Text>*/}
            <View style={{width: 300, height: 100, backgroundColor: 'steelblue'}} />{'\n'}world
            {/*</Text>*/}
        </Text>
    );
  }
}

68ba16f8-2fa0-4d80-9e3f-50c2eef90fc6

At last, I found the native module code, that's why the lineHeight change to View height: get NSTextAttachment height setting all text lineHeight

I try to fix this problem, i found these code will take out the size of NSTextAttachment and it position. boundingRectForGlyphRange

About the position incorrect I found a interesting thing that the boundingRectForGlyphRange method cannot get correct position when setting ParagraphStyle.maximumLineHeight. So I have made a demo about testing boundingRectForGlyphRange on the situation.

    NSMutableAttributedString *s = [_textView.attributedText mutableCopy];

    NSMutableParagraphStyle *pstyle = [NSMutableParagraphStyle new];
//    uncomment these the string and image will be overlap
//    pstyle.maximumLineHeight = 30;
//    pstyle.minimumLineHeight = 30;

//  correct display string and image
    pstyle.lineSpacing = 50;

    [s addAttribute:NSParagraphStyleAttributeName value:pstyle range:(NSRange){0, s.length}];

    NSLayoutManager *layout = _textView.textStorage.layoutManagers.firstObject;
    NSTextContainer *textContainer = layout.textContainers.firstObject;
    NSRange glyphRange = [layout glyphRangeForTextContainer:textContainer];
    NSRange characterRange = [layout characterRangeForGlyphRange:glyphRange actualGlyphRange:NULL];
    [layout.textStorage enumerateAttribute:NSAttachmentAttributeName inRange:characterRange options:0 usingBlock:^(NSTextAttachment *child, NSRange range, BOOL *_) {
        if (child) {
            CGRect glyphRect = [layout boundingRectForGlyphRange:range inTextContainer:textContainer];
            NSLog(@"%@", glyphRect.origin.y);
        }
    }];

    [self setAttributedText:s];

Now, I am stucking...

ymmuse commented 8 years ago

no anyone know what has happened?

ymmuse commented 8 years ago

I wrote a testing demo in github. the detail that you could see the README

lacker commented 8 years ago

I can't quite figure out what problem you are reporting exactly. It's also been a while, so I'm going to close this issue. If this is still a problem for you then I suggest opening a new issue and being very clear about what code you are testing, what you see, and what you expect to see.