CustomIOS7AlertView 适配 iOS 8

来源:互联网 发布:千里眼淘宝版下载 编辑:程序博客网 时间:2024/05/17 04:46

原来项目中用到一个很好用的自定义对话框 CustomIOS7AlertVIew

这个对话框在iOS 7下完全没有问题。

self.alertView = [[CustomIOS7AlertView alloc] init];        self.alertView.delegate = self;        self.dvController = [[ZYAlertDirectionalVersionViewController alloc] initWithNibName:@"ZYAlertDirectionalVersion" bundle:[NSBundle mainBundle]];        self.dvController.delegate = self;        self.dvController.view.layer.cornerRadius = 8;                [self.alertView setButtonTitles:[NSMutableArray arrayWithObjects: nil]];        [self.alertView setContainerView:self.dvController.view];        [self.alertView show];

使用方法很简单。视图是在xib里面的,使用setContainerView放入CustomIOS7AlertView里面就可以了。横竖屏也可以适应。

但是在iOS 8中,横屏的时候,弹出的框确实竖屏的样子。


查了资料后,才知道,原来是iOS 8 中UIScreen的方向与实际方向同步了,而不是iOS7中一直竖屏。所以iOS7中做了交换width、height的动作,而iOS 8中就多余了。

摘录一段:

Yes, it's orientation-dependent in iOS8, not a bug. You could review session 214 from WWDC 2014 for more info: "View Controller Advancements in iOS 8"

Quote from the presentation:

UIScreen is now interface oriented:

  • [UIScreen bounds] now interface-oriented
  • [UIScreen applicationFrame] now interface-oriented
  • Status bar frame notifications are interface-oriented
  • Keyboard frame notifications are interface-oriented

CustomIOS7AlertView中有四个地方需要修改:

1. 创建containerView的时候,计算屏幕大小。 8.0以上不需要交换高宽。

// Helper function: count and return the screen's size- (CGSize)countScreenSize{    if (buttonTitles!=NULL && [buttonTitles count] > 0) {        buttonHeight       = kCustomIOS7AlertViewDefaultButtonHeight;        buttonSpacerHeight = kCustomIOS7AlertViewDefaultButtonSpacerHeight;    } else {        buttonHeight = 0;        buttonSpacerHeight = 0;    }    CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;    CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;    //2015-1-27 dinghongyan 8.0以上适配。不转,屏幕大小对应屏幕方向。    if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) {        UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];        if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) {            CGFloat tmp = screenWidth;            screenWidth = screenHeight;            screenHeight = tmp;        }    }    return CGSizeMake(screenWidth, screenHeight);}


2. show的时候,添加到window上,不需要根据方向,在代码中转换。

// Create the dialog view, and animate opening the dialog- (void)show{    dialogView = [self createContainerView];      dialogView.layer.shouldRasterize = YES;    dialogView.layer.rasterizationScale = [[UIScreen mainScreen] scale];      self.layer.shouldRasterize = YES;    self.layer.rasterizationScale = [[UIScreen mainScreen] scale];#if (defined(__IPHONE_7_0))    if (useMotionEffects) {        [self applyMotionEffects];    }#endif    dialogView.layer.opacity = 0.5f;    dialogView.layer.transform = CATransform3DMakeScale(1.3f, 1.3f, 1.0);    self.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0];    [self addSubview:dialogView];    // Can be attached to a view or to the top most window    // Attached to a view:    if (parentView != NULL) {        [parentView addSubview:self];    // Attached to the top most window (make sure we are using the right orientation):    } else {        //2015-1-27 dinghongyan 8.0以上适配。不转。会自适应当前方向。        if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) {            UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];            switch (interfaceOrientation) {                case UIInterfaceOrientationLandscapeLeft:                    self.transform = CGAffineTransformMakeRotation(M_PI * 270.0 / 180.0);                    break;                                    case UIInterfaceOrientationLandscapeRight:                    self.transform = CGAffineTransformMakeRotation(M_PI * 90.0 / 180.0);                    break;                                    case UIInterfaceOrientationPortraitUpsideDown:                    self.transform = CGAffineTransformMakeRotation(M_PI * 180.0 / 180.0);                    break;                                    default:                    break;            }        }        [self setFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];        [[[[UIApplication sharedApplication] windows] firstObject] addSubview:self];    }    [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ self.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.4f];                         dialogView.layer.opacity = 1.0f;                         dialogView.layer.transform = CATransform3DMakeScale(1, 1, 1); } completion:NULL     ];}


