как сделать динамическую высоту UITextView в соответствии с длиной текста?

Как вы можете видеть на этом изображении

UITextView изменяет высоту в соответствии с длиной текста, я хочу настроить ее высоту в соответствии с длиной текста.

* Я видел другие вопросы, но решения там не работали для меня

example

Ответ 1

это работает для меня, других решений нет.

func adjustUITextViewHeight(arg : UITextView)
{
    arg.translatesAutoresizingMaskIntoConstraints = true
    arg.sizeToFit()
    arg.scrollEnabled = false
}

В Swift 4 синтаксис arg.scrollEnabled = false изменился на arg.isScrollEnabled = false.

Ответ 2

Попробуйте:

CGRect frame = self.textView.frame;
frame.size.height = self.textView.contentSize.height;
self.textView.frame = frame;

Edit- Здесь Swift:

var frame = self.textView.frame
frame.size.height = self.textView.contentSize.height
self.textView.frame = frame

Ответ 3

В Storyboard/Interface Builder просто отключите прокрутку в инспекторе атрибутов.

В коде textField.isScrollEnabled = false должен делать трюк.

Ответ 4

Swift 4

Добавить в свой класс

UITextViewDelegate

func textViewDidChange(_ textView: UITextView) {
      let fixedWidth = textView.frame.size.width
      textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
      let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
      var newFrame = textView.frame
      newFrame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)
      textView.frame = newFrame
}

Ответ 5

Затем отвечает Дея Элдин.
В моем случае. Я автоматически увеличиваю высоту текста, добавляя

быстрый 3

textView.translatesAutoresizingMaskIntoConstraints = false textView.isScrollEnabled = false

Ответ 6

просто подключитесь к своей структуре.

@IBOutlet var textView: UITextView!
@IBOutlet var textViewHeightConstraint: NSLayoutConstraint!

и используйте этот код ниже

textViewHeightConstraint.constant = self.textView.contentSize.height

Ответ 7

это прямое намерение сделать программным образом. просто выполните следующие действия

  1. добавить наблюдателя в длину содержимого текстового поля

    [yourTextViewObject addObserver:self forKeyPath:@"contentSize" options:(NSKeyValueObservingOptionNew) context:NULL];
    
  2. осуществлять наблюдателя

    -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    UITextView *tv = object;
    
        //Center vertical alignment
        CGFloat topCorrect = ([tv bounds].size.height - [tv contentSize].height * [tv zoomScale])/2.0;
        topCorrect = ( topCorrect < 0.0 ? 0.0 : topCorrect );
        tv.contentOffset = (CGPoint){.x = 0, .y = -topCorrect};
    
    
        mTextViewHeightConstraint.constant = tv.contentSize.height;
    
        [UIView animateWithDuration:0.2 animations:^{
    
            [self.view layoutIfNeeded];
        }];
    
    }
    
  3. если вы хотите, чтобы textviewHeight увеличивалось через некоторое время во время ввода, выполните это и установите делегат textview для себя.

    -(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
    {
        if(range.length + range.location > textView.text.length)
        {
            return NO;
        }
    
        NSUInteger newLength = [textView.text length] + [text length] - range.length;
    
        return (newLength > 100) ? NO : YES;
    
    }
    

Ответ 8

Если вашему textView разрешено расти так же высоко, как и контенту, тогда

textView.isScrollEnabled = false

должен просто работать с autolayout.

Если вы хотите оставить textView для textView, вам нужно добавить дополнительное ограничение высоты,

internal lazy var textViewHeightConstraint: NSLayoutConstraint = {
  let constraint = self.textView.heightAnchor.constraint(equalToConstant: 0)
  constraint.priority = .defaultHigh
  return constraint
}()

public override func layoutSubviews() {
  super.layoutSubviews()

  // Assuming there is width constraint setup on the textView.
  let targetSize = CGSize(width: textView.frame.width, height: CGFloat(MAXFLOAT))
  textViewHeightConstraint.constant = textView.sizeThatFits(targetSize).height
}

Причина переопределения layoutSubviews() состоит в том, чтобы убедиться, что textView правильно выложен по горизонтали, поэтому мы можем рассчитывать на ширину для вычисления высоты.

Поскольку ограничение по высоте имеет более низкий приоритет, если оно занимает свободное место вертикально, фактическая высота textView будет меньше, чем contentSize. И textView будет прокручиваться.

Ответ 9

работает

func textViewDidChange(_ textView: UITextView) {
    let fixedWidth = textviewconclusion.frame.size.width
    textviewconclusion.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
    let newSize = textviewconclusion.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
    var newFrame = textviewconclusion.frame
    newFrame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)
    textviewconclusion.frame = newFrame
}

