UIPresentationController 的使用

由于项目中经常会有一些需求页面是,从底部弹出一个视图,在当前视图的上面,因此为了减少那些没必要的工作量,基于UIPresentationController写了一个工具类,效果图如下:


弹出视图.gif

使用工具说明:

Snip20170711_1.png

代码实现如下:

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);//控制底部视图位置,如果不传
就使用内部定义的默认值
 [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 是在呈现过渡即将开始的时候被调用的。我们在这个方
法中把半透明黑色背景 View 加入到 containerView 中,并且做一个 alpha 从0到1的渐变
过渡动画。
- (void) presentationTransitionWillBegin
{
    //使用UIVisualEffectView实现模糊效果
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: 是在呈现过渡结束时被调用的,并且该方法提供一个布尔
变量来判断过渡效果是否完成。在我们的例子中,我们可以使用它在过渡效果已结束但没有完成时
移除半透明的黑色背景 View。
-(void)presentationTransitionDidEnd:(BOOL)completed {
    
    // 如果呈现没有完成,那就移除背景 View
    if (!completed) {
        [_visualView removeFromSuperview];
    }
}
//以上就涵盖了我们的背景 View 的呈现部分,我们现在需要给它添加淡出动画并且在它消失后
移除它。正如你预料的那样,dismissalTransitionWillBegin 正是我们把它的 alpha 重新设
回0的地方。
-(void)dismissalTransitionWillBegin {
    _visualView.alpha = 0.0;
}
//我们还需要在消失完成后移除背景 View。做法与上面 presentationTransitionDidEnd: 类
似,我们重载 dismissalTransitionDidEnd: 方法
-(void)dismissalTransitionDidEnd:(BOOL)completed{
    if (completed) {
        [_visualView removeFromSuperview];
    }
}
//还有最后一个方法需要重载。在我们的自定义呈现中,被呈现的 view 并没有完全完全填充整
个屏幕,而是很小的一个矩形。被呈现的 view 的过渡动画之后的最终位置,是由 
UIPresentationViewController 来负责定义的。我们重载 
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;

//该类是一个用来页面底部弹出一个弹框的单例需要传入一个跳转前和跳转后的控制器
@interface TTPresentationObject : NSObject

TTSingletonH(TTPresentationObject);
/**弹框视图位置 在调用下面方法之前一定要先给这个赋值*/
@property (nonatomic)CGRect subViewFrame;
/**
 弹出视图
 
 @param presentingViewController 跳转前的原控制器
 @param presentedViewController 将要跳转到的目标控制器
 */
-(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 跳转前的原控制器
 @param presentedViewController 将要跳转到的目标控制器
 */
-(void)showPresentingViewController:(UIViewController *)presentingViewControll
erPresentedViewController(UIViewController*)presentedViewController{
// 设置 动画样式
presentedViewController.modalPresentationStyle = UIModalPresentationCustom;
// 此对象要实现 UIViewControllerTransitioningDelegate 协议
presentedViewController.transitioningDelegate = self;
 [presentingViewController.navigationController presentViewController:presen
tedViewController animated:YES completion:nil];
}
#pragma mark - UIViewControllerTransitioningDelegate
// 返回控制控制器弹出动画的对象
/**
 *  参数: presentedViewController     将要跳转到的目标控制器
 presentingViewController    跳转前的原控制器
 */
- (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中就可以,相关的事件处理,都可以独立处理;以上只是对UIPresentationController使用的一种封装,后面会陆续上传相关的其他使用方案的封装,敬请关注,谢谢!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,884评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,067评论 4 62
  • 为了让飞鸟学生在紧张的一周学习之余得到放松和愉悦,从而更加精神振奋地投入下一周的学习中,本周六上午在飞鸟进行第...
    f8e4ed5b616b阅读 227评论 0 0
  • 目录:不长不短,刚好刻骨铭心 上一章:结婚五周年纪念日 文/陈康慧 呶,这是我们送给你们夫妻的礼物,她人呢?”明杰...
    陈康慧阅读 578评论 17 21
  • 原文地址其他参考资料 let:声明变量 const:声明只读常量 二者共同点: 只在代码块内有效,并且在用let或...
    没人能救你呀吼阅读 121评论 0 0