UIScrollView, который расширяется с содержанием "instrinsic size" до высоты X, а затем прокручивает
Я пытаюсь воспроизвести поведение раздела заголовка и сообщения в предупреждении.
![enter image description here]()
Метки заголовка и сообщения отображаются в режиме прокрутки. Если текст метки увеличивается, высота предупреждения также увеличивается вместе с внутренним размером содержимого меток. Но на определенной высоте высота предупреждения перестает увеличиваться, и заголовок и текст сообщения становятся прокручиваемыми.
Что я прочитал:
Статьи
Qaru
Ответ может быть там, но я не смог его абстрагировать.
Что я пробовал:
Сосредоточившись только на представлении прокрутки с двумя метками, я попытался сделать минимальный пример, в котором размер родительского представления будет изменяться в соответствии с внутренней высотой представления прокрутки. Я играл с большим количеством ограничений. Вот одна комбинация (среди многих), которая не работает:
![enter image description here]()
Я работал с автоматическим макетом и нормальными ограничениями и даже внутренними размерами контента. Кроме того, я знаю, как получить базовый вид прокрутки, работающий с автоматическим макетом. Тем не менее, я никогда не делал ничего с приоритетами, контентом и сопротивлением сжатию. Из прочитанного мною поверхностного понимания их смысла, но я не знаю, как их применять в данном случае. Я думаю, мне нужно что-то делать с содержанием и приоритетами.
Ответы
Ответ 1
Я думаю, что достиг эффекта, похожего на тот, который вы хотели с чистым автоматическим макетом.
СТРУКТУРА
Сначала позвольте мне показать вам мою структуру:
![enter image description here]()
Представление содержимого - это представление с белым фоном, а Caller View и Bottom View имеют фиксированную высоту. В нижней части есть ваша кнопка, а в Caller View есть название.
РЕШЕНИЕ
Таким образом, после установки основных ограничений (обратите внимание, что представление в представлении прокрутки имеет верхнюю, левую, правую и нижнюю часть для представления прокрутки И равную ширину), проблема заключается в том, что представление прокрутки не знает, какой размер должен иметь.
Итак, вот что я сделал:
Я хотел, чтобы свиток мог расти до максимума. Поэтому я добавил пропорциональную высоту к суперпредставлению, которое устанавливает этот максимум:
![enter image description here]()
Однако это создает две проблемы: представление прокрутки по-прежнему не знает, какая высота должна быть, и теперь вы можете изменить размер, и представление прокрутки пропустит размер его содержимого (если содержимое меньше максимального размера).
Итак, чтобы решить обе проблемы, я добавил одинаковую высоту с меньшим приоритетом из представления в представлении прокрутки и в представлении прокрутки
![enter image description here]()
Я надеюсь, что это может помочь вам.
Ответ 2
Ваша проблема не может быть решена только с помощью ограничений, вам нужно использовать какой-то код. Это потому, что вид прокрутки не имеет собственного содержимого.
Итак, создайте подкласс прокрутки. Может быть, дать ему свойство или делегата или что-то сказать, какова его максимальная высота.
В подклассе недействительно размер внутреннего содержимого всякий раз, когда изменяется размер содержимого, и вычисляет новый собственный размер как минимум размера содержимого и максимально допустимого размера.
Когда вид прокрутки имеет собственный размер, ваши ограничения между ним и его супер-представлением действительно сделают что-то значимое для вашей проблемы.
Ответ 3
Вы должны иметь возможность достичь этого решения с помощью чистого автозапуска.
Обычно, если я хочу, чтобы метки возрастали по мере роста их содержимого по вертикали, я делаю это
[label setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[label setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
Для того, чтобы ваш scrollview соответствовал вашим требованиям, вам нужно убедиться, что можно нарисовать линию, соединяющую верхнюю часть прокрутки, вплоть до меток в нижней части прокрутки, чтобы она могла рассчитать высоту. Чтобы scrollview ограничивал его родительским, вы можете установить ограничение высоты с помощью множителя супервизора, скажем 0,8
Ответ 4
С моим проектом у меня похожая проблема. Вы можете использовать следующий способ, чтобы обойти это.
Во-первых, высота заголовка и нижнего действия фиксированы Контент имеет переменную высоту. Вы можете добавить его в mainView как один дочерний элемент, используя размер шрифта, затем вызвать layoutIfNeeded, затем его высоту можно рассчитать и сохранить как XX. Затем удалил его из mainView.
Во-вторых, используя обычное ограничение для размещения части содержимого с scrollView, mainView имеет ограничение высоты XX и setContentCompressionResistancePriority (.defaultLow, для:.vertical).
Наконец, предупреждение может показывать точный размер при коротком контенте и ограниченный размер при длинном прокрутке.
Ответ 5
Мне удалось добиться такого точного поведения только с ограничениями AutoLayout. Вот общая демонстрация того, как это сделать: она может быть применена к вашей иерархии представлений, как вы считаете нужным.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let kTestContentHeight: CGFloat = 1200
// Subview that will shrink to fit content and expand up to 50% of the view controller height
let modalView = UIView()
modalView.backgroundColor = UIColor.gray
// Scroll view that will facilitate scrolling if the content > 50% of view controller height
let scrollView = UIScrollView()
scrollView.backgroundColor = .yellow
// Content which has an intrinsic height
let contentView = UIView()
contentView.backgroundColor = .green
// add modal view
view.addSubview(modalView)
modalView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([modalView.leftAnchor.constraint(equalTo: view.leftAnchor),
modalView.rightAnchor.constraint(equalTo: view.rightAnchor),
modalView.heightAnchor.constraint(lessThanOrEqualTo: view.heightAnchor,
multiplier: 0.5),
modalView.bottomAnchor.constraint(equalTo: view.bottomAnchor)])
let expandHeight = modalView.heightAnchor.constraint(equalTo: view.heightAnchor)
expandHeight.priority = UILayoutPriority.defaultLow
expandHeight.isActive = true
// add scrollview to modal view
modalView.addSubview(scrollView)
scrollView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([scrollView.topAnchor.constraint(equalTo: modalView.topAnchor),
scrollView.leftAnchor.constraint(equalTo: modalView.leftAnchor),
scrollView.rightAnchor.constraint(equalTo: modalView.rightAnchor),
scrollView.bottomAnchor.constraint(equalTo: modalView.bottomAnchor)])
// add content to scrollview
scrollView.addSubview(contentView)
contentView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([contentView.leftAnchor.constraint(equalTo: scrollView.leftAnchor),
contentView.widthAnchor.constraint(equalTo: modalView.widthAnchor),
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
contentView.heightAnchor.constraint(equalToConstant: kTestContentHeight)])
let contentBottom = contentView.bottomAnchor.constraint(equalTo: modalView.bottomAnchor)
contentBottom.priority = .defaultLow
contentBottom.isActive = true
}
}