2017-02-20 22 views
5

Я пытаюсь использовать preservesSuperviewLayoutMargins через иерархию вложенных представлений, но сталкиваясь с множеством проблем с UIKit и задаваясь вопросом, что я делаю неправильно (или это настоящая ошибка).Как использовать preserveesSuperviewLayoutMargins во вложенных представлениях

Я пытаюсь выложить несколько взглядов (некоторые на стороне друг друга, некоторые друг над другом), как так:

// Various combinations here will create different visual results (it will either work or won't) 

let i1 = ImageView() 
//let i1 = LabelView() 
let i2 = ImageView() 
//let i2 = LabelView() 
let i3 = ImageView() 
//let i3 = LabelView() 

let view = LeftRight(left: i1, right: TopBottom(top: i2, bottom: i3)) 
//let view = LeftRight(left: TopBottom(top: i2, bottom: i3), right: i1) 

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

Correctly embedded

Но с другими я борюсь:

Black screen!

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

отступов осуществляется с помощью layoutMargins так:

let masterView = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 500)) 
masterView.translatesAutoresizingMaskIntoConstraints = false 
masterView.layoutMargins = UIEdgeInsets(top: 5.0, left: 5.0, bottom: 5.0, right: 5.0) 

let subView = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 500)) 
subView.translatesAutoresizingMaskIntoConstraints = false 
subView.layoutMargins = UIEdgeInsets(top: 5.0, left: 5.0, bottom: 5.0, right: 5.0) 

Вот образец макета изображения с детской площадкой. The full playground project can be found here и можно легко загрузить и запустить в XCode, чтобы понять, что я имею в виду.

class ImageView: UIView { 

    init() { 

     super.init(frame: CGRect(x: 0, y: 0, width: 1000, height: 1000)) 

     self.preservesSuperviewLayoutMargins = true 
     self.layoutMargins = .zero 

     let imageView = UIImageView(image: UIImage(named: "jesus")) 
     imageView.contentMode = .center 

     imageView.translatesAutoresizingMaskIntoConstraints = false 
     imageView.clipsToBounds = true 
     self.clipsToBounds = true 
     imageView.backgroundColor = UIColor.red 

     self.addSubview(imageView) 

     imageView.leftAnchor.constraint(equalTo: self.layoutMarginsGuide.leftAnchor).isActive = true 
     imageView.rightAnchor.constraint(equalTo: self.layoutMarginsGuide.rightAnchor).isActive = true 
     imageView.topAnchor.constraint(equalTo: self.layoutMarginsGuide.topAnchor).isActive = true 
     imageView.bottomAnchor.constraint(equalTo: self.layoutMarginsGuide.bottomAnchor).isActive = true 
    } 
} 
+0

Я не могу понять, что проблема в случае «других». Вы показываете нам только черный экран, но никакого кода. Не могли бы вы добавить некоторые подробности? –

+0

код находится на детской площадке. Это довольно много, поэтому я только показал основы здесь. Черный экран - это потому, что система компоновки просто не отображается! – Sam

ответ

0

Ok. Нашел вашу проблему. В вашем главном представлении и вашем подвью есть как размер кадра 500x500, так и marginLayout из 5 точек на край. Если вы создаете экземпляры с рамкой .zero, тогда все должно быть хорошо.

Update

После взятия немного больше времени с Playground я также добавил, что это ImageView:

private var imageView: UIImageView! 
override var intrinsicContentSize: CGSize { 
    return imageView?.intrinsicContentSize ?? .zero 
} 

и LabelView:

private var textLabel: UILabel! 
override var intrinsicContentSize: CGSize { 
    return textLabel?.intrinsicContentSize ?? .zero 
} 

Теперь в ваших методах инициализации из оба ImageView и LabelView используют эти свойства экземпляра вместо локального variabl е. После этого кажется, что все возможные комбинации работают. Если бы у вас была одна конкретная комбинация, которую вы знали, это не понравилось, дайте мне знать, чтобы я мог ее протестировать.

+0

привет спасибо за то, что посмотрели. Вы попробовали это решение, потому что я изначально использовал .zero, и он не работал? Установив рамку, я смог заставить ее работать немного чаще. Они оба выложены с автозапуском, поэтому исходный кадр не должен иметь значения. – Sam

+0

Теперь я уточню свой ответ, чтобы добавить более подробную информацию. Я собирался. –

+0

Привет Я внес изменения, которые вы описываете, но все еще получая черный экран для этого объединения: 'let i1 = ImageView() let i2 = LabelView() let i3 = LabelView()' – Sam

0

Я считаю, что вы забыли что-то, что требуется.

  1. Осуществление intrinsicContentSize на ImageView и Этикетка
  2. отсутствующих ограничений, которые делают оба подвидов имеют одинаковую ширину и высоту в этих 2 UIView подклассов (TopBottom и LeftRight)
  3. правильного вид зрения (LeftRight) по-прежнему убежище «т был установлен его translatesAutoresizingMaskIntoConstraints свойства ложной
  4. Добавьте constraint for bottom самого внешней frame зрения
  5. вызова layoutIfNeeded() на frame вид

    top.widthAnchor.constraint (equalTo: bottom.widthAnchor) .isActive = истинный top.heightAnchor.constraint (equalTo: bottom.heightAnchor) .isActive = истина

+0

право на вид LeftRight имеет значение false: 'right.translatesAutoresizingMaskIntoConstraints = false' – Sam

+0

Я попытался реализовать' intrinsicContentSize' перед публикацией этого вопроса, но не смог заставить его работать ... Кроме того, почему я должен нужно установить ширину и высоту одинаковых в представлениях leftRight/topBottom? – Sam

+0

Поскольку механизм Auto Layout не может определить ширину обоих представлений влево/вправо и высоту в верхнем/нижнем диапазоне, используя только ваши текущие ограничения. –

Смежные вопросы