我在我的iOS应用程序中有一个UITextView,它显示大量的文本。
然后,我通过使用UITextView的offset margin参数来分页此文本。
我的问题是UITextView的填充使我的计算感到困惑,因为它似乎是不同的,取决于我使用的字体大小和字体。
是否有可能移除UITextView内容周围的填充?
我在我的iOS应用程序中有一个UITextView,它显示大量的文本。
然后,我通过使用UITextView的offset margin参数来分页此文本。
我的问题是UITextView的填充使我的计算感到困惑,因为它似乎是不同的,取决于我使用的字体大小和字体。
是否有可能移除UITextView内容周围的填充?
当前回答
使用用户定义运行时属性的故事板或接口构建器解决方案:
iOS 7.1和iOS 6.1的截图内容为contentInset ={{-10, -5},{0,0}}。
其他回答
基于已经给出的一些好的答案,这里是一个纯基于Storyboard / Interface builder的解决方案,适用于iOS 7.0+
为以下键设置UITextView的用户定义运行时属性:
textContainer.lineFragmentPadding
textContainerInset
textView滚动也会影响文本的位置,使它看起来不是垂直居中。我通过禁用滚动并将顶部插入设置为0来设法将文本置于视图的中心:
textView.scrollEnabled = NO;
textView.textContainerInset = UIEdgeInsetsMake(0, textView.textContainerInset.left, textView.textContainerInset.bottom, textView.textContainerInset.right);
由于某种原因,我还没有弄清楚,在开始输入之前,光标仍然没有居中,但当我开始输入时,文本立即居中。
2023年最新情况
这是iOS系统中最愚蠢的漏洞之一。
这里给出的类UITextViewFixed被广泛使用,通常是最合理的解决方案。
下面是这个类:
@IBDesignable class UITextViewFixed: UITextView {
override func layoutSubviews() {
super.layoutSubviews()
setup()
}
func setup() {
textContainerInset = UIEdgeInsets.zero
textContainer.lineFragmentPadding = 0
}
}
不要忘记在检查器中关闭scrollEnabled !
解决方案在故事板中正常工作 解决方案在运行时正常工作
你就完成了。一般来说,在大多数情况下,这应该是您所需要的。
即使您正在动态地更改文本视图的高度,UITextViewFixed通常也能满足您的所有需要。
(动态更改高度的一个常见示例是随着用户输入而更改它。)
这是来自苹果的破碎的UITextView…
这是UITextViewFixed:
请注意,当然你必须……
…在检查器中关闭scrollEnabled !
(打开scrollEnabled意味着“通过尽可能扩大底部边缘,使这个视图尽可能垂直地展开。”)
一些进一步的问题
(1)在非常特殊的情况下,当动态改变高度时,苹果会做一件奇怪的事情:在底部增加额外的空间。
不,真的!这可能是iOS中最让人恼火的事情之一。
如果你遇到这个问题,这里有一个“快速修复”通常会有帮助:
...
textContainerInset = UIEdgeInsets.zero
textContainer.lineFragmentPadding = 0
// this is not ideal, but sometimes this "quick fix"
// will solve the "extra space at the bottom" insanity:
var b = bounds
let h = sizeThatFits(CGSize(
width: bounds.size.width,
height: CGFloat.greatestFiniteMagnitude)
).height
b.size.height = h
bounds = b
...
(2)在极少数情况下,为了解决苹果的另一个微妙混乱,你必须补充:
override func setContentOffset(_ contentOffset: CGPoint, animated: Bool) {
super.setContentOffset(contentOffset, animated: false) // sic
}
(3)可以说,我们应该补充:
contentInset = UIEdgeInsets.zero
就在UITextViewFixed中的. linefragmentpadding = 0之后。
不管你信不信,这在当前的iOS系统中并不适用!(检查2023。)将来可能有必要添加这一行。
UITextView在iOS中被破坏的事实是所有移动计算中最奇怪的事情之一。这个问题已经十年了,但仍然没有解决!
最后,这里有一个有点类似的提示TextField:设置一个UITextField的最大字符长度在Swift
完全随机的提示:如何在结尾加上“…”
通常你会像使用UILabel一样使用UITextView。所以你想用省略号"…"来截断文本
如果是,请补充:
textContainer.lineBreakMode = .byTruncatingTail
如果你想要零高度,当,根本没有文本
通常使用文本视图只显示文本。你使用lines "0"表示文本视图会根据文本行数自动改变高度。
太好了。但如果根本没有文本,那么不幸的是,你得到的高度与只有一行文本!!!!相同文本视图永远不会“消失”。
如果你想让它“消失”,只需添加这个
override var intrinsicContentSize: CGSize {
var i = super.intrinsicContentSize
print("for \(text) size will be \(i)")
if text == "" { i.height = 1.0 }
print(" but we changed it to \(i)")
return i
}
(我把它的高度设为“1”,所以很清楚演示中发生了什么,“0”就可以了。)
那UILabel呢?
当只显示文本时,UILabel比UITextView有很多优势。UILabel不会遇到这个问答页面上描述的问题。
事实上,我们通常都“放弃”而只使用UITextView的原因是UILabel很难使用。特别是,正确地向UILabel添加填充是非常困难的。
事实上,这里有一个关于如何“最终”正确地添加填充到UILabel的完整讨论:添加空格/填充到UILabel。在某些情况下,如果你正在用动态高度单元格做一个困难的布局,有时候用UILabel来做会更好。
对于Swift 4, Xcode 9
使用下面的函数。它可以改变UITextView中文本的边距/填充:
public func UIEdgeInsetsMake(_ top: CGFloat, _ left: CGFloat, _ bottom: CGFloat, _ right: CGFloat) -> UIEdgeInsets
所以在这种情况下,它是:
self.textView?.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0)
以下是胖子非常有用的答案的更新版本。 它增加了两行重要的行,帮助我在iOS 10和11上(可能在较低的版本上也是如此)让布局正常运行:
@IBDesignable class UITextViewFixed: UITextView {
override func layoutSubviews() {
super.layoutSubviews()
setup()
}
func setup() {
translatesAutoresizingMaskIntoConstraints = true
textContainerInset = UIEdgeInsets.zero
textContainer.lineFragmentPadding = 0
translatesAutoresizingMaskIntoConstraints = false
}
}
重要的几行是两个translatesAutoresizingMaskIntoConstraints = <true/false>语句!
这令人惊讶地删除了我所有环境中的所有边缘!
虽然textView不是第一个响应器,但可能会发生一些奇怪的底边距无法使用接受的答案中提到的sizeThatFits方法解决的情况。
当敲入textView,突然奇怪的底部边缘消失了,一切看起来像它应该,但只要textView有firstResponder。
所以我在Stack Overflow上读到,启用和禁用translatesAutoresizingMaskIntoConstraints在调用之间手动设置帧/边界时确实有帮助。
幸运的是,这不仅适用于框架设置,而且还适用于夹在两个translatesAutoresizingMaskIntoConstraints调用之间的两行setup() !
例如,当在UIView上使用systemlayoutsizefiting计算视图的帧时,这是非常有用的。它会返回正确的大小(以前它没有)!
如原文所述:
不要忘记在检查器中关闭scrollEnabled !这个解决方案在故事板和运行时都能正常工作。
就是这样,现在你真的完成了!