iOS开发中如何实现不改变文字宽度仅调整字符高度的垂直压缩效果
iOS 端实现固定宽度下文本垂直压缩效果方案
你提到的Photoshop式垂直压缩文字效果,NSAttributedString 没有提供直接对应的内置属性,可通过以下几种方式实现:

轻量快速实现:直接对文本控件做y轴单方向缩放
对承载文本的UILabel、UITextView等控件直接设置形变属性,仅修改y轴缩放比例、x轴保持原比例,完全不会改变文字原有宽度,代码示例:let textLabel = UILabel() textLabel.text = "需要垂直压缩的文本内容" textLabel.font = .systemFont(ofSize: 16) textLabel.sizeToFit() // y轴参数小于1为压缩,大于1为拉伸,x轴固定为1.0保证宽度不变 textLabel.transform = CGAffineTransform(scaleX: 1.0, y: 0.65)这个方案实现成本最低,保留原生文本控件的所有交互能力(选中文本、点击链接等),性能开销可以忽略;仅在缩放比例极端(比如小于0.4)时可能出现轻微渲染锯齿,常规业务场景下完全可用。
精细渲染实现:自定义绘制时做上下文缩放
如果需要避免形变带来的布局偏移、锯齿问题,可以自定义UILabel子类,在绘制方法内对图形上下文做单轴缩放后再绘制文本:class VerticalScaleLabel: UILabel { /// 垂直方向缩放比例,<1压缩、>1拉伸 var verticalScale: CGFloat = 0.65 override func drawText(in rect: CGRect) { guard let ctx = UIGraphicsGetCurrentContext() else { super.drawText(in: rect) return } ctx.saveGState() // 做y轴缩放的同时平移坐标系,避免文本位置偏移 ctx.scaleBy(x: 1.0, y: verticalScale) let offsetY = (rect.height - rect.height / verticalScale) / 2 ctx.translateBy(x: 0, y: offsetY) super.drawText(in: rect) ctx.restoreGState() } }这个方案不会修改控件本身的frame和点击热区,渲染效果更稳定,适合对布局精度要求高的场景。
复杂排版场景:CoreText 自定义字形变换
如果需要在图文混排、逐字自定义效果的场景下实现垂直压缩,可以通过CoreText接口给每个字形设置单轴缩放的CGAffineTransform,将变换后的内容封装为富文本属性使用。这个方案灵活度最高,但实现复杂度也更高,适合专业排版类需求。
避坑提示:不要通过缩小字体字号再反向拉伸x轴的方式模拟效果,这种方式会改变字符的实际排版宽度,无法实现和PS一致的固定宽度压缩效果。
内容的提问来源于stack exchange,提问作者Gizmodo
相关产品推荐
相关产品推荐

