Saya pada dasarnya ingin subview saya diposisikan secara berbeda tergantung pada orientasi iPad (Portrait atau Landscape) menggunakan Sizing Classes yang diperkenalkan di xcode 6. Saya telah menemukan banyak tutorial yang menjelaskan bagaimana berbagai kelas sizing tersedia untuk iPhone dalam portrait dan landscape di IB tetapi bagaimanapun tampaknya tidak ada yang mencakup mode lanskap atau potret individu untuk iPad di IB. Adakah yang bisa membantu?
objective-c
ios8
size-classes
adaptive-ui
neelIVP
sumber
sumber
Jawaban:
Tampaknya niat Apple untuk memperlakukan kedua orientasi iPad sebagai hal yang sama - tetapi seperti yang banyak dari kita temukan, ada alasan desain yang sangat sah untuk ingin memvariasikan tata letak UI untuk iPad Portrait vs iPad Landscape.
Sayangnya, OS saat ini tampaknya tidak memberikan dukungan untuk perbedaan ini ... yang berarti bahwa kami kembali memanipulasi batasan tata letak otomatis dalam kode atau solusi serupa untuk mencapai apa yang idealnya kami dapatkan secara gratis menggunakan Adaptive UI .
Bukan solusi yang elegan.
Tidakkah ada cara untuk memanfaatkan keajaiban yang telah dibangun Apple ke dalam IB dan UIKit untuk menggunakan kelas ukuran yang kita pilih untuk orientasi tertentu?
~
Dalam memikirkan masalah secara lebih umum, saya menyadari bahwa 'kelas ukuran' hanyalah cara untuk menangani beberapa tata letak yang disimpan di IB, sehingga dapat dipanggil sesuai kebutuhan pada waktu proses.
Faktanya, 'kelas ukuran' sebenarnya hanyalah sepasang nilai enum. Dari UIInterface.h:
Jadi terlepas dari apa yang Apple putuskan untuk memberi nama variasi yang berbeda ini, pada dasarnya, mereka hanyalah sepasang bilangan bulat yang digunakan sebagai pengenal unik, untuk membedakan satu tata letak dari yang lain, disimpan di IB.
Sekarang, misalkan kita membuat tata letak alternatif (menggunakan kelas ukuran yang tidak terpakai) di IB - katakanlah, untuk Potret iPad ... adakah cara agar perangkat menggunakan pilihan kelas ukuran (tata letak UI) sesuai kebutuhan saat runtime ?
Setelah mencoba beberapa pendekatan berbeda (kurang elegan) untuk masalah ini, saya menduga mungkin ada cara untuk menimpa kelas ukuran default secara terprogram. Dan ada (di UIViewController.h):
Jadi, jika Anda dapat mengemas hierarki pengontrol tampilan sebagai pengontrol tampilan 'anak', dan menambahkannya ke pengontrol tampilan induk tingkat atas ... Anda dapat mengganti secara bersyarat anak tersebut dengan berpikir bahwa itu adalah kelas ukuran yang berbeda dari default dari OS.
Berikut adalah contoh implementasi yang melakukan ini, di pengontrol tampilan 'induk':
Sebagai demo cepat untuk melihat apakah itu berhasil, saya menambahkan label khusus secara khusus ke versi 'Reguler / Reguler' dan 'Ringkas / Reguler' dari tata letak pengontrol anak di IB:
Dan inilah yang tampak seperti berjalan, saat iPad berada dalam kedua orientasi:
Voila! Konfigurasi kelas ukuran khusus pada waktu proses.
Semoga Apple akan membuat ini tidak perlu di OS versi berikutnya. Sementara itu, ini mungkin pendekatan yang lebih elegan dan skalabel daripada mengotak-atik batasan tata letak otomatis atau melakukan manipulasi lain dalam kode secara terprogram.
~
EDIT (6/4/15): Harap diingat bahwa contoh kode di atas pada dasarnya adalah bukti konsep untuk mendemonstrasikan teknik tersebut. Jangan ragu untuk beradaptasi sesuai kebutuhan untuk aplikasi spesifik Anda sendiri.
~
EDIT (7/24/15): Sangat menyenangkan bahwa penjelasan di atas tampaknya membantu mengungkap masalah. Meskipun saya belum mengujinya, kode oleh mohamede1945 [di bawah] tampak seperti pengoptimalan yang berguna untuk tujuan praktis. Jangan ragu untuk mengujinya dan beri tahu kami pendapat Anda. (Demi kelengkapan, saya akan membiarkan kode contoh di atas apa adanya.)
sumber
UITraitCollection
cukup dioptimalkan danoverrideTraitCollectionForChildViewController
dipanggil cukup jarang sehingga seharusnya tidak menjadi masalah untuk melakukan pemeriksaan lebar dan membuatnya kemudian.Sebagai ringkasan dari jawaban yang sangat panjang oleh RonDiamond. Yang perlu Anda lakukan adalah di pengontrol tampilan root Anda.
Tujuan-c
Cepat:
Kemudian di storyborad gunakan compact width untuk Portrait dan Regular width untuk Landscape.
sumber
- (UITraitCollection *)traitCollection
bukanoverrideTraitCollectionForChildViewController
. Juga kendala harus sesuai dengan koleksi sifat, jadi wC (hAny).IPad memiliki ciri ukuran 'biasa' untuk dimensi horizontal dan vertikal, tidak memberikan perbedaan antara potret dan lanskap.
Sifat ukuran ini dapat diganti dalam
UIViewController
kode subkelas khusus Anda , melalui metodetraitCollection
, misalnya:Ini memberi iPad ciri ukuran yang sama dengan iPhone 7 Plus. Perhatikan bahwa model iPhone lainnya umumnya memiliki sifat 'lebar ringkas' (bukan lebar reguler) terlepas dari orientasinya.
Meniru iPhone 7 Plus dengan cara ini memungkinkan model tersebut digunakan sebagai stand-in untuk iPad dalam Pembuat Antarmuka Xcode, yang tidak menyadari adanya penyesuaian dalam kode.
Ketahuilah bahwa Split View di iPad mungkin menggunakan ciri ukuran yang berbeda dari operasi layar penuh normal.
Jawaban ini didasarkan pada pendekatan yang diambil dalam posting blog ini , dengan beberapa perbaikan.
Pembaruan 2019-01-02: Diperbarui untuk memperbaiki bilah status tersembunyi yang terputus-putus di lanskap iPad, dan potensi menginjak-injak sifat (lebih baru) di
UITraitCollection
. Juga dicatat bahwa dokumentasi Apple sebenarnya merekomendasikan untuk tidak menimpatraitCollection
, jadi di masa depan mungkin ada masalah dengan teknik ini.sumber
traitCollection
propertinya menjadi hanya baca: developer.apple.com/documentation/uikit/uitraitenvironment/…Jawaban panjang dan bermanfaat oleh RonDiamond adalah awal yang baik untuk memahami prinsip-prinsip tersebut, namun kode yang berhasil untuk saya (iOS 8+) didasarkan pada metode utama
(UITraitCollection *)traitCollection
Jadi, tambahkan batasan di InterfaceBuilder dengan variasi untuk Lebar - Kompak, misalnya untuk properti batasan Terpasang. Jadi Lebar - Apa pun akan valid untuk lanskap, Lebar - Ringkas untuk Potret.
Untuk mengganti batasan dalam kode berdasarkan ukuran pengontrol tampilan saat ini, cukup tambahkan yang berikut ini ke kelas UIViewController Anda:
sumber
Seberapa jauh perbedaan mode lanskap Anda dengan mode potret Anda? Jika sangat berbeda, mungkin ada baiknya untuk membuat pengontrol tampilan lain dan memuatnya saat perangkat dalam lanskap
Sebagai contoh
sumber
Versi Swift 5. Ini bekerja dengan baik.
sumber
Kode Swift 3.0 untuk solusi @RonDiamond
sumber