You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UITextView文本从上到下从左到右排列及旋转后异常求助

解决UITextView竖排(从上到下、从左到右)的排版问题

我之前做中文竖排文本的时候,也踩过直接用transform旋转的坑——视图转了,但内部文本的排版逻辑还是跟着原来的横排尺寸走,自然会出现内容尺寸不匹配、换行错位的问题。这里给你两个靠谱的解决方案,按需选:

方案一:用原生文本排版属性实现(推荐,无transform副作用)

直接通过NSAttributedString设置竖排样式,让UITextView原生支持垂直排版,这是最稳妥的方式,不会有布局错乱的问题:

// 1. 创建竖排的段落样式
let paragraphStyle = NSMutableParagraphStyle()
// 设置为垂直排版,从上到下、从左到右的方向
paragraphStyle.baseWritingDirection = .leftToRight
paragraphStyle.lineBreakMode = .byWordWrapping
// 关键:设置垂直排版的书写方向
paragraphStyle.writingDirection = [.leftToRight, .vertical]

// 2. 创建带样式的富文本
let attributedText = NSAttributedString(string: "你的竖排文本内容", attributes: [
    .paragraphStyle: paragraphStyle,
    .font: UIFont.systemFont(ofSize: 16)
])

// 3. 应用到UITextView
textView.attributedText = attributedText
// 调整textView的尺寸适配竖排内容
// 可以通过计算富文本的size来设置frame或约束
let textSize = attributedText.boundingRect(with: CGSize(width: CGFloat.greatestFiniteMagnitude, height: 300), options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil).size
textView.frame = CGRect(x: 50, y: 50, width: textSize.height, height: textSize.width)

这样设置后,文本会原生按照从上到下、从左到右的竖排逻辑排版,换行和尺寸都完全匹配,不需要依赖视图变换。

方案二:修复transform旋转后的布局问题(如果一定要用旋转)

如果因为某些原因必须用transform来实现,那需要手动修正内部的文本容器尺寸和视图布局,步骤如下:

// 1. 先执行你的旋转和翻转操作
textView.transform = CGAffineTransform(rotationAngle: .pi / 2).scaledBy(x: 1, y: -1)

// 2. 修正textContainer的尺寸(旋转后宽高互换)
let originalContainerSize = textView.textContainer.size
textView.textContainer.size = CGSize(width: originalContainerSize.height, height: originalContainerSize.width)

// 3. 修正contentSize和contentOffset
textView.contentSize = CGSize(width: textView.contentSize.height, height: textView.contentSize.width)
textView.contentOffset = CGPoint(x: textView.contentOffset.y, y: textView.contentOffset.x)

// 4. 在layoutSubviews里重新调整(如果用AutoLayout,建议重写UITextView子类)
class VerticalTextView: UITextView {
    override func layoutSubviews() {
        super.layoutSubviews()
        // 每次布局后重新修正容器尺寸
        let originalSize = textContainer.size
        textContainer.size = CGSize(width: bounds.height, height: bounds.width)
        // 同步contentSize
        let newContentSize = CGSize(width: contentSize.height, height: contentSize.width)
        contentSize = newContentSize
    }
}

这个方法的核心是:旋转只是改变视图的视觉呈现,而UITextView内部的文本排版还是基于textContainer的尺寸,所以必须把容器的宽高互换,让文本在旋转后的“视觉空间”里正确排版。


内容的提问来源于stack exchange,提问作者Buren

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:54:25