06-自定义转场动画遇到的坑

如果你在自定义转场动画的时候不设置modalPresentionStyle或者设置成UIModalPresentationCustom,很有可能在modal完成之后出现底部是黑屏的状况。
这个时候的解决方案就是:
[[UIApplication sharedApplication].keyWindow insertSubview:fromView belowSubview:containerView];
将之前底部可以看见的视图重新添加到视图层次结构中。
但是如果你把modalPresentionStyle设置为UIModalPresentationCustom,竟然没有出现这个问题。

坑:


06-自定义转场动画遇到的坑_第1张图片
1.gif

想要达到的效果:

06-自定义转场动画遇到的坑_第2张图片
1.gif

解决坑的参考代码:

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic,strong) UIButton* presentButton;
@property (nonatomic,strong) UIViewController* modalVC;
@property (nonatomic,assign) BOOL isPresenting;

@property (nonatomic,strong) UIView* dimingView;

@property (nonatomic,strong) UITapGestureRecognizer* tapGesture;


@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.modalVC = [[UIViewController alloc] init];
    self.modalVC.transitioningDelegate = self;
    self.modalVC.view.backgroundColor = [UIColor redColor];
//    self.modalVC.modalPresentationStyle = UIModalPresentationCustom;
    self.isPresenting = true;
    
    [self.view addSubview:self.presentButton];
    
    [self layoutPageSubviews];

    
}

#pragma mark - UIViewControllerAnimatedTransitioning


- (void)animateTransition:(id )transitionContext {
    
    //1.获得容器视图
    UIView* containerView = [transitionContext containerView];
    
    //2.获得目标控制器和视图
    UIView* toView = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view;
     UIView* fromView = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey].view;
    if (self.isPresenting) {
        //present
        
        toView.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width-100, [UIScreen mainScreen].bounds.size.height-300);
        toView.center = CGPointMake(containerView.center.x, -containerView.center.y);
        
        
        //3.创建遮罩视图
        self.dimingView = [[UIView alloc] initWithFrame:self.view.bounds];
        self.dimingView.backgroundColor = [UIColor blackColor];
//        self.dimingView.alpha = 0.0;
        self.dimingView.layer.opacity = 0.0;
        [self.dimingView addGestureRecognizer:self.tapGesture];
        //4.将要进行动画的视图添加到容器视图中
       
        [containerView addSubview:self.dimingView];
        [containerView addSubview:toView];
        /*
         一定要注意添加顺序,如果toView在dimingView之前添加,dimingView就把toView给覆盖了,这样就无法点击toView了,点击的全部都是dimingView
         */
        
        [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
            
            self.dimingView.layer.opacity = 0.2;
            toView.center = CGPointMake(containerView.center.x, containerView.center.y);
            
        } completion:^(BOOL finished) {
           
            [transitionContext completeTransition:true];
            //如果视图被移除,我们就自己添加上去
            [[UIApplication sharedApplication].keyWindow insertSubview:fromView belowSubview:containerView];
        }];

    }
    else {
    
        [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
           
            self.dimingView.alpha = 0.0;
            fromView.center =  CGPointMake(containerView.center.x, containerView.center.y+[UIScreen mainScreen].bounds.size.height);
            
        } completion:^(BOOL finished) {
            
            [transitionContext completeTransition:true];
            
        }];
        
    }
    
    
    
}


- (NSTimeInterval)transitionDuration:(nullable id )transitionContext {

    return 0.5;
}


#pragma mark - UIViewControllerTransitioningDelegate代理方法

- (nullable id )animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {

    self.isPresenting = true;
    
    return self;
}

- (nullable id )animationControllerForDismissedController:(UIViewController *)dismissed {

    self.isPresenting = false;
    
    return  self;
}


#pragma mark - 响应事件

//点击遮罩
- (void) exit:(UITapGestureRecognizer*) tap {

    [self.modalVC dismissViewControllerAnimated:true completion:^{
        
    }];
}
//点击测试
- (void) modal:(UIButton*) sender {
    
    [self presentViewController:self.modalVC animated:true completion:^{
        
    }];
}


#pragma mark - 设置约束
- (void) layoutPageSubviews{
    
    //代码自动布局要先机制掉autoResizing
    self.presentButton.translatesAutoresizingMaskIntoConstraints = NO;
    
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.presentButton attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0f constant:0]];
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.presentButton attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0f constant:0]];
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.presentButton attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0 constant:100]];
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.presentButton attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0 constant:100]];
    
}


#pragma mark - 懒加载

- (UITapGestureRecognizer *)tapGesture{

    if (_tapGesture==nil) {
        
        _tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(exit:)];
    }
    
    return _tapGesture;
}

- (UIButton *)presentButton{

    if (_presentButton==nil) {
        
        _presentButton = [[UIButton alloc] init];
        [_presentButton setTitle:@"测试" forState:UIControlStateNormal];
        [_presentButton setBackgroundColor:[UIColor orangeColor]];
        [_presentButton addTarget:self action:@selector(modal:) forControlEvents:UIControlEventTouchDown];
    }
    
    return _presentButton;
}


你可能感兴趣的:(06-自定义转场动画遇到的坑)