【问题标题】:Resizing UITextView调整 UITextView 的大小
【发布时间】:2010-10-18 05:46:38
【问题描述】:

我在UIView 上添加了一个UITextView。添加的textview是不可编辑的,只是为了显示一些数据。 textview 中显示的数据是动态的。那就是行数不固定。它可能会有所不同。所以如果行数增加,textview的大小也需要增加。我不知道该怎么做。请给我一些想法。

更新:

这就是我正在做的事情:

UIView *baseView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 200)];
baseView.backgroundColor = [UIColor grayColor];
[window addSubview:baseView];

UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(5, 30, 100, 30)];
textView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
textView.text = @"asdf askjalskjalksjlakjslkasj";
[textView sizeToFit];
[baseView addSubview:textView];

【问题讨论】:

标签: iphone uitextview


【解决方案1】:

How do I size a UITextView to its content?有回复

CGRect frame = _textView.frame;
frame.size.height = _textView.contentSize.height;
_textView.frame = frame;

或更好(考虑到 contentInset 感谢 kpower 的评论)

CGRect frame = _textView.frame;
UIEdgeInsets inset = textView.contentInset;
frame.size.height = _textView.contentSize.height + inset.top + inset.bottom;
_textView.frame = frame;

注意:如果您要多次引用对象的属性(例如 frame 或 contentInset),最好将其分配给局部变量,这样您就不会触发额外的方法调用(_textView.frame/[_textView frame ] 是方法调用)。如果您多次调用此代码(100000 次),那么这将明显变慢(十几个方法调用无关紧要)。

但是...如果您想在一行中执行此操作而没有额外的变量,那将是

_textView.frame = CGRectMake(_textView.frame.origin.x, _textView.frame.origin.y, _textView.frame.size.width, _textView.contentSize.height + _textView.contentInset.top + _textView.contentInset.bottom);

以 5 次额外的方法调用为代价。

【讨论】:

  • frame.size.height = _textView.contentInset.top + _textView.contentInset.bottom + _textView.contentSize.height;
  • [textView setFrame: CGRectMake([textView frame].origin.x, [textView frame].origin.y, [textView contentSize].width, [textView contentSize].height)];跨度>
  • 当内容是 HTML 格式时,有什么办法可以做到这一点?
  • 更好的答案,没有成本,没有脏代码,更好的性能。
  • 但是请看下面的答案。
【解决方案2】:

您可以使用setFrame:sizeToFit

更新:

我使用sizeToFitUILabel,它工作得很好,但是UITextViewUIScrollView 的子类,所以我可以理解为什么sizeToFit 没有产生预期的结果。

您仍然可以计算文本高度并使用setFrame,但如果文本太长,您可能需要利用UITextView 的滚动条。

获取文本高度的方法如下:

#define MAX_HEIGHT 2000

NSString *foo = @"Lorem ipsum dolor sit amet.";
CGSize size = [foo sizeWithFont:[UIFont systemFontOfSize:14]
              constrainedToSize:CGSizeMake(100, MAX_HEIGHT)
                  lineBreakMode:UILineBreakModeWordWrap];

然后您可以将其与您的UITextView 一起使用:

[textView setFont:[UIFont systemFontOfSize:14]];
[textView setFrame:CGRectMake(5, 30, 100, size.height + 10)];

或者你可以先计算高度,避开setFrame这一行:

UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(5, 30, 100, size.height + 10)];

【讨论】:

  • 其实我不知道如何删除这个答案以及如何更新我自己的问题。做这些是没有选择的。 (仅供参考,我使用的是 safari 浏览器)
  • 对不起!刚才我看到了那些选项
  • 这很好用。但它需要最初设置框架。那是在我添加的代码之前 textView = [[UITextView alloc] initWithFrame:CGRectMake(5.0, 30.0, 100, 30)];.
  • 添加上述内容后,只有文本视图可见。并且文本视图中的最后一行没有完全显示。只显示它的上半部分。
  • 正确答案如下,作者 Gabe。它不依赖于神奇的 +10,而且更准确。
【解决方案3】:

sizeToFit 确实有效

如果您在设置文本第一次调整大小后调用 sizeToFit。因此,在您第一次设置它之后,对设置文本的后续调用将不会导致大小发生变化。即使你调用 sizeToFit。

但是,您可以像这样强制它调整大小:

  1. 设置文本。
  2. 将 textView 框架高度更改为 CGFLOAT_MAX。
  3. 调用 sizeToFit。

