diff --git a/VDS/Components/Tilelet/Tilelet.swift b/VDS/Components/Tilelet/Tilelet.swift index 0f595343..b1367736 100644 --- a/VDS/Components/Tilelet/Tilelet.swift +++ b/VDS/Components/Tilelet/Tilelet.swift @@ -289,6 +289,11 @@ open class Tilelet: TileContainerBase { internal var titleLockupBottomGreaterThanConstraint: NSLayoutConstraint? internal var titleLockupCenterYConstraint: NSLayoutConstraint? internal var titleLockupTitleLabelBottomConstraint: NSLayoutConstraint? + //Truncation constraints + internal var badgeLabelHeightGreaterThanConstraint: NSLayoutConstraint? + internal var titleLockupEyebrowLabelHeightGreaterThanConstraint: NSLayoutConstraint? + internal var titleLockupTitleLabelHeightGreaterThanConstraint: NSLayoutConstraint? + internal var titleLockupSubTitleLabelHeightGreaterThanConstraint: NSLayoutConstraint? //-------------------------------------------------- // MARK: - Overrides @@ -319,7 +324,7 @@ open class Tilelet: TileContainerBase { titleLockupBottomConstraint = titleLockupContainerView.bottomAnchor.constraint(equalTo: titleLockup.bottomAnchor) titleLockupBottomConstraint?.activate() titleLockupTrailingConstraint = titleLockup.trailingAnchor.constraint(equalTo: titleLockupContainerView.trailingAnchor) - titleLockupTrailingConstraint?.isActive = true + titleLockupTrailingConstraint?.activate() titleLockupBottomGreaterThanConstraint = titleLockupContainerView.bottomAnchor.constraint(greaterThanOrEqualTo: titleLockup.bottomAnchor) titleLockupTopGreaterThanConstraint = titleLockup.topAnchor.constraint(greaterThanOrEqualTo: titleLockupContainerView.topAnchor) titleLockupCenterYConstraint = titleLockup.centerYAnchor.constraint(equalTo: titleLockupContainerView.centerYAnchor) @@ -337,11 +342,46 @@ open class Tilelet: TileContainerBase { .pinTop() .pinBottom() - //If a Tilelet has Badge, Title and Subtitle, then Subtitle will be truncated first and Badge will be truncated second. Title will be truncated last (lowest priority). + badge.bottomAnchor.constraint(equalTo: badge.label.bottomAnchor, constant: 2).activate() + + /** + Truncation: + If a Tilelet has only a Title or a Subtitle, then the Title or Subtitle is truncated and appended with an ellipsis when there is not enough space to display the full text. + If a Tilelet has both Title and Subtitle, then only Subtitle will be truncated. + If a Tilelet has Badge, Title and Subtitle, then Subtitle will be truncated first and Badge will be truncated second. Title will be truncated last (lowest priority). + Minimum bottom space below Badge is 4px; less than 4px results in truncation. + */ let labelPriority = UILayoutPriority.defaultHigh.rawValue titleLockup.titleLabel.setContentCompressionResistancePriority(UILayoutPriority(labelPriority), for: .vertical) badge.label.setContentCompressionResistancePriority(UILayoutPriority(labelPriority-1), for: .vertical) titleLockup.subTitleLabel.setContentCompressionResistancePriority(UILayoutPriority(labelPriority-2), for: .vertical) + titleLockup.eyebrowLabel.setContentCompressionResistancePriority(UILayoutPriority(labelPriority-3), for: .vertical) + + titleLockup.titleLabel.setContentHuggingPriority(UILayoutPriority(labelPriority), for: .vertical) + badge.label.setContentHuggingPriority(UILayoutPriority(labelPriority-1), for: .vertical) + titleLockup.subTitleLabel.setContentHuggingPriority(UILayoutPriority(labelPriority-2), for: .vertical) + titleLockup.eyebrowLabel.setContentHuggingPriority(UILayoutPriority(labelPriority-3), for: .vertical) + + /** + Added these constraints for: + At fixed width & height if all the labels(Badge, Eyebrow, Title, Subtitle) are having more number of lines then we should display atleast one line of content per label instead of pushing labels out of bounds. + So adding minimum single line height constraint + */ + badgeLabelHeightGreaterThanConstraint = badge.label.heightGreaterThanEqualTo(constant: badge.label.minimumLineHeight) + badgeLabelHeightGreaterThanConstraint?.priority = .defaultHigh + badgeLabelHeightGreaterThanConstraint?.activate() + + titleLockupEyebrowLabelHeightGreaterThanConstraint = titleLockup.eyebrowLabel.heightGreaterThanEqualTo(constant: titleLockup.eyebrowLabel.minimumLineHeight) + titleLockupEyebrowLabelHeightGreaterThanConstraint?.priority = .defaultHigh + titleLockupEyebrowLabelHeightGreaterThanConstraint?.activate() + + titleLockupTitleLabelHeightGreaterThanConstraint = titleLockup.titleLabel.heightGreaterThanEqualTo(constant: titleLockup.titleLabel.minimumLineHeight) + titleLockupTitleLabelHeightGreaterThanConstraint?.priority = .defaultHigh + titleLockupTitleLabelHeightGreaterThanConstraint?.activate() + + titleLockupSubTitleLabelHeightGreaterThanConstraint = titleLockup.subTitleLabel.heightGreaterThanEqualTo(constant: titleLockup.subTitleLabel.minimumLineHeight) + titleLockupSubTitleLabelHeightGreaterThanConstraint?.priority = .defaultHigh + titleLockupSubTitleLabelHeightGreaterThanConstraint?.activate() } /// Resets to default settings. @@ -391,6 +431,7 @@ open class Tilelet: TileContainerBase { badge.numberOfLines = badgeModel.numberOfLines badge.surface = badgeModel.surface badge.maxWidth = badgeModel.maxWidth + badgeLabelHeightGreaterThanConstraint?.constant = badge.label.minimumLineHeight if badgeContainerView.superview == nil { stackView.insertArrangedSubview(badgeContainerView, at: 0) setNeedsLayout() @@ -462,6 +503,9 @@ open class Tilelet: TileContainerBase { } else { removeFromSuperview(titleLockupContainerView) } + titleLockupEyebrowLabelHeightGreaterThanConstraint?.constant = titleLockup.eyebrowLabel.minimumLineHeight + titleLockupTitleLabelHeightGreaterThanConstraint?.constant = titleLockup.titleLabel.minimumLineHeight + titleLockupSubTitleLabelHeightGreaterThanConstraint?.constant = titleLockup.subTitleLabel.minimumLineHeight } private func updateIcons() { @@ -529,11 +573,11 @@ open class Tilelet: TileContainerBase { } } -extension TitleLockup { +extension Label { - fileprivate var lastElement: UIView? { - guard subTitleModel == nil else { return subTitleLabel } - guard titleModel == nil else { return titleLabel } - return nil + ///To calculate label single line height + fileprivate var minimumLineHeight: CGFloat { + guard let text, !text.isEmpty, let attributes = attributedText?.attributes(at: 0, longestEffectiveRange: nil, in: NSRange(location: 0, length: attributedText?.string.count ?? 0))[.paragraphStyle] as? NSParagraphStyle else { return font.lineHeight } + return attributes.minimumLineHeight } }