像在邮件应用程序中的模式转换样式

我试图实现一个模式的演示效果,其中呈现的视图只覆盖了父视图的一部分,如下图所示。

在这里输入图像说明

我知道我可以通过使用UIPresentationController实现自定义转换来实现这UIPresentationController 。 我不想重新发明轮子,所以在开发之前,我想问一下。

是否有构build支持API中的这种转换?

我研究了所有可用的Modal Presentation Styles ,看起来我并不支持我想要做的转换,而实现它的唯一方法就是编写它。

我遇到了同样的问题。 我沿着模式performance风格的路线,并不断打墙(特别是使它在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 

接下来,我们需要设置呈现控制器来运行以下animation:

  • 缩小自己
  • 淡出一点点
  • 使用presentViewController:animated:completion模态视图控制器presentViewController:animated:completion

这就是我所做的

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 

很确定它是这样做的

 let newVC = <view controller you want to display> let nav: UINavigationController = UINavigationController(rootViewController: newVC) if let currVc = UIApplication.sharedApplication().keyWindow?.rootViewController { nav.transitioningDelegate = currVc nav.modalPresentationStyle = UIModalPresentationStyle.Custom; currVc.presentViewController(nav, animated: true, completion: nil) }