由于項目中經(jīng)常會有一些需求頁面是,從底部彈出一個視圖,在當(dāng)前視圖的上面,因此為了減少那些沒必要的工作量,基于UIPresentationController寫了一個工具類,效果圖如下:

彈出視圖.gif
使用工具說明:

Snip20170711_1.png
代碼實現(xiàn)如下:
ViewController.m文件
#import "ViewController.h"
#import "TTPresentationObject.h"
#import "BViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
//點擊彈出
- (IBAction)alerAction:(UIButton *)sender {
CGFloat windowW = [UIScreen mainScreen].bounds.size.width;
TTPresentationObject *object =[TTPresentationObject
sharedTTPresentationObject];
object.subViewFrame=CGRectMake(0, 0, windowW, 100);//控制底部視圖位置,如果不傳
就使用內(nèi)部定義的默認值
[object showPresentingViewController:self PresentedViewController:[[BViewCon
troller alloc] init]];
}
@end
BViewController.m文件
#import "BViewController.h"
@interface BViewController ()
@end
@implementation BViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor=[UIColor redColor];
}
@end
TTCustomPresentationVc.h
#import <UIKit/UIKit.h>
@class TTPresentationObject;
@interface TTCustomPresentationVc : UIPresentationController
@property (nonatomic, strong)UIVisualEffectView *visualView;
@end
TTCustomPresentationVc.m
#import "TTCustomPresentationVc.h"
#import "TTPresentationObject.h"
@implementation TTCustomPresentationVc
//presentationTransitionWillBegin 是在呈現(xiàn)過渡即將開始的時候被調(diào)用的。我們在這個方
法中把半透明黑色背景 View 加入到 containerView 中,并且做一個 alpha 從0到1的漸變
過渡動畫。
- (void) presentationTransitionWillBegin
{
//使用UIVisualEffectView實現(xiàn)模糊效果
UIBlurEffect *blur = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
_visualView = [[UIVisualEffectView alloc]initWithEffect:blur];
_visualView.frame = self.containerView.bounds;
_visualView.alpha = 0.3;
_visualView.backgroundColor = [UIColor blackColor];
[_visualView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTar
get:self action:@selector(dismissController)]];
[self.containerView addSubview:_visualView];
}
-(void)dismissController{
[self.presentingViewController dismissViewControllerAnimated:YES completion:
nil];
}
//presentationTransitionDidEnd: 是在呈現(xiàn)過渡結(jié)束時被調(diào)用的,并且該方法提供一個布爾
變量來判斷過渡效果是否完成。在我們的例子中,我們可以使用它在過渡效果已結(jié)束但沒有完成時
移除半透明的黑色背景 View。
-(void)presentationTransitionDidEnd:(BOOL)completed {
// 如果呈現(xiàn)沒有完成,那就移除背景 View
if (!completed) {
[_visualView removeFromSuperview];
}
}
//以上就涵蓋了我們的背景 View 的呈現(xiàn)部分,我們現(xiàn)在需要給它添加淡出動畫并且在它消失后
移除它。正如你預(yù)料的那樣,dismissalTransitionWillBegin 正是我們把它的 alpha 重新設(shè)
回0的地方。
-(void)dismissalTransitionWillBegin {
_visualView.alpha = 0.0;
}
//我們還需要在消失完成后移除背景 View。做法與上面 presentationTransitionDidEnd: 類
似,我們重載 dismissalTransitionDidEnd: 方法
-(void)dismissalTransitionDidEnd:(BOOL)completed{
if (completed) {
[_visualView removeFromSuperview];
}
}
//還有最后一個方法需要重載。在我們的自定義呈現(xiàn)中,被呈現(xiàn)的 view 并沒有完全完全填充整
個屏幕,而是很小的一個矩形。被呈現(xiàn)的 view 的過渡動畫之后的最終位置,是由
UIPresentationViewController 來負責(zé)定義的。我們重載
frameOfPresentedViewInContainerView 方法來定義這個最終位置
- (CGRect)frameOfPresentedViewInContainerView
{
CGFloat windowH = [UIScreen mainScreen].bounds.size.height;
CGFloat windowW = [UIScreen mainScreen].bounds.size.width;
// self.presentedView.frame = CGRectMake(0, windowH - 260, windowW, 260);
self.presentedView.frame = [TTPresentationObject sharedTTPresentationObject].s
ubViewFrame;
if ([NSStringFromCGRect(self.presentedView.frame) isEqualToString:
NSStringFromCGRect(CGRectZero)]) {
self.presentedView.frame = CGRectMake(0, windowH - 260, windowW, 260);
}
return self.presentedView.frame;
}
@end
TTPresentationObject.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "TTSingleton.h"
@class TTCustomPresentationVc;
//該類是一個用來頁面底部彈出一個彈框的單例需要傳入一個跳轉(zhuǎn)前和跳轉(zhuǎn)后的控制器
@interface TTPresentationObject : NSObject
TTSingletonH(TTPresentationObject);
/**彈框視圖位置 在調(diào)用下面方法之前一定要先給這個賦值*/
@property (nonatomic)CGRect subViewFrame;
/**
彈出視圖
@param presentingViewController 跳轉(zhuǎn)前的原控制器
@param presentedViewController 將要跳轉(zhuǎn)到的目標控制器
*/
-(void)showPresentingViewController:(UIViewController *)presentingViewControll
er PresentedViewController:(UIViewController *)presentedViewController;
TTPresentationObject.m
#import "TTPresentationObject.h"
#import "TTCustomPresentationVc.h"
@interface TTPresentationObject ()<UIViewControllerTransitioningDelegate>
@end
@implementation TTPresentationObject
TTSingletonM(TTPresentationObject);
/**
彈出視圖
@param presentingViewController 跳轉(zhuǎn)前的原控制器
@param presentedViewController 將要跳轉(zhuǎn)到的目標控制器
*/
-(void)showPresentingViewController:(UIViewController *)presentingViewControll
erPresentedViewController(UIViewController*)presentedViewController{
// 設(shè)置 動畫樣式
presentedViewController.modalPresentationStyle = UIModalPresentationCustom;
// 此對象要實現(xiàn) UIViewControllerTransitioningDelegate 協(xié)議
presentedViewController.transitioningDelegate = self;
[presentingViewController.navigationController presentViewController:presen
tedViewController animated:YES completion:nil];
}
#pragma mark - UIViewControllerTransitioningDelegate
// 返回控制控制器彈出動畫的對象
/**
* 參數(shù): presentedViewController 將要跳轉(zhuǎn)到的目標控制器
presentingViewController 跳轉(zhuǎn)前的原控制器
*/
- (UIPresentationController *)presentationControllerForPresentedViewController:
(UIViewController *)presented presentingViewController:(UIViewController *)pre
senting sourceViewController:(UIViewController *)source{
return [[TTCustomPresentationVc alloc] initWithPresentedViewController:pre
sented presentingViewController:presenting];
}
TTSingleton.h 單例宏
#define TTSingletonH(name) + (instancetype)shared##name;
#if __has_feature(objc_arc)
#define TTSingletonM(name) \
static id _instatice;\
\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instatice=[super allocWithZone:zone];\
});\
return _instatice;\
}\
+ (instancetype)shared##name\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instatice=[[self alloc]init];\
});\
return _instatice;\
}\
-(id)copyWithZone:(NSZone *)zone{return _instatice;}
#else
#define TTSingletonM(name) \
static id _instatice;\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instatice=[super allocWithZone:zone];\
});\
return _instatice;\
}\
+ (instancetype)shared##name\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instatice=[[self alloc]init];\
});\
return _instatice;\
}\
-(id)copyWithZone:(NSZone *)zone{return _instatice;}\
-(oneway void)release{}\
-(instancetype)retain{return self;}\
-(NSUInteger)retainCount{return 1;}\
-(instancetype)autorelease{return self;}
#endif
底部視圖布局寫在BViewController中就可以,相關(guān)的事件處理,都可以獨立處理;以上只是對UIPresentationController使用的一種封裝,后面會陸續(xù)上傳相關(guān)的其他使用方案的封裝,敬請關(guān)注,謝謝!