如何让TextView可以水平滚动
How to let TextView be able to scroll horizontally
我知道 TextView
嵌入在 ScrollView
中。如果有一个相当长的 String
(其中不包含 "\n"
)
TextView
会根据TextView
的宽度自动换行。
如果TextView
的高度很短,那么我们可以垂直滚动它。
你如何禁用自动换行?这样,如果没有遇到“\n”,它就不会换行。相反,它允许用户水平滚动以查看文本。
我该如何实施?
[myTextView setContentSize:CGSizeMake(width, myTextView.frame.size.height)];
内容的宽度超出了 textView 框架的宽度,否则它不会滚动。
- 关闭 UITextView 上的所有滚动选项,然后将其嵌入另一个
UIScrollView
。 Reference:- 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/
我知道 TextView
嵌入在 ScrollView
中。如果有一个相当长的 String
(其中不包含 "\n"
)
TextView
会根据TextView
的宽度自动换行。
如果TextView
的高度很短,那么我们可以垂直滚动它。
你如何禁用自动换行?这样,如果没有遇到“\n”,它就不会换行。相反,它允许用户水平滚动以查看文本。
我该如何实施?
[myTextView setContentSize:CGSizeMake(width, myTextView.frame.size.height)];
内容的宽度超出了 textView 框架的宽度,否则它不会滚动。
- 关闭 UITextView 上的所有滚动选项,然后将其嵌入另一个
UIScrollView
。 Reference:- 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/