屏幕方向该知道的那些事儿

前言

这两天在学关于屏幕旋转的相关的知识,也延伸出了加速器和陀螺仪这些以前没有深入去学习过的知识点,在没有仔细看之前也有一些问题在想,比如;用户关闭了手机的屏幕旋转,但根据我们的使用经验,APP的界面还是可以旋转的,比如那些视屏播放类型的APP,还是可以全屏观看视频的,那这些是怎么做的?还有比如 你整个项目不允许横屏展示的,而某一个控制器却单独要求横屏展示,这个又该怎么做?用户关闭了手机屏幕旋转,我们还能不能判断手机屏幕的方向?带着这些问题我们一个一个的说一下屏幕方向的那些事儿。

从简单的开始

先说用户允许手机屏幕旋转的情况(明确一点,你APP允许旋转了,用户不允许屏幕旋转那你下面简单的勾选是没用的,至于怎么转,后面说!)

要是你的整个项目允许横竖屏,怎么设置,我想这个大家因该都清楚,下图勾选就是了。

接下来,要是用户改变了手机屏幕的方向,你需要做相应的一些操作,那你就得知道用户是横屏还是竖屏,这时候就有这个通知 UIDeviceOrientationDidChangeNotification 可以的上场了,每当用户改变了手机屏幕的方向之后,我们都可以通过这个通知去判断手机屏幕的方向:(前提是用户开启了手机屏幕旋转功能)要是没开启,这个通知我测试过你第一次打开APP的时候,这个通知是可以收到的,但因为你锁定屏幕之前,系统会强制竖屏的,不允许横屏关闭屏幕旋转!你第一次收到的通知也就变得没意义了,因为都关闭了旋转,都不会转了!怎么收到后序的通知!

[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(orientchang:) name:UIDeviceOrientationDidChangeNotification object:nil]; 

上面接受到通知,下面就可以做相应的判断:

-(void)orientchang:(NSNotification *)odentifile
{
    //获取 当前设备 实例
    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;
    }
}

说说上面的注意和延伸的点:

第一点:

UIDeviceOrientationDidChangeNotification 通知,点进去看的话,看到和它在一起的有下面几个通知,顺便也就在这里解释一下这几个通知给大家;

UIDeviceBatteryStateDidChangeNotification 电池状态改变到通知(像低于20%的低电量模式等)

UIDeviceBatteryLevelDidChangeNotification  电池的电量改变通知

UIDeviceProximityStateDidChangeNotification 这个是近距离传感器通知,就像打电话的时候,你把手机贴近脸的时候,屏幕会关闭,你把手机拿开之后会变亮,就是用的这个,后面还会给链接关于这块的知识!

其实像 UIApplicationDidChangeStatusBarFrameNotification 这个状态栏的改变通知也可以判断手机屏幕的方向!其实重点不是得用哪一个,都是在屏幕改变之后收到的通知,你收到通知之后知道屏幕方向变了立马再去判断获取手机屏幕的方向,这才是重点,也是核心吧!

UIKIT_EXTERN NSString *const UIDeviceOrientationDidChangeNotification __TVOS_PROHIBITED;
UIKIT_EXTERN NSString *const UIDeviceBatteryStateDidChangeNotification   NS_AVAILABLE_IOS(3_0) __TVOS_PROHIBITED;
UIKIT_EXTERN NSString *const UIDeviceBatteryLevelDidChangeNotification   NS_AVAILABLE_IOS(3_0) __TVOS_PROHIBITED;
UIKIT_EXTERN NSString *const UIDeviceProximityStateDidChangeNotification NS_AVAILABLE_IOS(3_0);

第二点:

UIDevice *device = [UIDevice currentDevice]  这个还是有必要延伸一下里面的内容的,我们把它常用的属性也通过代码展示出来;

NSString *ZXName = [[UIDevice currentDevice] name];
NSLog(@"设备名称:%@", ZXName);

NSString *ZXsysName = [[UIDevice currentDevice] systemName];
NSLog(@"系统名称:%@", ZXsysName);// 手机就是iPhone OS 

NSString *ZXSysVersion = [[UIDevice currentDevice] systemVersion];
NSLog(@"系统版本号:%@", ZXSysVersion);// 目前是9.3.4

NSString *ZXModel = [[UIDevice currentDevice] model];
NSLog(@"设备类型:%@", ZXModel);// iPhone

NSString *ZXlocalizedModel = [[UIDevice currentDevice] localizedModel];
NSLog(@"本地设备模式:%@", ZXlocalizedModel);// iPhone

 /**
  * UUIDString  可用于唯一地标识该设备
  */
NSUUID *identifierForVendor = [[UIDevice currentDevice] identifierForVendor];
NSLog(@"strIdentifierForVendor:%@", identifierForVendor.UUIDString);

关于这个 UUIDString 再多说两句,也上网搜了一下这个东西,答案是这样的:

NSString *identifierForVendor = [[UIDevice currentDevice].identifierForVendor UUIDString];

NSString *identifierForAdvertising = [[ASIdentifierManager sharedManager].advertisingIdentifier UUIDString];

解释说明:

