您的位置:首页 > 运维架构

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

2015-04-10 20:48 288 查看
用POP动画编写带富文本的自定义动画效果



【源码】

https://github.com/YouXianMing/UI-Component-Collection

【效果】



【特点】

* 支持富文本

* 可定制型强(继承父类重写父类的startAnimation方法即可)

* 支持动画的中断与持续

* 支持CAMediaTimingFunction

* 数据与UI隔离,便于你封装属于你的类

【核心】

//
//  POPNumberCount.h
//  POP
//
//  Created by XianMingYou on 15/4/10.
//  Copyright (c) 2015年 XianMingYou. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "POP.h"

@class POPNumberCount;

@protocol POPNumberCountDelegate <NSObject>
@optional
/**
*  最原始的方法
*
*  @param numberCount 对象自己
*  @param number      变化的值
*/
- (void)numberCount:(POPNumberCount *)numberCount currentNumber:(NSNumber *)number;

/**
*  子类可以实现的方法
*
*  @param numberCount 对象自己
*  @param string      子类返回的富文本
*/
- (void)numberCount:(POPNumberCount *)numberCount currentAttributedString:(NSAttributedString *)string;

/**
*  子类可以实现的方法
*
*  @param numberCount 对象自己
*  @param string      子类返回的文本
*/
- (void)numberCount:(POPNumberCount *)numberCount currentString:(NSString *)string;

@end

@interface POPNumberCount : NSObject

@property (nonatomic, weak)   id<POPNumberCountDelegate> delegate;       // 代理

@property (nonatomic, assign) CGFloat                    fromValue;      // 开始值
@property (nonatomic, assign) CGFloat                    toValue;        // 结束值
@property (nonatomic, assign) CGFloat                    currentValue;   // 当前值
@property (nonatomic, assign) NSTimeInterval             duration;       // 持续时间

@property (nonatomic, strong) CAMediaTimingFunction     *timingFunction; // 时间函数
@property (nonatomic, strong) POPBasicAnimation         *conutAnimation;

/*
*  存储值(执行动画之前,请先将设置的值进行存储)
*/
- (void)saveValues;

/*
*  开始动画(继承的子类需要重写本方法来,然后与代理一起配合使用)
*/
- (void)startAnimation;

/*
*  停止动画
*/
- (void)stopAnimation;

@end


//
//  POPNumberCount.m
//  POP
//
//  Created by XianMingYou on 15/4/10.
//  Copyright (c) 2015年 XianMingYou. All rights reserved.
//

#import "POPNumberCount.h"
#import "ConfigAttributedString.h"

@implementation POPNumberCount

- (instancetype)init {
self = [super init];
if (self) {
self.conutAnimation = [POPBasicAnimation animation];
}
return self;
}

- (void)saveValues {
self.conutAnimation.fromValue = @(self.fromValue);
self.conutAnimation.toValue   = @(self.toValue);
self.conutAnimation.duration  = (self.duration <= 0 ? 0.4f : self.duration);
if (self.timingFunction) {
self.conutAnimation.timingFunction = self.timingFunction;
}
}

- (void)startAnimation {
// 只有执行了代理才会执行计数引擎
if (self.delegate && [self.delegate respondsToSelector:@selector(numberCount:currentNumber:)]) {
/* 将计算出来的值通过writeBlock动态给控件设定 */
self.conutAnimation.property = \
[POPMutableAnimatableProperty propertyWithName:@"conutAnimation"
initializer:^(POPMutableAnimatableProperty *prop) {
prop.writeBlock      = ^(id obj, const CGFloat values[]) {
NSNumber *number = @(values[0]);
_currentValue    = values[0];

/* ------------- 子类重写父类的这个方法 ------------- */
[_delegate numberCount:self currentNumber:number];
/* ---------------------------------------------- */
};
}];

// 添加动画
[self pop_addAnimation:self.conutAnimation forKey:nil];
}
}

- (void)stopAnimation {
[self pop_removeAllAnimations];
}

@end


【说明】

父类 POPNumberCount 的设计类似于设计模式中的策略模式,提供接口让子类重写来实现不一样的功能,父类基本不会修改,具体到某个子类,只需要修改子类中的特定实现即可。(父类中的协议类似于一个个策略,具体由子类来实现)

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: