diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m index e42b9e6d2..1a0998609 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m @@ -518,46 +518,39 @@ - (CGSize)textContentSize:(NSAttributedString*)attributedText removeVerticalInset:(BOOL)removeVerticalInset { - static UITextView* measurementTextView = nil; - static UITextView* measurementTextViewWithoutInset = nil; - - if (attributedText.length) - { - if (!measurementTextView) - { - measurementTextView = [[UITextView alloc] init]; - - measurementTextViewWithoutInset = [[UITextView alloc] init]; - // Remove the container inset: this operation impacts only the vertical margin. - // Note: consider textContainer.lineFragmentPadding to remove horizontal margin - measurementTextViewWithoutInset.textContainerInset = UIEdgeInsetsZero; - } - - // Select the right text view for measurement - UITextView *selectedTextView = (removeVerticalInset ? measurementTextViewWithoutInset : measurementTextView); - - selectedTextView.frame = CGRectMake(0, 0, _maxTextViewWidth, 0); - selectedTextView.attributedText = attributedText; - - CGSize size = [selectedTextView sizeThatFits:selectedTextView.frame.size]; - - // Manage the case where a string attribute has a single paragraph with a left indent - // In this case, [UITextView sizeThatFits] ignores the indent and return the width - // of the text only. - // So, add this indent afterwards - NSRange textRange = NSMakeRange(0, attributedText.length); - NSRange longestEffectiveRange; - NSParagraphStyle *paragraphStyle = [attributedText attribute:NSParagraphStyleAttributeName atIndex:0 longestEffectiveRange:&longestEffectiveRange inRange:textRange]; - - if (NSEqualRanges(textRange, longestEffectiveRange)) - { - size.width = size.width + paragraphStyle.headIndent; - } - - return size; + if (attributedText.length == 0) { + return CGSizeZero; } - return CGSizeZero; + // Grab the default textContainer insets and lineFragmentPadding from a dummy text view. + // This has no business being here but the refactoring effort would be too great (sceriu 05.09.2022) + static UITextView* measurementTextView = nil; + if (!measurementTextView) + { + measurementTextView = [[UITextView alloc] init]; + } + + CGFloat verticalInset = measurementTextView.textContainerInset.top + measurementTextView.textContainerInset.bottom; + CGFloat horizontalInset = measurementTextView.textContainer.lineFragmentPadding * 2; + + CGSize size = [attributedText boundingRectWithSize:CGSizeMake(_maxTextViewWidth - horizontalInset, CGFLOAT_MAX) + options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading + context:nil].size; + + //In iOS 7 and later, this method returns fractional sizes (in the size component of the returned rectangle); + // to use a returned size to size views, you must use raise its value to the nearest higher integer using the + // [ceil](https://developer.apple.com/documentation/kernel/1557272-ceil?changes=latest_major) function. + size.width = ceil(size.width); + size.height = ceil(size.height); + + // The result is expected to contain the textView textContainer's paddings. Add them back if necessary + if (removeVerticalInset == NO) { + size.height += verticalInset; + } + + size.width += horizontalInset; + + return size; } #pragma mark - Properties diff --git a/changelog.d/6441.bugfix b/changelog.d/6441.bugfix new file mode 100644 index 000000000..7c00e558a --- /dev/null +++ b/changelog.d/6441.bugfix @@ -0,0 +1 @@ +Fixed incorrect iOS 16 timeline item text height calculations leading to empty gaps. \ No newline at end of file