Swift中NSAttributedString含不间断空格多行显示截断问题
解决UILabel显示NSAttributedString时末尾选项被截断的问题
这个问题的核心原因其实有两个:一是你固定了UILabel的高度,导致内容因换行增加高度后,超出部分被直接截断;二是不间断空格的换行逻辑可能让UILabel的尺寸计算出现偏差。下面是具体的解决方法:
1. 移除固定高度约束,让标签高度自适应内容
你当前的代码里把UILabel的高度强制设为和view一样高:
myLabel.heightAnchor.constraint(equalToConstant: self.view.frame.height).isActive = true
这就意味着,不管内容总高度有多高,标签只能显示这么多高度的内容——当填空空格换行导致总内容高度超过view高度时,最后一行选项自然会被切掉。
解决方法很简单:删掉这行固定高度的约束,让UILabel根据内容自动计算高度。如果需要限制标签的最大高度(比如不超出屏幕),可以设置最大高度约束:
// 移除固定高度约束,换成最大高度约束 myLabel.heightAnchor.constraint(lessThanOrEqualToConstant: self.view.frame.height).isActive = true // 同时让标签内容垂直居中(如果需要) myLabel.contentMode = .center
2. 优化填空子串的换行逻辑
为了确保不间断空格子串既不被拆分行,又能让UILabel正确计算换行后的尺寸,我们可以给这个子串单独设置段落样式:
// 创建段落样式,确保不间断空格不被拆分 let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineBreakMode = .byWordWrapping paragraphStyle.allowsDefaultLineBreakBefore = false // 禁止默认的换行前置逻辑 // 给填空子串添加段落样式 myAttributedText.addAttribute(.paragraphStyle, value: paragraphStyle, range: (myText as NSString).range(of: underlineString))
3. 强制标签重新计算尺寸
在设置完attributedText后,强制UILabel刷新布局,确保它根据最新的内容重新计算尺寸:
myLabel.attributedText = myAttributedText myLabel.invalidateIntrinsicContentSize() // 刷新固有内容尺寸 myLabel.layoutIfNeeded() // 立即更新布局
替代方案:用自定义宽度的占位符替代不间断空格
如果你想更精准控制填空的宽度,避免空格数量带来的换行不确定性,可以用字距调整+单个空格来创建固定宽度的下划线占位:
let font = UIFont(name: "My Font", size: round(self.view.frame.width / 15))! let placeholderWidth = font.pointSize * 3 // 自定义宽度,比如3个字符宽 // 通过kern(字距)调整单个空格的宽度到目标值 let placeholderAttributes: [NSAttributedString.Key: Any] = [ .font: font, .foregroundColor: UIColor(white: 1, alpha: 0.9), .underlineStyle: NSUnderlineStyle.styleThick.rawValue, .kern: placeholderWidth - font.pointSize ] let placeholderString = NSAttributedString(string: " ", attributes: placeholderAttributes) // 替换原文本中的空格子串 let baseText = "What do you think about and then what about this extra stuff at the end?\na) first choice\nb) second choice\nc) last choice" let mutableText = NSMutableAttributedString(string: baseText, attributes: myTextAttributes) // 找到" "的位置替换成占位符 let range = (baseText as NSString).range(of: " ") mutableText.replaceCharacters(in: range, with: placeholderString) myLabel.attributedText = mutableText
这样既可以实现固定宽度的下划线填空,又能避免不间断空格带来的换行计算问题。
内容的提问来源于stack exchange,提问作者Damien X
相关产品推荐
相关产品推荐

