Jak uzyskać szerokość i wysokość ekranu w iOS?

506

Jak uzyskać wymiary ekranu w iOS?

Obecnie używam:

lCurrentWidth = self.view.frame.size.width;
lCurrentHeight = self.view.frame.size.height;

w viewWillAppear:iwillAnimateRotationToInterfaceOrientation:duration:

Za pierwszym razem otrzymuję cały rozmiar ekranu. Za drugim razem dostaję ekran minus pasek nawigacyjny.

griotspeak
źródło

Odpowiedzi:

1063

Jak uzyskać wymiary ekranu w iOS?

Problem z opublikowanym kodem polega na tym, że liczysz na rozmiar widoku odpowiadający rozmiarowi ekranu, a jak już zauważyłeś, nie zawsze tak jest. Jeśli potrzebujesz rozmiaru ekranu, powinieneś spojrzeć na obiekt reprezentujący sam ekran, w następujący sposób:

CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
CGFloat screenHeight = screenRect.size.height;

Aktualizacja podzielonego widoku: W komentarzach Dmitry zapytał:

Jak mogę uzyskać rozmiar ekranu w podzielonym widoku?

Podany powyżej kod zgłasza rozmiar ekranu, nawet w trybie podzielonego ekranu. Gdy używasz trybu podzielonego ekranu, zmienia się okno aplikacji. Jeśli powyższy kod nie zawiera oczekiwanych informacji, to podobnie jak PO, patrzysz na niewłaściwy obiekt. W takim przypadku powinieneś jednak spojrzeć na okno zamiast na ekran:

CGRect windowRect = self.view.window.frame;
CGFloat windowWidth = windowRect.size.width;
CGFloat windowHeight = windowRect.size.height;

Szybki 4.2

let screenRect = UIScreen.main.bounds
let screenWidth = screenRect.size.width
let screenHeight = screenRect.size.height

// split screen            
let windowRect = self.view.window?.frame
let windowWidth = windowRect?.size.width
let windowHeight = windowRect?.size.height
Caleb
źródło
7
Orientacja jest naprawdę zarządzana na poziomie kontrolera widoku. Przyjrzeć Zarządzanie Interfejs Orientacja rzutem sterownika . Tak, spójrz na właściwość interfaceOrientation kontrolera widoku. BTW, zapytałeś o rozmiar ekranu, więc to właśnie ci pokazałem, ale do wyświetlania treści prawdopodobnie powinieneś użyć granic okna lub ramki aplikacji ekranu, w zależności od tego, co robisz.
Caleb
2
warto zauważyć, że zwraca to pełną szerokość ekranu bez dopełniania. Po prostu odejmij dopełnienie aplikacji (zwykle 20 z każdej strony) od tych wyników, aby uzyskać „użyteczną” przestrzeń dla większości elementów
Nick Daugherty
2
@NickDaugherty Tak, o to chodzi - OP chciał wymiary ekranu. Miejsce, w którym umieszczasz obiekty na ekranie, zależy wyłącznie od Ciebie i zależy od typu aplikacji, którą tworzysz. Jeśli na przykład wyświetlasz zdjęcie lub interfejs gry, możesz w ogóle nie chcieć żadnego dopełnienia.
Caleb
3
Należy jednak pamiętać, że zwraca wartość mierzoną w punktach. Więc jeśli spodziewałeś się rozdzielczości ekranu w pikselach, wynik byłby niepoprawny i powinieneś pomnożyć wynik przez [UIScreen scale].
Robotbugs
3
Ktoś zwrócił uwagę, że ponieważ CGRect może mieć ujemną szerokość lub wysokość , powinniśmy użyć CGRectGetWidth()i CGRectGetHeight()zamiast bezpośredniego dostępu do sizepola w prostokącie. Nie sądzę, aby kiedykolwiek pojawił się problem z prostokątem ekranu, ale przypuszczam, że należy o tym pamiętać.
Caleb
64

