Отримання орієнтації пристрою в Swift


79

Мені цікаво, як я можу отримати поточну орієнтацію пристрою в Swift? Я знаю, що є приклади для Objective-C, однак мені не вдалося змусити його працювати в Swift.

Я намагаюся отримати орієнтацію пристрою і ввести це в оператор if.

Це рядок, з яким у мене найбільше проблем:

[[UIApplication sharedApplication] statusBarOrientation]

Та що з тобою таке? Перекласти це на Свіфт або отримати ті очікувані значення?
Девід Роннквіст,

1
Орієнтація пристрою не обов'язково відповідає орієнтації інтерфейсу користувача. Точка корпусу - ляжте пристрій рівно і протестуйте свій код!
Патрік

Відповіді:


70

Ви можете використовувати:

override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation) {
    var text=""
    switch UIDevice.currentDevice().orientation{
    case .Portrait:
        text="Portrait"
    case .PortraitUpsideDown:
        text="PortraitUpsideDown"
    case .LandscapeLeft:
        text="LandscapeLeft"
    case .LandscapeRight:
        text="LandscapeRight"
    default:
        text="Another"
    }
    NSLog("You have moved: \(text)")        
}

SWIFT 3 ОНОВЛЕННЯ

override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) {
    var text=""
    switch UIDevice.current.orientation{
    case .portrait:
        text="Portrait"
    case .portraitUpsideDown:
        text="PortraitUpsideDown"
    case .landscapeLeft:
        text="LandscapeLeft"
    case .landscapeRight:
        text="LandscapeRight"
    default:
        text="Another"
    }
    NSLog("You have moved: \(text)")        
}

або

override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
}

за допомогою Notification ви можете перевірити: IOS8 Swift: Як виявити зміну орієнтації?

ПРИМІТКА: didRotateFromInterfaceOrientation застаріле Використовуйте viewWillTransitionToSize для iOS 2.0 та новіших версій

У випадку Face Up та Face Down це не буде працювати. Тому нам потрібно використовувати наступне.

if UIApplication.shared.statusBarOrientation.isLandscape {
     // activate landscape changes
} else {
     // activate portrait changes
}

Дякуємо за ваш спільний доступ!
ssowri1

Хм ... а що, якби користувач перейшов до цього подання вже після обертання, ми б не знали початкової орієнтації ...
ScottyBlades

Якщо ви все ще використовуєте цю функцію, незважаючи на те, що вона застаріла. не забудьте назвати це супер методом у вашій реалізації. тобто: super.didRotate(from: fromInterfaceOrientation). З документації Apple: "Ваша реалізація цього методу повинна викликати супер у певний момент під час його виконання".
Бокаксіка

55

Щоб отримати орієнтацію рядка стану (і відповідно до цього інтерфейсу), як у вас є код Objective-C, це просто:

UIApplication.sharedApplication().statusBarOrientation

Ви також можете використовувати orientationвластивість UIDevice:

UIDevice.currentDevice().orientation

Однак це може не відповідати орієнтації вашого інтерфейсу. З документації:

Значення властивості є константою, яка вказує на поточну орієнтацію пристрою. Це значення відображає фізичну орієнтацію пристрою і може відрізнятися від поточної орієнтації інтерфейсу користувача вашої програми. Опис можливих значень див. У розділі “UIDeviceOrientation”.


UIApplication.sharedApplication (). StatusBarOrientation є лише в основному потоці
Yair hadad

Дякую за твою допомогу!
ssowri1

1
Я використовував uidevice.current.orientation.isportrait, щоб перевірити орієнтацію пристрою та змінити інтерфейс користувача програми, але він змінювався, навіть якщо поставити пристрій на стіл. Але завдяки вам зараз він працює нормально
Галфхам-хан,

оновлено на швидкій версії 5.1 -> UIDevice.current.orientation
Роналду Альбертіні

UIDevice.current.orientation.isPor Portrait не працює, якщо орієнтація пристрою спрямована догори або донизу. Перевірка рядка стану, як ця відповідь, була послідовною і працюючою для мене.
Остін,

26

