ดูเหมือนว่า Apple มีเจตนาที่จะปฏิบัติต่อการวางแนว iPad ทั้งสองแบบเหมือนกัน - แต่ในขณะที่พวกเราหลายคนพบว่ามีเหตุผลในการออกแบบที่ถูกต้องมากที่ต้องการเปลี่ยนเค้าโครง UI สำหรับ iPad Portrait กับ iPad Landscape
น่าเสียดายที่ระบบปฏิบัติการปัจจุบันไม่ได้ให้การสนับสนุนสำหรับความแตกต่างนี้ ... หมายความว่าเรากลับมาจัดการข้อ จำกัด การจัดวางอัตโนมัติในโค้ดหรือวิธีแก้ปัญหาที่คล้ายกันเพื่อให้บรรลุสิ่งที่เราควรจะได้รับฟรีโดยใช้ Adaptive UI .
ไม่ใช่วิธีการแก้ปัญหาที่สวยงาม
ไม่มีวิธีใดที่จะใช้ประโยชน์จากเวทมนตร์ที่ Apple สร้างไว้แล้วใน IB และ UIKit เพื่อใช้คลาสขนาดที่เราเลือกสำหรับการวางแนวที่กำหนด?
~
ในการคิดถึงปัญหาโดยทั่วไปมากขึ้นฉันตระหนักว่า 'คลาสขนาด' เป็นเพียงวิธีการจัดการเลย์เอาต์หลาย ๆ แบบที่เก็บไว้ใน IB เพื่อให้สามารถเรียกใช้งานได้ตามต้องการในรันไทม์
ในความเป็นจริง 'class size' เป็นเพียงค่า enum คู่หนึ่ง จาก UIInterface.h:
typedef NS_ENUM(NSInteger, UIUserInterfaceSizeClass) {
UIUserInterfaceSizeClassUnspecified = 0,
UIUserInterfaceSizeClassCompact = 1,
UIUserInterfaceSizeClassRegular = 2,
} NS_ENUM_AVAILABLE_IOS(8_0);
ดังนั้นไม่ว่า Apple จะตัดสินใจตั้งชื่อรูปแบบต่างๆเหล่านี้อย่างไรโดยพื้นฐานแล้วพวกมันเป็นเพียงคู่ของจำนวนเต็มที่ใช้เป็นตัวระบุประเภทเฉพาะเพื่อแยกความแตกต่างของเลย์เอาต์หนึ่งจากอีกรูปแบบหนึ่งที่เก็บไว้ใน IB
ตอนนี้สมมติว่าเราสร้างเลย์เอาต์อื่น (โดยใช้คลาสขนาดที่ไม่ได้ใช้) ใน IB - พูดว่าสำหรับ iPad Portrait ... มีวิธีให้อุปกรณ์ใช้คลาสขนาดที่เราเลือก (เค้าโครง UI) ตามความจำเป็นในรันไทม์หรือไม่ เหรอ?
หลังจากลองใช้วิธีต่างๆ (สวยงามน้อยกว่า) ในการแก้ปัญหาแล้วฉันสงสัยว่าอาจมีวิธีแทนที่คลาสขนาดเริ่มต้นโดยทางโปรแกรม และมี (ใน UIViewController.h):
- (void)setOverrideTraitCollection:(UITraitCollection *)collection forChildViewController:(UIViewController *)childViewController NS_AVAILABLE_IOS(8_0);
- (UITraitCollection *)overrideTraitCollectionForChildViewController:(UIViewController *)childViewController NS_AVAILABLE_IOS(8_0);
ดังนั้นหากคุณสามารถรวมลำดับชั้นของตัวควบคุมมุมมองของคุณเป็นตัวควบคุมมุมมอง 'ลูก' และเพิ่มลงในตัวควบคุมมุมมองผู้ปกครองระดับบนสุด ... คุณสามารถแทนที่เด็กตามเงื่อนไขโดยคิดว่าเป็นคลาสขนาดที่แตกต่างจากค่าเริ่มต้น จากระบบปฏิบัติการ
นี่คือตัวอย่างการใช้งานที่ทำสิ่งนี้ในตัวควบคุมมุมมอง "หลัก":
@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
ในการสาธิตอย่างรวดเร็วเพื่อดูว่ามันใช้งานได้หรือไม่ฉันได้เพิ่มป้ายกำกับที่กำหนดเองโดยเฉพาะให้กับเลย์เอาต์คอนโทรลเลอร์เด็กรุ่น 'Regular / Regular' และ 'Compact / Regular' ใน IB:
และนี่คือลักษณะการทำงานเมื่อ iPad อยู่ในทั้งสองทิศทาง:
โวลา! การกำหนดค่าคลาสขนาดที่กำหนดเองที่รันไทม์
หวังว่า Apple จะทำให้สิ่งนี้ไม่จำเป็นใน OS เวอร์ชันถัดไป ในระหว่างนี้วิธีนี้อาจเป็นวิธีการที่สวยงามและปรับขนาดได้มากกว่าการใช้โปรแกรมโดยยุ่งกับข้อ จำกัด การจัดวางอัตโนมัติหรือการปรับแต่งอื่น ๆ ในโค้ด
~
แก้ไข (6/4/58): โปรดจำไว้ว่าโค้ดตัวอย่างด้านบนเป็นหลักฐานยืนยันแนวคิดเพื่อแสดงเทคนิค ปรับเปลี่ยนได้ตามต้องการสำหรับแอปพลิเคชันเฉพาะของคุณเอง
~
แก้ไข (24/7/58): เป็นเรื่องน่ายินดีที่คำอธิบายข้างต้นดูเหมือนจะช่วยให้เข้าใจปัญหาได้ชัดเจนขึ้น แม้ว่าฉันจะยังไม่ได้ทดสอบโค้ดของ mohamede1945 [ด้านล่าง] ดูเหมือนการเพิ่มประสิทธิภาพที่เป็นประโยชน์สำหรับวัตถุประสงค์ในทางปฏิบัติ อย่าลังเลที่จะทดสอบและแจ้งให้เราทราบว่าคุณคิดอย่างไร (เพื่อความสมบูรณ์ฉันจะปล่อยโค้ดตัวอย่างไว้ด้านบนตามที่เป็นอยู่)