iOS手动控制界面旋转

条条大道通罗马,解决同一个问题的手段也是多种多样的。对于《iOS 6及以上控制个别视图旋转案例》中提到的案例,我们是利用系统自带的旋转机制来解决问题的。同样地,我们也可以自己coding解决问题,且最终效果同系统的旋转动画效果是一模一样的。废话不多说,下面来大概讲解一下。

手动控制界面旋转的核心思路就是利用UIView的transform属性,旋转App的根视图。何为根视图?如果你的App的window.rootViewController是UINavigationController,那么根视图就是navigationController.view。为了旋转的效果和系统的一致,我们还需要为它添加一个UIView动画。

接着我们来具体操作一下,首先,建立一个测试工程,工程结构如下图。测试工程的根视图控制器是一个UINavigationController,在这个UINavigationController的栈中有视图控制器a(FirstViewController的一个实例)和控制器b(SecondViewController的一个实例),控制器b通过在控制器a中点击按钮push进入。

在SecondViewController.h文件中添加代码,如下

#import <UIKit/UIKit.h>

@interface SecondViewController : UIViewController

@property (nonatomic,assign) BOOL isLandscape;

- (IBAction)rotateBtnClicked:(id)sender;

@end

在SecondViewController.m文件中添加代码,如下

#import "SecondViewController.h"

@implementation SecondViewController

#pragma mark - view life cycle
- (void)viewDidLoad
{
    [super viewDidLoad];
    self.title = @"Second";
    self.isLandscape = NO;
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(changeFrames:)
                                                 name:UIDeviceOrientationDidChangeNotification
                                               object:nil];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - methods
- (void)rotateToLandscapeLeft
{
    NSTimeInterval duration = [[UIApplication sharedApplication] statusBarOrientationAnimationDuration];
    [UIView animateWithDuration:duration animations:^{
        [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft];
        self.navigationController.view.transform = CGAffineTransformMakeRotation(- M_PI/2);
        self.navigationController.view.bounds = CGRectMake(0, 0, [self screenHeight], 320);
    } completion:^(BOOL finished) {
        self.isLandscape = YES;
    }];
}

- (void)rotateToLandscapeRight
{
    NSTimeInterval duration = [[UIApplication sharedApplication] statusBarOrientationAnimationDuration];
    [UIView animateWithDuration:duration animations:^{
        [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];
        self.navigationController.view.transform = CGAffineTransformMakeRotation(M_PI/2);
        self.navigationController.view.bounds = CGRectMake(0, 0, [self screenHeight], 320);
    } completion:^(BOOL finished) {
        self.isLandscape = YES;
    }];
}

- (void)rotateToPortrait
{
    NSTimeInterval duration = [[UIApplication sharedApplication] statusBarOrientationAnimationDuration];
    [UIView animateWithDuration:duration animations:^{
        [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];
        self.navigationController.view.transform = CGAffineTransformMakeRotation(0);
        self.navigationController.view.bounds = CGRectMake(0, 0, 320, [self screenHeight]);
    } completion:^(BOOL finished) {
        self.isLandscape = NO;
    }];
}

- (CGFloat)screenHeight
{
    if (iPhone5) {
        return 568.0;
    }
    else {
        return 480.0;
    }
}

#pragma mark - actions
- (IBAction)rotateBtnClicked:(id)sender
{
    if (!self.isLandscape) {
        [self rotateToLandscapeRight];
    }
    else {
        [self rotateToPortrait];
    }
}

#pragma mark - handle notification
- (void)changeFrames:(NSNotification *)notification
{
    UIDeviceOrientation deviceOrientation = [[UIDevice currentDevice] orientation];
    if (deviceOrientation == UIDeviceOrientationLandscapeRight) {
        [self rotateToLandscapeLeft];
    }
    else if (deviceOrientation == UIDeviceOrientationLandscapeLeft) {
        [self rotateToLandscapeRight];
    }
    else if (deviceOrientation == UIDeviceOrientationPortrait){
        [self rotateToPortrait];
    }
}

@end

其中,rotateToLandscapeLeft/rotateToLandscapeRight/rotateToPortrait是视图旋转的核心方法。我们在viewDidLoad方法中注册了一个事件通知,当设备的物理旋转方向发生改变时,我们将调用方法changeFrames:来对视图进行相应的旋转,也可以通过点击某个按钮来旋转界面。可以看到,测试项目中还有一个UINavigationController的类别。类别中添加

#import "UINavigationController+Ext.h"

@implementation UINavigationController (Ext)

- (BOOL)shouldAutorotate
{
    return NO;
}

@end

为什么要添加UINavigationController类别?因为旋转的时候我们需要同时去旋转statusBar(状态栏),要旋转statusBar必须在shouldAutorotate方法中返回NO。