Ostrożnie, [Główny ekran UIScreen] zawiera również pasek stanu, jeśli chcesz pobrać ramkę dla swojej aplikacji (bez paska stanu), powinieneś użyć

+ (CGFloat) window_height   {
    return [UIScreen mainScreen].applicationFrame.size.height;
}

+ (CGFloat) window_width   {
    return [UIScreen mainScreen].applicationFrame.size.width;
}
Ege Akpinar
źródło
4
przestarzałe w iOS 9.0
Zakaria Darwish,
6
od applicationFrame jest przestarzała, zastąpreturn [[UIScreen mainScreen] bounds].size.width;
lizzy81
44

Przetłumaczyłem niektóre z powyższych odpowiedzi Celu C na kod Swift. Każde tłumaczenie jest poprzedzone odniesieniem do oryginalnej odpowiedzi.

Główna odpowiedź

let screen = UIScreen.main.bounds
let screenWidth = screen.size.width
let screenHeight = screen.size.height

Prosta funkcja odpowiedzi

func windowHeight() -> CGFloat {
    return UIScreen.mainScreen().applicationFrame.size.height
}

func windowWidth() -> CGFloat {
    return UIScreen.mainScreen().applicationFrame.size.width
}

Odpowiedź dotycząca orientacji urządzenia

var screenHeight : CGFloat
let statusBarOrientation = UIApplication.sharedApplication().statusBarOrientation
// it is important to do this after presentModalViewController:animated:
if (statusBarOrientation != UIInterfaceOrientation.Portrait
    && statusBarOrientation != UIInterfaceOrientation.PortraitUpsideDown){
    screenHeight = UIScreen.mainScreen().applicationFrame.size.width
} else {
    screenHeight = UIScreen.mainScreen().applicationFrame.size.height
}

Zaloguj się

let screenWidth = UIScreen.mainScreen().bounds.size.width
let screenHeight = UIScreen.mainScreen().bounds.size.height
println("width: \(screenWidth)")
println("height: \(screenHeight)")
Martin Woolstenhulme
źródło
Wydaje się, że w logu jest literówka Odpowiedź: Czy powinna to być UIScreen.mainScreen (). Bounds.size.width? Otrzymuję błąd kompilacji bez „.bounds”.
kamień
@skypecakes Naprawiłem odpowiedź, aby uwzględnić „.bounds”. Dzięki za opinie.
Martin Woolstenhulme
applicationFrame jest przestarzałe w iOS 9 i nowszych, zamień nareturn UIScreen.mainScreen().bounds].size.width
Suhaib
39

Wcześniej stosowałem następujące metody wygody:

- (CGRect)getScreenFrameForCurrentOrientation {
    return [self getScreenFrameForOrientation:[UIApplication sharedApplication].statusBarOrientation];
}

- (CGRect)getScreenFrameForOrientation:(UIInterfaceOrientation)orientation {

    CGRect fullScreenRect = [[UIScreen mainScreen] bounds];

    // implicitly in Portrait orientation.
    if (UIInterfaceOrientationIsLandscape(orientation)) {
      CGRect temp = CGRectZero;
      temp.size.width = fullScreenRect.size.height;
      temp.size.height = fullScreenRect.size.width;
      fullScreenRect = temp;
    }

    if (![[UIApplication sharedApplication] statusBarHidden]) {
      CGFloat statusBarHeight = 20; // Needs a better solution, FYI statusBarFrame reports wrong in some cases..
      fullScreenRect.size.height -= statusBarHeight;
    }

    return fullScreenRect;
} 
Luke Mcneice
źródło
Fajne rozwiązanie, ale uważaj, aby temp miał nieokreślone pochodzenie.
szemian
4
Czy domyślnie dostajesz 0,0? Kiedy zalogowałem fullScreenRect, otrzymałem: {{8.03294e-35, 3.09816e-40}, {480, 320}}. Zdecydowałem się zainicjować za pomocą CGRect temp = CGRectZero;
szemian
1
UIInterfaceOrientationIsL Landscape nie obsługuje „UIDeviceOrientationFaceUp” i „UIDeviceOrientationFaceDown”, które mogą być zwracane z UIDevice.
Andriy,
6
Możesz użyć właściwości screen.applicationFrame zamiast screen.bounds, która zajmuje się paskiem stanu.
Geraud.ch
W niektórych przypadkach okazuje się, że ramka aplikacji nie zwraca ramki z poprawnie odjętym paskiem stanu (moduły pełnoekranowe z widoku podzielonego)
Luke Mcneice 13.01.2013
15

