Подтвердить что ты не робот

Как заставить Interface Builder уважать собственный размер содержимого встроенного представления в макете с ограничениями?

Конструктор интерфейсов в XCode 4.5 относится к intrinsicContentSize для некоторых представлений, например. NSButton, но я не могу убедить его уважать его в своих собственных подзаголовках. Это заставляет IB добавлять дополнительные ограничения, пытаясь заставить макет, нарисованный в IB, что затем приводит к тому, что внутренние значения не будут использоваться при запуске программы.

Например, рассмотрим кнопку, центрированную в окне, и пользовательский вид, центрированный в окне...

IB constraints for centered NSButton

IB constraints for centered NSView

Вы можете видеть, что пользовательский вид получает четыре ограничения, по-видимому, потому, что IB не знает представление intrinsicContentSize. Вы можете изменить, какие дополнительные ограничения добавлены, например. вы можете заставить его быть шириной и высотой вместо этого, но вы не можете удалить их.

Теперь я справляюсь с этим путем поиска и удаления дополнительных ограничений в моем awakeFromNib, но должен быть лучший способ сделать это.

4b9b3361

Ответ 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).

Чтобы сделать цикл, попробуйте

  1. Обычный "Обновить все просмотры"

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

  3. И наконец:

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];
    }

Я знаю, что это взломать, но, надеюсь, это поможет вам.