运行测试项目并旋转设备,能看到我们已经成功手动控制界面旋转,且旋转的动画效果与系统默认的旋转效果是一模一样的。和之前那篇文章中提到的解决方法相比,有了更高的自由度,开发者能够随性控制界面的旋转。

测试工程:下载

iOS手动控制界面旋转

时间: 2024-10-09 19:23:32

iOS手动控制界面旋转的相关文章

Unity3D 研究院之IOS高级界面发送消息与Unity3D消息的接收

今天和盆友们讨论IOS的高级界面与unity3d游戏引擎的交互,这个在开发中是非常重要的,unity3d 毕竟是一个面向多平台的一个游戏引擎,它不可能全部为IOS 考虑的面面俱到,引擎中也不存在针对IOS的高级界面的控件的使用. 本例实现游戏背景是Unity3D 的游戏世界,前面添加4个IOS的高级界面的按钮,并且点击这些按钮可以将消息传递给背景的Unity3D ,让它做一些事情. 上一章介绍了触摸IOS屏幕 移动摄像机的位置,下面有盆友问我说他不想移动摄像机的位置,就想移动物体的位置,我在这里

iOS实现屏幕旋转

iOS实现屏幕旋转有两种方式 1. 应用本身支持 2. 手动旋转UIView (这种方式我没找到旋转 系统控件的方法 如:键盘.导航.UIAlertView) 如果你只是要把竖屏的播放器,做成支持横屏的,没有其他界面操作, 就可以考虑用第二种方式去做,比较简单 ,不过要注意计算view Frame 这两种方式看你具体的使用场景了,具体场景选择合适的方式. 公司项目中有几个界面要支持横竖屏,(直播录制界面.直播观看界面.视频回看界面). 刚开始我想着用第二种方式去解决,但是我们视频录制.观看界面有

iOS:Swift界面实例1, 简单界面

Apple推出了基于Objective-C的新语言Swift. 通过实例, 我们可以很好的感受这门新语言 注意事项: 在XCode6_Beta中, 如果有中文, IDE的自动补全功能就会失效, 所以开始调试的时候可以先用英文, 后面再用中文替代. 1. 新建iOS -> Single View Application. 2. 修改AppDelegate.swift文件 1 // 2 // AppDelegate.swift 3 // UIByCode_Swift_1_HelloWorld 4 /

iOS缩放、旋转UIButton

在练习缩放旋转UIButton控件时,出现点击控件x,y同时增加或者减一定像素,经过查找是xcode5开启了Auto Layout. 放大缩小的代码 - (IBAction)btnScale:(UIButton *)sender { //动画开始,设置执行时间 [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:1]; int tag = [sender tag]; float scale = tag ==

iOS图形界面优化-Instrument

1.图形界面优化打开Instrument进行如下选择: 左下角选项的作用: 1.color blended layers :让你了解哪一个层(纹理)被标记成透明,也就是说,GPU需要做合成工作.合成不透明层要比透明的层工作量少很多,因为没有那么多的数学运算在里面. 2.color misaligned images :检测像素是否对齐,当CALayer中存在像素不对齐的时候,把问题显示出来. 3.Color Hits Green and Misses Red:绿色代表无论何时一个屏幕外缓冲区被复

iOS 7 界面设计资源

太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. 这是苹果官方资源的界面复制,感觉设计的很漂亮,一直觉得苹果的开发文档,虽然文档内组织的很合理,但各文档间的关联性很差,这也是形成立体知识库于头脑中

IOS UIDevice & IOS检测屏幕旋转实例

一 UIDevice 简介 UIDevice类提供了一个单例实例代表当前的设备.从这个实例中可以获得的信息设备,比如操作系统名称.电池电量值(batteryLevel).电池状态(batteryState).设备的类型(model,比如iPod.iPhone等).设备的系统(systemVersion) 二 获取 UIDevice 实例 通过[UIDevice currentDevice]可以获取这个单粒对象 UIDevice *device = [UIDevice currentDevice]

16_Android生命周期再介绍,通过androidconfigChanges属性让界面旋转时不改变状态中保留的值

?? A  android:configChanges属性 对android:configChanges属性,一般认为有以下几点: 1 不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次. 2 设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横.竖屏时只会执行一次. 3.设置Activity的android:config

iOS开发- 界面传值(1)-通知模式(广播)

之后的几篇博客, 记录下不同界面间传值的常用办法. 这篇文章记录广播的方式. iOS的设计模式中,通知模式也是其中重要的模式之一,Notification直译为通知,其实本人觉得叫做广播模式更为贴切.它的作用就是一个对象对多个对象的同步操作.用法很简单,一个对象发出一个广播,需要收听的听众就先注册一下,然后选定频道,完了就可以收听广播的内容了. 但是要注意一点, 在收听之前, 一定要先注册. 不然发送的广播接受不到, 也就是值改变了, 不会做出响应. 下面是一个简单的demo, 效果如下: 第一