Zdaję sobie sprawę, że jest to stary post, ale czasami uważam, że przydatne jest #define stałe takie jak te, więc nie muszę się o to martwić:

#define DEVICE_SIZE [[[[UIApplication sharedApplication] keyWindow] rootViewController].view convertRect:[[UIScreen mainScreen] bounds] fromView:nil].size

Powyższa stała powinna zwracać prawidłowy rozmiar bez względu na orientację urządzenia. Zatem uzyskanie wymiarów jest tak proste, jak:

lCurrentWidth = DEVICE_SIZE.width;
lCurrentHeight = DEVICE_SIZE.height;
Losowy użytkownik
źródło
Możesz oprzeć makro na odpowiedzi AnswerBot, ponieważ wydaje się to najlepszą odpowiedzią.
griotspeak
13

Bardzo, bardzo łatwo jest uzyskać rozmiar urządzenia, a także wziąć pod uwagę orientację:

// grab the window frame and adjust it for orientation
UIView *rootView = [[[UIApplication sharedApplication] keyWindow] 
                                   rootViewController].view;
CGRect originalFrame = [[UIScreen mainScreen] bounds];
CGRect adjustedFrame = [rootView convertRect:originalFrame fromView:nil];
memmons
źródło
Cześć, używam tego w viewDidLoad w aplikacji przeznaczonej tylko do iPada w orientacji poziomej, czy jest jakiś powód, dla którego po raz pierwszy otrzymuje poprawną wartość, a następnie wartość „odwraca się” przy każdym ładowaniu po, tj. Czyta ją jako pierwszy widok krajobrazu, a następnie I przejdź dalej i wróć do widoku, który wydaje się czytać jako portret, nawet jeśli nie dokonano żadnej zmiany orientacji? Dzięki
craigk,
@LukeMcneice W moim kodzie produkcyjnym mam potwierdzenie, aby upewnić się, że ramka zostanie znaleziona ... Jeszcze nie udało mi się potwierdzić tego potwierdzenia. Co jest zwracane dla rootView i originalFrame?
memmons,
Używam tej techniki w singletonie, aby uzyskać szerokość / wysokość z poprawioną orientacją. Jeśli jednak ten kod działa, gdy okno UIAlert pokazujące metodę convertRect zwraca wartość adjustFrame o rozmiarze (co najmniej szerokości) równym 0. Wiesz, co się z tym dzieje?
Electro-Bunny,
Ach An UIAlertViewwstawi się jako widok rootViewController keyWindow. Mam logikę, która pozwala uniknąć narożnika, ponieważ jeśli pojawia się widok alertu, użytkownik nie może wchodzić w interakcje z klawiaturą, więc zwykle nie ma potrzeby chwytania ramki klawiatury w tym czasie.
memmons,
Dzięki za wgląd. Używałem twojej techniki w reklamie singletonowej. Był to prosty i przyjemny sposób na określenie w interfejsie reklamowym rozmiaru ramki ekranu dla nowej reklamy. Ponieważ nie będę w stanie wzajemnie wykluczać banerów reklamowych i UIAlert, prawdopodobnie wrócę do wykrywania krajobrazu w zależności od portretu i brutalnej siły x / y, jeśli to konieczne.
Electro-Bunny
9

