我们要实现同一个ViewController,在iPad和iPhone上显示效果不一样
iPad上时popover的,可以自定义其大小,iPhone上是全屏显示。推入方式为present
如图:
在PresentingViewController(也就是基础页面)中添加代码,用它来弹出PresentedViewController
//入口方法
- (IBAction)btnAction:(id)sender {
NextVC* vc = [[NextVC alloc] init];
vc.title = @"Blood Pressure";
vc.previousVC = self;
[self popOverToViewController:vc];
}
- (CGRect)centerRectForSize:(CGSize)forSize inSize:(CGSize)inSize{
CGFloat x = (inSize.width - forSize.width)/2;
CGFloat y = (inSize.height - forSize.height)/2;
CGFloat width = forSize.width;
CGFloat height = forSize.height;
return CGRectMake(x, y, width, height);
}
- (void)popOverToViewController:(UIViewController*)viewController{
UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:viewController];
if (!kIsIPAD) {
[self presentViewController:nav animated:YES completion:nil];
return;
}
viewController.preferredContentSize = CGSizeMake(640, 460);
nav.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController* poC = [nav popoverPresentationController];
// poC.barButtonItem = [self.navigationItem leftBarButtonItem];
poC.sourceView = self.view;
poC.permittedArrowDirections = 0;
poC.delegate = self;
poC.backgroundColor = [UIColor grayColor];
poC.sourceRect = [self centerRectForSize:CGSizeMake(640, 460) inSize:self.view.bounds.size];
[self presentViewController:nav animated:YES completion:^{
poC.containerView.layer.shadowOffset = CGSizeMake(4, 4);
poC.containerView.layer.shadowOpacity = 0.25;
poC.containerView.layer.shadowRadius = 6;
// poC.containerView.layer.shadowColor = [UIColor blackColor].CGColor;
// poC.containerView.layer.masksToBounds = NO;
}];
}
#pragma mark - popover delegate
- (void)prepareForPopoverPresentation:(UIPopoverPresentationController *)popoverPresentationController{
[self addBlurEffect:YES];
// self.navigationController.view.alpha = 0.2;
}
- (BOOL)popoverPresentationControllerShouldDismissPopover:(UIPopoverPresentationController *)popoverPresentationController{
return NO;
}
- (void)popoverPresentationControllerDidDismissPopover:(UIPopoverPresentationController *)popoverPresentationController{
// self.navigationController.view.alpha = 1;
[self addBlurEffect:NO];
}
- (void)addBlurEffect:(BOOL)add{
if (add) {
// 创建需要的毛玻璃特效类型
UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight];
// 毛玻璃view 视图
UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
//添加到要有毛玻璃特效的控件中
effectView.frame = self.navigationController.view.bounds;
[self.navigationController.view addSubview:effectView];
_blurView = effectView;
self.navigationController.view.alpha = 0.96;
[self.navigationController.view.layer setShouldRasterize:YES];
}else{
[_blurView removeFromSuperview];
self.navigationController.view.alpha = 1;
[self.navigationController.view.layer setShouldRasterize:NO];
}
}
除此之外,还需要在推入的界面(PresentedViewController)消失的时候,添加代码,再去掉上一个页面(PresentingViewController)的Blur效果:
if (_previousVC) {
[_previousVC addBlurEffect:NO];
}
[self.navigationController dismissViewControllerAnimated:NO completion:nil];
关于PresentingVC和PresentedVC,可以参考下图:
也可以参考文章:
http://www.15yan.com/story/jlkJnPmVGzc/
=========分割线=============
这样可以显示,但是代码不方便管理,于是在我们的项目里,把这个实现做成了分类,代码如下:
UIViewController+Popover.h:
//
// UIViewController+Popover.h
// iHealthLayeredApp
//
// Created by Realank on 2017/4/21.
// Copyright © 2017年 Realank. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIViewController (Popover)<UIPopoverPresentationControllerDelegate>
- (void)popOverToViewController:(UIViewController*)viewController;
- (void)removeBlurEffect;
@end
UIViewController+Popover.m:
//
// UIViewController+Popover.m
// iHealthLayeredApp
//
// Created by Realank on 2017/4/21.
// Copyright © 2017年 Realank. All rights reserved.
//
#import "UIViewController+Popover.h"
#import <objc/runtime.h>
@interface UIBlurEffect (Protected)
@property (nonatomic, readonly) id effectSettings;
@end
@interface MyBlurEffect : UIBlurEffect
@end
@implementation MyBlurEffect
+ (instancetype)effectWithStyle:(UIBlurEffectStyle)style
{
id result = [super effectWithStyle:style];
object_setClass(result, self);
return result;
}
- (id)effectSettings
{
id settings = [super effectSettings];
[settings setValue:@6 forKey:@"blurRadius"];
return settings;
}
- (id)copyWithZone:(NSZone*)zone
{
id result = [super copyWithZone:zone];
object_setClass(result, [self class]);
return result;
}
@end
@implementation UIViewController (Popover)
- (CGRect)centerRectForSize:(CGSize)forSize inSize:(CGSize)inSize{
CGFloat x = (inSize.width - forSize.width)/2;
CGFloat y = (inSize.height - forSize.height)/2;
CGFloat width = forSize.width;
CGFloat height = forSize.height;
return CGRectMake(x, y, width, height);
}
- (UIView*)backgroundView{
if (self.navigationController) {
return self.navigationController.view;
}
if ([self isKindOfClass:[UITableViewController class]]) {
UITableViewController* vc = (UITableViewController*)self;
return vc.tableView;
}else if ([self isKindOfClass:[UICollectionView class]]) {
UICollectionView* vc = (UICollectionView*)self;
return vc.backgroundView;
}else{
return self.view;
}
}
- (void)popOverToViewController:(UIViewController*)viewController{
UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:viewController];
if (!kIsIPAD) {
[self presentViewController:nav animated:YES completion:nil];
return;
}
viewController.preferredContentSize = CGSizeMake(640, 460);
nav.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController* poC = [nav popoverPresentationController];
// poC.barButtonItem = [self.navigationItem leftBarButtonItem];
poC.sourceView = [self backgroundView];
poC.permittedArrowDirections = 0;
poC.delegate = self;
poC.backgroundColor = [UIColor grayColor];
poC.sourceRect = [self centerRectForSize:CGSizeMake(640, 460) inSize:[self backgroundView].bounds.size];
[self presentViewController:nav animated:YES completion:^{
poC.containerView.layer.shadowOffset = CGSizeMake(4, 4);
poC.containerView.layer.shadowOpacity = 0.25;
poC.containerView.layer.shadowRadius = 6;
// poC.containerView.layer.shadowColor = [UIColor blackColor].CGColor;
// poC.containerView.layer.masksToBounds = NO;
}];
}
#pragma mark - popover delegate
- (void)prepareForPopoverPresentation:(UIPopoverPresentationController *)popoverPresentationController{
[self addBlurEffect:YES];
// self.navigationController.view.alpha = 0.2;
}
- (BOOL)popoverPresentationControllerShouldDismissPopover:(UIPopoverPresentationController *)popoverPresentationController{
return NO;
}
- (void)popoverPresentationControllerDidDismissPopover:(UIPopoverPresentationController *)popoverPresentationController{
// self.navigationController.view.alpha = 1;
[self addBlurEffect:NO];
}
- (void)addBlurEffect:(BOOL)add{
static UIVisualEffectView *blurView = nil;
if (add) {
// 创建需要的毛玻璃特效类型
MyBlurEffect *blurEffect = [MyBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight];
// 毛玻璃view 视图
UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
//添加到要有毛玻璃特效的控件中
effectView.frame = self.navigationController.view.bounds;
[[self backgroundView] addSubview:effectView];
blurView = effectView;
effectView.alpha = 0.8;
// self.navigationController.view.alpha = 0.96;
[[self backgroundView].layer setShouldRasterize:YES];
}else{
[blurView removeFromSuperview];
blurView = nil;
// self.navigationController.view.alpha = 1;
[[self backgroundView].layer setShouldRasterize:NO];
}
}
- (void)removeBlurEffect{
[self addBlurEffect:NO];
}
@end