如果你在自定义转场动画的时候不设置modalPresentionStyle或者设置成UIModalPresentationCustom,很有可能在modal完成之后出现底部是黑屏的状况。
这个时候的解决方案就是:
[[UIApplication sharedApplication].keyWindow insertSubview:fromView belowSubview:containerView];
将之前底部可以看见的视图重新添加到视图层次结构中。
但是如果你把modalPresentionStyle设置为UIModalPresentationCustom,竟然没有出现这个问题。
坑:
1.gif
想要达到的效果:
1.gif解决坑的参考代码:
#import "ViewController.h"
@interface ViewController ()<UIViewControllerTransitioningDelegate,UIViewControllerAnimatedTransitioning>
@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 <UIViewControllerContextTransitioning>)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 <UIViewControllerContextTransitioning>)transitionContext {
return 0.5;
}
#pragma mark - UIViewControllerTransitioningDelegate代理方法
- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
self.isPresenting = true;
return self;
}
- (nullable id <UIViewControllerAnimatedTransitioning>)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;
}
网友评论