Fix: Calculation of the frame for a bubble component

This commit is contained in:
Nicolas Mauri 2023-04-18 11:37:34 +02:00
parent f23575ef4d
commit e3ae9caf8d
5 changed files with 57 additions and 17 deletions

View file

@ -600,36 +600,47 @@ NSString *const kMXKRoomBubbleCellKeyVerificationIncomingRequestDeclinePressed =
}
else if (roomBubbleTableViewCell.messageTextView)
{
// Force the textView used underneath to layout its frame properly
[roomBubbleTableViewCell setNeedsLayout];
[roomBubbleTableViewCell layoutIfNeeded];
// Compute the height
CGFloat textMessageHeight = 0;
if ([bubbleCellData isKindOfClass:[RoomBubbleCellData class]])
{
RoomBubbleCellData *roomBubbleCellData = (RoomBubbleCellData*)bubbleCellData;
if (!roomBubbleCellData.attachment && selectedComponent.attributedTextMessage)
{
textMessageHeight = [roomBubbleCellData rawTextHeight:selectedComponent.attributedTextMessage];
// Get the width of messageTextView to compute the needed height
CGFloat maxTextWidth = CGRectGetWidth(roomBubbleTableViewCell.messageTextView.bounds);
// Compute text message height
textMessageHeight = [roomBubbleCellData rawTextHeight:selectedComponent.attributedTextMessage withMaxWidth:maxTextWidth];
}
}
selectedComponentPositionY = selectedComponent.position.y;
// Get the messageText frame in the cell content view (as the messageTextView may be inside a stackView and not directly a child of the tableViewCell)
UITextView *messageTextView = roomBubbleTableViewCell.messageTextView;
CGRect messageTextViewFrame = [messageTextView convertRect:messageTextView.bounds toView:roomBubbleTableViewCell.contentView];
if (textMessageHeight > 0)
{
selectedComponentHeight = textMessageHeight;
}
else
{
selectedComponentHeight = roomBubbleTableViewCell.frame.size.height - selectedComponentPositionY;
// if we don't have a height, use the messageTextView height without the text container vertical insets to stay aligned with the text.
selectedComponentHeight = CGRectGetHeight(messageTextViewFrame) - messageTextView.textContainerInset.top - messageTextView.textContainerInset.bottom;
}
// Force the textView used underneath to layout its frame properly
[roomBubbleTableViewCell setNeedsLayout];
[roomBubbleTableViewCell layoutIfNeeded];
selectedComponenContentViewYOffset = roomBubbleTableViewCell.messageTextView.frame.origin.y;
// Get the vertical position of the messageTextView relative to the contentView
selectedComponenContentViewYOffset = CGRectGetMinY(messageTextViewFrame);
// Get the position of the component inside the messageTextView
selectedComponentPositionY = selectedComponent.position.y;
}
if (roomBubbleTableViewCell.attachmentView || roomBubbleTableViewCell.messageTextView)
{
CGFloat x = 0;
@ -801,8 +812,7 @@ NSString *const kMXKRoomBubbleCellKeyVerificationIncomingRequestDeclinePressed =
- (void)addTickView:(UIView *)tickView atIndex:(NSInteger)index
{
CGRect componentFrame = [self componentFrameInContentViewForIndex: index];
CGRect componentFrame = [self componentFrameInContentViewForIndex:index];
tickView.frame = CGRectMake(self.contentView.bounds.size.width - tickView.frame.size.width - 2 * PlainRoomCellLayoutConstants.readReceiptsViewRightMargin, CGRectGetMaxY(componentFrame) - tickView.frame.size.height, tickView.frame.size.width, tickView.frame.size.height);
[self.contentView addSubview:tickView];

View file

@ -144,6 +144,15 @@
*/
- (CGFloat)rawTextHeight:(NSAttributedString*)attributedText;
/**
Return the raw height of the provided text by removing any vertical margin/inset and constraining the width.
@param attributedText the attributed text to measure
@param maxTextViewWidth the maximum text width
@return the computed height
*/
- (CGFloat)rawTextHeight:(NSAttributedString*)attributedText withMaxWidth:(CGFloat)maxTextViewWidth;
/**
Return the content size of a text view initialized with the provided attributed text.
CAUTION: This method runs only on main thread.

View file

@ -500,23 +500,34 @@
// Return the raw height of the provided text by removing any margin
- (CGFloat)rawTextHeight: (NSAttributedString*)attributedText
{
return [self rawTextHeight:attributedText withMaxWidth:_maxTextViewWidth];
}
// Return the raw height of the provided text by removing any vertical margin/inset and constraining the width.
- (CGFloat)rawTextHeight: (NSAttributedString*)attributedText withMaxWidth:(CGFloat)maxTextViewWidth
{
__block CGSize textSize;
if ([NSThread currentThread] != [NSThread mainThread])
{
dispatch_sync(dispatch_get_main_queue(), ^{
textSize = [self textContentSize:attributedText removeVerticalInset:YES];
textSize = [self textContentSize:attributedText removeVerticalInset:YES maxTextViewWidth:maxTextViewWidth];
});
}
else
{
textSize = [self textContentSize:attributedText removeVerticalInset:YES];
textSize = [self textContentSize:attributedText removeVerticalInset:YES maxTextViewWidth:maxTextViewWidth];
}
return textSize.height;
}
- (CGSize)textContentSize:(NSAttributedString*)attributedText removeVerticalInset:(BOOL)removeVerticalInset
{
return [self textContentSize:attributedText removeVerticalInset:removeVerticalInset maxTextViewWidth:_maxTextViewWidth];
}
- (CGSize)textContentSize:(NSAttributedString*)attributedText removeVerticalInset:(BOOL)removeVerticalInset maxTextViewWidth:(CGFloat)maxTextViewWidth
{
static UITextView* measurementTextView = nil;
static UITextView* measurementTextViewWithoutInset = nil;
@ -536,7 +547,7 @@
// Select the right text view for measurement
UITextView *selectedTextView = (removeVerticalInset ? measurementTextViewWithoutInset : measurementTextView);
selectedTextView.frame = CGRectMake(0, 0, _maxTextViewWidth, 0);
selectedTextView.frame = CGRectMake(0, 0, maxTextViewWidth, 0);
selectedTextView.attributedText = attributedText;
// Force the layout manager to layout the text, fixes problems starting iOS 16

View file

@ -35,6 +35,15 @@ class TextMessageOutgoingWithoutSenderInfoBubbleCell: TextMessageBaseBubbleCell,
self.textMessageContentView?.bubbleBackgroundView?.backgroundColor = theme.roomCellOutgoingBubbleBackgroundColor
}
override func render(_ cellData: MXKCellData!) {
// This cell displays an outgoing message without any sender information.
// However, we need to set the following properties to our cellData, otherwise, to make room for the timestamp, a whitespace could be added when calculating the position of the components.
// If we don't, the component frame calculation will not work for this cell.
(cellData as? RoomBubbleCellData)?.shouldHideSenderName = false
(cellData as? RoomBubbleCellData)?.shouldHideSenderInformation = false
super.render(cellData)
}
// MARK: - Private
private func setupBubbleConstraints() {

View file

@ -0,0 +1 @@
Fix the position of the send confirmation icon.