How to lose margin/padding in UITextView?

2019-01-05 06:58发布

I have a UITextView in my iOS Application, which displays a large amount of text. I am then paging this text by using the offset margin parameter of the UITextView. My problem is that the padding of the UITextView is confusing my calculations as it seems to be different depending on the font size and typeface that I use.

Therefore, I pose the question: Is it possible to remove the padding surrounding the content of the UITextView?

Look forward to hearing your responses!

19条回答
一夜七次
2楼-- · 2019-01-05 07:07

I would definitely avoid any answers involving hard-coded values, as the actual margins may change with user font-size settings, etc.

Here is @user1687195's answer, written without modifying the textContainer.lineFragmentPadding (because the docs state this is not the intended usage).

This works great for iOS 7 and later.

self.textView.textContainerInset = UIEdgeInsetsMake(
                                      0, 
                                      -self.textView.textContainer.lineFragmentPadding, 
                                      0, 
                                      -self.textView.textContainer.lineFragmentPadding);

This is effectively the same outcome, just a bit cleaner in that it doesn't misuse the lineFragmentPadding property.

查看更多
Ridiculous、
3楼-- · 2019-01-05 07:07

you can use textContainerInset property of UITextView:

textView.textContainerInset = UIEdgeInsetsMake(10, 10, 10, 10);

(top, left, bottom, right)

查看更多
Root(大扎)
4楼-- · 2019-01-05 07:07

Here's an easy little extension that will remove Apple's default margin from every text view in your app.

Note: Interface Builder will still show the old margin, but your app will work as expected.

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);
   }
}
查看更多
贪生不怕死
5楼-- · 2019-01-05 07:08

Building off some of the good answers already given, here is a purely Interface Builder-based solution that makes use of User Defined Runtime Attributes and works in iOS 7.0+:

enter image description here

查看更多
叼着烟拽天下
6楼-- · 2019-01-05 07:13

For me (iOS 11 & Xcode 9.4.1) what worked magically was setting up textView.font property to UIFont.preferred(forTextStyle:UIFontTextStyle) style and also the first answer as mentioned by @Fattie. But the @Fattie answer did not work till I set the textView.font property else UITextView keeps behaving erratically.

查看更多
迷人小祖宗
7楼-- · 2019-01-05 07:14

All these answers address the title question, but I wanted to propose some solutions for the problems presented in the body of the OP's question.

Size of Text Content

A quick way to calculate the size of the text inside the UITextView is to use the NSLayoutManager:

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

This gives the total scrollable content, which may be bigger than the UITextView's frame. I found this to be much more accurate than textView.contentSize since it actually calculates how much space the text takes up. For example, given an empty 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)

Line Height

UIFont has a property that quickly allows you to get the line height for the given font. So you can quickly find the line height of the text in your UITextView with:

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

Calculating Visible Text Size

Determining the amount of text that is actually visible is important for handling a "paging" effect. UITextView has a property called textContainerInset which actually is a margin between the actual UITextView.frame and the text itself. To calculate the real height of the visible frame you can perform the following calculations:

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

Determining Paging Size

Lastly, now that you have the visible text size and the content, you can quickly determine what your offsets should be by subtracting the textHeight from the textSize:

// 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

Using all of these methods, I didn't touch my insets and I was able to go to the caret or wherever in the text that I want.

查看更多
登录 后发表回答