首先系統(tǒng)設(shè)置只能豎屏
1谆级、UITabBarController 繼承類實(shí)現(xiàn)
//是否自動(dòng)旋轉(zhuǎn)
-(BOOL)shouldAutorotate{
? ? return self.selectedViewController.shouldAutorotate;
}
//支持哪些屏幕方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
? ? return [self.selectedViewController supportedInterfaceOrientations];
}
// persent出頁(yè)面時(shí)的默認(rèn)方向,
// 網(wǎng)上很多文章認(rèn)為是進(jìn)入頁(yè)面時(shí)的默認(rèn)方向, 這個(gè)是不對(duì)的, 這個(gè)方法只針對(duì)present出來(lái)的vc, 注意看方法名后面? ForPresentation
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
? ? return [self.selectedViewController preferredInterfaceOrientationForPresentation];
}
2、UINavigationController 繼承類實(shí)現(xiàn)
/是否自動(dòng)旋轉(zhuǎn)
-(BOOL)shouldAutorotate{
? ? return self.topViewController.shouldAutorotate;
}
//支持哪些屏幕方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
? ? return [self.topViewController supportedInterfaceOrientations];
}
// persent出頁(yè)面時(shí)的默認(rèn)方向,
// 網(wǎng)上很多文章認(rèn)為是進(jìn)入頁(yè)面時(shí)的默認(rèn)方向, 這個(gè)是不對(duì)的, 這個(gè)方法只針對(duì)present出來(lái)的vc, 注意看方法名后面? ForPresentation
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
? ? return [self.topViewController preferredInterfaceOrientationForPresentation];
}
3橄登、AppDelegate.m實(shí)現(xiàn)
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
?? ??//避免導(dǎo)航欄導(dǎo)致bug
? ? [[UIApplication sharedApplication] setStatusBarHidden:NO];
//_allowRotate 自己定義的屬性舰攒,隨便可以定義bool值败富,目的就是在某個(gè)viewController讓window先支持屏幕旋轉(zhuǎn)
? ? if (_allowRotate == 1) {
? ? ? ? ? ? return UIInterfaceOrientationMaskAll;
? ? ? ? }else{
? ? ? ? ? ? return (UIInterfaceOrientationMaskPortrait);
? ? ? ? }
}
4、viewController 頁(yè)面
//1.決定當(dāng)前界面是否開啟自動(dòng)轉(zhuǎn)屏摩窃,如果返回NO兽叮,后面兩個(gè)方法也不會(huì)被調(diào)用,只是會(huì)支持默認(rèn)的方向
- (BOOL)shouldAutorotate {
? ? ? return YES;
}
//2.返回支持的旋轉(zhuǎn)方向
//iPad設(shè)備上猾愿,默認(rèn)返回值UIInterfaceOrientationMaskAllButUpSideDwon
//iPad設(shè)備上鹦聪,默認(rèn)返回值是UIInterfaceOrientationMaskAll
- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
???return UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortrait;
}
// persent出頁(yè)面時(shí)的默認(rèn)方向,
// 網(wǎng)上很多文章認(rèn)為是進(jìn)入頁(yè)面時(shí)的默認(rèn)方向, 這個(gè)是不對(duì)的, 這個(gè)方法只針對(duì)present出來(lái)的vc, 注意看方法名后面? ForPresentation
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
? ? return UIInterfaceOrientationPortraitUpsideDown;
}
-(void)viewWillAppear:(BOOL)animated
{
? ? [super viewWillAppear:animated];
? ? [self.navigationController setNavigationBarHidden:YES animated:animated];
? ? //在視圖出現(xiàn)的時(shí)候,將allowRotate改為1
?? ? AppDelegate * delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
?? ? delegate.allowRotate = 1;
}
到此為止蒂秘,屏幕就可以根據(jù)你設(shè)置支持的方向進(jìn)行旋轉(zhuǎn)了
//當(dāng)發(fā)生轉(zhuǎn)屏事件時(shí)泽本,系統(tǒng)的回調(diào)方法是:
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
? ? [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
? ? // 即將開始轉(zhuǎn)屏
? ? [self viewWillBeginTransitionWithSize:size];
? ? WS(weakSelf)
? ? [coordinator animateAlongsideTransition:nil completion:^(id<UIViewControllerTransitionCoordinatorContext>? _Nonnull context) {
? ? ? ? [weakSelf viewDidEndTransitionWithSize:size];
? ? }];
}
/// 子視圖即將開始旋轉(zhuǎn)
- (void)viewWillBeginTransitionWithSize:(CGSize)size {
? ? if (size.width > size.height) { // 橫屏
? ? ? ? // 橫屏布局 balabala
? ?[self.view.layer setNeedsLayout];
? ? [self.view.layer layoutIfNeeded];
? ? } else {
? ? ? ? // 豎屏布局 balabala
? ?[self.view.layer setNeedsLayout];
? ? [self.view.layer layoutIfNeeded];
? ? }
}
/// 子視圖旋轉(zhuǎn)完成
- (void)viewDidEndTransitionWithSize:(CGSize)size {
? ? if (size.width > size.height) { // 橫屏
? ? ? ? // 橫屏布局 balabala
? ? ?[self.view.layer setNeedsLayout];
? ? ?[self.view.layer layoutIfNeeded];
? ? } else {
? ? ? ? // 豎屏布局 balabala
? [self.view.layer setNeedsLayout];
? ? [self.view.layer layoutIfNeeded];
? ? }
}
//最好刷新下view
? [self.view.layer setNeedsLayout];
? ?[self.view.layer layoutIfNeeded];
我項(xiàng)目里用的是監(jiān)聽的方法,監(jiān)聽屏幕發(fā)聲變化的時(shí)候
//在viewDidLoad 監(jiān)聽屏幕變化姻僧,但是這個(gè)方法不能判斷屏幕到底向左還是向右规丽,如果支持多個(gè)方向的話蒲牧,遇到劉海屏還得適配,不然劉海屏有可能遮住UI赌莺,還有一個(gè)方法監(jiān)聽屏幕方向的
?//屏幕方向通知
? ? [[NSNotificationCenter defaultCenter] addObserver:self
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? selector:@selector(onDeviceOrientationDidChange) name:UIDeviceOrientationDidChangeNotification
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? object:nil];
//屏幕尺寸變化的時(shí)候
? ? [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(videoListdetectOrientation) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
#pragma mark - Notification:
- (void)videoListdetectOrientation{
? ??[self.view.layer setNeedsLayout];
? ? [self.view.layer layoutIfNeeded];
? ?if(self.view.frame.size.width > self.view.frame.size.height){
? ? ? //橫屏
? }else{
? }
}
#pragma mark - 屏幕方向通知
- (BOOL)onDeviceOrientationDidChange{
? ? //獲取當(dāng)前設(shè)備Device
? ? UIDevice *device = [UIDevice currentDevice];
? ? //識(shí)別當(dāng)前設(shè)備的旋轉(zhuǎn)方向
? ? switch (device.orientation) {
? ? ? ? case UIDeviceOrientationFaceUp:
? ? ? ? ? ? DLog(@"屏幕幕朝上平躺");
? ? ? ? ? ?
? ? ? ? ? ? break;
?? ? ? ? ? ?
? ? ? ? case UIDeviceOrientationFaceDown:
? ? ? ? ? ? DLog(@"屏幕朝下平躺");
?? ? ? ? ?
? ? ? ? ? ? break;
? ? ? ? case UIDeviceOrientationUnknown:
? ? ? ? ? ? //系統(tǒng)當(dāng)前無(wú)法識(shí)別設(shè)備朝向冰抢,可能是傾斜
? ? ? ? ? ? DLog(@"未知方向");
?? ? ? ? ?
? ? ? ? ? ? break;
?? ? ? ? ? ?
? ? ? ? case UIDeviceOrientationLandscapeLeft:{
?? ? ? ? ? ?
? ? ? ? ? ? DLog(@"屏幕向左橫置"); //只支持的方向
? ? ? ? ? ??break;
? ? ? ? }
? ? ? ? case UIDeviceOrientationLandscapeRight:
? ? ? ? ? ? DLog(@"屏幕向右橫置");
? ? ? ? ? ? break;
?? ? ? ? ? ?
? ? ? ? case UIDeviceOrientationPortrait:{
? ? ? ? ? ? DLog(@"屏幕直立");? ? ? ? ? ??
? ? ? ? ? ? break;
? ? ? ? }
? ? ? ? case UIDeviceOrientationPortraitUpsideDown:
? ? ? ? ? ? DLog(@"屏幕直立,上下顛倒");
? ? ? ? ? ? break;
?? ? ? ? ? ?
? ? ? ? default:
? ? ? ? ? ? DLog(@"無(wú)法識(shí)別");
? ? ? ? ? ??break;
? ? }
? ? return YES;
}
//屏幕適配問(wèn)題艘狭,橫屏的時(shí)候獲取不到狀態(tài)欄高度挎扰,如果豎屏的時(shí)候self.view.layer layoutIfNeeded 不刷新view也獲取不到狀態(tài)欄高度,所以最好是豎屏的時(shí)候先用個(gè)屬性賦值下缓升,用Masonry 和 frame 都沒(méi)切換 的時(shí)候都沒(méi)問(wèn)題鼓鲁,橫屏的時(shí)候在調(diào)橫屏子view的約束,一開始可以在-(instancetype)initWithFrame:(CGRect)frame
{
? ? if (self = [super initWithFrame:frame]) {
?? ?
? ? ? ? [self initsubviews];
? ? }
? ? return self;
}
只初始化添加港谊,而不加約束
5骇吭、重點(diǎn),豎屏的時(shí)候點(diǎn)擊按鈕push跳轉(zhuǎn)沒(méi)問(wèn)題歧寺,橫屏的時(shí)候push跳轉(zhuǎn)過(guò)去之后燥狰,下個(gè)頁(yè)面布局錯(cuò)亂
解決辦法,一定要在跳轉(zhuǎn)之前先把橫屏變成豎屏在跳轉(zhuǎn)斜筐。
注意點(diǎn):如果只是寫在-(void)viewWillDisappear:(BOOL)animated 方法里是不管用的龙致,因?yàn)樗麜?huì)先執(zhí)行下個(gè)頁(yè)面的viewDidLoad 在執(zhí)行旋轉(zhuǎn),這個(gè)時(shí)候下個(gè)頁(yè)面的view的寬高是橫屏狀態(tài)顷链,導(dǎo)致頁(yè)面錯(cuò)亂目代,顯示的是豎屏的樣式,實(shí)際寬高是橫屏
- (void)orientationPortrait{
?? ? ? AppDelegate * delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
?? ? ? delegate.allowRotate = 0;
? ?
? ? if (@available(iOS 16.0, *)) {
? ? ? ? // iOS 16新增加了一個(gè)方法setNeedsUpdateOfSupportedInterfaceOrientations 方法是 UIViewController 的方法嗤练。這和更新狀態(tài)欄的方法有點(diǎn)像榛了,簡(jiǎn)單點(diǎn)說(shuō)就是你想轉(zhuǎn)屏可以,需要通知UIViewController 你已經(jīng)準(zhǔn)備好要轉(zhuǎn)屏的方向了煞抬,然后再調(diào)用轉(zhuǎn)屏方法即可(轉(zhuǎn)屏方法后面會(huì)講到)
? ? ? ? [self setNeedsUpdateOfSupportedInterfaceOrientations];
? ? ? ? NSArray *array = [[[UIApplication sharedApplication] connectedScenes] allObjects];
? ? ? ? UIWindowScene *scene = [array firstObject];
? ? ? ? // 屏幕方向
? ? ? ? UIInterfaceOrientationMaskorientation =? UIInterfaceOrientationMaskPortrait;
? ? ? ? UIWindowSceneGeometryPreferencesIOS *geometryPreferencesIOS = [[UIWindowSceneGeometryPreferencesIOS alloc] initWithInterfaceOrientations:orientation];
? ? ? ? // 開始切換
? ? ? ? [scenerequestGeometryUpdateWithPreferences:geometryPreferencesIOS errorHandler:^(NSError * _Nonnull error) {
? ? ? ? ? ?
? ? ? ? }];
? ? }else{
?? ? ? ?
? ? ? ? //這個(gè)方法只有在- (BOOL)shouldAutorotate( return YES; )時(shí)霜大,才會(huì)生效。并且請(qǐng)注意使用的枚舉值的不同革答。
?? ? ? ? if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
? ? ? ? ? ? ? ? SEL selector = NSSelectorFromString(@"setOrientation:");
? ? ? ? ? ? ? ? NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];
? ? ? ? ? ? ? ? [invocationsetSelector:selector];
? ? ? ? ? ? ? ? [invocationsetTarget:[UIDevice currentDevice]];
? ? ? ? ? ? ? ? int val = UIInterfaceOrientationPortrait;
? ? ? ? ? ? ? ? [invocationsetArgument:&val atIndex:2];
? ? ? ? ? ? ? ? [invocationinvoke];
? ? ? ? ? ? }
?? ? ? ?
?? ? ? ? ? //會(huì)強(qiáng)制系統(tǒng)嘗試將界面旋轉(zhuǎn)到新的方向(必須加战坤,不然橫屏的時(shí)候跳到下個(gè)頁(yè)面,下個(gè)頁(yè)面會(huì)錯(cuò)亂)
?? ? ? ? ? [UIViewController attemptRotationToDeviceOrientation];
?? ? ? ?
? ? }