合并展开弹出动画
效果图:
70917765-21f2-4844-8f97-b87e9d4e018d.png要留的接口:
1、外界设置跳转视图的Frame
内部实现原理:
- 1、完成UIViewControllerTransitioningDelegate的代理方法
- 1.1、自定义frame,完成代理方法
- (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source
说明:需自定义UIPresentationController的子类,
presentedFrame传递流程:
外部控制器设置presentedFrame具体数值 -----> PopoverAnimator的代理方法中 ----> SHPresentationController设置
- 1.2、自定义弹出和取消的动画
- //自定义弹出的动画
(id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
return self;
}
- //自定义消失的动画
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
return self;
}
说明:
如果要自定义弹出和消失的动画,需要遵守另一个代理UIViewControllerAnimatedTransitioning,包括动画的执行时间和具体的动画内容
//动画执行的时间
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
return 0.5;
}
/// 获取转场的上下文
:可以通过转场上下文获取弹出的View和消失的View
// UITransitionContextFromViewKey : 获取消失的View
// UITransitionContextToViewKey : 获取弹出的View
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
}
外部调用接口:
#import "ViewController.h"
#import "PopoverViewController.h"
#import "PopoverAnimator.h"
@interface ViewController ()
@property (nonatomic, strong) PopoverAnimator *popoverAnimator;
@end
@implementation ViewController
- (void)titleBtnClick:(TitleBtn *)titleBtn
{
// 1. 创建弹出控制器
PopoverViewController *popoverVc = [[PopoverViewController alloc]init];
// 2. 设置控制器的model样式
popoverVc.modalPresentationStyle = UIModalPresentationCustom;
// 3.设置转场的代理
popoverVc.transitioningDelegate = self.popoverAnimator;
self.popoverAnimator.presentedFrame = CGRectMake(0, 64, 375, 200);
// 4.弹出控制器
[self presentViewController:popoverVc animated:YES completion:nil];
}
OC代码实现:
PopoverAnimator.h
//
// PopoverAnimator.h
// DidClick(展开合并弹出动画)
//
// Created by sunhui on 16/10/10.
// Copyright © 2016年 sunhui. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
typedef void(^PopoverAnimatorBlock)(BOOL ispresented);
@interface PopoverAnimator : NSObject<UIViewControllerTransitioningDelegate>
@property (nonatomic, assign) CGRect presentedFrame; // 弹出视图的frame
@property (nonatomic, assign) BOOL isPresented;
@property (nonatomic, copy) PopoverAnimatorBlock popAniBlock;
- (instancetype)initWithPopoverAnimatorBlock:(PopoverAnimatorBlock)popAniBlock;
/*
presentedFrame传递流程:
外部控制器设置presentedFrame具体数值 -----> PopoverAnimator的代理方法中 ----> SHPresentationController设置
*/
@end
PopoverAnimator.m
//
// PopoverAnimator.m
// DidClick(展开合并弹出动画)
//
// Created by sunhui on 16/10/10.
// Copyright © 2016年 sunhui. All rights reserved.
//
#import "PopoverAnimator.h"
#import "SHPresentationController.h"
@interface PopoverAnimator ()<UIViewControllerAnimatedTransitioning>
@end
@implementation PopoverAnimator
- (instancetype)initWithPopoverAnimatorBlock:(PopoverAnimatorBlock)popAniBlock
{
self = [super init];
if (self) {
self.isPresented = false;
self.popAniBlock = popAniBlock;
}
return self;
}
#pragma mark - UIViewControllerTransitioningDelegate
// 改变弹出View的尺寸
- (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source
{
SHPresentationController *presentation = [[SHPresentationController alloc]initWithPresentedViewController:presented presentingViewController:presenting];
presentation.presentedFrame = self.presentedFrame;
return presentation;
}
//自定义弹出的动画
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
self.isPresented = YES;
if (self.popAniBlock) {
self.popAniBlock(self.isPresented);
}
return self;
}
//自定义消失的动画
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
self.isPresented = NO;
if (self.popAniBlock) {
self.popAniBlock(self.isPresented);
}
return self;
}
#pragma mark - UIViewControllerAnimatedTransitioning弹出和消失动画代理的方法
//动画执行的时间
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
return 0.5;
}
/// 获取`转场的上下文`:可以通过转场上下文获取弹出的View和消失的View
// UITransitionContextFromViewKey : 获取消失的View
// UITransitionContextToViewKey : 获取弹出的View
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
self.isPresented ? [self animationForPresentedView:transitionContext] : [self animationForDismissedView:transitionContext];
}
#pragma mark - 自定义弹出动画和消失动画
// 自定义弹出动画
- (void)animationForPresentedView:(id<UIViewControllerContextTransitioning>)transitionContext
{
/// 1.获取弹出的View
UIView *presentedView = [transitionContext viewForKey:UITransitionContextToViewKey];
// 2. 将弹出的View添加到ContainerView中
[[transitionContext containerView] addSubview:presentedView];
// 3.执行动画
presentedView.transform = CGAffineTransformMakeScale(1.0, 0.0);
//3.1、 更改锚点
presentedView.layer.anchorPoint = CGPointMake(0.5, 0);
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
presentedView.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
// 必须告诉转场上下文你已经完成动画
[transitionContext completeTransition:YES];
}];
}
// 自定义消失动画
- (void)animationForDismissedView:(id<UIViewControllerContextTransitioning>)transitionContext
{
// 1.获取消失的View
UIView *dismissView = [transitionContext viewForKey:UITransitionContextFromViewKey];
// 2.执行动画
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
// 之所以设置为0.00001,算是xocde的bug,设置为0的话就没有动画效果了
dismissView.transform = CGAffineTransformMakeScale(1.0, 0.00001);
} completion:^(BOOL finished) {
[dismissView removeFromSuperview];
[transitionContext completeTransition:YES];
}];
}
@end
SHPresentationController.h
//
// SHPresentationController.h
// DidClick(展开合并弹出动画)
//
// Created by sunhui on 16/10/10.
// Copyright © 2016年 sunhui. All rights reserved.
// 作用:设置弹出视图的frame
#import <UIKit/UIKit.h>
@interface SHPresentationController : UIPresentationController
@property (nonatomic, assign) CGRect presentedFrame; // 弹出视图的frame
@end
SHPresentationController.m
//
// SHPresentationController.m
// DidClick(展开合并弹出动画)
//
// Created by sunhui on 16/10/10.
// Copyright © 2016年 sunhui. All rights reserved.
//
#import "SHPresentationController.h"
@interface SHPresentationController ()
@property (nonatomic, strong) UIView *coverView;
@end
@implementation SHPresentationController
#pragma mark - 系统回调函数
- (void)containerViewWillLayoutSubviews
{
[super containerViewWillLayoutSubviews];
// 1.设置弹出View的尺寸
self.presentedView.frame = self.presentedFrame;
// 2.添加蒙版
[self setupCoverView];
}
#pragma 添加蒙版
- (void)setupCoverView
{
// 1、添加蒙版
[self.containerView insertSubview:self.coverView atIndex:0];
// 2、设置蒙版的属性
// 3、添加手势
UITapGestureRecognizer *tapGes = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(coverViewClick)];
[self.coverView addGestureRecognizer:tapGes];
}
#pragma mark - coverViewClick
- (void)coverViewClick
{
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - Getters
- (UIView *)coverView
{
if (!_coverView) {
_coverView = [[UIView alloc]init];
_coverView.backgroundColor = [UIColor colorWithWhite:0.8 alpha:0.2];
_coverView.frame = self.containerView.bounds;
}
return _coverView;
}
@end
点击上下箭头切换按钮:
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setImage:[UIImage imageNamed:@"navigationbar_arrow_up"] forState:UIControlStateNormal];
[self setImage:[UIImage imageNamed:@"navigationbar_arrow_down"] forState:UIControlStateSelected];
[self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[self sizeToFit];
}
return self;
}
- (void)layoutSubviews
{
[super layoutSubviews];
CGRect titleLabelF = self.titleLabel.frame;
titleLabelF.origin.x = 0;
self.titleLabel.frame = titleLabelF;
CGRect imageViewF = self.imageView.frame;
imageViewF.origin.x = self.titleLabel.frame.size.width + 5;
self.imageView.frame = imageViewF;
}
网友评论