如何让NSAttributedString实现的分隔线强制填充指定宽度?
解决固定宽度分隔线的实现问题
你当前用删除线样式结合空白字符实现的分隔线,受字体、排版影响无法稳定控制宽度。要实现指定宽度(比如300px)的分隔线,推荐用NSTextAttachment的方式,这是最可靠的方案:
方法一:基于NSTextAttachment的固定宽度分隔线
直接绘制指定宽度的线条作为文本附件,嵌入富文本中,宽度完全可控:
extension NSAttributedString { static func separator(withWidth width: CGFloat) -> NSAttributedString { // 创建文本附件 let attachment = NSTextAttachment() // 线条高度可根据需求调整,这里设为1px let lineHeight: CGFloat = 1 // 调整附件垂直位置,让线条和文本基线对齐(适配系统字体) let font = UIFont.systemFont(ofSize: 17) let yOffset = (font.descender + lineHeight) / 2 attachment.bounds = CGRect(x: 0, y: yOffset, width: width, height: lineHeight) // 绘制灰色线条 let renderer = UIGraphicsImageRenderer(size: CGSize(width: width, height: lineHeight)) attachment.image = renderer.image { context in UIColor.lightGray.setFill() context.fill(CGRect(x: 0, y: 0, width: width, height: lineHeight)) } // 组合换行符和分隔线,控制上下间距 let prefix = NSAttributedString(string: "\n\n") let separatorAttachment = NSAttributedString(attachment: attachment) let suffix = NSAttributedString(string: "\n\n") let result = NSMutableAttributedString() result.append(prefix) result.append(separatorAttachment) result.append(suffix) return result } }
使用方式
attributed.append(.separator(withWidth: 300))
方法二:基于删除线的兼容方案(不推荐)
如果坚持用删除线样式,可以通过计算固定数量的全角空格来凑宽度,但这种方法依赖字体,不同字体下宽度会有偏差:
extension NSAttributedString { static func separator(withWidth width: CGFloat) -> NSAttributedString { let font = UIFont.systemFont(ofSize: 17) // 计算单个全角空格的宽度 let singleSpaceWidth = font.stringWidth(" ") // 计算需要的空格数量 let spaceCount = Int(ceil(width / singleSpaceWidth)) let spaceString = String(repeating: " ", count: spaceCount) let attributes: [NSAttributedString.Key: Any] = [ .strikethroughStyle: NSUnderlineStyle.single.rawValue, .strikethroughColor: UIColor.lightGray, .font: font ] return NSAttributedString(string: "\n\n\(spaceString)\n\n", attributes: attributes) } } // 给UIFont加扩展,计算字符串宽度 extension UIFont { func stringWidth(_ string: String) -> CGFloat { let attributes = [NSAttributedString.Key.font: self] return string.size(withAttributes: attributes).width } }
说明
优先选择方法一,因为它不依赖字体和排版规则,能精准控制分隔线宽度,适配各种场景。
内容的提问来源于stack exchange,提问作者kunass2
相关产品推荐
相关产品推荐