Musimy również wziąć pod uwagę orientację urządzenia:

CGFloat screenHeight;
// it is important to do this after presentModalViewController:animated:
if ([[UIApplication sharedApplication] statusBarOrientation] == UIDeviceOrientationPortrait || [[UIApplication sharedApplication] statusBarOrientation] == UIDeviceOrientationPortraitUpsideDown){
    screenHeight = [UIScreen mainScreen].applicationFrame.size.height;
}
else{
    screenHeight = [UIScreen mainScreen].applicationFrame.size.width;
}
Oleh Kudinov
źródło
Dobre rozwiązanie Zrobiłem to, aby moja aplikacja na iPada działała w układzie poziomym z wbudowanego kontrolera widoku podczas prezentacji modalnego VC.
StackRunner
8
NSLog(@"%.0f", [[UIScreen mainScreen] bounds].size.width);
NSLog(@"%.0f", [[UIScreen mainScreen] bounds].size.height);
Gaurav Gilani
źródło
5

Tutaj zaktualizowałem do Swift 3

applicationFrame przestarzałe z iOS 9

W szybkich trzech usunęli () i zmienili kilka konwencji nazewnictwa, możesz odwołać się tutaj Link

func windowHeight() -> CGFloat {
    return UIScreen.main.bounds.size.height
}

func windowWidth() -> CGFloat {
    return UIScreen.main.bounds.size.width
}
karthikeyan
źródło
4

Nowoczesna odpowiedź:

jeśli Twoja aplikacja obsługuje podzielony widok na iPadzie, problem ten staje się nieco skomplikowany. Potrzebujesz rozmiaru okna, a nie ekranu, który może zawierać 2 aplikacje. Rozmiar okna może się również różnić podczas działania.

Użyj rozmiaru głównego okna aplikacji:

UIApplication.shared.delegate?.window??.bounds.size ?? .zero

Uwaga: powyższa metoda może mieć niepoprawną wartość, zanim okno stanie się kluczowym oknem podczas uruchamiania. jeśli potrzebujesz tylko szerokości, bardzo zalecana jest metoda poniżej :

UIApplication.shared.statusBarFrame.width

Używanie starego rozwiązania UIScreen.main.boundszwróci granice urządzenia. Jeśli Twoja aplikacja działa w trybie podzielonego widoku, ma nieprawidłowe wymiary.

self.view.window w najgorętszej odpowiedzi może mieć zły rozmiar, gdy aplikacja zawiera 2 lub więcej okien, a okno ma mały rozmiar.

Leavez
źródło
4

Skorzystaj z nich, Structsaby poznać przydatne informacje o bieżącym urządzeniu w Swift 3.0

struct ScreenSize { // Answer to OP's question

    static let SCREEN_WIDTH         = UIScreen.main.bounds.size.width
    static let SCREEN_HEIGHT        = UIScreen.main.bounds.size.height
    static let SCREEN_MAX_LENGTH    = max(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
    static let SCREEN_MIN_LENGTH    = min(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)

}

struct DeviceType { //Use this to check what is the device kind you're working with

    static let IS_IPHONE_4_OR_LESS  = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH < 568.0
    static let IS_IPHONE_SE         = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 568.0
    static let IS_IPHONE_7          = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 667.0
    static let IS_IPHONE_7PLUS      = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 736.0
    static let IS_IPHONE_X          = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 812.0
    static let IS_IPAD              = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1024.0

}


struct iOSVersion { //Get current device's iOS version

