XCode: как изменить расположение видов между альбомным и портретным режимами
В портретном режиме у меня есть четыре вида поверх друг друга сверху донизу контроллера вида (см. изображение).
Затем я хочу изменить положение видов относительно друг друга, когда устройство переходит в альбомную ориентацию (см. Рисунок 2).
Я хочу, чтобы вид 4 двигался рядом с видами 2 и 3, и все они сидят ниже вида 1.
Некоторые условия компоновки:
- Вид 1 прикреплен к верхней части контроллер вида как в альбомной, так и в портретной ориентации.
- виды 2, 3 и 4 центрируются горизонтально в пределах портретного вида.
Вид 4 прикрепляется к левому, правому и нижнему полям контроллера вида в портретном режиме.
Каков наилучший метод достижения различных макетов?
Было бы самым элегантным решением сделать ссылку на ограничения в коде контроллеров вида и активировать и деактивировать их в viewWillTransition? Или есть есть способ использовать vary for traits для достижения этой цели (я могу представить, что виды 2, 3 и 4, центрированные по горизонтали, сделают это труднодостижимым, а также добавят новые ограничения для вида 4 в ландшафтном режиме)?
2 ответов:
Мы привыкли устанавливать различные наборы ограничений и активировать/деактивировать их на основе изменения ориентации. Но в наше время можно использовать размерные классы и "варьировать по признакам".
Например, я начинаю с простого представления и выбираю класс компактной ширины, а затем выбираю "варьировать по признакам":
Я затем добавить соответствующие ограничения и нажмите на кнопку "сделать изменения":
Затем я выбираю "обычный размерный класс ширины" и повторяю: процесс ("варьировать по признакам", добавить ограничения, нажать на кнопку "сделано варьирование":
Затем вы получите сцену, которая будет иметь совершенно другой набор ограничений, действующих для классов компактной ширины и обычных классов ширины. Т. е. при запуске приложения, если устройство вращается, активируются новые ограничения:
Дополнительную информацию смотрите в видеороликах WWDC 2016 об адаптивных макетах:
Я использую массивы ограничений и активирую / деактивирую в соответствии с ориентацией.
var p = [NSLayoutConstraint]() var l = [NSLayoutConstraint]() var initialOrientation = true var isInPortrait = false override func viewDidLoad() { super.viewDidLoad() // add any subviews here view.turnOffAutoResizing() // add constraints here.... // common constraints you can set their isActive = true // otherwise, add in to portrait(p) and landscape(l) arrays } override func viewWillLayoutSubviews() { super.viewDidLayoutSubviews() if initialOrientation { initialOrientation = false if view.frame.width > view.frame.height { isInPortrait = false } else { isInPortrait = true } view.setOrientation(p, l) } else { if view.orientationHasChanged(&isInPortrait) { view.setOrientation(p, l) } } } extension UIView { public func turnOffAutoResizing() { self.translatesAutoresizingMaskIntoConstraints = false for view in self.subviews as [UIView] { view.translatesAutoresizingMaskIntoConstraints = false } } public func orientationHasChanged(_ isInPortrait:inout Bool) -> Bool { if self.frame.width > self.frame.height { if isInPortrait { isInPortrait = false return true } } else { if !isInPortrait { isInPortrait = true return true } } return false } public func setOrientation(_ p:[NSLayoutConstraint], _ l:[NSLayoutConstraint]) { NSLayoutConstraint.deactivate(l) NSLayoutConstraint.deactivate(p) if self.bounds.width > self.bounds.height { NSLayoutConstraint.activate(l) } else { NSLayoutConstraint.activate(p) } } }Мои потребности различать портрет или ландшафт требуют использования чего-то иного, чем классы размеров, поскольку мое приложение универсально, а iPad (если не использовать split или slide out view) - это Всегда нормальный размер. Кроме того, вы можете использовать
viewWillTransistion(toSize:)илиviewDidLoadSubviews()вместо "viewWillLoadSubviews ()" - но всегда тестируйте, так как они могут выполняться несколько раз при изменении ориентации!





Comments