Top row baseline and badge to spec

- Single visual baseline for all top row text
- Snippet should not flow under badge, it should stop at it's left edge
- unread font to spec (same as date stamp font, but never bold)

// FREEBIE
This commit is contained in:
Michael Kirk 2018-04-19 19:08:16 -04:00
parent c693beb763
commit ee4d038d2d

View file

@ -24,10 +24,6 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic) UILabel *nameLabel; @property (nonatomic) UILabel *nameLabel;
@property (nonatomic) UILabel *snippetLabel; @property (nonatomic) UILabel *snippetLabel;
@property (nonatomic) UILabel *dateTimeLabel; @property (nonatomic) UILabel *dateTimeLabel;
// The unread badge has a larger v-height than the other elements in its
// row. We don't want it to distort the v-alignment of the cell's labels
// so we use a container to reserve the correct width.
@property (nonatomic) UIView *unreadBadgeContainer;
@property (nonatomic) UIView *unreadBadge; @property (nonatomic) UIView *unreadBadge;
@property (nonatomic) UILabel *unreadLabel; @property (nonatomic) UILabel *unreadLabel;
@ -65,20 +61,19 @@ NS_ASSUME_NONNULL_BEGIN
OWSAssert(!self.avatarView); OWSAssert(!self.avatarView);
[self setTranslatesAutoresizingMaskIntoConstraints:NO]; [self setTranslatesAutoresizingMaskIntoConstraints:NO];
self.layoutMargins = UIEdgeInsetsZero; self.layoutMargins = UIEdgeInsetsMake(0, self.cellHMargin, 0, self.cellHMargin);
self.contentView.layoutMargins = UIEdgeInsetsZero; self.contentView.preservesSuperviewLayoutMargins = YES;
self.preservesSuperviewLayoutMargins = NO;
self.contentView.preservesSuperviewLayoutMargins = NO;
self.backgroundColor = [UIColor whiteColor]; self.backgroundColor = [UIColor whiteColor];
_viewConstraints = [NSMutableArray new]; _viewConstraints = [NSMutableArray new];
self.avatarView = [[AvatarImageView alloc] init]; self.avatarView = [[AvatarImageView alloc] init];
[self.contentView addSubview:self.avatarView]; [self.contentView addSubview:self.avatarView];
[self.avatarView autoSetDimension:ALDimensionWidth toSize:self.avatarSize]; [self.avatarView autoSetDimension:ALDimensionWidth toSize:self.avatarSize];
[self.avatarView autoSetDimension:ALDimensionHeight toSize:self.avatarSize]; [self.avatarView autoSetDimension:ALDimensionHeight toSize:self.avatarSize];
[self.avatarView autoPinLeadingToSuperviewMarginWithInset:self.cellHMargin]; [self.avatarView autoPinLeadingToSuperviewMargin];
[self.avatarView autoVCenterInSuperview]; [self.avatarView autoVCenterInSuperview];
[self.avatarView setContentHuggingHigh]; [self.avatarView setContentHuggingHigh];
[self.avatarView setCompressionResistanceHigh]; [self.avatarView setCompressionResistanceHigh];
@ -87,11 +82,11 @@ NS_ASSUME_NONNULL_BEGIN
self.payloadView.axis = UILayoutConstraintAxisVertical; self.payloadView.axis = UILayoutConstraintAxisVertical;
[self.contentView addSubview:self.payloadView]; [self.contentView addSubview:self.payloadView];
[self.payloadView autoPinLeadingToTrailingEdgeOfView:self.avatarView offset:self.avatarHSpacing]; [self.payloadView autoPinLeadingToTrailingEdgeOfView:self.avatarView offset:self.avatarHSpacing];
[self.payloadView autoPinTrailingToSuperviewMarginWithInset:self.cellHMargin];
[self.payloadView autoVCenterInSuperview]; [self.payloadView autoVCenterInSuperview];
// Ensure that the cell's contents never overflow the cell bounds. // Ensure that the cell's contents never overflow the cell bounds.
[self.payloadView autoPinEdgeToSuperviewMargin:ALEdgeTop relation:NSLayoutRelationGreaterThanOrEqual]; [self.payloadView autoPinEdgeToSuperviewMargin:ALEdgeTop relation:NSLayoutRelationGreaterThanOrEqual];
[self.payloadView autoPinEdgeToSuperviewMargin:ALEdgeBottom relation:NSLayoutRelationGreaterThanOrEqual]; [self.payloadView autoPinEdgeToSuperviewMargin:ALEdgeBottom relation:NSLayoutRelationGreaterThanOrEqual];
// We pin the payloadView traillingEdge later, as part of the "Unread Badge" logic.
self.nameLabel = [UILabel new]; self.nameLabel = [UILabel new];
self.nameLabel.lineBreakMode = NSLineBreakByTruncatingTail; self.nameLabel.lineBreakMode = NSLineBreakByTruncatingTail;
@ -108,7 +103,7 @@ NS_ASSUME_NONNULL_BEGIN
self.dateTimeLabel, self.dateTimeLabel,
]]; ]];
self.topRowView.axis = UILayoutConstraintAxisHorizontal; self.topRowView.axis = UILayoutConstraintAxisHorizontal;
self.topRowView.alignment = UIStackViewAlignmentCenter; self.topRowView.alignment = UIStackViewAlignmentBottom;
[self.payloadView addArrangedSubview:self.topRowView]; [self.payloadView addArrangedSubview:self.topRowView];
self.snippetLabel = [UILabel new]; self.snippetLabel = [UILabel new];
@ -125,20 +120,12 @@ NS_ASSUME_NONNULL_BEGIN
self.unreadLabel.lineBreakMode = NSLineBreakByTruncatingTail; self.unreadLabel.lineBreakMode = NSLineBreakByTruncatingTail;
self.unreadLabel.textAlignment = NSTextAlignmentCenter; self.unreadLabel.textAlignment = NSTextAlignmentCenter;
self.unreadBadgeContainer = [UIView containerView];
[self.unreadBadgeContainer setContentHuggingHigh];
[self.unreadBadgeContainer setCompressionResistanceHigh];
self.unreadBadge = [NeverClearView new]; self.unreadBadge = [NeverClearView new];
self.unreadBadge.backgroundColor = [UIColor ows_materialBlueColor]; self.unreadBadge.backgroundColor = [UIColor ows_materialBlueColor];
[self.unreadBadgeContainer addSubview:self.unreadBadge];
[self.unreadBadge autoCenterInSuperview];
[self.unreadBadge setContentHuggingHigh];
[self.unreadBadge setCompressionResistanceHigh];
[self.unreadBadge addSubview:self.unreadLabel]; [self.unreadBadge addSubview:self.unreadLabel];
[self.unreadLabel autoVCenterInSuperview]; [self.unreadLabel autoCenterInSuperview];
[self.unreadLabel autoPinWidthToSuperview]; [self.unreadLabel setContentHuggingHigh];
[self.unreadLabel setCompressionResistanceHigh];
} }
+ (NSString *)cellReuseIdentifier + (NSString *)cellReuseIdentifier
@ -178,7 +165,7 @@ NS_ASSUME_NONNULL_BEGIN
[self updateAvatarView]; [self updateAvatarView];
self.payloadView.spacing = 0.f; self.payloadView.spacing = 0.f;
self.topRowView.spacing = ceil([HomeViewCell scaleValueWithDynamicType:5]); self.topRowView.spacing = self.topRowHSpacing;
// We update the fonts every time this cell is configured to ensure that // We update the fonts every time this cell is configured to ensure that
// changes to the dynamic type settings are reflected. // changes to the dynamic type settings are reflected.
@ -197,10 +184,11 @@ NS_ASSUME_NONNULL_BEGIN
} }
NSUInteger unreadCount = [[OWSMessageUtils sharedManager] unreadMessagesInThread:thread]; NSUInteger unreadCount = [[OWSMessageUtils sharedManager] unreadMessagesInThread:thread];
if (unreadCount > 0) { if (unreadCount == 0) {
[self.topRowView addArrangedSubview:self.unreadBadgeContainer]; [self.viewConstraints addObject:[self.payloadView autoPinTrailingToSuperviewMargin]];
} else {
[self.contentView addSubview:self.unreadBadge];
self.unreadLabel.font = [UIFont ows_dynamicTypeCaption1Font];
self.unreadLabel.text = [OWSFormat formatInt:MIN(99, (int)unreadCount)]; self.unreadLabel.text = [OWSFormat formatInt:MIN(99, (int)unreadCount)];
// TODO: Will this localize? It assumes that the worst case // TODO: Will this localize? It assumes that the worst case
@ -210,9 +198,22 @@ NS_ASSUME_NONNULL_BEGIN
self.unreadBadge.layer.cornerRadius = unreadBadgeSize / 2; self.unreadBadge.layer.cornerRadius = unreadBadgeSize / 2;
[self.viewConstraints addObjectsFromArray:@[ [self.viewConstraints addObjectsFromArray:@[
[self.unreadBadgeContainer autoSetDimension:ALDimensionWidth toSize:unreadBadgeSize], // badge sizing
[self.unreadBadge autoSetDimension:ALDimensionWidth toSize:unreadBadgeSize], [self.unreadBadge autoSetDimension:ALDimensionWidth toSize:unreadBadgeSize],
[self.unreadBadge autoSetDimension:ALDimensionHeight toSize:unreadBadgeSize], [self.unreadBadge autoSetDimension:ALDimensionHeight toSize:unreadBadgeSize],
// Horizontally, badge is inserted after the tail of the payloadView, pushing back the date *and* snippet
// view
[self.payloadView autoPinEdge:ALEdgeTrailing
toEdge:ALEdgeLeading
ofView:self.unreadBadge
withOffset:-self.topRowHSpacing],
[self.unreadBadge autoPinTrailingToSuperviewMargin],
// Vertically, badge is positioned vertically by aligning it's label *subview's* baseline.
// This allows us a single visual baseline of text across the top row across [name, dateTime,
// optional(unread count)]
[self.unreadLabel autoAlignAxis:ALAxisBaseline toSameAxisOfView:self.dateTimeLabel]
]]; ]];
} }
} }
@ -381,6 +382,12 @@ NS_ASSUME_NONNULL_BEGIN
return 12.f; return 12.f;
} }
// Using an NSUInteger precludes us from negating this value
- (CGFloat)topRowHSpacing
{
return ceil([HomeViewCell scaleValueWithDynamicType:5]);
}
#pragma mark - Reuse #pragma mark - Reuse
- (void)prepareForReuse - (void)prepareForReuse
@ -393,7 +400,7 @@ NS_ASSUME_NONNULL_BEGIN
self.thread = nil; self.thread = nil;
self.contactsManager = nil; self.contactsManager = nil;
[self.unreadBadgeContainer removeFromSuperview]; [self.unreadBadge removeFromSuperview];
[[NSNotificationCenter defaultCenter] removeObserver:self]; [[NSNotificationCenter defaultCenter] removeObserver:self];
} }