【问题标题】:Get UITextView dynamic height with auto layout after setting text设置文本后使用自动布局获取 UITextView 动态高度
【发布时间】:2015-01-19 12:33:36
【问题描述】:

我有一个 UITextView 不能通过界面生成器设置的自动布局滚动,并且文本动态增加或减少没有问题,但我想知道设置文本后新的 UITextView 高度是多少,我正在尝试这样做:

NSLog(@"text before: %.2f",self.myText.frame.size.height);
[self.myText setText:self.string];
NSLog(@"text after: %.2f",self.myText.frame.size.height);

这是结果:

text before: 47.50
text after: 47.50

运行时视图中的文本增加了,但大小相同,设置文本后如何获得真实高度?

【问题讨论】:

  • 我遇到了一个问题,即我的 textview 无法变大以容纳更大的文本,您能否分享一下您实现此目标所遵循的步骤?
  • relevant: TextViewHeightConstraint.constant = [TextView intrinsicContentSize].height 另外不要忘记取消选中滚动!!
  • 已在以下链接中回答:stackoverflow.com/a/56156621/6386213

标签: ios objective-c autolayout uitextview


【解决方案1】:

这应该可行:

NSLog(@"text before: %.2f",self.myText.frame.size.height);
[self.myText setText:self.string];
[self.myText layoutIfNeeded]; // <--- Add this
NSLog(@"text after: %.2f",self.myText.frame.size.height);

这是我的 Github 上的示例实现:https://github.com/guillaume-algis/SO-27060338

【讨论】:

【解决方案2】:

就在更改文本调用之后

[self.myText sizeToFit];

