Swift中能否调整UILabel省略号的垂直位置?
实现垂直底部的省略号(替代UILabel的byTruncatingTail)
原生UILabel的.byTruncatingTail换行模式无法直接将省略号调整到垂直底部——系统默认会让省略号和最后一行文本保持对齐(你的文本设置了居中,所以省略号会落在垂直中间位置)。要实现省略号在底部的效果,需要自定义处理逻辑,以下是可行的实现方案:
实现思路
- 先判断完整文本是否超出label的高度限制
- 若需要截断,逐步截取文本内容,确保加上省略号后的整体高度不超过label高度
- 调整文本的垂直对齐方式,让最终内容(含省略号)贴紧label底部
示例代码
class BottomTruncationLabel: UILabel { override var text: String? { didSet { updateTruncatedText() } } override var attributedText: NSAttributedString? { didSet { updateTruncatedText() } } private func updateTruncatedText() { guard let originalContent = self.attributedText ?? text.map({ NSAttributedString(string: $0) }) else { return } let maxLabelSize = CGSize(width: bounds.width, height: bounds.height) let fullTextHeight = originalContent.boundingRect(with: maxLabelSize, options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil).height // 文本未超出限制,直接显示 if fullTextHeight <= maxLabelSize.height { super.attributedText = originalContent return } // 开始处理截断逻辑 let mutableContent = NSMutableAttributedString(attributedString: originalContent) let ellipsisAttrs = mutableContent.attributes(at: 0, effectiveRange: nil) let ellipsis = NSAttributedString(string: "...", attributes: ellipsisAttrs) let ellipsisWidth = ellipsis.boundingRect(with: CGSize(width: CGFloat.greatestFiniteMagnitude, height: maxLabelSize.height), options: .usesLineFragmentOrigin, context: nil).width var truncatedLength = mutableContent.length while truncatedLength > 0 { truncatedLength -= 1 let truncatedSubstring = mutableContent.attributedSubstring(from: NSRange(location: 0, length: truncatedLength)) let combinedContent = NSMutableAttributedString(attributedString: truncatedSubstring) combinedContent.append(ellipsis) let combinedHeight = combinedContent.boundingRect(with: maxLabelSize, options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil).height if combinedHeight <= maxLabelSize.height { // 调整段落样式,确保文本垂直底部对齐 let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = 2 paragraphStyle.alignment = .center paragraphStyle.lineBreakMode = .byClipping combinedContent.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: combinedContent.length)) self.contentMode = .bottom super.attributedText = combinedContent break } } } override func layoutSubviews() { super.layoutSubviews() updateTruncatedText() } }
使用方式
将原来的UILabel替换为BottomTruncationLabel,直接设置文本或富文本即可,它会自动完成截断并将省略号固定在label底部。
内容的提问来源于stack exchange,提问作者hey
相关产品推荐
相关产品推荐

