【原】UI随设备旋转从iOS6到iOS8的适配策略

- (void)statusBarOrientationChange:(NSNotification *)notification
{
    WClassAndFunctionName;
    UIInterfaceOrientation oriention = [UIApplication sharedApplication].statusBarOrientation;
    [self adaptUIBaseOnOriention:oriention];
}

 

通常状况下,关于屏幕旋转的适配用view自带的autoresizingmask属性就能轻松适配宽度以及边距,并且从iOS6到iOS8通吃。不过,前提是“通常状况下”。当你须要在横屏与竖屏状态下让你封装的view有不一样的布局,那autoresizingMask属性就显得力不从新了。这也是本文要解决的主要问题。ios

显然,检测视图旋转事件是必需要作的。通常咱们封装一个自定义控件,老是但愿调用者能够轻松的调用它,所以检测视图旋转也应该在控件内作。布局

开始检测视图旋转。spa

在init方法中注册通知server

- (void)registerListeningDeviceOriention
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(statusBarOrientationChange:)
                                                 name:UIApplicationDidChangeStatusBarOrientationNotification
                                               object:nil];
}

 一旦屏幕产生旋转,则调用statusBarOrientionChange:方法。好比:blog

- (void)statusBarOrientationChange:(NSNotification *)notification
{
    WClassAndFunctionName;
    UIInterfaceOrientation oriention = [UIApplication sharedApplication].statusBarOrientation;
    [self adaptUIBaseOnOriention:oriention];//好比改变self.frame
}

然而,事情并非那么顺利跟想固然的!当你满怀信心地在adaptUIBaseOnOriention方法中根据oriention作布局后会发现,iOS8跑出来的效果很完美,而非iOS8版本却乱七八糟。不少时候自定义view(如下简称superview)的subviews的布局要依赖于superview的size。因此一旦superview的frame没有适配好,那看起来就乱七八糟了!为何会出现上述差别呢?根本缘由是statusBarOrientationChange的触发时机依赖于ios版本。打log后发现,iOS8及以上的版本,statusBarOrientationChange在旋转结束后调用;在iOS8如下的版本,statusBarOrientationChange在旋转前调用。而若是你在statusBarOrientationChange方法中想固然地去读取当前的设备高度跟宽度,那必然产生差别!事件

整体思路是没错的,下一步就是在statusBarOrientationChange里面对当前的设备方向以及系统版本进行判断,这样才能取到真正的设备高度跟宽度,真正的设备高度宽度对于布局是相当重要的!it

    CGFloat windowWidth = kDeviceWindowWidth4Panel;//iOS8不用更改
    CGFloat windowHeight = kDeviceWindowHeight4Panel;
    if (!IsIOS8orAbove) {
        windowWidth = (!kIsDeviceLandscape) ? kDeviceWindowWidth4Panel:kDeviceWindowHeight;
        windowHeight = (!kIsDeviceLandscape) ? kDeviceWindowHeight4Panel:(kDeviceWindowWidth - (IsIOS7orAbove ? 0 : kSystemStatusBarHeight));
    }

 其实,本质上能够简述为:iOS8上windowSize取的是当前时刻的windowSize值,所以能够直接赋值;iOS8如下的windowSize取得是下一时刻旋转后的值,至关于预判了io

最后一点须要注意的地方是,若是你须要在statusBarOrientationChange方法中手动改变superview的frame,那请把init方法中的autoresizingMask属性所有注释掉,由于二者是冲突的,尤为是在iOS8如下。由于在iOS8如下本质上是在旋转以前就将全部的subviews的布局更新为旋转后的状态了,这样翻转过去就能正常显示。若是你加了autoresizingMask属性,那系统会根据旋转前最后一刻的状态来适配,这样旋转后就群魔乱舞了。class

相关文章
相关标签/搜索