Use reference cells for measurement.

// FREEBIE
pull/1/head
Matthew Chen 7 years ago
parent de56c77f3f
commit 91af4f93e1

@ -31,8 +31,20 @@ NS_ASSUME_NONNULL_BEGIN
- (CGSize)jsq_avatarSizeForMessageData:(id<JSQMessageData>)messageData
withLayout:(JSQMessagesCollectionViewFlowLayout *)layout;
- (CGFloat)textBubbleWidthForLayout:(JSQMessagesCollectionViewFlowLayout *)layout;
@end
#pragma mark -
@interface OWSMessagesBubblesSizeCalculator ()
@property (nonatomic) OWSSystemMessageCell *referenceSystemMessageCell;
@property (nonatomic) OWSUnreadIndicatorCell *referenceUnreadIndicatorCell;
@end
#pragma mark -
@implementation OWSMessagesBubblesSizeCalculator
/**
@ -98,6 +110,7 @@ NS_ASSUME_NONNULL_BEGIN
cacheKey:(id)cacheKey
layout:(JSQMessagesCollectionViewFlowLayout *)layout
{
OWSAssert([NSThread isMainThread]);
OWSAssert(interaction);
OWSAssert(cacheKey);
@ -106,8 +119,12 @@ NS_ASSUME_NONNULL_BEGIN
return [cachedSize CGSizeValue];
}
CGSize result =
[OWSSystemMessageCell cellSizeForInteraction:interaction collectionViewWidth:layout.collectionView.width];
if (!self.referenceSystemMessageCell) {
self.referenceSystemMessageCell = [OWSSystemMessageCell new];
}
CGSize result = [self.referenceSystemMessageCell cellSizeForInteraction:interaction
collectionViewWidth:layout.collectionView.width];
[self.cache setObject:[NSValue valueWithCGSize:result] forKey:cacheKey];
@ -126,8 +143,12 @@ NS_ASSUME_NONNULL_BEGIN
return [cachedSize CGSizeValue];
}
CGSize result =
[OWSUnreadIndicatorCell cellSizeForInteraction:interaction collectionViewWidth:layout.collectionView.width];
if (!self.referenceUnreadIndicatorCell) {
self.referenceUnreadIndicatorCell = [OWSUnreadIndicatorCell new];
}
CGSize result = [self.referenceUnreadIndicatorCell cellSizeForInteraction:interaction
collectionViewWidth:layout.collectionView.width];
[self.cache setObject:[NSValue valueWithCGSize:result] forKey:cacheKey];

@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)configureWithInteraction:(TSInteraction *)interaction;
+ (CGSize)cellSizeForInteraction:(TSInteraction *)interaction collectionViewWidth:(CGFloat)collectionViewWidth;
- (CGSize)cellSizeForInteraction:(TSInteraction *)interaction collectionViewWidth:(CGFloat)collectionViewWidth;
@end

@ -51,7 +51,10 @@ NS_ASSUME_NONNULL_BEGIN
- (void)commontInit
{
OWSAssert(!self.imageView);
if (self.imageView) {
// Don't init twice.
return;
}
[self setTranslatesAutoresizingMaskIntoConstraints:NO];
@ -62,7 +65,7 @@ NS_ASSUME_NONNULL_BEGIN
self.titleLabel = [UILabel new];
self.titleLabel.textColor = [UIColor colorWithRGBHex:0x403e3b];
self.titleLabel.font = [OWSSystemMessageCell titleFont];
self.titleLabel.font = [self titleFont];
self.titleLabel.numberOfLines = 0;
self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
[self.contentView addSubview:self.titleLabel];
@ -86,13 +89,13 @@ NS_ASSUME_NONNULL_BEGIN
UIImage *icon = [self iconForInteraction:self.interaction];
self.imageView.image = [icon imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
self.imageView.tintColor = [self iconColorForInteraction:self.interaction];
self.titleLabel.textColor = [OWSSystemMessageCell textColor];
[OWSSystemMessageCell applyTitleForInteraction:self.interaction label:self.titleLabel];
self.titleLabel.textColor = [self textColor];
[self applyTitleForInteraction:self.interaction label:self.titleLabel];
[self setNeedsLayout];
}
+ (UIColor *)textColor
- (UIColor *)textColor
{
return [UIColor colorWithRGBHex:0x303030];
}
@ -162,7 +165,7 @@ NS_ASSUME_NONNULL_BEGIN
return result;
}
+ (void)applyTitleForInteraction:(TSInteraction *)interaction label:(UILabel *)label
- (void)applyTitleForInteraction:(TSInteraction *)interaction label:(UILabel *)label
{
OWSAssert(interaction);
OWSAssert(label);
@ -204,32 +207,32 @@ NS_ASSUME_NONNULL_BEGIN
}
}
+ (UIFont *)titleFont
- (UIFont *)titleFont
{
return [UIFont ows_regularFontWithSize:13.f];
}
+ (CGFloat)hMargin
- (CGFloat)hMargin
{
return 25.f;
}
+ (CGFloat)topVMargin
- (CGFloat)topVMargin
{
return 5.f;
}
+ (CGFloat)bottomVMargin
- (CGFloat)bottomVMargin
{
return 5.f;
}
+ (CGFloat)hSpacing
- (CGFloat)hSpacing
{
return 8.f;
}
+ (CGFloat)iconSize
- (CGFloat)iconSize
{
return 20.f;
}
@ -238,36 +241,32 @@ NS_ASSUME_NONNULL_BEGIN
{
[super layoutSubviews];
CGFloat maxTitleWidth = (self.contentView.width
- ([OWSSystemMessageCell hMargin] * 2.f + [OWSSystemMessageCell hSpacing] + [OWSSystemMessageCell iconSize]));
CGFloat maxTitleWidth = (self.contentView.width - ([self hMargin] * 2.f + [self hSpacing] + [self iconSize]));
CGSize titleSize = [self.titleLabel sizeThatFits:CGSizeMake(maxTitleWidth, CGFLOAT_MAX)];
CGFloat contentWidth = ([OWSSystemMessageCell iconSize] + [OWSSystemMessageCell hSpacing] + titleSize.width);
CGFloat contentWidth = ([self iconSize] + [self hSpacing] + titleSize.width);
self.imageView.frame = CGRectMake(round((self.contentView.width - contentWidth) * 0.5f),
round((self.contentView.height - [OWSSystemMessageCell iconSize]) * 0.5f),
[OWSSystemMessageCell iconSize],
[OWSSystemMessageCell iconSize]);
self.titleLabel.frame = CGRectMake(round(self.imageView.right + [OWSSystemMessageCell hSpacing]),
round((self.contentView.height - [self iconSize]) * 0.5f),
[self iconSize],
[self iconSize]);
self.titleLabel.frame = CGRectMake(round(self.imageView.right + [self hSpacing]),
round((self.contentView.height - titleSize.height) * 0.5f),
ceil(titleSize.width + 1.f),
ceil(titleSize.height + 1.f));
}
+ (CGSize)cellSizeForInteraction:(TSInteraction *)interaction collectionViewWidth:(CGFloat)collectionViewWidth
- (CGSize)cellSizeForInteraction:(TSInteraction *)interaction collectionViewWidth:(CGFloat)collectionViewWidth
{
CGSize result = CGSizeMake(collectionViewWidth, 0);
result.height += self.topVMargin;
result.height += self.bottomVMargin;
// Creating a UILabel to measure the layout is expensive, but it's the only
// reliable way to do it.
UILabel *label = [UILabel new];
label.font = [self titleFont];
[OWSSystemMessageCell applyTitleForInteraction:interaction label:label];
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakByWordWrapping;
self.titleLabel.font = [self titleFont];
[self applyTitleForInteraction:interaction label:self.titleLabel];
self.titleLabel.numberOfLines = 0;
self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
CGFloat maxTitleWidth = (collectionViewWidth - ([self hMargin] * 2.f + [self hSpacing] + [self iconSize]));
CGSize titleSize = [label sizeThatFits:CGSizeMake(maxTitleWidth, CGFLOAT_MAX)];
CGSize titleSize = [self.titleLabel sizeThatFits:CGSizeMake(maxTitleWidth, CGFLOAT_MAX)];
CGFloat contentHeight = ceil(MAX([self iconSize], titleSize.height));
result.height += contentHeight;

@ -15,7 +15,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)configureWithInteraction:(TSUnreadIndicatorInteraction *)interaction;
+ (CGSize)cellSizeForInteraction:(TSUnreadIndicatorInteraction *)interaction
- (CGSize)cellSizeForInteraction:(TSUnreadIndicatorInteraction *)interaction
collectionViewWidth:(CGFloat)collectionViewWidth;
@end

@ -49,7 +49,10 @@ NS_ASSUME_NONNULL_BEGIN
- (void)commontInit
{
OWSAssert(!self.bannerView);
if (self.bannerView) {
// Don't init twice.
return;
}
[self setTranslatesAutoresizingMaskIntoConstraints:NO];
@ -72,15 +75,15 @@ NS_ASSUME_NONNULL_BEGIN
[self.bannerView addSubview:self.bannerBottomHighlightView2];
self.titleLabel = [UILabel new];
self.titleLabel.text = [OWSUnreadIndicatorCell titleForInteraction:self.interaction];
self.titleLabel.text = [self titleForInteraction:self.interaction];
self.titleLabel.textColor = [UIColor colorWithRGBHex:0x403e3b];
self.titleLabel.font = [OWSUnreadIndicatorCell titleFont];
self.titleLabel.font = [self titleFont];
[self.bannerView addSubview:self.titleLabel];
self.subtitleLabel = [UILabel new];
self.subtitleLabel.text = [OWSUnreadIndicatorCell subtitleForInteraction:self.interaction];
self.subtitleLabel.text = [self subtitleForInteraction:self.interaction];
self.subtitleLabel.textColor = [UIColor ows_infoMessageBorderColor];
self.subtitleLabel.font = [OWSUnreadIndicatorCell subtitleFont];
self.subtitleLabel.font = [self subtitleFont];
self.subtitleLabel.numberOfLines = 0;
self.subtitleLabel.lineBreakMode = NSLineBreakByWordWrapping;
self.subtitleLabel.textAlignment = NSTextAlignmentCenter;
@ -103,23 +106,23 @@ NS_ASSUME_NONNULL_BEGIN
[self setNeedsLayout];
}
+ (UIFont *)titleFont
- (UIFont *)titleFont
{
return [UIFont ows_regularFontWithSize:16.f];
}
+ (UIFont *)subtitleFont
- (UIFont *)subtitleFont
{
return [UIFont ows_regularFontWithSize:12.f];
}
+ (NSString *)titleForInteraction:(TSUnreadIndicatorInteraction *)interaction
- (NSString *)titleForInteraction:(TSUnreadIndicatorInteraction *)interaction
{
return NSLocalizedString(@"MESSAGES_VIEW_UNREAD_INDICATOR", @"Indicator that separates read from unread messages.")
.uppercaseString;
}
+ (NSString *)subtitleForInteraction:(TSUnreadIndicatorInteraction *)interaction
- (NSString *)subtitleForInteraction:(TSUnreadIndicatorInteraction *)interaction
{
if (!interaction.hasMoreUnseenMessages) {
return nil;
@ -137,32 +140,32 @@ NS_ASSUME_NONNULL_BEGIN
return [NSString stringWithFormat:subtitleFormat, loadMoreButtonName];
}
+ (CGFloat)subtitleHMargin
- (CGFloat)subtitleHMargin
{
return 20.f;
}
+ (CGFloat)subtitleVSpacing
- (CGFloat)subtitleVSpacing
{
return 3.f;
}
+ (CGFloat)titleInnerHMargin
- (CGFloat)titleInnerHMargin
{
return 10.f;
}
+ (CGFloat)titleVMargin
- (CGFloat)titleVMargin
{
return 5.5f;
}
+ (CGFloat)topVMargin
- (CGFloat)topVMargin
{
return 5.f;
}
+ (CGFloat)bottomVMargin
- (CGFloat)bottomVMargin
{
return 5.f;
}
@ -180,9 +183,9 @@ NS_ASSUME_NONNULL_BEGIN
// This layout logic assumes that the cell insets are symmetrical and can be deduced
// from the cell frame.
CGRect bannerViewFrame = CGRectMake(-self.left,
round(OWSUnreadIndicatorCell.topVMargin),
round(self.topVMargin),
round(self.width + self.left * 2.f),
round(self.titleLabel.height + OWSUnreadIndicatorCell.titleVMargin * 2.f));
round(self.titleLabel.height + self.titleVMargin * 2.f));
self.bannerView.frame = [self convertRect:bannerViewFrame toView:self.contentView];
// The highlights should be 1px (not 1pt), so adapt their thickness to
@ -198,16 +201,15 @@ NS_ASSUME_NONNULL_BEGIN
if (self.subtitleLabel.text.length > 0) {
CGSize subtitleSize = [self.subtitleLabel
sizeThatFits:CGSizeMake(
self.contentView.width - [OWSUnreadIndicatorCell subtitleHMargin] * 2.f, CGFLOAT_MAX)];
sizeThatFits:CGSizeMake(self.contentView.width - [self subtitleHMargin] * 2.f, CGFLOAT_MAX)];
self.subtitleLabel.frame = CGRectMake(round((self.contentView.width - subtitleSize.width) * 0.5f),
round(self.bannerView.bottom + OWSUnreadIndicatorCell.subtitleVSpacing),
round(self.bannerView.bottom + self.subtitleVSpacing),
ceil(subtitleSize.width),
ceil(subtitleSize.height));
}
}
+ (CGSize)cellSizeForInteraction:(TSUnreadIndicatorInteraction *)interaction
- (CGSize)cellSizeForInteraction:(TSUnreadIndicatorInteraction *)interaction
collectionViewWidth:(CGFloat)collectionViewWidth
{
CGSize result = CGSizeMake(collectionViewWidth, 0);
@ -220,7 +222,7 @@ NS_ASSUME_NONNULL_BEGIN
// Creating a UILabel to measure the layout is expensive, but it's the only
// reliable way to do it. Unread indicators should be rare, so this is acceptable.
UILabel *label = [UILabel new];
UILabel *label = self.titleLabel;
label.font = [self titleFont];
label.text = title;
result.height += ceil([label sizeThatFits:CGSizeZero].height);

Loading…
Cancel
Save