Apple нещодавно позбулася ідеї пейзажу проти портрета і вважає за краще використовувати розмір екрану. Однак це працює:

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    if UIDevice.currentDevice().orientation.isLandscape.boolValue {
        print("landscape")
    } else {
        print("portrait")
    }
}

7
З вашим рішенням я б зауважив, що apple стверджує: "Якщо ви перевизначите цей метод у своїх користувацьких контролерах подання, завжди телефонуйте супер у якийсь момент вашої реалізації"
Popmedic

25
struct DeviceInfo {
struct Orientation {
    // indicate current device is in the LandScape orientation
    static var isLandscape: Bool {
        get {
            return UIDevice.current.orientation.isValidInterfaceOrientation
                ? UIDevice.current.orientation.isLandscape
                : UIApplication.shared.statusBarOrientation.isLandscape
        }
    }
    // indicate current device is in the Portrait orientation
    static var isPortrait: Bool {
        get {
            return UIDevice.current.orientation.isValidInterfaceOrientation
                ? UIDevice.current.orientation.isPortrait
                : UIApplication.shared.statusBarOrientation.isPortrait
        }
    }
}}

відповідь swift4: ось як я це роблю,

1. працює для всіх видів контролера перегляду

2. також працювати, коли користувач обертає додаток

3. також вперше встановіть програму


1
ідеальна відповідь! Дякую
завершіть

Приємно, але чому ви пишете це час буксирування замість класу @objc var isLandscape: Bool {return! IsPor Portrait} Я не отримую чогось вирішального? ;)
Ренетик

Ого, це чудово працює, як і я не буду .. Щиро дякую :)
Йогеш Патель

Як я знаю, що орієнтація змінилася?
Даніель Спрінгер

14

Свіфт 4:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        if UIDevice.current.orientation.isLandscape {
            print("landscape")
        } else {
            print("portrait")
        }
    }

А як щодо плоскої орієнтації?
Міхал Зіобро,

2
Не забудьте зателефонувати super.viewWillTransition (до: size, with: координатар) у певний момент у вашій функції заміщення.
Бокаксіка,

13

Щоб знайти поточну орієнтацію пристрою, просто скористайтеся цим кодом:

UIApplication.sharedApplication (). StatusBarOrientation

для швидкого 3.0

UIApplication.shared.statusBarOrientation


iPad air 1 & 2 повертає неправильне значення, iPad 2 і iPhone правильні. Я справді намагаюся знайти той, який працює на всіх пристроях, але тут яблуко зробило справжню безлад! :(
Стівен Б.

на відміну від UIDevice.current.orientation, UIApplication.shared.statusBarOrientationдоступний при початковому завантаженні, а не лише після обертання екрана.
ewizard

10

У мене були проблеми з використанням InterfaceOrientation, це працювало нормально, за винятком того, що він не отримував доступ до орієнтації при завантаженні. Тож я спробував це, і це хранитель. Це спрацьовує, оскільки значення bounds.widthзавжди посилається на поточну орієнтацію, на відміну від nativeBounds.widthякої є абсолютною.

    if UIScreen.mainScreen().bounds.height > UIScreen.mainScreen().bounds.width {
        // do your portrait stuff
    } else {    // in landscape
        // do your landscape stuff
    }

Я називаю це від willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval)і від, viewDidLoadале це гнучко.

Завдяки zSprawl за вказівник у цьому напрямку. Слід зазначити, що це добре лише для iOS 8 і пізніших версій.


НЕ працює на iPad 9 та 10 iPad, лише початкове значення є правильним, усі наступні значення мають протилежну орієнтацію.
Стівен Б.

@ Steven.B Hmmm ... чудово працює на моєму iPad Air, iPad 3 та симуляторі під iOS 9. Також працював із бета-тестерами. Можливо, ви також використовуєте інший код, який впливає на це.
bpedit

Цей код, ймовірно, працює лише при використанні в контролері UIView, я намагаюся отримати орієнтацію та межі у власному класі UIView, але майже кожен тестований пристрій повертає різні значення, коли орієнтація правильна, ніж рамка, або межі все ще помиляються.
Стівен Б.

10

Отже, якщо Apple відмовляється від цілого елемента орієнтаційного рядка ("портрет", "пейзаж"), то все, що вам важливо, - це відношення ширини до висоти. (як-от відповідь @ bpedit)

