POP动画[2]

POP动画[2]

 

1:定制控制器间的转场动画.

源码有点多-_-!!

//
//  RootViewController.h
//  Animation
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface RootViewController : UIViewController

@end

RootViewController.h
//
//  RootViewController.m
//  Animation
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import "RootViewController.h"

#import "ModelViewController.h"
#import "PresentingAnimator.h"
#import "DismissingAnimator.h"

#import "POP.h"

@interface RootViewController ()<UIViewControllerTransitioningDelegate>

@end

@implementation RootViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    UIButton *presentButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 150, 50)];
    [self.view addSubview:presentButton];
    presentButton.center = self.view.center;
    presentButton.layer.cornerRadius = 5.f;
    presentButton.backgroundColor = [UIColor redColor];

    [presentButton setTitle:@"推出控制器"
                   forState:UIControlStateNormal];

    // 添加button事件
    [presentButton addTarget:self
                      action:@selector(present:)
            forControlEvents:UIControlEventTouchUpInside];
}

- (void)present:(id)sender
{
    // 推出控制器
    ModelViewController *modalViewController = [ModelViewController new];

    // 设置转场动画代理
    modalViewController.transitioningDelegate = self;

    // 定制转场动画
    modalViewController.modalPresentationStyle = UIModalPresentationCustom;

    [self.navigationController presentViewController:modalViewController
                                            animated:YES
                                          completion:NULL];
}

#pragma mark - UIViewControllerTransitioningDelegate

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented
                                                                  presentingController:(UIViewController *)presenting
                                                                      sourceController:(UIViewController *)source
{
    // 推出控制器的动画
    return [PresentingAnimator new];
}

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
    // dismissing控制器的动画
    return [DismissingAnimator new];
}

@end

RootViewController.m
//
//  ModelViewController.h
//  Animation
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface ModelViewController : UIViewController

@end

ModelViewController.h
//
//  ModelViewController.m
//  Animation
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import "ModelViewController.h"

@interface ModelViewController ()

@end

@implementation ModelViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.view.layer.cornerRadius = 8.f;
    self.view.backgroundColor = [UIColor blackColor];
    [self addDismissButton];
}

- (void)addDismissButton
{
    UIButton *dismissButton = [UIButton buttonWithType:UIButtonTypeSystem];
    dismissButton.translatesAutoresizingMaskIntoConstraints = NO;
    dismissButton.tintColor = [UIColor whiteColor];
    dismissButton.titleLabel.font = [UIFont fontWithName:@"Avenir" size:20];
    [dismissButton setTitle:@"Dismiss" forState:UIControlStateNormal];
    [dismissButton addTarget:self
                      action:@selector(dismiss:)
            forControlEvents:UIControlEventTouchUpInside];

    [self.view addSubview:dismissButton];

    // 自动布局
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:dismissButton
                                                          attribute:NSLayoutAttributeCenterX
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:self.view
                                                          attribute:NSLayoutAttributeCenterX
                                                         multiplier:1.f
                                                           constant:0.f]];

    // 自动布局
    [self.view addConstraints:[NSLayoutConstraint
                               constraintsWithVisualFormat:@"V:[dismissButton]-|"
                               options:0
                               metrics:nil
                               views:NSDictionaryOfVariableBindings(dismissButton)]];
}

- (void)dismiss:(id)sender
{
    [self dismissViewControllerAnimated:YES
                             completion:nil];
}

@end

ModelViewController.m
//
//  PopAnimator.h
//  Popping
//
//  Created by André Schneider on 14.05.14.
//  Copyright (c) 2014 André Schneider. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface PresentingAnimator : NSObject <UIViewControllerAnimatedTransitioning>

@end

PresentingAnimator.h
//
//  PopAnimator.m
//  Popping
//
//  Created by André Schneider on 14.05.14.
//  Copyright (c) 2014 André Schneider. All rights reserved.
//

#import "PresentingAnimator.h"
#import "POP.h"

@implementation PresentingAnimator

