Görünüşe göre Apple, her iki iPad yönünü de aynı şekilde ele almak gibi görünüyor - ancak birçoğumuz bulduğumuz gibi, iPad Dikey ve iPad Yatay için UI düzenini değiştirmek istemek için çok meşru tasarım nedenleri var.
Maalesef, mevcut işletim sistemi bu ayrım için destek sağlamıyor gibi görünüyor ... bu, Adaptive UI kullanarak ideal olarak ücretsiz olarak elde edebilmemiz gereken şeyi elde etmek için kodda veya benzer geçici çözümlerde otomatik düzen kısıtlamalarını değiştirmeye geri döndüğümüz anlamına geliyor. .
Zarif bir çözüm değil.
Apple'ın zaten bir boyut sınıfı kullanmak IB ve UIKit yerleşik olduğu sihirli kaldıraç için bir yol yok mudur bizim seçme verilen bir yönlendirme için?
~
Sorunu daha genel bir şekilde düşünürken, 'boyut sınıflarının' IB'de depolanan birden çok düzeni ele almanın basit bir yolu olduğunu fark ettim, böylece çalışma zamanında gerektiğinde çağrılabilirler.
Aslında, 'boyut sınıfı' gerçekten sadece bir enum değer çiftidir. UIInterface.h'den:
typedef NS_ENUM(NSInteger, UIUserInterfaceSizeClass) {
UIUserInterfaceSizeClassUnspecified = 0,
UIUserInterfaceSizeClassCompact = 1,
UIUserInterfaceSizeClassRegular = 2,
} NS_ENUM_AVAILABLE_IOS(8_0);
Dolayısıyla, Apple'ın bu farklı varyasyonları adlandırmaya karar verdiği şey ne olursa olsun , temelde, IB'de depolanan bir düzeni diğerinden ayırmak için benzersiz bir tür tanımlayıcısı olarak kullanılan bir çift tam sayıdır.
Şimdi, IB'de (kullanılmayan bir boyut sınıfı kullanarak) alternatif bir düzen oluşturduğumuzu varsayalım - mesela, iPad Portre için ... cihazın , çalışma zamanında ihtiyaç duyulan boyut sınıfı seçimimizi (UI düzeni) kullanmasını sağlamanın bir yolu var mı? ?
Soruna birkaç farklı (daha az zarif) yaklaşım denedikten sonra, varsayılan boyut sınıfını programla geçersiz kılmanın bir yolu olabileceğinden şüphelendim. Ve (UIViewController.h dosyasında):
// Call to modify the trait collection for child view controllers.
- (void)setOverrideTraitCollection:(UITraitCollection *)collection forChildViewController:(UIViewController *)childViewController NS_AVAILABLE_IOS(8_0);
- (UITraitCollection *)overrideTraitCollectionForChildViewController:(UIViewController *)childViewController NS_AVAILABLE_IOS(8_0);
Bu nedenle, görünüm denetleyici hiyerarşinizi bir 'alt' görünüm denetleyicisi olarak paketleyebilir ve bunu en üst düzey bir üst düzey denetleyiciye ekleyebilirseniz ... OS'den.
İşte bunu 'üst' görünüm denetleyicisinde yapan örnek bir uygulama:
@interface RDTraitCollectionOverrideViewController : UIViewController {
BOOL _willTransitionToPortrait;
UITraitCollection *_traitCollection_CompactRegular;
UITraitCollection *_traitCollection_AnyAny;
}
@end
@implementation RDTraitCollectionOverrideViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setUpReferenceSizeClasses];
}
- (void)setUpReferenceSizeClasses {
UITraitCollection *traitCollection_hCompact = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassCompact];
UITraitCollection *traitCollection_vRegular = [UITraitCollection traitCollectionWithVerticalSizeClass:UIUserInterfaceSizeClassRegular];
_traitCollection_CompactRegular = [UITraitCollection traitCollectionWithTraitsFromCollections:@[traitCollection_hCompact, traitCollection_vRegular]];
UITraitCollection *traitCollection_hAny = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassUnspecified];
UITraitCollection *traitCollection_vAny = [UITraitCollection traitCollectionWithVerticalSizeClass:UIUserInterfaceSizeClassUnspecified];
_traitCollection_AnyAny = [UITraitCollection traitCollectionWithTraitsFromCollections:@[traitCollection_hAny, traitCollection_vAny]];
}
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
_willTransitionToPortrait = self.view.frame.size.height > self.view.frame.size.width;
}
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]
_willTransitionToPortrait = size.height > size.width;
}
-(UITraitCollection *)overrideTraitCollectionForChildViewController:(UIViewController *)childViewController {
UITraitCollection *traitCollectionForOverride = _willTransitionToPortrait ? _traitCollection_CompactRegular : _traitCollection_AnyAny;
return traitCollectionForOverride;
}
@end
Çalışıp çalışmadığını görmek için hızlı bir demo olarak, IB'deki alt denetleyici düzeninin 'Normal / Normal' ve 'Kompakt / Normal' sürümlerine özel etiketler ekledim:
Ve işte iPad her iki yöndeyken çalışıyor gibi görünüyor:
Voila! Çalışma zamanında özel boyut sınıfı yapılandırmaları.
Umarım Apple bunu işletim sisteminin bir sonraki sürümünde gereksiz hale getirir. Bu arada, bu, otomatik mizanpaj kısıtlamalarıyla programatik olarak uğraşmaktan veya kodda başka manipülasyonlar yapmaktan daha zarif ve ölçeklenebilir bir yaklaşım olabilir.
~
DÜZENLEME (6/4/15): Yukarıdaki örnek kodun, tekniği göstermek için esasen bir kavram kanıtı olduğunu lütfen unutmayın. Kendi özel uygulamanız için gerektiği gibi uyarlamaktan çekinmeyin.
~
DÜZENLEME (7/24/15): Yukarıdaki açıklamanın konuyu aydınlatmaya yardımcı olması sevindirici. Test etmemiş olsam da, mohamede1945 tarafından hazırlanan kod [aşağıda], pratik amaçlar için yararlı bir optimizasyon gibi görünüyor. Denemekten çekinmeyin ve ne düşündüğünüzü bize bildirin. (Eksiksizlik adına yukarıdaki örnek kodu olduğu gibi bırakacağım.)