Вращение только в одном ViewController
Я пытаюсь повернуть один вид, в то время как все остальные виды (5) прикреплены к портрету. Причина в том, что в этом представлении я хочу, чтобы пользователь просматривал фотографии, которые он сохранил раньше. Я думаю, это возможно, но пока я не мог понять, как это достичь. Может ли кто-нибудь помочь или дать мне подсказку? Я программирую, что в Swift работает на iOS8
Ответы
Ответ 1
Это для Swift 3 и Swift 4. Вы можете использовать следующий код в своем AppDelegate.swift:
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
guard let rootViewController = self.topViewControllerWithRootViewController(rootViewController: window?.rootViewController),
(rootViewController.responds(to: Selector(("canRotate")))) else{
// Only allow portrait (standard behaviour)
return .portrait;
}
// Unlock landscape view orientations for this view controller
return .allButUpsideDown;
}
private func topViewControllerWithRootViewController(rootViewController: UIViewController!) -> UIViewController? {
guard rootViewController != nil else { return nil }
guard !(rootViewController.isKind(of: (UITabBarController).self)) else{
return topViewControllerWithRootViewController(rootViewController: (rootViewController as! UITabBarController).selectedViewController)
}
guard !(rootViewController.isKind(of:(UINavigationController).self)) else{
return topViewControllerWithRootViewController(rootViewController: (rootViewController as! UINavigationController).visibleViewController)
}
guard !(rootViewController.presentedViewController != nil) else{
return topViewControllerWithRootViewController(rootViewController: rootViewController.presentedViewController)
}
return rootViewController
}
вы можете узнать больше в исходном посте: http://www.jairobjunior.com/blog/2016/03/05/how-to-rotate-only-one-view-controller-to-landscape-in-ios-slash -swift/
Ответ 2
Я бы рекомендовал использовать supportedInterfaceOrientationsForWindow
в вашем appDelegate
, чтобы обеспечить вращение только в том, что конкретный вид контроллера, напр:
Свифт 4/Свифт 5
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
// Make sure the root controller has been set
// (won't initially be set when the app is launched)
if let navigationController = self.window?.rootViewController as? UINavigationController {
// If the visible view controller is the
// view controller you'd like to rotate, allow
// that window to support all orientations
if navigationController.visibleViewController is SpecificViewController {
return UIInterfaceOrientationMask.all
}
// Else only allow the window to support portrait orientation
else {
return UIInterfaceOrientationMask.portrait
}
}
// If the root view controller hasn't been set yet, just
// return anything
return UIInterfaceOrientationMask.portrait
}
Обратите внимание, что если этот SpecificViewController
находится в альбомной ориентации, прежде чем перейти к портретному экрану, другой вид все равно откроется в альбомной ориентации. Чтобы обойти это, я бы порекомендовал запретить переходы, когда это представление в ландшафте.
Свифт 3
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {
// Make sure the root controller has been set
// (won't initially be set when the app is launched)
if let navigationController = self.window?.rootViewController as? UINavigationController {
// If the visible view controller is the
// view controller you'd like to rotate, allow
// that window to support all orientations
if navigationController.visibleViewController is SpecificViewController {
return Int(UIInterfaceOrientationMask.All.rawValue)
}
// Else only allow the window to support portrait orientation
else {
return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}
}
// If the root view controller hasn't been set yet, just
// return anything
return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}
Ответ 3
Вы также можете сделать это в соответствии с протоколом. Просто создайте протокол
protocol CanRotate {
}
Добавьте те же 2 метода в AppDelegate более "осторожным" способом
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
if topViewController(in: window?.rootViewController) is CanRotate {
return .allButUpsideDown
} else {
return .portrait
}
}
func topViewController(in rootViewController: UIViewController?) -> UIViewController? {
guard let rootViewController = rootViewController else {
return nil
}
if let tabBarController = rootViewController as? UITabBarController {
return topViewController(in: tabBarController.selectedViewController)
} else if let navigationController = rootViewController as? UINavigationController {
return topViewController(in: navigationController.visibleViewController)
} else if let presentedViewController = rootViewController.presentedViewController {
return topViewController(in: presentedViewController)
}
return rootViewController
}
И в каждом ViewController, что вы хотите другого поведения, просто добавьте имя протокола в определение класса.
class ViewController: UIViewController, CanRotate {}
Если вам нужна какая-то конкретная комбинация, вы можете добавить в протокол переменную, чтобы переопределить
protocol CanRotate {
var supportedInterfaceOrientations: UIInterfaceOrientationMask
}
Ответ 4
Используйте метод shouldAutorotate
и метод supportedInterfaceOrientations
в ViewController, который вы хотите отображать в ландшафтном и портретном режимах:
Этот метод должен переопределить настройки раскадровки.
override func shouldAutorotate() -> Bool {
return true
}
override func supportedInterfaceOrientations() -> Int {
return UIInterfaceOrientation.Portrait.rawValue | UIInterfaceOrientation.LandscapeLeft.rawValue | UIInterfaceOrientation.LandscapeRight.rawValue
}
Ответ 5
Я просто столкнулся с очень похожей проблемой, когда хотел представить видеоплеер в портретном и ландшафтном режимах, тогда как остальная часть приложения - только портрет. Моя основная проблема заключалась в том, что когда я отклонил видео vc в ландшафтном режиме, презентация vc была только ненадолго в ландшафтном режиме.
Как было отмечено в комментарии к @Lyndsey Скотт ответить на это можно обойти, запрещая переходами в ландшафтном режиме, но комбинируя это и это я нашел более и более общее решение (ИМО). Это решение допускает вращение во всех vc, где вы помещаете canRotate(){}
и не поворачиваете презентацию vc.
Swift 3:
В AppDelegate.swift:
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
if let rootViewController = self.topViewControllerWithRootViewController(rootViewController: window?.rootViewController) {
if (rootViewController.responds(to: Selector(("canRotate")))) {
// Unlock landscape view orientations for this view controller if it is not currently being dismissed
if !rootViewController.isBeingDismissed{
return .allButUpsideDown
}
}
}
// Only allow portrait (standard behaviour)
return .portrait
}
private func topViewControllerWithRootViewController(rootViewController: UIViewController!) -> UIViewController? {
if (rootViewController == nil) {
return nil
}
if (rootViewController.isKind(of: UITabBarController.self)) {
return topViewControllerWithRootViewController(rootViewController: (rootViewController as! UITabBarController).selectedViewController)
} else if (rootViewController.isKind(of: UINavigationController.self)) {
return topViewControllerWithRootViewController(rootViewController: (rootViewController as! UINavigationController).visibleViewController)
} else if (rootViewController.presentedViewController != nil) {
return topViewControllerWithRootViewController(rootViewController: rootViewController.presentedViewController)
}
return rootViewController
}
В каждом контроллере просмотра, где должно быть разрешено вращение:
func canRotate(){}
Ответ 6
Swift 3: добавьте код в AppDelegate.swift
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
if let rootViewController = self.topViewControllerWithRootViewController(rootViewController: window?.rootViewController) {
if (rootViewController.responds(to: Selector(("canRotate")))) {
// Unlock landscape view orientations for this view controller
return .allButUpsideDown;
}
}
// Only allow portrait (standard behaviour)
return .portrait;
}
private func topViewControllerWithRootViewController(rootViewController: UIViewController!) -> UIViewController? {
if (rootViewController == nil) { return nil }
if (rootViewController.isKind(of: (UITabBarController).self)) {
return topViewControllerWithRootViewController(rootViewController: (rootViewController as! UITabBarController).selectedViewController)
} else if (rootViewController.isKind(of:(UINavigationController).self)) {
return topViewControllerWithRootViewController(rootViewController: (rootViewController as! UINavigationController).visibleViewController)
} else if (rootViewController.presentedViewController != nil) {
return topViewControllerWithRootViewController(rootViewController: rootViewController.presentedViewController)
}
return rootViewController
}
Затем:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillDisappear(_ animated : Bool) {
super.viewWillDisappear(animated)
if (self.isMovingFromParentViewController) {
UIDevice.current.setValue(Int(UIInterfaceOrientation.portrait.rawValue), forKey: "orientation")
}
}
func canRotate() -> Void {}
}
http://www.jairobjunior.com/blog/2016/03/05/how-to-rotate-only-one-view-controller-to-landscape-in-ios-slash-swift/
Ответ 7
SWIFT 4
Для UITabBarController
мы можем использовать эту строку кода в AppDelegate.swift
.
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
if let tabBarController = window?.rootViewController as? UITabBarController {
if let tabBarViewControllers = tabBarController.viewControllers {
if let projectsNavigationController = tabBarViewControllers[1] as? UINavigationController {
if projectsNavigationController.visibleViewController is PickerViewController //use here your own ViewController class name {
return .all
}
}
}
}
return .portrait
}
Ответ 8
Иногда, когда вы используете настраиваемый поток навигации (который может стать очень сложным), вышеупомянутые решения могут не всегда работать. Кроме того, если у вас несколько ViewControllers, которые нуждаются в поддержке для нескольких ориентаций, это может стать довольно утомительным.
Вот довольно быстрое решение, которое я нашел. Определите класс OrientationManager
и используйте его для обновления поддерживаемых ориентаций в AppDelegate:
class OrientationManager {
static var landscapeSupported: Bool = false
}
Затем в AppDelegate поместите ориентировки, которые вы хотите для этого конкретного случая:
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
if OrientationManager.landscapeSupported {
return .allButUpsideDown
}
return .portrait
}
Затем в ViewControllers, что вы хотите иметь несколько навигаций, обновите OrientationManager
:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
OrientationManager.landscapeSupported = true
}
Кроме того, не забудьте обновить его еще раз, когда вы выйдете из этого ViewController:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
OrientationManager.landscapeSupported = false
//The code below will automatically rotate your device orientation when you exit this ViewController
let orientationValue = UIInterfaceOrientation.portrait.rawValue
UIDevice.current.setValue(orientationValue, forKey: "orientation")
}
Надеюсь это поможет!
Ответ 9
Просто хотел поделиться своим решением как человек, который потратил слишком много времени на вращение одного контроллера представления в приложении:
var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { get }
переопределение этого метода UIViewController помогло мне сделать то, что мне нужно.
- На контроллере представления, который вы хотите повернуть, сделайте это для поворота влево:
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { return UIInterfaceOrientation.landscapeLeft }
- Убедитесь, что вы включили вращение в нужных направлениях из настроек проекта:
- И добавьте это в AppDelegate, чтобы отключить вращение других экранов:
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) → UIInterfaceOrientationMask { return.portrait }
Ответ 10
Swift 5
Другой ответ, этот покрывает случай isBeingDismissed.
В AppDelegate:
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
if
let vvc = navigationController?.visibleViewController,
vvc is YOURViewControllerClassName &&
!vvc.isBeingDismissed
{
return UIInterfaceOrientationMask.landscape
} else {
return UIInterfaceOrientationMask.portrait
}
}