zoukankan      html  css  js  c++  java
  • How do I size a UITextView to its content?

    UITextView 自适应高度,搬来一篇stack上的:
     
    Is there a good way to adjust the size of a UITextView to conform to its content? Say for instance I have a UITextView that contains one line of text:

    "Hello world"

    I then add another line of text:

    "Goodbye world"

    Is there a good way in Cocoa Touch to get the rect that will hold all of the lines in the text view so that I can adjust the parent view accordingly?

    As another example, look at the Notes field for events in the Calendar application--note how the cell (and the UITextView it contains) expands to hold all lines of text in the notes string.

    In my (limited) experience,

     1 - (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode 

    does not respect newline characters, so you can end up with a lot shorter
    CGSize than is actually required.
     1 - (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size 

    does seem to respect the newlines.

    Also, the text isn't actually rendered at the top of the UITextView. In my code, I set the new height of the UITextView to be 24 pixels larger than the height returned by the sizeOfFont methods.

    This works for both iOS 6.1 and iOS 7:

    1 - (void)textViewDidChange:(UITextView *)textView
    2 {
    3     CGFloat fixedWidth = textView.frame.size.width;
    4     CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
    5     CGRect newFrame = textView.frame;
    6     newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
    7     textView.frame = newFrame;
    8 }
    Or in Swift

    1     let fixedWidth = textView.frame.size.width
    2     textView.sizeThatFits(CGSize( fixedWidth, height: CGFloat.max))
    3     let newSize = textView.sizeThatFits(CGSize( fixedWidth, height: CGFloat.max))
    4     var newFrame = textView.frame
    5     newFrame.size = CGSize( max(newSize.width, fixedWidth), height: newSize.height)
    6     textView.frame = newFrame;


    If you want support for iOS 6.1 then you should also:
     1 textview.scrollEnabled = NO;  

    There is actually a very easy way to do resizing of the UITextView to its correct height of the content. It can be done using the UITextView contentSize.

     1 CGRect frame = _textView.frame;
    2 frame.size.height = _textView.contentSize.height;
    3 _textView.frame = frame;
     

    One thing to note is that the correct
    contentSize is only available after the UITextView has been added to the view with addSubview. Prior to that it is equal to frame.size

    This will not work if auto layout is ON. With auto layout, the general approach is to use the sizeThatFits method and update the constant value on a height constraint.

     1 CGSize sizeThatShouldFitTheContent = [_textView sizeThatFits:_textView.frame.size]; 

    2 heightConstraint.constant = sizeThatShouldFitTheContent.height;
     

    heightConstraint is a layout constraint that you typically setup via a IBOutlet by linking the property to the height constraint created in a storyboard.


    Just to add to this amazing answer, 2014, if you:

     1 [self.textView sizeToFit]; 

    there is a difference in behaviour with the
    iPhone6+ only:

    enter image description here

    With the 6+ only (not the 5s or 6) it does add "one more blank line" to the UITextView. The "RL solution" fixes this perfectly:

     1 CGRect _f = self.mainPostText.frame;
    2 _f.size.height = self.mainPostText.contentSize.height;
    3 self.mainPostText.frame = _f;
     

    It fixes the "extra line" problem on 6+.

     

    In my (limited) experience,

     1 - (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode 

    does not respect newline characters, so you can end up with a lot shorter
    CGSize than is actually required.
     1 - (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size 

    does seem to respect the newlines.

    Also, the text isn't actually rendered at the top of the UITextView. In my code, I set the new height of the UITextView to be 24 pixels larger than the height returned by the sizeOfFont methods.

    In iOS6, you can check the contentSize property of UITextView right after you set the text. In iOS7, this will no longer work. If you want to restore this behavior for iOS7, place the following code in a subclass of UITextView.

     1 - (void)setText:(NSString *)text
     2 {
     3     [super setText:text];
     4 
     5     if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
     6         CGRect rect = [self.textContainer.layoutManager usedRectForTextContainer:self.textContainer];
     7         UIEdgeInsets inset = self.textContainerInset;
     8         self.contentSize = UIEdgeInsetsInsetRect(rect, inset).size;
     9     }
    10 }
     

    To make a dynamically sizing UITextView inside a UITableViewCell, I found the following combination works in Xcode 6 with the iOS 8 SDK:

    • In Storyboard/IB, add a UITextView to a UITableViewCell and constrain it to the sides
    • In Storyboard/IB, uncheck Scrolling Enabled (with scrolling enabled, the frame of the UITextView is independent of the content size, but with scrolling disabled, there is a relationship between the two)
    • In viewDidLoad, tell the tableView to automatically calculate row heights:

       1 tableView.estimatedRowHeight = 150; 
    • 2 tableView.rowHeight = UITableViewAutomaticDimension; 
      

    For read-only dynamically sizing UITextViews, that’s it. If you’re allowing users to edit the text in your UITextView, you also need to:

    • Implement the textViewDidChange: method of the UITextViewDelegate protocol, and tell the tableView to repaint itself every time the text is edited:

      1 - (void)textViewDidChange:(UITextView *)textView;
      2 {
      3     [tableView beginUpdates];
      4     [tableView endUpdates];
      5 }
    • And don’t forget to set the UITextView delegate somewhere, either in Storyboard/IB or in tableView:cellForRowAtIndexPath:

  • 相关阅读:
    AD用户移除所属组
    Mysql中文乱码问题完美解决方案
    将sqllite3数据库迁移到mysql
    检查远端服务器端口是否打开
    远程桌面卡
    不同平台的线程并发接口对比
    stm32之中断配置
    stm32之CMSIS标准、库目录、GPIO
    stm32 中断几个库函数实现过程分析
    Tree命令使用
  • 原文地址:https://www.cnblogs.com/A--G/p/4651483.html
Copyright © 2011-2022 走看看