// 转场动画时间
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
    return 0.5f;
}

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
    // 获取原始控制器的View
    UIView *fromView = \
        [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey].view;

    fromView.tintAdjustmentMode = UIViewTintAdjustmentModeDimmed;
    fromView.userInteractionEnabled = NO;

    // 获取推出控制器的View
    UIView *toView = \
        [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view;
    toView.frame = \
        CGRectMake(0, 0,
                   CGRectGetWidth(transitionContext.containerView.bounds) - 104.f,
                   CGRectGetHeight(transitionContext.containerView.bounds) - 288.f);

    // 设置toView的初始的位置
    toView.center = \
        CGPointMake(transitionContext.containerView.center.x,
                    -transitionContext.containerView.center.y);

    // 用来让背景变暗的动画效果
    UIView *dimmingView         = [[UIView alloc] initWithFrame:fromView.bounds];
    dimmingView.backgroundColor = [UIColor blackColor];
    dimmingView.layer.opacity   = 0.0;

    // 添加的转场动画容器当中
    [transitionContext.containerView addSubview:dimmingView];
    [transitionContext.containerView addSubview:toView];

    // 位置动画(Spring系列)
    POPSpringAnimation *positionAnimation = \
        [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPositionY];
    positionAnimation.toValue          = @(transitionContext.containerView.center.y);
    positionAnimation.springBounciness = 10;
    [positionAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {

        // 动画结束后记得设置这个参数
        [transitionContext completeTransition:YES];
    }];

    // 缩放动画(Spring系列)
    POPSpringAnimation *scaleAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerScaleXY];
    scaleAnimation.springBounciness    = 20;
    scaleAnimation.fromValue           = [NSValue valueWithCGPoint:CGPointMake(1.2, 1.4)];

    // 透明度动画(基本动画系列)
    POPBasicAnimation *opacityAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerOpacity];
    opacityAnimation.toValue            = @(0.7);

    // 添加动画
    [toView.layer pop_addAnimation:positionAnimation
                            forKey:@"positionAnimation"];

    [toView.layer pop_addAnimation:scaleAnimation
                            forKey:@"scaleAnimation"];

    [dimmingView.layer pop_addAnimation:opacityAnimation
                                 forKey:@"opacityAnimation"];
}

@end

PresentingAnimator.m
//
//  DismissingAnimator.h
//  Popping
//
//  Created by André Schneider on 16.05.14.
//  Copyright (c) 2014 André Schneider. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface DismissingAnimator : NSObject <UIViewControllerAnimatedTransitioning>

@end

DismissingAnimator.h
//
//  DismissingAnimator.m
//  Popping
//
//  Created by André Schneider on 16.05.14.
//  Copyright (c) 2014 André Schneider. All rights reserved.
//

#import "DismissingAnimator.h"
#import "POP.h"

@implementation DismissingAnimator

// 转场动画时间
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
    return 0.5f;
}

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
    /*
     - 在Dismiss动画中,transitionContext.containerView.subviews里面包含了
     - 之前添加进去的View哦,这点很重要
     */

    // 开启toVC的用户交互
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    toVC.view.tintAdjustmentMode = UIViewTintAdjustmentModeNormal;
    toVC.view.userInteractionEnabled = YES;

    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

    // 找到刚刚的那个用于改变透明度的View
    __block UIView *dimmingView;
    [transitionContext.containerView.subviews enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) {
        if (view.layer.opacity < 1.f) {
            dimmingView = view;
            *stop = YES;
        }
    }];

    // 改变透明度动画(基本动画类型)
    POPBasicAnimation *opacityAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerOpacity];
    opacityAnimation.toValue = @(0.0);

    // 改变位置动画(基本类型)
    POPBasicAnimation *offscreenAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerPositionY];

    offscreenAnimation.toValue = @(-fromVC.view.layer.position.y);
    [offscreenAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
        // 通知动画结束
        [transitionContext completeTransition:YES];
    }];

    // 执行动画
    [fromVC.view.layer pop_addAnimation:offscreenAnimation forKey:@"offscreenAnimation"];
    [dimmingView.layer pop_addAnimation:opacityAnimation forKey:@"opacityAnimation"];
}