【讨论】:

    【解决方案3】:
    - (void)textViewDidChange:(UITextView *)textView
    {
        UIFont *myFont = [UIFont systemFontOfSize:14];
        CGSize size =   [self sizeOfText:textView.text widthOfTextView:TextviewWidth withFont:myFont];
        NSLog(@"Height : %f", size.height);
    }
    
    -(CGSize)sizeOfText:(NSString *)textToMesure widthOfTextView:(CGFloat)width withFont:(UIFont*)font
    {
        CGSize ts = [textToMesure sizeWithFont:font constrainedToSize:CGSizeMake(width-20.0, FLT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
        return ts;
    }
    

    【讨论】:

      【解决方案4】:

      我使用了以下链接AutoLayout with Dynamic UITextView height 上给出的代码,它对我有用:)

      【讨论】:

      • 这是一个仅链接的答案,你能在你的答案中总结一下链接的内容吗?
      • 这适用于我的消息设计。但我只需要在四行之后增加四行。 textView 停止高度增加和滚动。任何知道的人请回答或分享链接。
      【解决方案5】:

      与 UILabel 不同,UITextView 没有固有的大小属性。所以我是如何设置UITextView 的高度约束,通过IBOutlet 挂钩,并在textViewDidChange 或文本更改时更改其值。

      @IBOutlet weak var textViewHeight: NSLayoutConstraint!
      
      func textViewDidChange(textView: UITextView) {
      
          // dynamic height adjustments
      
          var height = ceil(textView.contentSize.height) // ceil to avoid decimal
      
          if height != textViewHeight.constant { // set when height changed
              textViewHeight.constant = height
              textView.setContentOffset(CGPointZero, animated: false) // scroll to top to avoid "wrong contentOffset" artefact when line count changes
          }
      }
      

      【讨论】:

      • 但是当您键入时,您应该会看到文本的结尾。使用下一行代码滚动到底部: textView.setContentOffset(CGPoint(x: 0, y: textHeight - textView.bounds.size.height), animated: true)
      • @RomanFilippov 这比这有点棘手。您可以将文本输入光标移动到顶部并在那里添加新文本。这意味着可以在任何地方添加新文本。我猜一个缺失的部分是检测文本的插入位置并滚动到那里,它可以是顶部、底部或中心的某个位置。
      【解决方案6】:

      你所要做的就是:

      • 设置除高度之外的所有约束 AND
      • textViewscrollEnabled 属性设置为NO

      最后一部分是什么技巧。

      您的文本视图将根据其文本值自动调整大小。

      【讨论】:

      • 这对我不起作用:输入的文字是不可见的,输入几行后它终于出现在底部!
      • 算了:添加textView.setContentOffset(CGPoint.zero, animated: false) 修复它。
      • 这就是答案。
      【解决方案7】:

      使用下面的代码:

      Objective-C 代码

      [textView setScrollEnabled:NO];
      

      Swift 代码

      textView.isScrollEnabled = false
      

      【讨论】:

      • 现在是 isScrollEnabled。无法编辑,因为它的编辑量太小了
      • 感谢您的建议,我已经更新了我的答案。
      【解决方案8】:

      选择文本视图并取消选中“启用滚动”

      从顶部菜单“编辑器 > 大小以适应内容”中选择文本视图

      选择它下面的视图,用 textview 底部 将其 顶部约束 设置为您想要的任何边距,然后转到“Size Inspector”,双击或编辑您刚刚添加的约束,并将“关系”设置为“大于或等于”

      【讨论】:

        【解决方案9】:

        另一种方法是使用

        myTextView.textContainer.heightTracksTextView = true
        

        允许启用滚动

        【讨论】:

          【解决方案10】:

          Swift 3.0

          textView.isScrollEnabled = false
          

          这允许 AutoLayout 完成它的工作。

          【讨论】:

          • 这基本上是唯一需要的东西。我已经在界面生成器中添加了 textView,所以我必须在UITextView 的身份检查器中取消选中 IB 中的“启用滚动”。此外,我添加的唯一约束是顶部、前导和尾随。所以高度不是由约束定义的,那些允许大小自动改变的。
          【解决方案11】:

          如果您更喜欢通过自动布局来完成这一切:

          在尺寸检查器中:

          1. Content Compression Resistance Priority Vertical 设置为 1000。

          2. 降低 UITextView 约束高度的优先级。只需使其小于 1000。

          在属性检查器中:

          1. 取消选中启用滚动

          【讨论】:

          • 它工作得很好,否则上述所有代码在我的情况下都不起作用。谢谢。
          • 是的,这种方法效果很好。我在编码设计部分使用了这个想法。
          【解决方案12】:

          好吧,我还没有将这段代码转换成 swift4 语法,但逻辑将保持不变。这是 Xamarin.ios(C#) 的扩展方法。

          public static nfloat GetEstimateHeight(this UITextView textView, UIView View)
          {
              var size = new CoreGraphics.CGSize(View.Frame.Width, height: float.PositiveInfinity);
              var estimatedSize = textView.SizeThatFits(size);
              return estimatedSize.Height;
          }
          

          这里适用于 swift 的逻辑是

          var size = new CoreGraphics.CGSize(View.Frame.Width, height: float.PositiveInfinity);
              var estimatedSize = textView.SizeThatFits(size);
              var textViewFinalHeight = estimatedSize.Height;
          

          【讨论】:

            【解决方案13】:

            只是根据@Pavel Gurov 的回答添加。如果您已经设置了高度限制,只需将其设为非活动状态即可。之后也值得致电.sizeToFit() 以确保执行调整大小操作。

            theTextViewHeightConstraint.isActive = false
            
            theTextView.isScrollEnabled = false
            theTextView.text = "some text"
            theTextView.sizeToFit()
            

            【讨论】:

              【解决方案14】:

              使用纯swift代码设计增加文本视图高度。我只是做编码部分。

              我的这个想法来自 https://stackoverflow.com/a/45071002/9110213

              首先创建文本视图

                  import UIKit
                  
                  class TextFieldCell: UITableViewCell {
                      
                      lazy var btnEdit: UIButton! = {
                        
                        let button = UIButton()
                        button.translatesAutoresizingMaskIntoConstraints = false
                        button.addTarget(self, action: #selector(self.actionEdit(_:)), for: .touchUpInside)
                        button.setTitle("Edit", for: .normal)
                        button.titleLabel?.font = UIFont(name: "ProximaNova-Medium", size: 18)
                        button.setTitleColor( UIColor(red: 0.29, green: 0.56, blue: 0.89, alpha: 1), for: .normal)
                        button.titleLabel?.textAlignment = .left
                        return button
                        
                      }()
                    
                    lazy var separatorView: UIView! = {
                      
                      let view = UIView()
                      view.translatesAutoresizingMaskIntoConstraints = false
                      return view
                      
                    }()
                    
                    lazy var textView: UITextView! = {
                      
                      let textView = UITextView.init(frame: .zero)
                      textView.translatesAutoresizingMaskIntoConstraints = false
                      textView.delegate = self
                      textView.isScrollEnabled = false
                      return textView
                      
                    }()
                    
                    lazy var titleLabel: UILabel! = {
                      
                      let label = UILabel(frame: CGRect(x: 27, y: 318, width: 27, height: 12))
                      label.text = "Name"
                      label.font = UIFont(name: "ProximaNova-Medium", size: 10)
                      label.textColor = UIColor(red: 0.61, green: 0.61, blue: 0.61, alpha: 1)
                      label.textAlignment = .left
                      label.translatesAutoresizingMaskIntoConstraints = false
                      return label
                      
                    }()
                      
                    
                    deinit {
                      self.titleLabel = nil
                      self.textView = nil
                      self.separatorView = nil
                      self.btnEdit = nil
                    }
                      
                    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
                      super.init(style: style, reuseIdentifier: reuseIdentifier)
                      
                      self.selectionStyle = .none
                      
                      self.addView()
                      self.setConstraint()
                      
                    }
                    
                    required init?(coder: NSCoder) {
                      fatalError("init(coder:) has not been implemented")
                    }
                    
                  }
                  
                  extension TextFieldCell {
                  
                    func addView(){
                      
                      self.contentView.addSubview(self.btnEdit)
                      self.contentView.addSubview(self.titleLabel)
                      self.contentView.addSubview(self.textView)
                      self.contentView.addSubview(self.separatorView)
                  
                    }
                    
                    func setConstraint(){
                      
                     // This part is very important to increase the textview height dyamically   
              
                      let textViewHeight = self.textView.heightAnchor.constraint(equalToConstant: 27)
                      textViewHeight.priority = .defaultHigh
                      self.textView.setContentCompressionResistancePriority(.required, for: .vertical)
                      self.textView.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
                  
                      NSLayoutConstraint.activate([
                        
                        self.titleLabel.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 27),
                        self.titleLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 38),
                        
                        self.textView.topAnchor.constraint(equalTo: self.titleLabel.bottomAnchor, constant: 9),
                        self.textView.leadingAnchor.constraint(equalTo: self.titleLabel.leadingAnchor),
                        textViewHeight,
                        self.textView.trailingAnchor.constraint(equalTo: self.btnEdit.leadingAnchor, constant: -25),
                  
                        self.btnEdit.centerYAnchor.constraint(equalTo: self.textView.centerYAnchor),
                        self.btnEdit.widthAnchor.constraint(equalToConstant: 40),
                        self.btnEdit.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor, constant: -33),
                        
                        self.separatorView.topAnchor.constraint(equalTo: self.textView.bottomAnchor, constant: 10),
                        self.separatorView.heightAnchor.constraint(equalToConstant: 1),
                        self.separatorView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor),
                        self.separatorView.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 27),
                        self.separatorView.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor, constant: -15),
                        
                      ])
                      
                    }
                    
                  }
                  
                  extension TextFieldCell {
                  
                       @objc func actionEdit(_ sender: UIButton) {
                          
                      }
                    
                  }
                  
                  extension TextFieldCell: UITextViewDelegate {
                    func notifyViewController(text:String){
                      
                    }
                    func textViewDidEndEditing(_ textView: UITextView) {
                      
                    }
                  }
              

              【讨论】:

                猜你喜欢
                • 2013-12-20
                • 1970-01-01
                • 2014-01-11
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2014-01-03
                • 1970-01-01
                相关资源
                最近更新 更多