【讨论】:

    【解决方案4】:
    textViewDidChange 中的

    textView.contentSize.height 只能在 文本实际增长后调整大小。为了获得最佳视觉效果,最好事先调整大小。几个小时后,我想出了如何让它和 Instagram 一样完美(它拥有所有 BTW 中最好的算法)

    用这个初始化:

        // Input
        _inputBackgroundView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, size.height - _InputBarHeight, size.width, _InputBarHeight)];
        _inputBackgroundView.autoresizingMask = UIViewAutoresizingNone;
       _inputBackgroundView.contentMode = UIViewContentModeScaleToFill;
        _inputBackgroundView.userInteractionEnabled = YES;
        [self addSubview:_inputBackgroundView];
       [_inputBackgroundView release];
    
       [_inputBackgroundView setImage:[[UIImage imageNamed:@"Footer_BG.png"] stretchableImageWithLeftCapWidth:80 topCapHeight:25]];
    
        // Text field
        _textField = [[UITextView alloc] initWithFrame:CGRectMake(70.0f, 0, 185, 0)];
       _textField.backgroundColor = [UIColor clearColor];
        _textField.delegate = self;
       _textField.contentInset = UIEdgeInsetsMake(-4, -2, -4, 0);
       _textField.showsVerticalScrollIndicator = NO;
       _textField.showsHorizontalScrollIndicator = NO;
        _textField.font = [UIFont systemFontOfSize:15.0f];
        [_inputBackgroundView addSubview:_textField];
       [_textField release];
    
       [self adjustTextInputHeightForText:@""];
    

    填充 UITextView 委托方法:

    - (void) textViewDidBeginEditing:(UITextView*)textView {
    
       [self adjustTextInputHeightForText:_textField.text];
    }
    
    - (void) textViewDidEndEditing:(UITextView*)textView {
    
       [self adjustTextInputHeightForText:_textField.text];
    }
    
    - (BOOL) textView:(UITextView*)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString*)text {
    
       if ([text isEqualToString:@"\n"])
       {
          [self performSelector:@selector(inputComplete:) withObject:nil afterDelay:.1];
          return NO;
       }
       else if (text.length > 0)
       {
          [self adjustTextInputHeightForText:[NSString stringWithFormat:@"%@%@", _textField.text, text]];
       }
       return YES;
    }
    
    - (void) textViewDidChange:(UITextView*)textView {
    
       [self adjustTextInputHeightForText:_textField.text];
    }
    

    诀窍是……

    - (void) adjustTextInputHeightForText:(NSString*)text {
    
       int h1 = [text sizeWithFont:_textField.font].height;
       int h2 = [text sizeWithFont:_textField.font constrainedToSize:CGSizeMake(_textField.frame.size.width - 16, 170.0f) lineBreakMode:UILineBreakModeWordWrap].height;
    
       [UIView animateWithDuration:.1f animations:^
       {
          if (h2 == h1)
          {
             _inputBackgroundView.frame = CGRectMake(0.0f, self.frame.size.height - _InputBarHeight, self.frame.size.width, _InputBarHeight);
          }
          else
          {
             CGSize size = CGSizeMake(_textField.frame.size.width, h2 + 24);
             _inputBackgroundView.frame = CGRectMake(0.0f, self.frame.size.height - size.height, self.frame.size.width, size.height);
          }
          CGRect r = _textField.frame;
          r.origin.y = 12;
          r.size.height = _inputBackgroundView.frame.size.height - 18;
          _textField.frame = r;
    
       } completion:^(BOOL finished)
       {
          //
       }];
    }
    

    【讨论】:

    • 按下回车键时不会增加字段。自动更正提示显示在键盘下方。不处理横向。
    【解决方案5】:

    这对我来说非常适合:

    #define MAX_HEIGHT 2000     
    CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:14]
          constrainedToSize:CGSizeMake(100, MAX_HEIGHT)
              lineBreakMode:UILineBreakModeWordWrap];
    
    [textview setFont:[UIFont systemFontOfSize:14]];
    [textview setFrame:CGRectMake(45, 6, 100, size.height + 10)];
    textview.text = text;
    

    【讨论】:

      【解决方案6】:

      执行以下操作:

      _textView.text = someText;
      [_textView sizeToFit];
      _textView.frame.height = _textView.contentSize.height;
      

      【讨论】:

        【解决方案7】:

        解决了类似的问题,我刚刚创建了一个基于自动布局的轻量级 UITextView 子类,它会根据用户输入的大小自动增长和缩小,并且可以通过最大和最小高度来限制 - 所有这些都无需一行代码.

        https://github.com/MatejBalantic/MBAutoGrowingTextView

        【讨论】:

          【解决方案8】:

          @Gabe 给出的答案似乎直到 viewDidAppear 之后才在 iOS7.1 中起作用。请参阅下面的测试。

          更新:实际上,情况更加复杂。如果您在 resizeTheTextView 方法中分配 textView.text,则在 iOS7 中,调整大小相当于只允许单行文本。真的很奇怪。

          UPDATE2:另见UITextView content size different in iOS7

          UPDATE3:请参阅最底部的代码以了解我现在正在使用的内容。似乎可以胜任。

          #import "ViewController.h"
          
          @interface ViewController ()
          {
              UITextView *textView;
          }
          @end
          
          @implementation ViewController
          
          - (void)viewDidLoad
          {
              [super viewDidLoad];
              // Do any additional setup after loading the view, typically from a nib.
          
              textView = [[UITextView alloc] initWithFrame:CGRectMake(50, 50, 200, 1)];
              [self.view addSubview:textView];
              CALayer *layer = textView.layer;
              layer.borderColor = [UIColor blackColor].CGColor;
              layer.borderWidth = 1;
          
              textView.text = @"hello world\n\n";
          
              // Calling the method directly, after the view is rendered, i.e., after viewDidAppear, works on both iOS6.1 and iOS7.1
              UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
              [button setTitle:@"Change size" forState:UIControlStateNormal];
              [button addTarget:self action:@selector(resizeTheTextView) forControlEvents:UIControlEventTouchUpInside];
              [button sizeToFit];
              CGRect frame = button.frame;
              frame.origin.y = 400;
              button.frame = frame;
              [self.view addSubview:button];
          
              // Works on iOS6.1, but does not work on iOS7.1
              //[self resizeTheTextView];
          }
          
          - (void) viewWillAppear:(BOOL)animated
          {
              // Does not work on iOS7.1, but does work on iOS6.1
              //[self resizeTheTextView];
          }
          
          - (void) viewDidAppear:(BOOL)animated
          {
              // Does work on iOS6.1 and iOS7.1
              //[self resizeTheTextView];
          }
          
          - (void) resizeTheTextView
          {
              NSLog(@"textView.frame.size.height: %f", textView.frame.size.height);
          
              NSLog(@"textView.contentSize.height: %f", textView.contentSize.height);
          
              // 5) From https://stackoverflow.com/questions/728704/resizing-uitextview
              CGRect frame = textView.frame;
              UIEdgeInsets inset = textView.contentInset;
              frame.size.height = textView.contentSize.height + inset.top + inset.bottom;
              textView.frame = frame;
          
              NSLog(@"inset.top: %f, inset.bottom: %f",  inset.top,  inset.bottom);
          
              NSLog(@"textView.frame.size.height: %f", textView.frame.size.height);
          
              NSLog(@"textView.contentSize.height: %f", textView.contentSize.height);
          }
          
          - (void)didReceiveMemoryWarning
          {
              [super didReceiveMemoryWarning];
              // Dispose of any resources that can be recreated.
          }
          
          @end
          

          更新3:

          if ([[UIDevice currentDevice] majorVersionNumber] < 7.0) {
              CGRect frame = _abstractTextView.frame;
              UIEdgeInsets inset = _abstractTextView.contentInset;
              frame.size.height = _abstractTextView.contentSize.height + inset.top + inset.bottom;
              _abstractTextView.frame = frame;
          }
          else {
              CGSize textViewSize = [_abstractTextView sizeThatFits:CGSizeMake(_abstractTextView.frame.size.width, FLT_MAX)];
              _abstractTextView.frameHeight = textViewSize.height;
          }
          

          【讨论】:

            【解决方案9】:

            如果您在其上设置内容模式,将 UITextView 添加到其父级后,它似乎会自动调整大小。

            这意味着您无需手动计算高度并应用高度约束。它似乎工作!在 iPad 上的 iOS7 和 iOS8 中测试。

            例如

            --
            textView.contentMode = UIViewContentMode.Center;
            --
            

            如果有人能解释为什么这会起作用,我将不胜感激。我在搞乱界面生成器中的选项时偶然发现了它。

            【讨论】:

            • @Martijn Pieters 我已将此问题投票为重复问题。您应该取消删除另一个问题的答案,如果这些是规则,则删除这个答案。
            【解决方案10】:

            只需将scrollEnabled 设置为NO,或在IB 的滚动视图部分取消选中启用滚动UITextView 将自动调整大小。

            【讨论】:

              猜你喜欢
              • 2013-10-09
              • 2014-01-10
              • 2012-12-26
              • 1970-01-01
              • 2014-01-18
              • 2012-11-24
              • 2023-03-11
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多