@end

DismissingAnimator.m

 

2:TableView动画

//
//  RootTableViewController.h
//  POPTableView
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface RootTableViewController : UITableViewController

@end

RootTableViewController.h
//
//  RootTableViewController.m
//  POPTableView
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import "RootTableViewController.h"
#import "PopTableViewCell.h"

@interface RootTableViewController ()

@end

@implementation RootTableViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 50;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *resuseID = @"YouXianMing";

    PopTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:resuseID];

    if (cell == nil)
    {
        cell = [[PopTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                       reuseIdentifier:resuseID];
    }

    cell.showTitle.text = @"YouXianMing";

    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 50;
}

@end

RootTableViewController.m
//
//  PopTableViewCell.h
//  POPTableView
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface PopTableViewCell : UITableViewCell

@property (nonatomic, strong) UILabel  *showTitle;

@end

PopTableViewCell.h
//
//  PopTableViewCell.m
//  POPTableView
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import "PopTableViewCell.h"
#import "POP.h"

@implementation PopTableViewCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self)
    {
        _showTitle = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];
        [self addSubview:_showTitle];

        _showTitle.textAlignment = NSTextAlignmentCenter;
        _showTitle.font = [UIFont fontWithName:@"HelveticaNeue-Thin"
                                          size:20.f];
    }
    return self;
}

- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
{
    [super setHighlighted:highlighted animated:animated];

    if (self.highlighted)
    {
        // 选中时动画
        POPBasicAnimation *scaleAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPViewScaleXY];
        scaleAnimation.duration = 0.1;
        scaleAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(0.85, 0.85)];
        [_showTitle pop_addAnimation:scaleAnimation forKey:@"scaleAnimation"];
    }
    else
    {
        // 没有选中或者再次显示时的动画
        POPSpringAnimation *scaleAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewScaleXY];
        scaleAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(1, 1)];
        scaleAnimation.velocity = [NSValue valueWithCGPoint:CGPointMake(3, 3)];
        scaleAnimation.springBounciness = 20.f;
        [_showTitle pop_addAnimation:scaleAnimation forKey:@"scaleAnimation"];
    }
}

@end

PopTableViewCell.m

这个地方才是动画效果的关键哦:).

 

3:高逼格按钮动画

//
//  RootViewController.m
//  ButtonAnimation
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import "RootViewController.h"
#import "CAShapeLayer+Circle.h"
#import "POP.h"

@interface RootViewController ()<POPAnimationDelegate>

@property (nonatomic, strong) UIButton          *button;
@property (nonatomic, strong) CAShapeLayer      *circleShape1;
@property (nonatomic, strong) CAShapeLayer      *circleShape2;

@end

@implementation RootViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // 圆环1
    _circleShape1 = [CAShapeLayer LayerWithCircleCenter:self.view.center
                                                radius:70.f
                                            startAngle:DEGREES(0)
                                              endAngle:DEGREES(360)
                                             clockwise:YES
                                       lineDashPattern:nil];
    _circleShape1.lineWidth = 3.f;
    _circleShape1.strokeColor = [UIColor cyanColor].CGColor;
    _circleShape1.strokeEnd = 0.f;
    [self.view.layer addSublayer:_circleShape1];

    // 圆环2
    _circleShape2 = [CAShapeLayer LayerWithCircleCenter:self.view.center
                                                 radius:90.f
                                             startAngle:DEGREES(0)
                                               endAngle:DEGREES(360)
                                              clockwise:NO
                                        lineDashPattern:nil];
    _circleShape2.lineWidth = 1.f;
    _circleShape2.strokeColor = [UIColor magentaColor].CGColor;
    _circleShape2.strokeEnd = 0.f;
    [self.view.layer addSublayer:_circleShape2];

    // 完整显示按住按钮后的动画效果
    _button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    _button.layer.cornerRadius = 50.f;
    _button.backgroundColor = [UIColor cyanColor];
    _button.center = self.view.center;
    [self.view addSubview:_button];

    // 按住按钮后没有松手的动画
    [_button addTarget:self
                action:@selector(scaleToSmall)
      forControlEvents:UIControlEventTouchDown | UIControlEventTouchDragEnter];

    // 按住按钮松手后的动画
    [_button addTarget:self
                action:@selector(scaleAnimations)
      forControlEvents:UIControlEventTouchUpInside];

    // 按住按钮后拖拽出去的动画
    [_button addTarget:self
                action:@selector(scaleToDefault)
      forControlEvents:UIControlEventTouchDragExit];
}

