Как заставить Interface Builder уважать собственный размер содержимого встроенного представления в макете с ограничениями?
Конструктор интерфейсов в XCode 4.5 относится к intrinsicContentSize для некоторых представлений, например. NSButton, но я не могу убедить его уважать его в своих собственных подзаголовках. Это заставляет IB добавлять дополнительные ограничения, пытаясь заставить макет, нарисованный в IB, что затем приводит к тому, что внутренние значения не будут использоваться при запуске программы.
Например, рассмотрим кнопку, центрированную в окне, и пользовательский вид, центрированный в окне...
![IB constraints for centered NSButton]()
![IB constraints for centered NSView]()
Вы можете видеть, что пользовательский вид получает четыре ограничения, по-видимому, потому, что IB не знает представление intrinsicContentSize. Вы можете изменить, какие дополнительные ограничения добавлены, например. вы можете заставить его быть шириной и высотой вместо этого, но вы не можете удалить их.
Теперь я справляюсь с этим путем поиска и удаления дополнительных ограничений в моем awakeFromNib, но должен быть лучший способ сделать это.
Ответы
Ответ 1
Установите размер внутреннего содержимого-заполнителя - "предположите", если хотите - в Interface Builder.
- Выберите свое собственное представление.
- Показать инспектор размера (⌘ Shift 5).
- Измените раскрывающийся список "Внутренний размер" с "Default (System Defined)" на "Placeholder".
- Введите разумные догадки по ширине и высоте времени просмотра.
Эти ограничения удаляются во время компиляции, что означает, что они не будут влиять на ваше запущенное приложение, а механизм компоновки добавит ограничения по мере необходимости во время выполнения, чтобы уважать ваше представление intrinsicContentSize
.
Ответ 2
Как на самом деле это сделать, 2019
import UIKit
@IBDesignable class TagPerson: ShadowRoundedImageView {
override var intrinsicContentSize: CGSize {
var s = super.intrinsicContentSize
s.height = 40
s.width = 40
return s
}
override func prepareForInterfaceBuilder() {
invalidateIntrinsicContentSize()
}
}
Тем не менее, есть проблема. Xcode глючит. Иногда вы можете сбросить его:
Вышеуказанное, конечно, будет работать безупречно во время выполнения. Но он случайно не работает в конструкторе интерфейсов (даже с 10.3).
Чтобы сделать цикл, попробуйте
Обычный "Обновить все просмотры"
Прикрепите и удалите бессмысленное ограничение для одного из ваших представлений о внутреннем размере. (Я заметил, что если у вас их несколько, этого обычно достаточно, чтобы цикл Xcode работал, тогда все они работают.)
И наконец:
XCode имеет удивительно глупую функцию "заполнителя внутреннего размера". (Это одна из самых поразительно глупых вещей во всех разработках Apple, но оставим это в стороне.)
![enter image description here]()
Выберите один или несколько элементов собственного размера. Переключите причудливую заполнитель назад и вперед несколько раз. Часто это приводит к цикличности, и представление будет работать правильно.
В худшем случае перезапуск XCode с обычным чистым способом - все это обычно работает.
Это абсолютно ужасная ошибка или неадекватность в построителе интерфейса - это шокирует.
Ответ 3
Хорошо, здесь нужно сделать Xcode использовать intrinsicContentSize вашего пользовательского представления в IB.
Это может быть достигнуто путем добавления в пользовательский вид в узле placeholder view с фиксированной шириной и высотой (вы можете центрировать его по горизонтали и по вертикали)
![enter image description here]()
Затем выберите свое пользовательское представление и коснитесь "Размер по размеру содержимого" в меню редактирования в IB.
На этом этапе все дополнительные ограничения, определяющие размер, будут удаляться, оставив только позиционирование.
![enter image description here]()
Таким образом, IB будет определять размер вашего пользовательского представления, чтобы он соответствовал представлению-заполнителю, а Autolayout будет зависеть от вашего переопределения внешнего вида - (CGSize)intrinsicContentSize
во время выполнения, чтобы определить ваш пользовательский размер.
Последний шаг - удалить представление заполнителя, чтобы позволить вашему представлению правильно отображать его содержимое и размер:
- (void)viewDidLoad
{
[super viewDidLoad];
[_placeholderView removeFromSuperview];
}
Я знаю, что это взломать, но, надеюсь, это поможет вам.