identifierForVendor对供应商来说是唯一的一个值,也就是说,由同一个公司发行的的app在相同的设备上运行的时候都会有这个相同的标识符。然而,如果用户删除了这个供应商的app然后再重新安装的话,这个标识符就会不一致。

advertisingIdentifier会给这个设备上所有软件的供应商返回给相同的一个值,所以只能在广告的时候使用。这个值会因为很多情况而有所变化,比如说用户初始化设备的时候便会改变。

用户关闭了手机屏幕旋转怎么办?

这个我们也就从简单点的说起吧,说个简单的需求,用户把手机屏幕旋转关闭了,我们还有一个播放器界面还是需要横屏显示,我们该怎么办?先说简单的,我们有一个全屏的点击按钮,点击了按钮之后界面横屏。看代码解释,按钮的和点击事件就不写了,直接到重点:

// UIInterfaceOrientationLandscapeLeft 向左横置,具体向右或者向左的值自己取出来。
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];

点击按钮,这个界面就变成了相应横屏的模式!其实这里也会相应的启发到你,那整个APP不允许旋转,唯独这一个界面要能横屏该怎么做?就简单了。这个任务就交给你实践了,要觉得不行,你再给留言或者加我QQ联系我!

CoreMotion.frameWork 主角该登场了!

这个框架就是处理加速器和陀螺仪的东西!先添加到自己的项目里面,导入系统头文件

#import <CoreMotion/CoreMotion.h>

iOS 开发----CMDeviceMotion陀螺仪的使用    iOS学习笔记34 - 加速计和陀螺仪

先把我的学习链接给大家,感谢作者!

至于陀螺仪和加速器是什么,这个我就不再描述了。原理大家可以看上面给的学习链接!说说怎么用它们判断手机屏幕的方向!看代码解释:

- (void)zxMotionManager{
    if (_motionManager == nil) {
        _motionManager = [[CMMotionManager alloc] init];
    }
    if ([_motionManager isGyroAvailable]) {
        // deviceMotion 加速器和陀螺仪的复合型数据
        _motionManager.deviceMotionUpdateInterval = 0.01f;
        [self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMDeviceMotion * _Nullable motion, NSError * _Nullable error) {
         [self performSelectorOnMainThread:@selector(handleDeviceMotion:) withObject:motion waitUntilDone:YES];
       }];
      }
     else
     {
           NSLog(@"陀螺仪/加速器不可用");
           [self setMotionManager:nil];
     }
}

- (void)handleDeviceMotion:(CMDeviceMotion *)deviceMotion{
    double x = deviceMotion.gravity.x;
    double y = deviceMotion.gravity.y;
    if (fabs(y) >= fabs(x))
    {
        if (y >= 0){
            NSLog(@"屏幕直立,上下顛倒");
        }
        else{
             NSLog(@"屏幕直立");
        }
    }
    else
    {
        if (x >= 0){
            NSLog(@"屏幕向右橫置");
        }
        else{              NSLog(@"屏幕向左横置");
        }
    }
}

你在你需要的地方去调用 zxMotionManager 方法就能够判断出手机屏幕的方向,就算是用户关闭了手机旋转按钮!!

扩展一下:

下面的内容只是自己觉得好玩,区别看待!

在上面的学习链接里面,有这样的一个效果,图片看似随着你手机屏幕的转动而转动,但仔细看看好像方向是没变的!效果如下图

            

先把加速器和陀螺仪的代码给出来,但其实只是它们任何一个单独做的话效果不会很好,会感觉一闪一闪的!

- (void)creatMotionManager{

    if (_motionManager == nil) {

        _motionManager = [[CMMotionManager alloc] init];
    }

    if ([_motionManager isGyroAvailable]) {

        __weak typeof (self) weakSelf = self;
//      CMAccelerometerData 加速器效果
//      _motionManager.accelerometerUpdateInterval = 0.01f;
//      [self.motionManager  startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMAccelerometerData * _Nullable accelerometerData, NSError * _Nullable error) {
//
//      double rotation = atan2(accelerometerData.acceleration.x,accelerometerData.acceleration.y) - M_PI;
//      weakSelf.imageview.transform = CGAffineTransformMakeRotation(rotation);
//      }];

        // 陀螺仪的效果
        _motionManager.gyroUpdateInterval = 0.01f;
        [self.motionManager startGyroUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMGyroData *gyroData, NSError *error) {
                  double rotation = atan2(gyroData.rotationRate.x, gyroData.rotationRate.y) - M_PI;
        weakSelf.imageview.transform = CGAffineTransformMakeRotation(rotation);

        }];
    }
}

最后经过验证,还是它们俩复合型的数据效果比较棒!

- (void)creatMotionManager{
       // deviceMotion 加速器和陀螺仪的复合型数据
        _motionManager.deviceMotionUpdateInterval = 0.01f;

        [self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMDeviceMotion * _Nullable motion, NSError * _Nullable error) {

        double rotation = atan2(motion.gravity.x,motion.gravity.y) - M_PI;
        weakSelf.imageview.transform = CGAffineTransformMakeRotation(rotation);

        }];
}