- (void)scaleToSmall
{
    // 变小尺寸
    POPBasicAnimation *scaleAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerScaleXY];
    scaleAnimation.toValue = [NSValue valueWithCGSize:CGSizeMake(0.7f, 0.7f)];
    scaleAnimation.delegate = self; // 核心
    [_button.layer pop_addAnimation:scaleAnimation forKey:nil];

    // 颜色
    POPSpringAnimation *backgroundColor = \
        [POPSpringAnimation animationWithPropertyNamed:kPOPLayerBackgroundColor];
    backgroundColor.toValue = (id)[UIColor magentaColor].CGColor;
    [_button.layer pop_addAnimation:backgroundColor forKey:@"magentaColor"];
}

- (void)scaleAnimations
{
    // 恢复尺寸
    POPBasicAnimation *scaleAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerScaleXY];
    scaleAnimation.toValue = [NSValue valueWithCGSize:CGSizeMake(1.f, 1.f)];
    scaleAnimation.delegate = self; // 核心
    [_button.layer pop_addAnimation:scaleAnimation forKey:nil];

    // 颜色
    POPSpringAnimation *backgroundColor = \
    [POPSpringAnimation animationWithPropertyNamed:kPOPLayerBackgroundColor];
    backgroundColor.toValue = (id)[UIColor cyanColor].CGColor;
    [_button.layer pop_removeAnimationForKey:@"magentaColor"]; // 先移除再添加
    [_button.layer pop_addAnimation:backgroundColor forKey:nil];
}

- (void)scaleToDefault
{
    // 恢复尺寸
    POPBasicAnimation *scaleAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerScaleXY];
    scaleAnimation.toValue = [NSValue valueWithCGSize:CGSizeMake(1.f, 1.f)];
    scaleAnimation.delegate = self; // 核心
    [_button.layer pop_addAnimation:scaleAnimation forKey:nil];

    // 颜色
    POPSpringAnimation *backgroundColor = \
    [POPSpringAnimation animationWithPropertyNamed:kPOPLayerBackgroundColor];
    backgroundColor.toValue = (id)[UIColor cyanColor].CGColor;
    [_button.layer pop_removeAnimationForKey:@"magentaColor"]; // 先移除再添加
    [_button.layer pop_addAnimation:backgroundColor forKey:nil];
}

// 代理
- (void)pop_animationDidApply:(POPAnimation *)anim
{
    NSValue *toValue = (NSValue *)[anim valueForKeyPath:@"currentValue"];
    CGSize size = [toValue CGSizeValue];

    _circleShape1.strokeEnd = \
        (size.height - calculateConstant(0, 1, 1, 0.7))/calculateSlope(0, 1, 1, 0.7);

    _circleShape2.strokeEnd = \
        (size.height - calculateConstant(0, 1, 1, 0.7))/calculateSlope(0, 1, 1, 0.7);
}

CGFloat calculateSlope(CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2)
{
    return (y2 - y1) / (x2 - x1);
}

CGFloat calculateConstant(CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2)
{
    return (y1*(x2 - x1) - x1*(y2 - y1)) / (x2 - x1);
}

@end

几个非常核心的地方:

按钮的3个交互用状态一个都不能少哦:

需要实现动画的代理获取按钮的实时尺寸的信息,最为关键的一步哦:

计算一元一次方程:

时间: 2024-12-22 15:33:29

POP动画[2]的相关文章

ios-使用CAKeyframeAnimation导致导航栏的pop动画卡顿

