UIPresentationController 的使用

由于項目中經(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)注,謝謝!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,366評論 25 708
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,828評論 4 61
  • 為了讓飛鳥學(xué)生在緊張的一周學(xué)習(xí)之余得到放松和愉悅,從而更加精神振奮地投入下一周的學(xué)習(xí)中,本周六上午在飛鳥進行第...
    f8e4ed5b616b閱讀 287評論 0 0
  • 目錄:不長不短,剛好刻骨銘心 上一章:結(jié)婚五周年紀念日 文/陳康慧 呶,這是我們送給你們夫妻的禮物,她人呢?”明杰...
    陳康慧閱讀 819評論 17 21
  • 原文地址其他參考資料 let:聲明變量 const:聲明只讀常量 二者共同點: 只在代碼塊內(nèi)有效,并且在用let或...
    沒人能救你呀吼閱讀 175評論 0 0

友情鏈接更多精彩內(nèi)容