Адаптивный UIPresentationController на основе размера представления

Я перехожу к презентациям на основе UIPresentationController для своих контроллеров представлений, но столкнулся с некоторой путаницей с API.

У меня есть специальная презентация контроллера стиля в стиле боковой панели (похожая на демонстрационный код LookInside WWDC 2014).

Этот кластер классов (UIPresentationController, UIViewControllerTransitioningDelegate и UIViewControllerAnimatedTransitioning) представляет собой контроллер вида как боковую панель от края экрана на представлениях класса обычного размера и представляет тот же контроллер вида, что и полный экран на компактном размер класса.

Тестирование этого на цели Resizable iPad показывает правильное поведение: я устанавливаю класс горизонтального размера в "Compact", а мой контроллер просмотра переключается с боковой панели на полный экран.

Однако я хочу больше детализации. Я хотел бы использовать презентацию диспетчера представлений в стиле боковой панели на iPhone 6 и 6+, когда устройство находится в альбомной ориентации, и использовать полноэкранную презентацию стиля для всех iPhone в портретной ориентации.

Итак, в моем методе

- (void) viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator

Я реализовал некоторую логику, чтобы определить, будет ли боковая панель занимать слишком много экрана, допустим, я использую следующее условие:

//If my sidebar is going to occupy more than half the new width of the view...
if( self.sidebarTransitionController.width > size.width / 2.0 )
{
    //Override the presentation controller trait collection with Compact horizontal size class
    sidebarPresentationController.overrideTraitCollection = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassCompact];
}
else
{
    //Otherwise override the trait collection with Regular
    sidebarPresentationController.overrideTraitCollection = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassRegular];

}

Однако это ничего не делает. В документации для UIPresentationController.overrideTraitCollection указано:

Используйте это свойство, чтобы указать какие-либо черты, которые вы хотите применить к представленным и представленным контроллерам представлений. Указанные вами черты переопределяют любые существующие в настоящее время свойства для контроллеров представления. Значение по умолчанию этого свойства равно nil.

Присвоение нового значения этому свойству заставляет контроллер представления перейти к новому набору признаков, что может привести к анимации к представленному интерфейсу.

Назначение нового значения контроллеру презентации не приводит к изменению моего отображаемого интерфейса. (Даже если я назначаю overrideTraitCollection, когда UIPresentationController создается из объекта UIViewControllerTransitioningDelegate.)

Что мне не хватает? Возможно ли выполнить адаптивное представление с UIPresentationController на более гранулированном уровне?

Ответы

Ответ 1

Возможно ли выполнить адаптивное представление с UIPresentationController на более узком уровне?

Не легко.

Я предлагаю один из следующих вариантов:

  • Отказаться от контроля и принять ограниченную адаптивность UIKits: вы можете перейти на полноэкранную презентацию или представить другой контроллер представления для определенной коллекции признаков. Пойдите с этим, чтобы быстрее отправить ваше приложение.

  • Используйте презентации, но работайте с UIKit. Один из способов - переопределить viewWillTransitionToSize:withTransitionCoordinator: и уволить, а затем повторно представить представленный контроллер представления, внести любые изменения, которые вы хотите, например, предоставить другой стиль презентации или контроллер представления. Это может дать хорошие результаты, не занимая слишком много времени.

  • Использовать сдерживание контроллера. Это самый низкий уровень, который вы можете использовать, придерживаясь лучших практик UIKit. Ваш главный контроллер представлений становится дочерним элементом контроллера представления контейнера, и вместо того, чтобы представлять, вы спрашиваете контейнер, чтобы показать другой контроллер представления. Пойдите с этим, если приложение должно быть обычным и изысканным, и вы можете потратить время, чтобы сделать его в порядке.

Ответ 2

Использование:

- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller
                                                               traitCollection:(UITraitCollection *)traitCollection NS_AVAILABLE_IOS(8_3);

Он вызвал вращение, даже если класс размера не изменился, поэтому это хорошее место для адаптации к идиоме/ориентации. Помните, что iPhone 6 может работать в увеличенном режиме.

Ответ 3

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

От Программирование iOS 9: погружение в глубину в представления, просмотр контроллеров и фреймворков, отличная книга, полная важных деталей вроде этого:

horizontalSizeClass, verticalSizeClass

A UIUserInterfaceSizeClass значение, либо .Regular, либо .Compact. Они называются классами размера. Классы размера в сочетании имеют следующие значения:

Оба вертикальных и горизонтальных класса размера .Regular: мы работаем на iPad

Класс вертикального размера .Regular, но класс горизонтального размера .Compact: мы работаем на iPhone с приложением в портретной ориентации. (В качестве альтернативы мы можем работать на iPad в многозадачной конфигурации iPad сплит-скриншотом, см. Главу 9).

Оба класса по вертикали и горизонтали .Compact: мы работаем на iPhone (кроме iPhone 6 плюс) с приложением в альбомной ориентации.

Класс вертикального размера .Compact, а класс горизонтального размера .Regular: мы работаем на iPhone 6 плюс в альбомной ориентации.

например. в контроллере просмотра:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "ShowComposeView" {
        segue.destinationViewController.presentationController!.delegate = self
        segue.destinationViewController.modalPresentationStyle = .PageSheet
    }
}

func adaptivePresentationStyleForPresentationController(controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
    // If we do an adaptive presentation, and adapt from Page Sheet to Form Sheet,
    // then on iPhone 6 we will get the nice rounded corners of the nav bar 
    // in both portrait and landscape. (From pg. 298 of Programming iOS 9)

    // We want this behaviour on iPhone in Portrait orientation only.
    if traitCollection.horizontalSizeClass == .Compact && traitCollection.verticalSizeClass == .Regular {
        return .FormSheet
    }
    else {
        return .PageSheet
    }
}