動畫的世界豐富多彩,令人陶醉
隨著工作的深入正压,其實(shí)每個 App 中,最關(guān)鍵的莫過于用戶交互责球,隨著技術(shù)時代的發(fā)展焦履,人們已經(jīng)不再滿足于手指點(diǎn)點(diǎn)碰碰就完成功能。用戶更加期待炫酷的操作體驗(yàn)雏逾。需要眼前一亮的感覺嘉裤。這些都是 App 將要解決的問題。而動畫交互無疑是最多的一種手段栖博。但是屑宠,現(xiàn)在也不是簡單動畫的天下,需要更多的創(chuàng)意仇让,繁雜而簡潔的創(chuàng)意典奉。
動畫效果的UIView Object
// 顯示動畫
- (void)showWithDuration:(CGFloat)duration animated:(BOOL)animated;
// 隱藏動畫
- (void)hideWithDuration:(CGFloat)duration animated:(BOOL)animated;
// 創(chuàng)建view
- (void)buildView;
// 動畫百分比(手動設(shè)置動畫的程度)
- (void)percent:(CGFloat)percent;
制定統(tǒng)一的動畫接口
即:相關(guān)有動畫效果的類,有同一的動畫方法命名
- 為了實(shí)現(xiàn)后續(xù)復(fù)雜的動畫組合
- 后續(xù)的代碼維護(hù)極為方便
- 優(yōu)先考慮里氏代換原則
動畫中的高內(nèi)聚低耦合原理
- 高內(nèi)聚:有動畫效果的類丧叽,自身具有動畫方法
- 不要把實(shí)現(xiàn)動畫的細(xì)節(jié)暴露在外
- 設(shè)計(jì)動畫類盡量要符合單一職能原則卫玖,以便后續(xù)方便組合成復(fù)雜的動畫效果
設(shè)計(jì)動畫函數(shù)的注意事項(xiàng)
- 動畫方法的命名統(tǒng)一
- 預(yù)留非動畫情形的設(shè)計(jì)(tableView等reuse情況)
- 用百分比來表示動畫的執(zhí)行程度
- 懶加載的使用
動畫效果就是frame值的重新設(shè)定
[UIView animateWithDuration:duration animations:^{
self.frame = self.midRect;
self.alpha = 1.f;
}];
一個具有動畫效果的類
// TranslateView.h
#import <UIKit/UIKit.h>
@interface TranslateView : UIView
//** 顯示動畫 */
- (void)show;
/** 隱藏動畫 */
- (void)hide;
/** 創(chuàng)建view */
- (void)buildView;
/** 動畫百分比(手動設(shè)置動畫的程度) */
- (void)percent:(CGFloat)percent;
@end
// TranslateView.m
#import "TranslateView.h"
@interface TranslateView ()
@property (nonatomic) CGFloat offsetY;
@property (nonatomic) CGRect startRect;
@property (nonatomic) CGRect midRect;
@property (nonatomic) CGRect endRect;
@property (nonatomic) CGRect curRect;
@end
@implementation TranslateView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.alpha = 0.f;
self.offsetY = 20.0f;
self.backgroundColor = [UIColor blackColor];
[self buildView];
}
return self;
}
// 創(chuàng)建view
- (void)buildView {
self.startRect = self.frame;
self.midRect = CGRectMake(self.startRect.origin.x,
self.startRect.origin.y + self.offsetY,
self.startRect.size.width,
self.startRect.size.height);
self.endRect = CGRectMake(self.startRect.origin.x,
self.startRect.origin.y + self.offsetY * 2,
self.startRect.size.width,
self.startRect.size.height);
}
// 顯示動畫
- (void)showWithDuration:(CGFloat)duration animated:(BOOL)animated {
if (animated == YES) {
[UIView animateWithDuration:duration animations:^{
self.frame = self.midRect;
self.alpha = 1.f;
self.curRect = self.frame;
}];
} else {
self.frame = self.midRect;
self.alpha = 1.f;
self.curRect = self.frame;
}
}
// 隱藏動畫
- (void)hideWithDuration:(CGFloat)duration animated:(BOOL)animated {
if (animated == YES) {
[UIView animateWithDuration:duration animations:^{
self.frame = self.endRect;
self.alpha = 0.f;
} completion:^(BOOL finished) {
self.frame = self.startRect;
}];
} else {
self.frame = self.startRect;
self.alpha = 0.f;
}
}
// 動畫百分比(手動設(shè)置動畫的程度)
- (void)percent:(CGFloat)percent {
CGFloat tmpOffsetY = 0;
CGFloat stateHeight = 20;
if (percent <= 0) {
tmpOffsetY = percent * self.offsetY;
} else if (percent >= 1) {
tmpOffsetY = self.offsetY;
} else {
tmpOffsetY = percent * self.offsetY;
}
if (CGRectGetMinY(self.curRect) + tmpOffsetY < stateHeight || CGRectGetMaxY(self.curRect) + tmpOffsetY > CGRectGetHeight([UIScreen mainScreen].bounds)) {
return;
}
self.frame = CGRectMake(self.curRect.origin.x,
self.curRect.origin.y + tmpOffsetY,
self.curRect.size.width,
self.curRect.size.height);
self.curRect = self.frame;
}
- (void)show
{
[self showWithDuration:2.0f animated:YES];
}
- (void)hide
{
[self hideWithDuration:0.5f animated:YES];
}
@end
里氏代換原則處理動畫類的繼承問題
SourceView *tmpView = [[ChildTwoView alloc] init];
[tmpView show];
- 里氏代換原則的基本原理 (多態(tài))
- 設(shè)計(jì)中要確保父類可以直接調(diào)用子類的方法
- 將父類設(shè)計(jì)成虛類
什么是多態(tài)
1.定義
某一類事物的多種表現(xiàn)形態(tài)
舉例說明:
1)生活中:動物:貓—波斯貓
2)程序中:父類指針指向子類對象
2.條件
- 子類繼承父類
- 子類有重寫父類的方法
- 父類指針指向子類對象
動物 a = [貓 alloc]init];
動物 a = [狗 alloc]init];
表現(xiàn)形式:在父類指針指向不同的對象的時候,通過父類指針調(diào)用被重寫的方法踊淳,會執(zhí)行該指針?biāo)赶虻哪莻€對象的方法假瞬;
3.實(shí)現(xiàn)
@interface Computer : NSObject
- (void)system;
@end
@interface PC : Computer
// 重寫system方法
@end
@interface Mac : Computer
// 重寫system方法
@end
Computer *com = nil;
Computer = [PC alloc]init]; //實(shí)例化PC對象
[PC system];
Computer = [Mac alloc]init; //實(shí)例化Mac對象
[Mac system];
4.原理
- id類型:通用對象指針類型迂尝,弱類型脱茉,編譯的時候不進(jìn)行具體的類型檢查。
- 動態(tài)綁定:動態(tài)類型可以做到在程序直到執(zhí)行時才確定對象的真實(shí)類型雹舀,進(jìn)而確定需要調(diào)用那個對象方法芦劣。
ObjC 不同于其他程序設(shè)計(jì)語言,它可以在運(yùn)行的時候加入新的數(shù)據(jù)類型和新的程序模塊说榆,動態(tài)類型識別虚吟,動態(tài)綁定寸认,動態(tài)加載。
5.優(yōu)點(diǎn):
- 多態(tài)最重要的優(yōu)點(diǎn)在于簡化了編程接口串慰,何以理解?它允許在類和類之間重用一些習(xí)慣性的命名偏塞,而不是為每一個新加的函數(shù)命名一個新的名字。這樣邦鲫,編程接口就是一些抽象行為的集合灸叼,從而和實(shí)現(xiàn)接口的類區(qū)分開。
- 多態(tài)也使得代碼可以分散在不同的對象中庆捺,而不用視圖在一個函數(shù)中考慮到所有可能的對象古今。這樣可以優(yōu)化代碼的擴(kuò)展性和復(fù)用性。當(dāng)一個新的情景出現(xiàn)時滔以,無需對現(xiàn)有的代碼進(jìn)行改動捉腥,而只需要增加一個新的類和新的同名的方法。
詳細(xì)參考
動畫中的模塊化設(shè)計(jì)
- 動畫效果實(shí)現(xiàn)難度的判斷
- 將看到的動畫效果拆分成小模塊
- 將寫好的小模塊組合成你所需要的動畫效果
//ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// 復(fù)雜的動畫被寫進(jìn)了BaseAnimationView當(dāng)中你画,沒有暴露不必要的細(xì)節(jié)
BaseAnimationView *baseView = [[BaseAnimationView alloc] initWithFrame:CGRectZero];
[self.view addSubview:baseView];
[baseView show];
}
//BaseAnimationView.m
- (void)show
{
[self.translateView show];
}
- (void)hide
{
[self.translateView hide];
}
- (void)buildView
{
self.translateView = [[TranslateView alloc] initWithFrame:CGRectMake(50, 100, 2, 50)];
[self addSubview:self.translateView];
}
- (void)percent:(CGFloat)percent
{
[self.translateView percent:percent];
}
延時執(zhí)行某方法
[self performSelector:@selector(excuteAfterDelay) withObject:nil afterDelay:6];
初始化UIView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// ......
}
return self;
}