Zasadniczo chcę, aby moje podglądy były ustawione inaczej w zależności od orientacji iPada (pionowa lub pozioma) przy użyciu klas rozmiaru wprowadzonych w xcode 6. Znalazłem wiele samouczków wyjaśniających, jak różne klasy rozmiaru są dostępne dla iPhone'ów w orientacji pionowej i poziomej na IB ale wydaje się, że nie ma żadnego, który obejmowałby indywidualne tryby krajobrazu lub portretu dla iPada na IB. Czy ktoś może pomóc?
objective-c
ios8
size-classes
adaptive-ui
neelIVP
źródło
źródło
Odpowiedzi:
Wygląda na to, że intencją Apple jest traktowanie obu orientacji iPada jako tej samej - ale jak wielu z nas odkrywa, istnieją bardzo uzasadnione powody projektowe, aby chcieć zmienić układ interfejsu użytkownika dla iPad Portrait i iPad Landscape.
Niestety, wydaje się, że obecny system operacyjny nie zapewnia wsparcia dla tego rozróżnienia ... co oznacza, że wracamy do manipulowania ograniczeniami automatycznego układu w kodzie lub podobnych obejść, aby osiągnąć to, co powinniśmy uzyskać za darmo za pomocą Adaptive UI .
Nie jest to eleganckie rozwiązanie.
Nie jest jakiś sposób wykorzystać magię, że Apple jest już wbudowany w IB i UIKit użyć klasy wielkości naszego wyboru dla danej orientacji?
~
Myśląc o problemie bardziej ogólnie, zdałem sobie sprawę, że „klasy rozmiarów” to po prostu sposoby rozwiązania wielu układów przechowywanych w IB, tak aby można je było wywoływać w razie potrzeby w czasie wykonywania.
W rzeczywistości „klasa wielkości” to tak naprawdę tylko para wartości wyliczeniowych. Z UIInterface.h:
Więc niezależnie od tego, co Apple zdecydowało się nazwać te różne odmiany, zasadniczo są one tylko parą liczb całkowitych używanych jako swoisty unikalny identyfikator, aby odróżnić jeden układ od drugiego, przechowywany w IB.
Teraz, zakładając, że utworzymy alternatywny układ (używając nieużywanej klasy rozmiaru) w IB - powiedzmy, dla iPad Portrait ... czy istnieje sposób, aby urządzenie użyło naszej wybranej klasy rozmiaru (układu interfejsu użytkownika) w razie potrzeby w czasie wykonywania ?
Po wypróbowaniu kilku różnych (mniej eleganckich) podejść do problemu, podejrzewałem, że może istnieć sposób na programowe zastąpienie domyślnej klasy rozmiaru. I jest (w UIViewController.h):
Tak więc, jeśli możesz spakować swoją hierarchię kontrolera widoku jako `` podrzędny '' kontroler widoku i dodać go do nadrzędnego kontrolera widoku najwyższego poziomu ... wtedy możesz warunkowo zastąpić dziecko myśląc, że jest to inna klasa rozmiaru niż domyślna z systemu operacyjnego.
Oto przykładowa implementacja, która to robi w kontrolerze widoku „nadrzędnego”:
Aby szybko sprawdzić, czy to zadziałało, dodałem niestandardowe etykiety specjalnie do wersji „Regular / Regular” i „Compact / Regular” układu kontrolera podrzędnego w IB:
A oto jak wygląda bieganie, gdy iPad jest w obu orientacjach:
Voila! Konfiguracje klas rozmiaru niestandardowego w czasie wykonywania.
Miejmy nadzieję, że Apple uczyni to niepotrzebnym w następnej wersji systemu operacyjnego. W międzyczasie może to być bardziej eleganckie i skalowalne podejście niż programowe manipulowanie ograniczeniami automatycznego układu lub wykonywanie innych operacji w kodzie.
~
EDYCJA (6/4/15): Należy pamiętać, że powyższy przykładowy kod jest zasadniczo dowodem słuszności koncepcji w celu zademonstrowania techniki. Możesz dowolnie dostosowywać się do własnych potrzeb.
~
EDYCJA (24.07.15): To satysfakcjonujące, że powyższe wyjaśnienie wydaje się pomóc w wyjaśnieniu problemu. Chociaż tego nie testowałem, kod mohamede1945 [poniżej] wygląda na przydatną optymalizację do celów praktycznych. Zapraszam do przetestowania i daj nam znać, co myślisz. (Ze względu na kompletność pozostawię powyższy przykładowy kod bez zmian).
źródło
UITraitCollection
jest wystarczająco zoptymalizowany ioverrideTraitCollectionForChildViewController
jest wywoływany na tyle rzadko, że sprawdzenie szerokości i utworzenie go nie powinno stanowić problemu.Podsumowując bardzo długą odpowiedź RonDiamonda. Wszystko, co musisz zrobić, to w głównym kontrolerze widoku.
Cel C
Szybki:
Następnie w storyborad użyj małej szerokości dla opcji Pionowej i Normalnej szerokości dla Poziomu.
źródło
- (UITraitCollection *)traitCollection
zamiastoverrideTraitCollectionForChildViewController
. Również ograniczenia powinny pasować do kolekcji traitcoll, czyli wC (hAny).IPad ma cechę „regularnego” rozmiaru zarówno w przypadku wymiarów poziomych, jak i pionowych, bez rozróżnienia między portretem a krajobrazem.
Te cechy rozmiaru można przesłonić w
UIViewController
kodzie niestandardowej podklasy za pomocą metodytraitCollection
, na przykład:Dzięki temu iPad ma takie same cechy rozmiaru jak iPhone 7 Plus. Zwróć uwagę, że inne modele iPhone'a generalnie mają cechę „niewielkiej szerokości” (zamiast zwykłej szerokości), niezależnie od orientacji.
Naśladowanie iPhone'a 7 Plus w ten sposób pozwala na użycie tego modelu jako stand-in dla iPada w Interface Builder Xcode, który nie jest świadomy dostosowań w kodzie.
Należy pamiętać, że Split View na iPadzie może mieć inne cechy rozmiaru niż normalne działanie na pełnym ekranie.
Ta odpowiedź jest oparta na podejściu przyjętym w tym poście na blogu , z pewnymi ulepszeniami.
Aktualizacja 2019-01-02: Zaktualizowano, aby naprawić przerywany ukryty pasek stanu w krajobrazie iPada i potencjalne deptanie (nowszych) cech w
UITraitCollection
. Zauważyłem również, że dokumentacja Apple faktycznie odradza zastępowanietraitCollection
, więc w przyszłości mogą pojawić się problemy z tą techniką.źródło
traitCollection
właściwość ma być tylko do odczytu: developer.apple.com/documentation/uikit/uitraitenvironment/…Długa i pomocna odpowiedź RonDiamond to dobry początek zrozumienia zasad, jednak kod, który u mnie zadziałał (iOS 8+) oparty jest na metodzie nadrzędnej
(UITraitCollection *)traitCollection
Dlatego Dodaj ograniczenia w InterfaceBuilder z odmianami Width - Compact, na przykład dla właściwości ograniczenia Installed. Tak więc Szerokość - dowolna będzie obowiązywać w przypadku poziomego, a Szerokość - kompaktowa w przypadku orientacji pionowej.
Aby przełączyć ograniczenia w kodzie na podstawie bieżącego rozmiaru kontrolera widoku, po prostu dodaj następujące elementy do swojej klasy UIViewController:
źródło
Jak bardzo różni się twój tryb poziomy od trybu portretowego? Jeśli jest bardzo inny, dobrym pomysłem może być utworzenie innego kontrolera widoku i załadowanie go, gdy urządzenie jest w trybie poziomym
Na przykład
źródło
Wersja Swift 5. To działa dobrze.
źródło
Kod Swift 3.0 dla rozwiązania @RonDiamond
źródło