我正在尝试实现模态呈现效果,其中所呈现的视图仅部分覆盖父视图,如下图所示.
我知道我可以通过使用UIPresentationController实现自定义转换来实现这一点.我不想重新发明,所以在我开始发展之前,我想问一下.
在API中是否有这种转型的支持?
我研究了所有可用的Modal Presentation Styles,在我看来,我不想支持我想要的转换,唯一的方法就是编写它.
解决方法
我遇到了同样的问题.我也去了模式演示风格的路线,并不断击中墙壁(具体让它在iPhone而不是iPad上工作).
经过一些挖掘,我能够得到它的工作.这是我如何做到的:
要开始,我们需要一个视图控制器,我们将呈现(模态的)将其视图的背景颜色设置为透明,并将导航控制器视图的框架设置为一些偏移.
ModalViewController.h
@import UIKit; @class ModalViewController; @protocol ModalViewControllerDelegate <NSObject> - (void)modalViewControllerDidCancel:(ModalViewController *)modalViewController; @end @interface ModalViewController : UIViewController @property (weak,nonatomic) id<ModalViewControllerDelegate> delegate; - (instancetype)initWithRootViewController:(UIViewController *)rootViewController; @end
ModalViewController.m
static const CGFloat kTopOffset = 50.0f; @implementation ModalViewController { UINavigationController *_navController; } - (instancetype)initWithRootViewController:(UIViewController *)rootViewController { self = [super initWithNibName:nil bundle:nil]; if (self) { rootViewController.navigationItem.leftBarButtonItem = [self cancelButton]; _navController = [[UINavigationController alloc] initWithRootViewController:rootViewController]; self.view.backgroundColor = [UIColor clearColor]; [self.view addSubview:_navController.view]; // this is important (prevents black overlay) self.modalPresentationStyle = UIModalPresentationOverFullScreen; } return self; } - (void)viewDidLoad { [super viewDidLoad]; CGRect bounds = self.view.bounds; _navController.view.frame = CGRectMake(0,kTopOffset,CGRectGetWidth(bounds),CGRectGetHeight(bounds) - kTopOffset); } - (UIBarButtonItem *)cancelButton { return [[UIBarButtonItem alloc] initWithTitle:@"Cancel" style:UIBarButtonItemStylePlain target:self action:@selector(cancelButtonClicked:)]; } - (void)cancelButtonClicked:(id)sender { [_delegate modalViewControllerDidCancel:self]; } @end
接下来,我们需要设置演示控制器来运行以下动画:
>缩小自己
淡出一点点
>使用presentViewController呈现模态视图控制器:动画:完成
这就是我所做的
PresentingViewController.m
static const CGFloat kTransitionScale = 0.9f; static const CGFloat kTransitionAlpha = 0.6f; static const NSTimeInterval kTransitionDuration = 0.5; @interface PresentingViewController <ModalViewControllerDelegate> @end @implementation PresentingViewController ... ... - (void)showModalViewController { self.navigationController.view.layer.shouldRasterize = YES; self.navigationController.view.layer.rasterizationScale = [UIScreen mainScreen].scale; UIViewController *controller = // init some view controller ModalViewController *container = [[ModalViewController alloc] initWithRootViewController:controller]; container.delegate = self; __weak UIViewController *weakSelf = self; [UIView animateWithDuration:kTransitionDuration animations:^{ weakSelf.navigationController.view.transform = CGAffineTransformMakeScale(kTransitionScale,kTransitionScale); weakSelf.navigationController.view.alpha = kTransitionAlpha; [weakSelf presentViewController:container animated:YES completion:nil]; } completion:^(BOOL finished) { weakSelf.navigationController.view.layer.shouldRasterize = NO; }]; } #pragma mark - ModalViewControllerDelegate - (void)modalViewControllerDidCancel:(ModalViewController *)modalViewController { __weak UIViewController *weakSelf = self; [UIView animateWithDuration:kTransitionDuration animations:^{ weakSelf.navigationController.view.alpha = 1; weakSelf.navigationController.view.transform = CGAffineTransformIdentity; [weakSelf dismissViewControllerAnimated:YES completion:nil]; }]; } @end