    static let SYS_VERSION_FLOAT  = (UIDevice.current.systemVersion as NSString).floatValue
    static let iOS7               = (iOSVersion.SYS_VERSION_FLOAT >= 7.0 && iOSVersion.SYS_VERSION_FLOAT < 8.0)
    static let iOS8               = (iOSVersion.SYS_VERSION_FLOAT >= 8.0 && iOSVersion.SYS_VERSION_FLOAT < 9.0)
    static let iOS9               = (iOSVersion.SYS_VERSION_FLOAT >= 9.0 && iOSVersion.SYS_VERSION_FLOAT < 10.0)
    static let iOS10              = (iOSVersion.SYS_VERSION_FLOAT >= 10.0 && iOSVersion.SYS_VERSION_FLOAT < 11.0)
    static let iOS11              = (iOSVersion.SYS_VERSION_FLOAT >= 11.0 && iOSVersion.SYS_VERSION_FLOAT < 12.0)
    static let iOS12              = (iOSVersion.SYS_VERSION_FLOAT >= 12.0 && iOSVersion.SYS_VERSION_FLOAT < 13.0)

}
badhanganesh
źródło
3

Jeśli chcesz szerokość / wysokość ekranu niezależnie od orientacji urządzenia (dobre do zmiany rozmiaru tylko kontrolery widoku uruchamiane z orientacji poziomej):

CGFloat screenWidthInPoints = [UIScreen mainScreen].nativeBounds.size.width/[UIScreen mainScreen].nativeScale;
CGFloat screenHeightInPoints = [UIScreen mainScreen].nativeBounds.size.height/[UIScreen mainScreen].nativeScale;

[UIScreen mainScreen] .nativeBounds <- Z dokumentów -> Granica prostokąta ekranu fizycznego, mierzona w pikselach. Ten prostokąt opiera się na urządzeniu w orientacji pionowej. Ta wartość nie zmienia się, gdy urządzenie się obraca.

John Erck
źródło
2

Oto szybki sposób uzyskania rozmiarów ekranu:

print(screenWidth)
print(screenHeight)

var screenWidth: CGFloat {
    if UIInterfaceOrientationIsPortrait(screenOrientation) {
        return UIScreen.mainScreen().bounds.size.width
    } else {
        return UIScreen.mainScreen().bounds.size.height
    }
}

var screenHeight: CGFloat {
    if UIInterfaceOrientationIsPortrait(screenOrientation) {
        return UIScreen.mainScreen().bounds.size.height
    } else {
        return UIScreen.mainScreen().bounds.size.width
    }
}

var screenOrientation: UIInterfaceOrientation {
    return UIApplication.sharedApplication().statusBarOrientation
}

Są one zawarte jako funkcja standardowa w:

https://github.com/goktugyil/EZSwiftExtensions

Esqarrouth
źródło
1

CGFloat width = [[UIScreen mainScreen] bounds].size.width; CGFloat height = [[UIScreen mainScreen]bounds ].size.height;

Himanshu jamnani
źródło
1

szybki 3.0

dla szerokości

UIScreen.main.bounds.size.width

na wysokość

UIScreen.main.bounds.size.height
Amul4608
źródło
-2

Możesz umieścić te makra w pliku pch i używać ich w dowolnym miejscu w projekcie, używając „SCREEN_WIDTH”

#define SCREEN_WIDTH                ((([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) || ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown)) ? [[UIScreen mainScreen] bounds].size.width : [[UIScreen mainScreen] bounds].size.height)

i „SCREEN_HEIGHT”

#define SCREEN_HEIGHT               ((([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) || ([UIApplication sharedApplication].statusBarOrientation ==   UIInterfaceOrientationPortraitUpsideDown)) ? [[UIScreen mainScreen] bounds].size.height : [[UIScreen mainScreen] bounds].size.width)

Przykład użycia:

CGSize calCulateSizze ;
calCulateSizze.width = SCREEN_WIDTH/2-8;
calCulateSizze.height = SCREEN_WIDTH/2-8;
Anny
źródło
Czy możesz wyciąć kod zgodnie z formatem przeceny? Obecnie użytkownicy społeczności oznaczali to jako „niską jakość” w kolejce recenzji.
Manoj Kumar,