我在我的iOS应用程序中有一个UITextView,它显示大量的文本。

然后,我通过使用UITextView的offset margin参数来分页此文本。

我的问题是UITextView的填充使我的计算感到困惑,因为它似乎是不同的,取决于我使用的字体大小和字体。

是否有可能移除UITextView内容周围的填充?


当前回答

对于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)

其他回答

这个解决方案是在2009年iOS 3.0发布时编写的。它不再适用。

我遇到了完全相同的问题,最后我不得不吸毒

nameField.contentInset = UIEdgeInsetsMake(-4, -8, 0, 0);

其中nameField是一个UITextView。我使用的字体是Helvetica 16号。这只是我所绘制的特定字段大小的自定义解决方案。这使得左偏移量与左侧齐平,以及我想要它被绘制的盒子的顶部偏移量。

此外,这似乎只适用于你使用默认对齐的UITextViews,即,

nameField.textAlignment = NSTextAlignmentLeft;

例如,向右对齐,UIEdgeInsetsMake似乎对右边缘没有任何影响。

至少,使用. contentinset属性允许你将字段放置在“正确”的位置,并在不偏移UITextViews的情况下调整偏差。

所有这些答案都针对标题问题,但我想对OP问题主体中提出的问题提出一些解决方案。

文本内容大小

一个快速计算UITextView中文本大小的方法是使用NSLayoutManager:

UITextView *textView;
CGSize textSize = [textView usedRectForTextContainer:textView.textContainer].size;

这给出了总的可滚动内容,它可能比UITextView的帧大。我发现这比textView更准确。contentSize,因为它实际计算文本占用了多少空间。例如,给定一个空的UITextView:

textView.frame.size = (width=246, height=50)
textSize = (width=10, height=16.701999999999998)
textView.contentSize = (width=246, height=33)
textView.textContainerInset = (top=8, left=0, bottom=8, right=0)

行高

UIFont有一个属性,可以让你快速获得给定字体的行高。所以你可以快速找到文本的行高在你的UITextView:

UITextView *textView;
CGFloat lineHeight = textView.font.lineHeight;

计算可见文本大小

确定实际可见的文本数量对于处理“分页”效果很重要。UITextView有一个属性叫textContainerInset它实际上是UITextView。frame和文本本身之间的边距。要计算可视帧的实际高度,可以执行以下计算:

UITextView *textView;
CGFloat textViewHeight = textView.frame.size.height;
UIEdgeInsets textInsets = textView.textContainerInset;
CGFloat textHeight = textViewHeight - textInsets.top - textInsets.bottom;

确定分页大小

最后,现在你已经有了可见文本大小和内容,你可以通过从textSize中减去textHeight来快速确定你的偏移量:

// where n is the page number you want
CGFloat pageOffsetY = textSize - textHeight * (n - 1);
textView.contentOffset = CGPointMake(textView.contentOffset.x, pageOffsetY);

// examples
CGFloat page1Offset = 0;
CGFloat page2Offset = textSize - textHeight
CGFloat page3Offset = textSize - textHeight * 2

使用所有这些方法,我不需要触摸我的嵌入,我可以去插入号或文本中任何我想要的地方。

对于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)

最新迅速:

self.textView.textContainerInset = .init(top: -2, left: 0, bottom: 0, right: 0)
self.textView.textContainer.lineFragmentPadding = 0

这是一个简单的小扩展,将删除苹果的默认边际从每个文本视图在你的应用程序。

注意:界面构建器仍将显示旧的边缘,但你的应用程序将按预期工作。

extension UITextView {

   open override func awakeFromNib() {
      super.awakeFromNib();
      removeMargins();
   }

   /** Removes the Apple textview margins. */
   public func removeMargins() {
      self.contentInset = UIEdgeInsetsMake(
         0, -textContainer.lineFragmentPadding,
         0, -textContainer.lineFragmentPadding);
   }
}