Как настроить высоту textview для его содержимого в SWIFT?

в моем контроллере просмотра у меня есть UITextView. Этот textview заполняется строкой. Строка может быть короткой или длинной. В зависимости от длины строки высота textview должна регулироваться. Я использую раскадровки и макет авто.

у меня есть некоторые проблемы с высотой textview.

иногда высота идеально настраивается на текст. Иногда, нет, текст обрезается на первой линии. Ниже текстовое представление желтого цвета. синий-это containerview внутри scrollview. Фиолетовый-это место для фотографии.

title1title2

тексты из моей основной базы данных, они являются строковыми атрибутами. Между экраном 1 и 2, единственное, что изменилось-это строка.
Если я печатаю строки в консоли, у меня есть правильные тексты:

my amazing new title

Another funny title for demo

ограничения моего textview:

enter image description here

Я не понимаю, почему у меня 2 разных дисплеи.

редактировать

я попробовал совет @Nate, в viewDidLoad, я добавил:

    myTextViewTitle.text="my amazing new title"

    myTextViewTitle.setContentHuggingPriority(1000, forAxis: UILayoutConstraintAxis.Vertical)
    myTextViewTitle.setContentCompressionResistancePriority(1000, forAxis: UILayoutConstraintAxis.Vertical)
    myTextViewTitle.setTranslatesAutoresizingMaskIntoConstraints(false)  

    let views = ["new_view": myTextViewTitle]
    var constrs = NSLayoutConstraint.constraintsWithVisualFormat("|-8-[new_view]-8-|", options: NSLayoutFormatOptions(0), metrics: nil, views: views)
    self.view.addConstraints(constrs)
    self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-8-[new_view]", options: NSLayoutFormatOptions(0), metrics: nil, views: views))
    self.myTextViewTitle.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[new_view(220@300)]", options: NSLayoutFormatOptions(0), metrics: nil, views: views))

никаких результатов. С или без высоты contraint добавлен для моего textview в interface builder...

Изменить 2

мне нужен UITextView, а не UIlabel, из-за кнопки "назад", чтобы использовать путь исключения.

     let exclusionPathBack:UIBezierPath = UIBezierPath(rect: CGRect(x:backButton.bounds.origin.x, y:backButton.bounds.origin.y, width:backButton.bounds.width+10, height:backButton.bounds.height))
     myTextViewTitle.textContainer.exclusionPaths=[exclusionPathBack]

7 ответов


Я нашел решение.

Я был сосредоточен на высоте моего UITextView, затем я прочитал сообщение о соотношении сторон. Я хотел попробовать, и это сработало!

поэтому в раскадровке я добавил соотношение сторон для textview, и я проверил опцию "Удалить во время сборки".

в viewDidLayoutSubviews () я написал :

override func viewDidLayoutSubviews() {

    super.viewDidLayoutSubviews()

    let contentSize = self.myTextViewTitle.sizeThatFits(self.myTextViewTitle.bounds.size)
    var frame = self.myTextViewTitle.frame
    frame.size.height = contentSize.height
    self.myTextViewTitle.frame = frame

    aspectRatioTextViewConstraint = NSLayoutConstraint(item: self.myTextViewTitle, attribute: .Height, relatedBy: .Equal, toItem: self.myTextViewTitle, attribute: .Width, multiplier: myTextViewTitle.bounds.height/myTextViewTitle.bounds.width, constant: 1)
    self.myTextViewTitle.addConstraint(aspectRatioTextViewConstraint!)

}

Он отлично работает.


во-первых, отключите прокрутку UITextView. Два варианта:

  1. снимите флажок прокрутка включена .xib.
  2. [TextView setScrollEnabled: NO];

создайте UITextView и подключите его к IBOutlet (TextView). Добавьте ограничение высоты UITextView с высотой по умолчанию, подключите его к IBOutlet (TextViewHeightConstraint). Когда вы устанавливаете текст UITextView асинхронно, вы должны рассчитать высоту UITextView и установить высоту UITextView принуждение к этому. Пример кода:

CGSize sizeThatFitsTextView = [TextView sizeThatFits:CGSizeMake(TextView.frame.size.width, MAXFLOAT)];

TextViewHeightConstraint.constant = sizeThatFitsTextView.height; 

в Swift 3.0, где tvHeightConstraint является ограничением высоты объекта TextView (если используется для нескольких textviews, добавьте его к входам функции):

func textViewDidChange(textView: UITextView) {

        let size = textView.sizeThatFits(CGSize(width: textView.frame.size.width, height: CGFloat.greatestFiniteMagnitude))
        if size.height != tvHeightConstraint.constant && size.height > textView.frame.size.height{
            tvHeightConstraint.constant = size.height
            textView.setContentOffset(CGPoint.zero, animated: false)
        }
    }

H / T к @cmi и @Pablo Ruan


в swift 2.3:

 func textViewDidChange(textView: UITextView) {

    let size = textView.sizeThatFits(CGSize(width: textView.frame.size.width, height: CGFloat.max))
    if size.height != TXV_Height.constant && size.height > textView.frame.size.height{
        TXV_Height.constant = size.height
        textView.setContentOffset(CGPointZero, animated: false)
    }
}

Почему бы не иметь изображение для кнопки "назад" и UILabel для вашего текста и использовать autolayout для их размещения? И, возможно, третий вид на желтом фоне.


мое простое решение очень похожей проблемы:

Я использовал метки с числом строк, равным 0, вместо того, чтобы пытаться использовать текстовые поля или представления. Затем я прикрепил передний и задний края к контейнерам этикеток, которые ограничивают их ширину в моем случае, с 0 в качестве константы для ограничений. Уловка состоит в том, чтобы установить количество строк равным 0, чтобы позволить меткам расти или сжиматься в соответствии с их содержанием. Текст никогда не рубится, а высота надписей никогда не превышайте их содержимое" для всех классов разных размеров, которые я настроил для ширины (ширины контейнера в моем случае). Протестировано для IOS 8.0 и более поздних версий (также убедитесь, что "явный" не установлен рядом с атрибутами "предпочтительная ширина" для всех этикеток для ширины меток для настройки для разных классов размера) - отлично работает.


я адаптировал ваш код и использовал его для обоих: layout subview и textViewDidChange. Большое спасибо, что сделали мой день после часа устранения неполадок...

override func viewDidLayoutSubviews() {

    super.viewDidLayoutSubviews()
    textViewDidChange(self.recordingTitleTV)


}

func textViewDidChange(_ textView: UITextView) {

    let contentSize = textView.sizeThatFits(textView.bounds.size)
    var frame = textView.frame
    frame.size.height = contentSize.height
    textView.frame = frame

    let aspectRatioTextViewConstraint = NSLayoutConstraint(item: textView, attribute: .height, relatedBy: .equal, toItem: textView, attribute: .width, multiplier: textView.bounds.height/textView.bounds.width, constant: 1)
    textView.addConstraint(aspectRatioTextViewConstraint)
}