Ответ 10

SWIFT 4

Изменить размер при наборе

UITextViewDelegate

func textViewDidChange(_ textView: UITextView) {
        yourTextView.translatesAutoresizingMaskIntoConstraints = true
        yourTextView.sizeToFit()
        yourTextView.isScrollEnabled = false

        let calHeight = yourTextView.frame.size.height
        yourTextView.frame = CGRect(x: 16, y: 193, width: self.view.frame.size.width - 32, height: calHeight)
    }

Изменить размер при загрузке

func textViewNotasChange(arg : UITextView) {
        arg.translatesAutoresizingMaskIntoConstraints = true
        arg.sizeToFit()
        arg.isScrollEnabled = false

        let calHeight = arg.frame.size.height
        arg.frame = CGRect(x: 16, y: 40, width: self.view.frame.size.width - 32, height: calHeight)
    }

Вызовите функцию второй опции следующим образом:

textViewNotasChange(arg: yourTextView)

Ответ 11

В моем проекте диспетчер представлений задействован с множеством Constraints и StackView, и я устанавливал высоту TextView как ограничение и менялся в зависимости от значения textView.contentSize.height.

step1: получить выход IB

@IBOutlet weak var textViewHeight: NSLayoutConstraint!

step2: используйте метод делегирования ниже.

extension NewPostViewController: UITextViewDelegate {
     func textViewDidChange(_ textView: UITextView) {
          textViewHeight.constant = self.textView.contentSize.height + 10
     }
}

Ответ 12

Лучше, но быстро 4 добавить как расширение:

extension UITextView {
    func resizeForHeight(){
        self.translatesAutoresizingMaskIntoConstraints = true
        self.sizeToFit()
        self.isScrollEnabled = false
    }
}

Ответ 13

Свифт 4+

Это очень легко с autolayout ! Я объясню самый простой вариант использования. Допустим, в вашем UITableViewCell есть только UITextView.

  • textView к contentView с ограничениями.
  • Отключите прокрутку для textView.
  • Обновите tableView в textViewDidChange.

(Вы можете сделать последний шаг двумя способами - либо передать экземпляр tableView в ячейку, либо установить делегат textView на свой контроллер представления, реализовать textViewDidChange делегат textViewDidChange и обновить представление таблицы.)

Все это!

class TextViewCell: UITableViewCell {

    //MARK: UI Element(s)
    /// Reference of the parent table view so that it can be updated
    var tableView: UITableView!

    lazy var textView: UITextView = {
        let textView = UITextView()
        textView.isScrollEnabled = false
        // Other textView properties
        return textView
    }()

    //MARK: Padding Variable(s)
    let padding: CGFloat = 50

    //MARK: Initializer(s)
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        addSubviews()
        addConstraints()