3. 键盘弹出事件中,横屏不需要交换高宽

// Handle keyboard show/hide changes- (void)keyboardWillShow: (NSNotification *)notification{    CGSize screenSize = [self countScreenSize];    CGSize dialogSize = [self countDialogSize];    CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;    UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];        //2015-1-29 dinghongyan iOS8适配。    if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) {        if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) {            CGFloat tmp = keyboardSize.height;            keyboardSize.height = keyboardSize.width;            keyboardSize.width = tmp;        }    }        [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionTransitionNone animations:^{                         dialogView.frame = CGRectMake((screenSize.width - dialogSize.width) / 2, (screenSize.height - keyboardSize.height - dialogSize.height) / 2, dialogSize.width, dialogSize.height); } completion:nil ];}



4. 转屏的时候,不要代码中强制转。因为转屏的时候,原来的代码是整个dialogView旋转的,所以底层的View旋转了,上层的containerView和我自定义的view都转了。

实际上,底层的View转不转都无所谓的,不转的话,frame要调整。而上层的containerView和自定义的view是不需要转的。

所以,索性不使用旋转,而是改变底层view的frame。

// Handle device orientation changes- (void)deviceOrientationDidChange: (NSNotification *)notification{    // If dialog is attached to the parent view, it probably wants to handle the orientation change itself    if (parentView != NULL) {        return;    }        if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) {        UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];        CGAffineTransform rotation = [self changeOrientation];        [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionTransitionNone                         animations:^{                             dialogView.transform = rotation;                         }                         completion:^(BOOL finished){                             // fix errors caused by being rotated one too many times                             dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{                                 UIInterfaceOrientation endInterfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];                                 if (interfaceOrientation != endInterfaceOrientation) {                                     dialogView.transform = [self changeOrientation];                                 }                             });                         }         ];    }else{        //2015-1-27 dinghongyan 8.0以上适配。不转,改frame        [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionTransitionNone                         animations:^{                             self.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);                                                          dialogView.center = self.center;                         }                         completion:^(BOOL finished){                             UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];                             // fix errors caused by being rotated one too many times                             dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{                                 UIInterfaceOrientation endInterfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];                                 if (interfaceOrientation != endInterfaceOrientation) {                                     //如果转屏失败,再转回去                                     self.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);                                                                          dialogView.center = self.center;                                 }                             });                         }         ];    }}//iOS7中转屏处理-(CGAffineTransform)changeOrientation{    UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];        CGFloat startRotation = [[self valueForKeyPath:@"layer.transform.rotation.z"] floatValue];    CGAffineTransform rotation;        switch (interfaceOrientation) {        case UIInterfaceOrientationLandscapeLeft:            rotation = CGAffineTransformMakeRotation(-startRotation + M_PI * 270.0 / 180.0);            break;                    case UIInterfaceOrientationLandscapeRight:            rotation = CGAffineTransformMakeRotation(-startRotation + M_PI * 90.0 / 180.0);            break;                    case UIInterfaceOrientationPortraitUpsideDown:            rotation = CGAffineTransformMakeRotation(-startRotation + M_PI * 180.0 / 180.0);            break;                    default:            rotation = CGAffineTransformMakeRotation(-startRotation + 0.0);            break;    }    return rotation;}


5. 这个应该是ps了。跟适配没有关系,但是是CustomIOS7AlertView提醒我要注意的一个地方。

就是转屏失败怎么办?

原来的代码,在转屏失败的时候,很萌的来了一句TODO

UIInterfaceOrientation endInterfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];                             if (interfaceOrientation != endInterfaceOrientation) {                                 // TODO user moved phone again before than animation ended: rotation animation can introduce errors here                             }

如果按照旋转角度的话,其实我拎不清的。左转右转、多少度神马的,转不过弯儿来。但是改frame的话,就好做多了。只要失败的时候,再根据当前的屏幕重新调整一次就好了。于是:

//2015-1-27 dinghongyan 8.0以上适配。不转,改frame        [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionTransitionNone                         animations:^{                             self.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);                                                          dialogView.center = self.center;                         }                         completion:^(BOOL finished){                             UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];                             // fix errors caused by being rotated one too many times                             dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{                                 UIInterfaceOrientation endInterfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];                                 if (interfaceOrientation != endInterfaceOrientation) {                                     //如果转屏失败,再转回去                                     self.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);                                                                          dialogView.center = self.center;                                 }                             });                         }         ];

至此,大功告成!



0 0
原创粉丝点击