经常在项目中 , 我们会用到一些下拉菜单 , 或者上弹菜单等 . 简单的做法就是加一层蒙板 , 自定义一个view , 写一下动画就完成了 . 但是这样写的话 , 首先是比较low , 其次是性能略有损耗 , 且比较杂乱 . 其实在iOS中 , 如果是iPad开发的 , 苹果直接就有提供PopoVerController使用 . 如果是iPhone呢 , 也可以通过重写类 , 来实现
#import "ViewController.h"
#import "MYShowAnimationController.h"
#import "MYPresentationController.h"
@interface ViewController ()<UIViewControllerTransitioningDelegate,UIViewControllerAnimatedTransitioning>
@property (assign, nonatomic) BOOL isOpen;
//下拉菜单控制器
@property (strong, nonatomic) MYShowAnimationController *showVc;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
[button setTitle:@"开始动画" forState:UIControlStateNormal];
button.frame = CGRectMake(275 *0.5,20,100, 44);
[self.view addSubview:button];
[button addTarget:self action:@selector(animationBegin) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.titleView = button;
}
- (void)animationBegin
{
if (!self.isOpen) {
self.showVc = [[MYShowAnimationController alloc]init];
//设定模态风格 , custom可以保持容器下层的图层不被隐藏
self.showVc.modalPresentationStyle = UIModalPresentationCustom;
self.showVc.transitioningDelegate = self;
[self presentViewController:self.showVc animated:YES completion:^{
self.isOpen = YES;
}];
}else{
[self.showVc dismissViewControllerAnimated:YES completion:^{
[self.showVc.view removeFromSuperview];
self.showVc = nil;
// self.isOpen = NO;
}];
}
}
//代理方法:改变弹出控制器view的frame
//返回自定义的容器控制器,我们自己来写它的布局
- (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source
{
return [[MYPresentationController alloc]initWithPresentedViewController:presented presentingViewController:presenting];
}
// UIViewControllerTransitioningDelegate 协议中方法 , 自定义弹出动画 , 返回一个遵循 UIViewControllerAnimatedTransitioning 协议的控制器
- (id)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
return self;
}
//消失动画
- (id)animationControllerForDismissedController:(UIViewController *)dismissed
{
return self;
}
//动画持续时间
- (NSTimeInterval)transitionDuration:(id)transitionContext
{
return 0.25;
}
//获取转场上下文 , 拿到presentedView 和 presentingView自定义动画
- (void)animateTransition:(id)transitionContext
{
// if (!self.isOpen) {
//
// //根据key值取出被模态视图view
// // UITransitionContextToViewKey
// // UITransitionContextFromViewKey
// UIView *presentedView = [transitionContext viewForKey:UITransitionContextToViewKey];
//
// //设置锚点 (从顶点中心弹出)
// presentedView.layer.anchorPoint = CGPointMake(0.5, 0);
//
// //添加被模态视图view到容器view中
// [[transitionContext containerView]addSubview:presentedView];
// NSLog(@"%@",presentedView);
//
// //执行动画
// presentedView.transform = CGAffineTransformMakeScale(1.0,0.001);
// [UIView animateWithDuration:0.25 animations:^{
//
// presentedView.transform = CGAffineTransformIdentity;
//
// }
// completion:^(BOOL finished) {
//
// //告知动画已经执行完毕
// [transitionContext completeTransition:YES];
// self.isOpen = YES;
// }];
// }else{
//
// UIView *presentingView = [transitionContext viewForKey:UITransitionContextFromViewKey];
//
// //添加被模态视图view到容器view中
// [[transitionContext containerView]addSubview:presentingView];
//
// presentingView.transform = CGAffineTransformMakeScale(1.0,1.0);
// //执行动画
// [UIView animateWithDuration:0.25 animations:^{
//
// presentingView.transform = CGAffineTransformMakeScale(1.0,0.001);
//
// } completion:^(BOOL finished) {
//
// //告知动画已经执行完毕
// [transitionContext completeTransition:YES];
// self.isOpen = NO;
//
// }];
// }
if (!self.isOpen) {
//根据key值取出被模态视图view
// UITransitionContextToViewKey
// UITransitionContextFromViewKey
UIView *presentedView = [transitionContext viewForKey:UITransitionContextToViewKey];
//设置锚点 (从顶点中心弹出)
presentedView.layer.anchorPoint = CGPointMake(0.5, 0);
//添加被模态视图view到容器view中
[[transitionContext containerView]addSubview:presentedView];
NSLog(@"%@",presentedView);
//执行动画
// presentedView.transform = CGAffineTransformMakeScale(1.0,0.001);
presentedView.frame = CGRectMake(([UIScreen mainScreen].bounds.size.width - 200) *0.5, -300, 200, 300);
[UIView animateWithDuration:0.25 delay:0.0 usingSpringWithDamping:0.2 initialSpringVelocity:5 options:UIViewAnimationOptionCurveEaseIn animations:^{
presentedView.frame = CGRectMake(([UIScreen mainScreen].bounds.size.width - 200) *0.5, 0, 200, 300);
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
self.isOpen = YES;
}];
}else{
UIView *presentingView = [transitionContext viewForKey:UITransitionContextFromViewKey];
//添加被模态视图view到容器view中
[[transitionContext containerView]addSubview:presentingView];
[UIView animateWithDuration:0.25 animations:^{
presentingView.transform = CGAffineTransformMakeScale(1.0, 0.001);
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
self.isOpen = NO;
}];
}
}
被模态类
#import "MYShowAnimationController.h"
@interface MYShowAnimationController ()
@end
@implementation MYShowAnimationController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor redColor];
}
模态时 容器view控制器
#import
//继承与 UIPresentationController
@interface MYPresentationController : UIPresentationController
@end
--------------------------------------------------------
#import "MYPresentationController.h"
@interface MYPresentationController ()
//蒙板
@property (strong, nonatomic) UIControl *coverView;
@end
@implementation MYPresentationController
//蒙板
- (UIControl *)coverView
{
if (!_coverView) {
_coverView = [[UIControl alloc]init];
_coverView.frame = CGRectMake(0,0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
_coverView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
[_coverView addTarget:self action:@selector(coverTouch) forControlEvents:UIControlEventTouchUpInside];
}
return _coverView;
}
//容器view即将布局
- (void)containerViewWillLayoutSubviews
{
[super containerViewWillLayoutSubviews];
//调整容器view大小
self.containerView.frame = (CGRect){0,64,[UIScreen mainScreen].bounds.size.width,[UIScreen mainScreen].bounds.size.height - 64};
//被模态出来控制器的view尺寸
CGFloat width = 200;
CGFloat height = 300;
CGFloat presentedViewX = ([UIScreen mainScreen].bounds.size.width - width) *0.5;
CGFloat presentedViewY = 0;
self.presentedView.frame = CGRectMake(presentedViewX,presentedViewY, width, height);
//添加蒙板在presentedView下面
[self.containerView insertSubview:self.coverView belowSubview:self.presentedView];
}
//蒙板点击方法
- (void)coverTouch
{
[UIView animateWithDuration:0.1 animations:^{
self.coverView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.001];
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
} completion:^(BOOL finished) {
[self.coverView removeFromSuperview];
}];
}
还有很多有意思的动画 , 都可以实现 .当然也可以自行封装一下 ,以供今后使用 , 比如将返回self处改为 继承与NSObject类的对象 , 然后将所有代理方法封装与 该类中
简单效果如下 , 在showViewController中可以添加控件 , 比如常见的下拉tableView , collectionView , 九宫格按钮等等 .. .