如何让TextView可以水平滚动

How to let TextView be able to scroll horizontally

我知道 TextView 嵌入在 ScrollView 中。如果有一个相当长的 String(其中不包含 "\n"

TextView会根据TextView的宽度自动换行。

如果TextView的高度很短,那么我们可以垂直滚动它。 你如何禁用自动换行?这样,如果没有遇到“\n”,它就不会换行。相反,它允许用户水平滚动以查看文本。

我该如何实施?

  1. [myTextView setContentSize:CGSizeMake(width, myTextView.frame.size.height)];

内容的宽度超出了 textView 框架的宽度,否则它不会滚动。

  1. 关闭 UITextView 上的所有滚动选项,然后将其嵌入另一个 UIScrollViewReference:- DualScrollTextView

在你们的帮助下我想出了如何做到这一点 :D,谢谢,我们开始吧!

1. 所以,首先,我们需要一个 longlonglong 字符串,对吧?

let displayStr = "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 "

2. 假设我们有一个 UIScrollView 由 @IBOutlet 链接或通过调用 .viewWithTag(xxx) 获得。我们将把它命名为 scroll :

3. 是时候获取字符串的 size 了,这是我们将要使用的关键函数:

哦!我差点忘了定义我们将使用哪种 Font(这是一个关键参数),以及字符串大小的 max-size 是多少

let maxSize = CGSizeMake(9999, 9999)
let font = UIFont(name: "Menlo", size: 16)!
//key function is coming!!!
let strSize = (displayStr as NSString).boundingRectWithSize(maxSize, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName : font], context: nil)

4. OK,现在我们可以把字符串放到一个textView中,需要通过编程方式新建一个UITextView,这样我们就可以定义其中的frame了与字符串的大小相同(哦,可能大一点:D):

let frame = CGRectMake(0, 0, size.width+50, size.height+10)
let textView = UITextView(frame: frame)
textView.editable = false
textView.scrollEnabled = false//let textView becomes unScrollable
textView.font = font
textView.text = displayStr

5. 回到我们的scroll,我们将设置它的contentSize:

scroll.contentSize = CGSizeMake(size.width, size.height)

6. 最后,addSubview: scroll.addSubview(textView)

You can see, textView is embed in a scrollView, which allow it to scroll with 2 directions.

B.T.W. My implement is just a demo for static String. if you want user to use a textView which will not line wrap if he doesn't input any "\n", you may need dynamically calculate the string size. :D

[希望对您有所帮助]

@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet weak var textView: UITextView!

var yourText: String = "Whatever your text is going to be." 

override func viewDidLayoutSubviews() {

    super.viewDidLayoutSubviews()
    self.scrollView.layoutIfNeeded()
    self.scrollView.contentSize = self.textView.bounds.size

}


override func viewDidLoad() {
    super.viewDidLoad()

textView.text = yourText

    textView.sizeThatFits(CGSizeMake(textView.frame.size.width, 80)) //height to equal the actual size of your text view.

}

我认为这应该是即插即用的,但我确信 textView.sizeThatFits 可以工作。您必须确保将文本视图限制在其父滚动视图中才能正常工作。 (前导、尾随、顶部、底部和高度。)

已接受的答案不适用于 AutoLayout,所以我将分享我的方法:

1. 添加一个带有 UITextView 的 UIScrollView,并固定 它们

的所有边缘

2. 为您的 UITextView 添加宽度和高度限制(无论您将它们设置为什么)

3. 为 UITextView 创建 IBOutlets,高度约束和宽度约束

4. 取消勾选 TextView'Scrolling Enabled'

5.更新文本时,计算文本的边界大小,并用边界大小更新高宽约束

@IBOutlet weak var textView: UITextView!
@IBOutlet weak var textViewHeightConstraint: NSLayoutConstraint!
@IBOutlet weak var textViewWidthConstraint: NSLayoutConstraint!

let displayText = "Your text here."

override func viewDidLoad() {
    super.viewDidLoad()

    let maxSize = CGSize(width: 10000, height: 30000)
    let textRect = displayText.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, attributes: [.font : self.textView.font!], context: nil)

    self.textView.text = displayText
    self.textViewHeightConstraint.constant = textRect.height
    self.textViewWidthConstraint.constant = textRect.width
}

更新: 我发现这种方法对大量文本使用大量内存(我看到使用了超过 1GB)。以下是我如何将内存影响从 1GB 减少到 100MB:

1. 像上面的步骤 1 一样设置边缘约束。

2. 为可滚动内容的宽度添加一个TextView的宽度约束(我用的是2000但是你可以根据自己的喜好调整它,越宽你的内存越多不过会用)。

3.添加约束使TextView和ScrollView等高

就是这样!可滚动宽度将保持不变,一旦您为 TextView 设置文本,可滚动高度将自动调整。

注意:这种方法的一些注意事项:

  • 可滚动宽度始终是您设置的宽度,但如果您想根据文本调整大小,您可以使用第一种解决方案的混合方法
  • 您看不到垂直滚动条(除非一直向右滚动),但可以通过调整 TextView 的滚动条插入来恢复它。

参考:https://www.ralfebert.de/ios-examples/auto-layout/uiscrollview-storyboard/