Подвид, который обрезает родительский вид в Swift

Я пытаюсь добавить подвид, который всегда будет иметь тот же размер, что и его родитель, так что он всегда будет изменять размер, если размер родителя изменится.

Я думал о добавлении (верхних, нижних, ведущих, конечных) ограничений из кода.

Когда я добавляю подвид, выполняется этот код:

subview.frame = parent.frame
subview.translatesAutoresizingMaskIntoConstraints = false
subview.leadingAnchor.constraint(equalTo: parent.leadingAnchor).isActive = true
subview.trailingAnchor.constraint(equalTo: parent.trailingAnchor).isActive = true
subview.topAnchor.constraint(equalTo: parent.topAnchor).isActive = true
subview.bottomAnchor.constraint(equalTo: parent.bottomAnchor).isActive = true

Но размер подпредставления остается равным 0 и отображается в левом верхнем углу экрана. Я не понимаю, почему его размер равен нулю, так как я установил его рамку, а также потому, что у него есть все ограничения для установки его размера.

Вид инспектора:

Примечание. Родительский элемент находится слева, а подпредставление (LoaderView) — справа

родительский вид subview


person Xys    schedule 20.04.2020    source источник
comment
Являются ли какие-либо из этих представлений прокруткой (я так предполагаю, поскольку вижу, что размер прокручиваемого содержимого сообщения неоднозначен)? Есть ли у вас какие-либо предупреждения автомакета в вашей раскадровке или xib? Почему вы добавляете ограничения в свою раскадровку и в код? Вам нужно сделать это только в одном месте. Наконец, вам не нужно беспокоиться о настройке рамки подпредставления, если вы используете автомакет.   -  person Rob    schedule 20.04.2020
comment
@Rob Спасибо за ваш ответ. Я не добавляю ограничения в раскадровку, потому что добавляю подпредставление программно. И да, ты прав, мне не нужно устанавливать рамку   -  person Xys    schedule 20.04.2020
comment
@Rob Это скриншоты отладчика иерархии представлений - я сначала подумал, что они тоже из раскадровки, хех.   -  person Tyler    schedule 20.04.2020


Ответы (1)


Ваше родительское представление похоже на представление прокрутки, и в нем отсутствуют ограничения, которые сообщают ему, каков размер его прокручиваемого содержимого (обратите внимание на предупреждение на первом снимке экрана). Поскольку ничто не определяет размер содержимого, размер прокручиваемой области равен нулю.

Я не уверен, какие именно ограничения вам нужны, поскольку это зависит от деталей вашей ситуации, но для того, чтобы хотя бы увидеть ваше подпредставление, вы можете добавить (например) ограничения равной ширины и равной высоты к вашему подпредставлению и его родителю. вид (вид прокрутки):

NSLayoutConstraint.activate([
    subview.widthAnchor.constraint(equalTo: parent.widthAnchor),
    subview.heightAnchor.constraint(equalTo: parent.heightAnchor)
])

Это определяет прокручиваемую область как равную по ширине и высоте рамке представления прокрутки. Однако, если вы сделаете это, то на самом деле не будет никакой прокрутки, кроме поведения подпрыгивания, когда вы пытаетесь прокрутить за пределы прокручиваемой области (если это включено для этого вида прокрутки).

Вместо этого вы можете изменить якорь высоты, чтобы он был равен некоторой константе, просто чтобы обеспечить некоторую фактическую прокрутку:

NSLayoutConstraint.activate([
    subview.widthAnchor.constraint(equalTo: parent.widthAnchor),
    subview.heightAnchor.constraint(equalToConstant: 2000) // just some arbitrary amount for demonstration purposes
])

Это делает прокручиваемую высоту равной 2000 точкам, независимо от высоты фрейма прокрутки.

Или, если вы хотите, чтобы прокручиваемая область была кратна высоте кадра представления прокрутки, вы можете установить множитель для привязки высоты:

NSLayoutConstraint.activate([
    subview.widthAnchor.constraint(equalTo: parent.widthAnchor),
    subview.heightAnchor.constraint(equalTo: parent.heightAnchor, multiplier: 3)
])

Это делает прокручиваемую высоту равной трехкратной высоте фрейма прокрутки.

А если вам нужен вид с горизонтальной прокруткой, просто измените widthAnchor вместо heightAnchor, как я сделал выше. Или, если вам нужна область с двумерной прокруткой, которая позволяет вам перемещаться как по вертикали, так и по горизонтали, измените оба.

person Tyler    schedule 20.04.2020
comment
Большое спасибо, все работает идеально! Но мне все еще кажется странным, что он работает с ограничениями по ширине и высоте, но не с нижней/конечной частью? Я понимаю, что, поскольку это прокручиваемый вид, высота и ширина не определены, но тогда почему он работает с ограничением ширины? Или может я что-то упускаю? - person Xys; 20.04.2020
comment
Вам нужно сообщить прокрутке, насколько велика прокручиваемая область. Недостаточно просто задать верхнее, ведущее, нижнее и конечное ограничения вашего подпредставления (которые ограничены прокручиваемой областью, а не рамкой прокрутки — важно понимать разница), так как одни только эти ограничения не дают прокрутке достаточно информации, чтобы определить ширину и высоту прокручиваемой области. Надеюсь, это имеет смысл! - person Tyler; 20.04.2020
comment
Спасибо ! Идея в том, что я хотел отобразить пользовательское представление загрузки поверх представления коллекции, пока я загружаю его содержимое;) - person Xys; 20.04.2020