Является ли UITraitsCollection путем к отличию iPad Landscape от Portrait AutoLayout в IB / Storyboard

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

Что я сделал / пробовал:

Читая и ища через Google и SO, я не нашел решения. То, что я узнал, касалось переопределения UITraitsCollection, и, если возможно, я хотел бы заставить ландшафтную конфигурацию iPad следовать той же конфигурации, которую я уже установил для ландшафтного режима iPhone с помощью hCompact

Я попробовал это решение https://stackoverflow.com/a/60409218/14414215, но не уверен, где его поставить и когда просто помещенный в UIViewController, при запуске приложение даже не вызывает его. (Вероятно, потому что у меня нет своих представлений в childViewController?)

В этом сообщении также упоминается UITraitsCollection https://stackoverflow.com/a/41374705/14414215, однако отсутствует пример.

Я почти уверен, что это то, что делают многие приложения, но я не могу найти решение.

Для справки: это то, чего я хочу добиться и на iPad. (iPhone отлично работает с этим решением от @DonMag)

Макет StackView рядом и сверху друг друга (например, zStack)


person myjunk    schedule 20.01.2021    source источник


Ответы (1)


Благодаря разному соотношению сторон экрана устройства, и возможности многозадачности на iPad вы можете думать о размере, а не о <сильном > ориентация.

Если ваше приложение выполняется в режиме Slide Over / Split View, класс размера может быть wC hR, даже если устройство находится в альбомной ориентации.

Если вы хотите изменить макет на основе соотношения сторон:

  • если ширина ›высота, используйте альбомную ориентацию.
  • если высота ›ширина, используйте портретную ориентацию.

Вы можете создать свои собственные коллекции ограничений и активировать / деактивировать их в viewWillTransition(to size:...)

Если вы хотите придерживаться вариантов Trait, вы столкнетесь с проблемами, пытаясь манипулировать ими для корневого представления контроллера.

Вы можете попробовать сделать свой контроллер дочерним контроллером представления, либо встроив его в UIContainerView, либо добавив с помощью кода, а затем реализовав (в родительском контроллере представления):

class ParentViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        if let vc = storyboard?.instantiateViewController(withIdentifier: "myVC") as? MyRealViewController {
            addChild(vc)
            view.addSubview(vc.view)
            vc.didMove(toParent: self)
        }
        
    }
    
    override func overrideTraitCollection(forChild childViewController: UIViewController) -> UITraitCollection? {
        if childViewController.view.bounds.width > childViewController.view.bounds.height {
            let collections = [UITraitCollection(horizontalSizeClass: .regular),
                               UITraitCollection(verticalSizeClass: .compact)]
            return UITraitCollection(traitsFrom: collections)
        }
        return super.overrideTraitCollection(forChild: childViewController)
    }
    
}
person DonMag    schedule 20.01.2021
comment
Я не собираюсь использовать вариации черт, но можно ли viewWIllTransition разрешить использование Storyboard / IB вместо выполнения макета с помощью кода? Я очень хочу использовать предложение о соотношении сторон, но мне все еще интересно, будет ли оно таким же простым, как если бы ширина ›высота, а затем использовать то же соотношение сторон, что и в ландшафте iPhone (но, конечно, я уверен, что это не будет будь так просто ( - person myjunk; 20.01.2021
comment
@myjunk - если вы используете viewWillTransition(to size:...), вам, вероятно, придется создавать коллекции ограничений вместо того, чтобы устанавливать варианты признаков. - person DonMag; 20.01.2021