demo技术重塑iOS开发

iOS自定义弹窗UIPresentationController

2017-01-16  本文已影响2095人  贤宇

本文主要介绍UIPresentationController和UIPopoverPresentationController的使用.
UIPresentationController 是 iOS8 新增的一个 API,可以用它实现自定义的弹窗.
UIPopoverPresentationController是UIPresentationController的子类, 添加了指向箭头, 使用起来比较方便.

UIPresenationController.png PresentVC的可视化.png UIPopoverPresentationController.png
// ================== 1.UIPresentationController ===========
//  ————————————— PresentVC.h
#import <UIKit/UIKit.h>

@interface PresentationController : UIPresentationController
@end

@interface PresentVC : UIViewController
@end

//  ————————————— PresentationController.m

#import "PresentVC.h"

@interface PresentationController ()

@property (nonatomic,strong) UIVisualEffectView *visualView;

@end
@implementation PresentationController

//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.4;
    _visualView.backgroundColor = [UIColor blackColor];

    [self.containerView addSubview:_visualView];
}

//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 方法来定义这个最终位置
这个位置要和PresentVC里面内容位置一致
- (CGRect)frameOfPresentedViewInContainerView{

    CGFloat windowH = [UIScreen mainScreen].bounds.size.height;
    CGFloat windowW = [UIScreen mainScreen].bounds.size.width;

    self.presentedView.frame = CGRectMake(0, windowH - 300, windowW, 300);

    return self.presentedView.frame;
}
@end

//  ————————————— PresentVC.m

@interface PresentVC ()
@end

@implementation PresentVC

- (void)viewDidLoad {
    [super viewDidLoad];

     // 此处弹出视图自定义内容: 比如table列表, 提示框等

}
// 取消按钮

- (IBAction)cancelButton:(UIButton *)sender {
    [self dismissViewControllerAnimated:YES completion:nil];
}
@end

//  ————————————— UIViewController.m 在此处弹出

/**
 UIPresentationController 是 iOS8 新增的一个 API,用来控制 controller 之间的跳转特效。比如希望实现一个特效,显示一个窗口,大小和位置都是自定义的,并且遮罩在原来的页面上。在之前,可以操作view的一些方法来实现。
 */
- (IBAction)presentView:(UIButton *)sender {

    PresentVC *presentVC = [[PresentVC alloc] init];
    // 设置 动画样式
    presentVC.modalPresentationStyle = UIModalPresentationCustom;
    //presentVC.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
    // 此对象要实现 UIViewControllerTransitioningDelegate 协议
    presentVC.transitioningDelegate = self;
    [self presentViewController:presentVC animated:YES completion:nil];
}
// delegate-弹出视图代理

// 返回控制控制器弹出动画的对象
/**
 presentedViewController     将要跳转到的目标控制器
 presentingViewController    跳转前的原控制器
 */
- (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source{

    return [[PresentationController alloc] initWithPresentedViewController:presented presentingViewController:presenting];
}
// ============== 2.UIPopoverPresentationController =============
- (IBAction)popoverButton:(UIButton *)sender {

    // UIPopoverPresentationController是iOS8以后新增的, 是UIPresentationController的子类,是UIViewController的属性。使用的的时候,需要创建的是UIViewController。UIViewController自定义内容
    UIViewController *popVC = [[UIViewController alloc] init];
    popVC.modalPresentationStyle = UIModalPresentationPopover;
    // 弹出视图的大小
    popVC.preferredContentSize = CGSizeMake(100, 200);

    // 弹出视图设置
    UIPopoverPresentationController *popver = popVC.popoverPresentationController;
    popver.delegate = self;
    //弹出时参照视图的大小,与弹框的位置有关
    popver.sourceRect = self.popoverButton.bounds;
    //弹出时所参照的视图,与弹框的位置有关
    popver.sourceView = self.popoverButton;
    //弹框的箭头方向
    popver.permittedArrowDirections = UIPopoverArrowDirectionUp;

    popver.backgroundColor = [UIColor orangeColor];
    [self presentViewController:popVC animated:YES completion:nil];
}

// -------UIPopoverPresentationControllerDelegate
// 默认返回的是覆盖整个屏幕,需设置成UIModalPresentationNone。
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller{
    return UIModalPresentationNone;
}
// 设置点击蒙版是否消失,默认为YES
- (BOOL)popoverPresentationControllerShouldDismissPopover:(UIPopoverPresentationController *)popoverPresentationController{
    return YES;
}
// 弹出视图消失后调用的方法
- (void)popoverPresentationControllerDidDismissPopover:(UIPopoverPresentationController *)popoverPresentationController{
}


上一篇下一篇

猜你喜欢

热点阅读