有兴趣的可以自己试一下,要看到上面有什么问题了,加我Q或者留言给我! !

时间: 2024-10-29 19:11:07

屏幕方向该知道的那些事儿的相关文章

WP8.1:关于屏幕尺寸和分辨率的那些事儿

目前市面上的Windows Phone设备越来越多,尺寸和分辨率也越来越多,特别是WP8.1时代的到来.做过wp开发的人都知道应用适配其实较安卓要简单太多了,其中有一个重要原因,就是微软号称所有WP设备都将以2个基准分辨率来发展,即800 : 480和853 : 480.WP8+的应用适配相对来说比较简单,主要让屏幕布局适配这两种比例足矣,想必对WVGA.WXGA和720p三种分辨率及对应的模拟器都有一定了解. 撸主最近深陷Universal Apps的大坑,虽说API变化很大,却提供了更多有价

Windows Phone开发(6):处理屏幕方向的改变

俺们都知道,智能手机可以通过旋转手机来改变屏幕的显示方向,更多的时候,对于屏幕方向的改变,我们要做出相应的处理,例如,当手机屏幕方向从纵向变为横向时,可能要重新排列页面上的控件以适应显示区域的变化. 前面我们讨论过,Silverlight for Windows Phone的页面布局有三个常用的布局控件,那么,当屏幕方向改变后,我们所做的对布局的更改基础上是基于这几个容器进行的操作. 本文我将通过三个示例来分别说明. 开始之前,先说一下PhoneApplicationPage类的Orientat

Android自适应屏幕方向、大小和分辨率,及字体设置

屏幕大小 1.不同的layout Android手机屏幕大小不一,有480x320,640x360,800x480.怎样才能让App自动适应不同的屏幕呢? 其实很简单,只需要在 res目录下创建不同的layout文件夹,比如:layout-640x360,layout-800x480,所有的layout文件在编译之后都会 写入R.java里,而系统会根据屏幕的大小自己选择合适的layout进行使用. 2.hdpi.mdpi.ldpi 之前的版本中,只有一个drawable,而2.1版本中有dra

iOS_关于手机支持的屏幕方向

设置支持的屏幕方向有两个级别,一个是app级别的,另一个是viewController级别的. app 级别的可以在[target]-[general]-[device orientation]里面设置,如下图: 默认情况下Upside Down没有勾选,其他都勾选了. (为什么Upside Down不推荐勾选呢,因为iPhone的电话app是不支持Upside Down的,如果你的app支持Upside Down,万一用户在用你的app的时候Upside Down了,这时候来了电话,就会看到整

Android中Activity运行时屏幕方向与显示方式详解

现在我们的手机一般都内置有方向感应器,手机屏幕会根据所处位置自动进行横竖屏切换(前提是未锁定屏幕方向).但有时我们的应用程序仅限在横屏或者竖屏状态下才可以运行,此时我们需要锁定该程序Activity运行时的屏幕方向.还有就是在我们用手机观看视频时,随意的进行横竖屏切换,但播放进度不会随着屏幕的转换而从头开始播放,为了实现这个功能,我们就需要在Activity转换时对当前数据进行保存. 现在根据以上两种需求,个人提出以下解决方案: 一.锁定Activity运行时屏幕方向,如下图(演示锁定横屏):

【Xamarin挖墙脚系列:IOS-关于手机支持的屏幕方向】

设置支持的屏幕方向有两个级别,一个是app级别的,另一个是viewController级别的. app 级别的可以在[target]-[general]-[device orientation]里面设置, 默认情况下Upside Down没有勾选,其他都勾选了. (为什么Upside Down不推荐勾选呢,因为iPhone的电话app是不支持Upside Down的,如果你的app支持Upside Down,万一用户在用你的app的时候Upside Down了,这时候来了电话,就会看到整个来电的

ios开发过程中屏幕方向判断的问题

判断屏幕的方法有很多着及仅提供几个我个人认为好用的方案 Landscape 竖屏 Portrait 横屏 最有效的方法是: 在willRotateToInterfaceOrientation:duration: 方法中将方向存储起来: DrviceOrientation = toInterfaceOrientation; 然后在别的方法中使用相应的屏幕的方向 方法一: 直接获取设备的方法:self.interfaceOrientation(此方法已经过期) 方法二: 通过下面的方法: UIDev

详解Android中的屏幕方向

详解Android中的屏幕方向 屏幕方向 是对Activity而言的,所以你可以在AndroidManifest.xml 文件中,通过<activity> 标记的screenOrientation 属性进行设定,例如: <activity android:name=".SketchpadActivity" android:screenOrientation="landscape"/><!--让该Activity总是显示为横屏-->

屏幕方向 横竖屏切换

屏幕方向的控制 屏幕方向是对Activity而言的,你可以在AndroidManifest.xml 文件中,通过activity的android:screenOrientation属性进行设定.在此配置的值会反映在Activity的getRequestedOrientation()方法的返回值中,与之对应的setRequestedOrientation()方法可以动态改变该属性的值. 另外, 还可以通过Configuration对象来取得Activity当前的显示方向 取值: unspecifi