        textView.becomeFirstResponder()
    }

    //MARK: Helper Method(s)
    func addSubviews() {
        contentView.addSubview(textView)
    }

    func addConstraints() {
        textView.leadingAnchor  .constraint(equalTo: contentView.leadingAnchor, constant: padding).isActive = true
        textView.trailingAnchor .constraint(equalTo: contentView.trailingAnchor, constant: -padding).isActive = true
        textView.topAnchor      .constraint(equalTo: contentView.topAnchor, constant: padding).isActive = true
        textView.bottomAnchor   .constraint(equalTo: contentView.bottomAnchor, constant: -padding).isActive = true
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

extension TextViewCell: UITextViewDelegate {

    func textViewDidChange(_ textView: UITextView) {
        self.tableView.beginUpdates()
        self.tableView.endUpdates()
    }

}

Проверьте мой репо для полной реализации.

Ответ 14

Вот два подводных textView.textContainer.maximumNumberOfLines = 10 в iOS 8.3, когда вы textView.textContainer.maximumNumberOfLines = 10 с textView.textContainer.maximumNumberOfLines = 10

Обратитесь к моему тексту, пожалуйста.

textView.attributedText = originalContent

let lineLimit = 10
textView.isEditable = true
textView.isScrollEnabled = false
textView.textContainerInset = .zero // default is (8, 0, 8, 0)
textView.textContainer.maximumNumberOfLines = lineLimit // Important condition
textView.textContainer.lineBreakMode = .byTruncatingTail

// two incomplete methods, which do NOT work in iOS 8.3

// size.width可能比maxSize.width小 ————遗憾的是 iOS 8.3 上此方法无视maximumNumberOfLines参数,所以得借助于UILabel
// size.width may be less than maxSize.width, ---- Do NOT work in iOS 8.3, which disregards textView.textContainer.maximumNumberOfLines
// let size = textView.sizeThatFits(maxSize) 

// 遗憾的是 iOS 8.3 上此方法失效了,得借助于UILabel
// Does not work in iOS 8.3
// let size = textView.layoutManager.usedRectForTextContainer(textView.textContainer).size 

// Suggested method: use a temperary label to get its size
let label = UILabel(); label.attributedText = originalContent
let size = label.textRect(forBounds: CGRect(origin: .zero, size: maxSize), limitedToNumberOfLines: lineLimit).size
textView.frame.size = size

Ответ 15

1 Добавьте наблюдателя в длину содержимого текстового поля

   yourTextView.addObserver(self, forKeyPath: "contentSize", options: (NSKeyValueObservingOptions.new), context: nil);

2 Внедрение наблюдателя

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        let tv = object as! UITextView;
        var topCorrect = (tv.bounds.size.height - tv.contentSize.height * tv.zoomScale)/2.0;
        topCorrect = ( topCorrect < 0.0 ? 0.0 : topCorrect );
        tv.contentOffset.x = 0;
        tv.contentOffset.y = -topCorrect;
        self.yourTextView.contentSize.height = tv.contentSize.height;
        UIView.animate(withDuration: 0.2, animations: {
            self.view.layoutIfNeeded();
        });
    }

Ответ 16

Вы можете сделать это с IB.

  1. Создайте выход из ограничения высоты UITextView. enter image description here

  2. Унаследуйте свой UIViewController от UITextViewDelegate

  3. затем

'

func textViewDidChange(_ textView: UITextView) {

    // calculate text height
    let constraintRect = CGSize(width: textView.frame.width,
                                height: .greatestFiniteMagnitude)
    let boundingBox = self.boundingRect(with: constraintRect,
                                        options: .usesLineFragmentOrigin,
                                        attributes: [.font: textView.font],
                                        context: nil)
    let height = ceil(boundingBox.height)

    // textViewHeightConstraint - your height constraint outlet from IB
    if height > textViewHeightConstraint.constant {
        textViewHeightConstraint.constant = height

        UIView.animate(withDuration: 0.3, animations: {
            self.view.layoutIfNeeded()
        })
    }
}'

Ответ 17

Этот ответ может быть поздно, но я надеюсь, что это кому-то поможет.

Для меня эти 2 строки кода работали:

textView.isScrollEnabled = false
textView.sizeToFit()

Но не устанавливайте ограничение высоты для вашего Textview