Поворот экрана iOS всегда был четким и расплывчатым понятием, кажется простым, но всегда будут проблемы в процессе стыковки, такие как мерцание экрана, отсутствие эффекта поворота, исчезновение строки состояния и ряд отвратительных багов. Проект, за который я отвечаю, относится к гибридному режиму разработки Reactnative&&ObjectC. Текущие потребности требуют, чтобы основное приложение по умолчанию отображалось вертикально, и в то же время предоставляли Reactnative ViewController, который поддерживает автоматические горизонтальные и вертикальные экраны. Вращение экрана iOS организовано и обобщено в надежде помочь разработчикам.
1. Три отвратительных перечисления анализа
1. Ориентация устройства (физический поворот) — UIDeviceOrientation
- Направление вращения задней панели аппаратного устройства (ipad, iPhone) с исходным положением «Дом».
//Portrait 表示纵向,Landscape 表示横向。
typedef NS_ENUM(NSInteger, UIDeviceOrientation) {
UIDeviceOrientationUnknown,
// Device oriented vertically, home button on the top
UIDeviceOrientationPortraitUpsideDown,
// Device oriented horizontally, home button on the right
UIDeviceOrientationLandscapeLeft,
// Device oriented horizontally, home button on the left
UIDeviceOrientationLandscapeRight,
// Device oriented flat, face up
UIDeviceOrientationFaceUp,
// Device oriented flat, face down
UIDeviceOrientationFaceDown
} __TVOS_PROHIBITED;
- Направление вращения устройства доступно только для чтения, но не для записи.
获取当前屏幕的方法:[UIDevice currentDevice].orientation
- Мониторинг вращения устройства
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onDeviceOrientationDidChange)
name:UIDeviceOrientationDidChangeNotification
object:nil];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
监听方法实现
- (BOOL)onDeviceOrientationDidChange{
//获取当前设备Device
UIDevice *device = [UIDevice currentDevice] ;
//识别当前设备的旋转方向
switch (device.orientation) {
case UIDeviceOrientationFaceUp:
NSLog(@"屏幕幕朝上平躺");
break;
case UIDeviceOrientationFaceDown:
NSLog(@"屏幕朝下平躺");
break;
case UIDeviceOrientationUnknown:
//系统当前无法识别设备朝向,可能是倾斜
NSLog(@"未知方向");
break;
case UIDeviceOrientationLandscapeLeft:
NSLog(@"屏幕向左橫置");
break;
case UIDeviceOrientationLandscapeRight:
NSLog(@"屏幕向右橫置");
break;
case UIDeviceOrientationPortrait:
NSLog(@"屏幕直立");
break;
case UIDeviceOrientationPortraitUpsideDown:
NSLog(@"屏幕直立,上下顛倒");
break;
default:
NSLog(@"无法识别");
break;
}
return YES;
}
2. Поворот страницы (поворот вида) — UIInterfaceOrientation
- Текущее направление вращения интерфейса программы UIInterfaceOrientation (можно задать)
// Note that UIInterfaceOrientationLandscapeLeft is equal to UIDeviceOrientationLandscapeRight (and vice versa).
// This is because rotating the device to the left requires rotating the content to the right.
typedef NS_ENUM(NSInteger, UIInterfaceOrientation) {
UIInterfaceOrientationUnknown = UIDeviceOrientationUnknown,
UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait,
UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,
UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft
} __TVOS_PROHIBITED;
- Ориентация интерфейса программы использует UIInterfaceOrientation, который не имеет ничего общего с направлением вращения устройства
为了达到页面的流畅效果
UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,
UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft
3. Агрегация поворота страницы (появилась после iOS6) — UIInterfaceOrientationMask
Поддерживает несколько направлений поворота страницы
typedef NS_OPTIONS(NSUInteger, UIInterfaceOrientationMask) {
UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),
UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),
UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),
UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),
UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown),
UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
} __TVOS_PROHIBITED;
2. Установка направления вращения одной страницы
- Реализация
//方法1
- (BOOL)shouldAutorotate NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
//方法2
- (UIInterfaceOrientationMask)supportedInterfaceOrientations NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
// Returns interface orientation masks.
//方法3
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;!
- Разбор метода
方法1:页面是否支持自动旋转
方法2:页面支持的旋转方向有哪些
方法3:页面优先展示的旋转方向
3. Два триггерных режима поворота экрана
1. В системе не отключается функция автоматического поворота экрана
//1.决定当前界面是否开启自动转屏,如果返回NO,后面两个方法也不会被调用,只是会支持默认的方向
- (BOOL)shouldAutorotate {
return YES;
}
//2.返回支持的旋转方向
//iPad设备上,默认返回值UIInterfaceOrientationMaskAllButUpSideDwon
//iPad设备上,默认返回值是UIInterfaceOrientationMaskAll
- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskAll;
}
//3.返回进入界面默认显示方向
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
2. Система отключает функцию автоматического поворота экрана
Переключитесь на альбомный экран, нажав на интерфейс программы
// 方法1:
- (void)setInterfaceOrientation:(UIDeviceOrientation)orientation {
if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
[[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:orientation]
forKey:@"orientation"];
}
}
//方法2:
- (void)setInterfaceOrientation:(UIInterfaceOrientation)orientation {
if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
SEL selector = NSSelectorFromString(@"setOrientation:");
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice
instanceMethodSignatureForSelector:selector]];
[invocation setSelector:selector];
[invocation setTarget:[UIDevice currentDevice]];
int val = orientation;
[invocation setArgument:&val atIndex:2];
[invocation invoke];
}
}
- Убедитесь, что метод shouldAutorotate возвращает YES
- Типы параметров, используемые обоими, не
В-четвертых, приоритет управления поворотом экрана
1. Способ настройки поворота экрана
- Xcode的General设置
- Xcode的nfo.plist设置
- 代码设置Appdelegete中
2. Приоритет вращения
工程Target属性配置(全局权限) > Appdelegate&&Window > 根视图控制器> 普通视图控制器
3. Включите глобальное разрешение для ротации приложений.
- Настройка свойства ориентации устройства
【General】—>【Deployment Info】—>【Device Orientation】
值得注意的是,对于iPhone,如果四个属性我们都选或者都不选,效果和默认的情况一样
- Настройки Info.Plist
Supported interface orientation
与第一种方式一样的效果,两种方式最终都是设置info.plist中的属性
- Appdelegate&&Настройки окна
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft;
}
Если мы реализуем этот метод Appdelegate, то глобальные настройки вращения нашего приложения будут основаны на этом, даже если настройки первых двух методов отличаются от здесь.
5. Установите разрешение на вращение одной страницы
Контроллеры часто участвуют в разработке
UITabbarViewController,UINavigationBarController ,UIViewController
Все наши проекты используют UITabbarViewController в качестве корневого контроллера представления Window, а затем управляют несколькими навигационными контроллерами UINavigationBarController, а затем контроллер панели навигации управляет обычным контроллером представления UIViewController. Если это пример, приоритет вращения от высокого к низкомуUITabbarViewController>UINavigationBarController >UIViewController. еслиКонтроллер с высоким приоритетомКогда настройка вращения отключена, низкоприоритетный контроллер не может вращаться.
Например, мы настроили один контроллер представления для автоматического поворота, которым нужно управлять, добавив метод shouldAutorotate к контроллеру представления, чтобы возвращать YES или NO. Но если есть верхний корневой вью-контроллер, и мы реализуем метод только в этом вью-контроллере, мы обнаружим, что этот метод не проходит, потому что этот метод перехватывается верхним корневым вью-контроллером
6. Реализуйте автоматическое и контролируемое вращение
1. Осознавайте шаг за шагом
- 1. UITabbarViewController
//是否自动旋转
-(BOOL)shouldAutorotate{
return self.selectedViewController.shouldAutorotate;
}
//支持哪些屏幕方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return [self.selectedViewController supportedInterfaceOrientations];
}
//默认方向
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return [self.selectedViewController preferredInterfaceOrientationForPresentation];
}
- 2. UINavigationController
//是否自动旋转
//返回导航控制器的顶层视图控制器的自动旋转属性,因为导航控制器是以栈的原因叠加VC的
//topViewController是其最顶层的视图控制器,
-(BOOL)shouldAutorotate{
return self.topViewController.shouldAutorotate;
}
//支持哪些屏幕方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return [self.topViewController supportedInterfaceOrientations];
}
//默认方向
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return [self.topViewController preferredInterfaceOrientationForPresentation];
}
На самом деле высокоприоритетный контроллер представления должен следовать конфигурации вращения низкоприоритетного контроллера. Это позволит достичь цели
2. Используйте модальный вид
使用模态视图可以不受这种根视图控制器优先级的限制。这个也很容易理解,模态弹出的视图控制器是隔离出来的,不受根视图控制的影响。具体的设置和普通视图器代码相同
7. Выполнение требований
Основной основной интерфейс приложения отображается вертикально, а некоторые страницы отображаются горизонтально.
два решения
1. Пошаговое управление
- Шаговый путь
1.开启全局权限设置项目支持的旋转方向
2.自定义标签控制器和导航控制器来设置屏幕的自动旋转。
3.自定义基类控制器设置不支持自动转屏,并默认只支持竖屏
4.对项目中需要转屏幕的控制器开启自动转屏、设置支持的旋转方向并设置默认方向
2. Отслеживайте глобальное изменение текущего направления
- ступенчатый метод
1.在Applegate文件中增加一个用于记录当前屏幕是否横屏的属性
2.需要横屏的界面,进入界面后强制横屏,离开界面时恢复竖屏
- основной код
1、添加监听
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onDeviceOrientationDidChange) name:UIDeviceOrientationDidChangeNotification
object:nil];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
2、实现监听
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if (_allowAutoRotate) {
//只支持横屏
return UIInterfaceOrientationMaskLandscape;
}else{
//支持竖屏
return UIInterfaceOrientationMaskPortrait;
}
}
3、页面控制
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
AppDelegate* delegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
delegate.allowAutoRotate = YES;
//进入界面:设置横屏
[self setDeviceInterfaceOrientation:UIDeviceOrientationLandscapeLeft];
}
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
AppDelegate* delegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
delegate.allowAutoRotate = NO;
//离开界面:设置竖屏
[self setDeviceInterfaceOrientation:UIDeviceOrientationPortrait];
}
Восемь, оптимизируйте отображение
Ненормальная проблема с переключением дисплея
Текущий viewController достигает ожидаемого эффекта, но при возврате на предыдущую страницу или при входе предыдущей страницы в ориентации, не поддерживаемой текущей страницей, он не может сразу достичь ожидаемого состояния, и ориентацию устройства необходимо изменить один раз вернуться к нормальной жизни
#pragma mark -UITabBarControllerDelegate
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
[self presentViewController:[UIViewController new] animated:NO completion:^{
[self dismissViewControllerAnimated:NO completion:nil];
}];
}
#pragma mark -UINavigationControllerDelegate
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
[self presentViewController:[UIViewController new] animated:NO completion:^{
[self dismissViewControllerAnimated:NO completion:nil];
}];
}
Тем не менее, будет проблема с мерцанием экрана.Это решение не рекомендуется.Вы можете вручную управлять функцией ловушки представления, принудительно установив ориентацию экрана.
После поворота экрана строка состояния не может отображаться
- Установить вид строки состояния View на основе контроллера YES в info.plist
- Соответствующий элемент управления реализует следующий код
//设置样式
- (UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleLightContent;
}
//设置是否隐藏
- (BOOL)prefersStatusBarHidden {
// [super prefersStatusBarHidden];
return NO;
}
//设置隐藏动画
- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation {
return UIStatusBarAnimationNone;
}
Ссылка на исходный текст: tech.meicai.cn/detail/83, вы также можете найти апплет «Техническая команда Meicai по продуктам» на WeChat. Он полон галантереи и обновляется каждую неделю. Если вы хотите изучать технологии, не не пропустите.