问题描述 使用CAKeyframeAnimation导致导航栏的pop动画卡顿 我的一个提示框消失的时候,使用自定义的动画,用了CAKeyframeAnimation,此提示框消失的同时,导航栏执行pop viewcontroller操作,这时候,就出现了pop特效有卡顿的现象,如果我用UIView 的animateWithDuration 方法执行那个自定义的动画或者用uialertview代替我自己的提示框,pop特效就很流畅,这是什么原因呢? 代码如下: -(void)hideOnPopA

用POP动画编写带富文本的自定义动画效果

用POP动画编写带富文本的自定义动画效果 [源码] https://github.com/YouXianMing/UI-Component-Collection   [效果]   [特点] * 支持富文本 * 可定制型强(继承父类重写父类的startAnimation方法即可) * 支持动画的中断与持续 * 支持CAMediaTimingFunction * 数据与UI隔离,便于你封装属于你的类   [核心] // // POPNumberCount.h // POP // // Created

POP动画[3]

POP动画[3] 这一节主要讲解POP动画的自定义动画属性. POP动画中有一个参数,叫timingFunction,与CoreAnimation中的一个参数CAMediaTimingFunction基本一样,下图表示的是kCAMediaTimingFunctionEaseInEaseOut的曲线图. 下图是Spring动画效果: 我们可以使用自定义的属性来实现POP的库中没有提供的动画. 实现的效果: 源码: // // RootViewController.m // YXPOP // //

POP动画[1]

POP动画[1] pop动画是facebook扩展CoreAnimation的,使用及其方便:)   1:Spring系列的弹簧效果(两个动画kPOPLayerBounds与kPOPLayerCornerRadius同时运行) #import "RootViewController.h" #import "YXEasing.h" #import "POP.h" #import "YXGCD.h" @interface Root

用POP动画模拟真实秒钟摆动效果

用POP动画模拟真实秒钟摆动效果 静态图: 动画图: 此处用到了POP中的Spring系列动画,现提供源码如下: SecondClockView.h 与 SecondClockView.m // // SecondClockView.h // YouXianMingClock // // Created by YouXianMing on 14-10-12. // Copyright (c) 2014年 YouXianMing. All rights reserved. // #import <

ios7 push/pop转场动画

前言 iOS 7之后,苹果提供了自定义转场动画的API,我们可以自己去定义任意动画效果.本篇为笔者学习push.pop自定义转场效果的笔记,如何有任何不正确或者有指导意见的,请在评论中留下您的宝贵意见!!! 请注意:如果要求支持iOS 7以下版本,则不可使用此效果. 我们本篇文章目标效果: 视图切换种类 如下效果图,这是有两大类视图切换动画的,一种是交互式的,另一种就是自定义的. 本篇只讲其中的UIViewControllerAnimatedTransitioning协议,来实现push.pop

POP按钮动画

POP按钮动画   效果   源码 https://github.com/YouXianMing/Animations // // ButtonPressViewController.m // Facebook-POP-Animation // // Created by YouXianMing on 15/11/16. // Copyright 2015年 ZiPeiYi. All rights reserved. // #import "ButtonPressViewController.h

Swift:超炫的View Controller切换动画

匿名社交应用Secret的开发者开发了一款叫做Ping的应用,用户可以他们感兴趣的话题的推送. Ping有一个很炫的东西,就是主界面和之间切换的动画做的非常的好.每次看到一个非常炫的动画,都不由得会想:"这个东西我要不要自己实现以下".哈哈~~~ 这个教程里,你会学到如何用Swift实现这样的很酷的动画.你会学到如何使用shape layer,遮罩和使用UIViewControllerAnimnatedTransitioning协议和UIPercentDrivenInteractive

控制器转场动画详解

控制器转场动画详解   效果   说明 1. 控制器转场动画包括了普通控制器的present与dismiss转场动画,还有NavigationController的push与pop转场动画.其中,NavigationController的pop动画包含了回退百分比显示 2. 对转场动画对象进行行为抽象,让使用更加简单 3. 即使简化了使用,控制器转场动画也是属于比较难掌握的   源码 https://github.com/YouXianMing/ViewControllersTransition