Коли ви ділите ширину на висоту, якщо результат менше 1, тоді mainScreen або контейнер або що завгодно перебуває у "портретному" "режимі". Якщо результат перевищує 1, це картина "пейзаж". ;)

override func viewWillAppear(animated: Bool) {
    let size: CGSize = UIScreen.mainScreen().bounds.size
    if size.width / size.height > 1 {
        print("landscape")
    } else {
        print("portrait")
    }
}
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    if size.width / size.height > 1 {
        print("landscape")
    } else {
        print("portrait")
    }
}

(Я здогадуюсь, що якщо ви використовуєте такий підхід, то вам, мабуть, насправді не цікаво конкретно обробляти умову, коли коефіцієнт рівно 1, рівна ширина та висота.)


1
Приємно! Невелике вдосконалення вашої відповіді: Не забудьте зателефонувати super.viewWillAppear(animated)і super.viewWillTransition(to: size, with: coordinator)в якийсь момент у ваших головних функціях
Бокаксіка

8

Свіфт 3+

В основному:

NotificationCenter.default.addObserver(self, selector: #selector(self.didOrientationChange(_:)), name: .UIDeviceOrientationDidChange, object: nil)

@objc func didOrientationChange(_ notification: Notification) {
    //const_pickerBottom.constant = 394
    print("other")
    switch UIDevice.current.orientation {
        case .landscapeLeft, .landscapeRight:
            print("landscape")
        case .portrait, .portraitUpsideDown:
            print("portrait")
        default:
            print("other")
    }
}

:)


Я люблю цю відповідь. Це дуже корисно для великих екранів, таких як iPad, де ви не можете використовувати, func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)оскільки колекція ознак буде завжди, width.regularі height.regular, отже, traitCollection не зміниться при обертанні. У Swift 4 повідомлення було перейменовано на UIDevice.orientationDidChangeNotification.
Бокаксіка,

3

Свіфт 3 , заснований на відповіді Роба

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    if (size.width / size.height > 1) {
        print("landscape")
    } else {
        print("portrait")
    }
}

2
Не забудьте зателефонувати super.viewWillTransition(to: size, with: coordinator)в якийсь момент у вашій
замінній

3

Я виявив, що альтернативний код у Swift для коду Obj-C

if (UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) 

є

if UIApplication.shared.statusBarOrientation.isLandscape

Примітка: ми намагаємось знайти, щоб орієнтація рядка стану була альбомною чи ні. Якщо це пейзаж, то твердження if відповідає дійсності.


3

statusBarOrientation НЕ рекомендується , тому НЕ більш доступні для використання , як в вищенаведених відповідей

У цьому коді можна отримати орієнтацію, не турбуючись про амортизацію. Swift 5 ioS 13.2 Перевірено на 100%

struct Orientation {
    // indicate current device is in the LandScape orientation
    static var isLandscape: Bool {
        get {
            return UIDevice.current.orientation.isValidInterfaceOrientation
                ? UIDevice.current.orientation.isLandscape
                : (UIApplication.shared.windows.first?.windowScene?.interfaceOrientation.isLandscape)!
        }
    }
    // indicate current device is in the Portrait orientation
    static var isPortrait: Bool {
        get {
            return UIDevice.current.orientation.isValidInterfaceOrientation
                ? UIDevice.current.orientation.isPortrait
                : (UIApplication.shared.windows.first?.windowScene?.interfaceOrientation.isPortrait)!
        }
    }
}

2
   override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
    if (toInterfaceOrientation.isLandscape) {
        NSLog("Landscape");
    }
    else {
        NSLog("Portrait");
    }
}

0

Спробуйте використовувати horizontalSizeClass& verticalSizeClass:

import SwiftUI

struct DemoView: View {
    
    @Environment(\.horizontalSizeClass) var hSizeClass
    @Environment(\.verticalSizeClass) var vSizeClass
    
    var body: some View {
        VStack {
            if hSizeClass == .compact && vSizeClass == .regular {
                VStack {
                    Text("Vertical View")
                }
            } else {
                HStack {
                    Text("Horizontal View")
                }
            }
        }
    }
}

Знайшов це в цьому посібнику . Пов’язана документація Apple .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.