簡(jiǎn)單使用篇
簡(jiǎn)介
iOS10帶來(lái)了很多新特性,其中有個(gè) UIViewPropertyAnimator
類(lèi)烈炭,光從名字上就可以看出,這是一個(gè)操作屬性動(dòng)畫(huà)的類(lèi)宝恶。實(shí)際上符隙,這個(gè)類(lèi)能夠讓我們對(duì)視圖進(jìn)行動(dòng)畫(huà)控制趴捅,我們除了可進(jìn)行正常的運(yùn)行動(dòng)畫(huà),如開(kāi)始霹疫、暫停拱绑、重啟等操作動(dòng)畫(huà),還可以將動(dòng)畫(huà)轉(zhuǎn)換為交互式動(dòng)畫(huà)丽蝎,任意的控制時(shí)間猎拨。
它可以對(duì)視圖的可動(dòng)畫(huà)屬性進(jìn)行操作,例如frame屠阻,center红省,alpha 和 transform等,并且可以任意的添加多個(gè)動(dòng)畫(huà)塊和完成塊国觉,相比于之前的 UIView 動(dòng)畫(huà)吧恃,它改變了我們習(xí)慣的動(dòng)畫(huà)流程,變得更加靈活麻诀。
簡(jiǎn)單例子
改變一個(gè)視圖的 center 動(dòng)畫(huà):
// 創(chuàng)建動(dòng)畫(huà)器
UIViewPropertyAnimator* animator = [[UIViewPropertyAnimator alloc] initWithDuration:1.0
curve:UIViewAnimationCurveEaseOut
animations:^{
self.contentView.center = self.view.center;
}];
// 開(kāi)始動(dòng)畫(huà)
[animator startAnimation];
在使用 UIViewPropertyAnimator 做動(dòng)畫(huà)時(shí)痕寓,需要關(guān)注下面幾個(gè)點(diǎn):
- 包含改變一個(gè)或多個(gè)視圖屬性的動(dòng)畫(huà)塊
- 用于定義動(dòng)畫(huà)運(yùn)行過(guò)程中的時(shí)間速率曲線(xiàn)
- 動(dòng)畫(huà)的持續(xù)時(shí)間(以秒為單位)
- 動(dòng)畫(huà)完成塊(可選)
在上面的簡(jiǎn)單實(shí)例中,我們?cè)?秒的時(shí)間內(nèi)针饥,改變了視圖的中心位置厂抽,其中動(dòng)畫(huà)塊即為 animations 的代碼塊,在此代碼塊中我們可以針對(duì)可動(dòng)動(dòng)規(guī)劃進(jìn)行新增改變丁眼。對(duì)于運(yùn)行的動(dòng)畫(huà)時(shí)間速率筷凤,動(dòng)畫(huà)器 animator 支持 UIKit 動(dòng)畫(huà)中的時(shí)間速率函數(shù),即linear苞七、ease-in藐守、ease-out等。
一般來(lái)說(shuō)蹂风,我們所創(chuàng)建的動(dòng)畫(huà)器都是處于非活躍狀態(tài)卢厂,需要手動(dòng)調(diào)用-startAnimation
將其變?yōu)榛钴S狀態(tài)執(zhí)行動(dòng)畫(huà)。
初始化動(dòng)畫(huà)器
UIViewPropertyAnimator 為我們提供了多個(gè)快捷創(chuàng)建動(dòng)畫(huà)器的方法惠啄。
- 使用內(nèi)置
時(shí)間速率函數(shù)
-initWithDuration:curve:animations:
這種方式就是我們節(jié)例子中的使用到的創(chuàng)建方法慎恒,curve 參數(shù)即時(shí)間速率函數(shù),其所支持的以下幾種:
UIViewAnimationCurveEaseInOut //緩進(jìn)緩出
UIViewAnimationCurveEaseIn //緩進(jìn)
UIViewAnimationCurveEaseOut //緩出
UIViewAnimationCurveLinear //線(xiàn)性勻速
如果所說(shuō) UIKit 提供的速率曲線(xiàn)函數(shù)不能夠滿(mǎn)足你的執(zhí)行動(dòng)畫(huà)的速率要求撵渡,你還可以通過(guò)自定義來(lái)創(chuàng)建自己的速度曲線(xiàn)融柬。
- 使用
三次貝塞爾曲線(xiàn)
-initWithDuration:controlPoint1:controlPoint2:animations:
三次貝塞爾曲線(xiàn)的起點(diǎn)為(0,0)且其終點(diǎn)為(1,1),因此兩個(gè)控制點(diǎn)的取值范圍是(0,1)趋距。
- 使用
基于彈簧的彈性
-initWithDuration:dampingRatio:animations:
dampingRatio:
所對(duì)應(yīng)的參數(shù)叫做阻尼粒氧,一般去值為(0,1)較低的阻尼值對(duì)應(yīng)較小阻力和在靜止之前更多更大的振蕩节腐。反之則阻力大外盯,振蕩少而小摘盆。例如你想不振蕩的情況下平滑的減速動(dòng)畫(huà),就可以指定值為1饱苟。
// 創(chuàng)建動(dòng)畫(huà)器
UIViewPropertyAnimator* animator = [[UIViewPropertyAnimator alloc] initWithDuration:1.0
dampingRatio:0.35
animations:^{
self.contentView.center = CGPointMake(self.view.center.x+100, self.view.center.y);
}];
// 開(kāi)始動(dòng)畫(huà)
[animator startAnimation];
- 使用
自定義時(shí)間速率對(duì)象
-initWithDuration:timingParameters:
該方法需要你提供支持 UITimingCurveProvider
協(xié)議的對(duì)象孩擂,如果你要自定義實(shí)現(xiàn)此協(xié)議,必須提供所有屬性的實(shí)現(xiàn)掷空。
系統(tǒng)有兩個(gè)遵循該協(xié)議的類(lèi)
UICubicTimingParameters
UISpringTimingParameters
如果你查看UICubicTimingParameters
類(lèi)時(shí)肋殴,你會(huì)發(fā)現(xiàn),這個(gè)類(lèi)也只是提供了支持 UIKit 內(nèi)置的時(shí)間速率曲線(xiàn)和三次貝塞爾曲線(xiàn)坦弟。類(lèi)似的UISpringTimingParameters
也提供了CASpringAnimation
中的幾個(gè)物理參數(shù)。
示例:我們通過(guò)該方法實(shí)現(xiàn)一下和上一個(gè)方法類(lèi)似的效果
// 彈性的時(shí)間速率
UISpringTimingParameters* parameters = [[UISpringTimingParameters alloc] initWithDampingRatio:0.35];
// 創(chuàng)建動(dòng)畫(huà)器
UIViewPropertyAnimator* animator = [[UIViewPropertyAnimator alloc] initWithDuration:1.0 timingParameters:parameters];
// 由于該創(chuàng)建方法沒(méi)有動(dòng)畫(huà)塊官地,因此需要自行追加
[animator addAnimations:^{
self.contentView.center = CGPointMake(self.view.center.x+100, self.view.center.y);
}];
// 開(kāi)始動(dòng)畫(huà)
[animator startAnimation];
如果說(shuō)酿傍,你受不了每次都需要主動(dòng)調(diào)用-startAnimation
方法來(lái)啟動(dòng)視圖動(dòng)畫(huà),還是習(xí)慣 UIView 的快捷使用驱入!??赤炒,蘋(píng)果似乎注意到了這一點(diǎn),為了適應(yīng)開(kāi)發(fā)者的習(xí)慣亏较,除了上述幾種創(chuàng)建動(dòng)畫(huà)器的方式莺褒,還有一種可以啟動(dòng)開(kāi)啟動(dòng)畫(huà)并能返回當(dāng)前動(dòng)畫(huà)器的方法。
- 類(lèi)方法便捷創(chuàng)建
+ runningPropertyAnimatorWithDuration:delay:options:animations:completion:
該方法提供了動(dòng)畫(huà)的幾個(gè)相對(duì)比較重要的參數(shù)雪情,如動(dòng)畫(huà)執(zhí)行時(shí)間遵岩、延遲時(shí)間、時(shí)間速率巡通、動(dòng)畫(huà)塊尘执、完成塊。該方法兼容了 UIView 動(dòng)畫(huà)塊的形式宴凉。
[UIViewPropertyAnimator runningPropertyAnimatorWithDuration:1.0
delay:0
options:UIViewAnimationCurveEaseOut
animations:^{
self.contentView.center = CGPointMake(self.view.center.x+100, self.view.center.y);
}
completion:^(UIViewAnimatingPosition finalPosition) {}];
控制動(dòng)畫(huà)
UIViewPropertyAnimator 遵守了 UIViewImplicitlyAnimating 協(xié)議誊锭,而UIViewImplicitlyAnimating 協(xié)議是 UIViewAnimating 協(xié)議的子類(lèi),該類(lèi)定義了如何控制動(dòng)畫(huà)的協(xié)議弥锄。除了上一節(jié)中使用到的-startAnimation
方法丧靡,還有其他幾個(gè)控制動(dòng)畫(huà)的方法。
- 開(kāi)始執(zhí)行動(dòng)畫(huà)
-startAnimation
:方法可以啟動(dòng)動(dòng)畫(huà)或者在暫停動(dòng)畫(huà)后恢復(fù)動(dòng)畫(huà)籽暇。
-startAnimationAfterDelay:
:和上面方法類(lèi)似温治,不過(guò)可以指定延遲執(zhí)行的時(shí)間
- 暫停動(dòng)畫(huà)
-pauseAnimation
:暫停動(dòng)畫(huà),當(dāng)使用該方法后图仓,動(dòng)畫(huà)會(huì)停留在“當(dāng)前位置”罐盔,會(huì)保持當(dāng)前的狀態(tài)。暫停后可以使用-startAnimation
恢復(fù)救崔,恢復(fù)的動(dòng)畫(huà)會(huì)從“當(dāng)前位置”繼續(xù)剩余的動(dòng)畫(huà)惶看,包括剩余的時(shí)間捏顺。
示例:我們執(zhí)行一個(gè)2秒時(shí)長(zhǎng)的動(dòng)畫(huà),在1秒處停止纬黎,延遲1秒后恢復(fù)動(dòng)畫(huà)幅骄,讓其繼續(xù)執(zhí)行。
UIViewPropertyAnimator* animator = [UIViewPropertyAnimator runningPropertyAnimatorWithDuration:2.0 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
self.contentView.center = CGPointMake(self.view.center.x+100, self.view.center.y);
} completion:nil];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 暫停當(dāng)前動(dòng)畫(huà)
[animator pauseAnimation];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 恢復(fù)動(dòng)畫(huà)
[animator startAnimation];
});
});
-
-stopAnimation:
:停止動(dòng)畫(huà)
停止動(dòng)畫(huà)有多種情況本今,由于動(dòng)畫(huà)狀態(tài)的機(jī)制(進(jìn)階篇會(huì)講)的存在拆座,當(dāng)我們停止動(dòng)畫(huà)后,這些動(dòng)畫(huà)狀態(tài)信息何去何從冠息?蘋(píng)果給出了兩種的去處挪凑,一種時(shí)清除所有狀態(tài)信息,動(dòng)畫(huà)器重置為初始的非活躍狀態(tài)逛艰,以等待下一個(gè)動(dòng)畫(huà)躏碳;另外一種是保留所有狀態(tài)信息,等待下一步操作散怖。這里的 withoutFinishing 參數(shù)就是用來(lái)指明去處菇绵。
參數(shù) withoutFinishing,表示是否應(yīng)執(zhí)行任何最終操作镇眷。如果值為 YES咬最,則會(huì)清除任何動(dòng)畫(huà)并將動(dòng)畫(huà)器重置為非活躍狀態(tài),并且不會(huì)執(zhí)行完成塊的回調(diào)欠动。
示例:我們執(zhí)行一個(gè)2秒的動(dòng)畫(huà)永乌,在一秒處停止當(dāng)前動(dòng)畫(huà),并且在完成塊中將視圖的背景色更改為紅色翁垂。
UIViewPropertyAnimator* animator = [UIViewPropertyAnimator runningPropertyAnimatorWithDuration:2.0 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
self.contentView.center = CGPointMake(self.view.center.x+100, self.view.center.y);
} completion:^(UIViewAnimatingPosition finalPosition) {
// 動(dòng)畫(huà)的完成回調(diào)
self.contentView.backgroundColor = UIColor.redColor;
}];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[animator stopAnimation:YES];
});
運(yùn)行結(jié)果發(fā)現(xiàn)铆遭,動(dòng)畫(huà)在1秒處停止了,但是并沒(méi)變成紅色背景沿猜,這說(shuō)明枚荣,此時(shí)的動(dòng)畫(huà)器并不會(huì)執(zhí)行完成塊。
當(dāng)參數(shù)為 NO 時(shí)啼肩,動(dòng)畫(huà)器狀態(tài)為 stopped橄妆,此時(shí)通常會(huì)配合finishAnimationAtPosition:
使用,該方法可以幫助動(dòng)畫(huà)器執(zhí)行最終的完成塊的內(nèi)容祈坠,當(dāng)然害碾,這兩個(gè)方法的目的是停下當(dāng)前動(dòng)畫(huà),讓你完成此刻需要完成的內(nèi)容赦拘,如其他動(dòng)畫(huà)慌随,之后,你再使用finishAnimationAtPosition:
完成動(dòng)畫(huà)的回調(diào)以及動(dòng)畫(huà)需要停止的位置。
在演示示例之前阁猜,我們來(lái)介紹一下finishAnimationAtPosition:
丸逸。
-
-finishAnimationAtPosition:
:結(jié)束動(dòng)畫(huà)
該方法可以將處于 stopped 狀態(tài)的動(dòng)畫(huà)重置為非活躍狀態(tài)宇色,并執(zhí)行動(dòng)畫(huà)的完成塊喇澡。
此方法通常配合 -stopAnimation:
使用,并且該方法必須在動(dòng)畫(huà)器狀態(tài)為 stopped 狀態(tài)才可以诫尽,否則會(huì)出現(xiàn)錯(cuò)誤民效。該方法的 UIViewAnimatingPosition
參數(shù)有一下三種:
UIViewAnimatingPositionEnd //動(dòng)畫(huà)的終點(diǎn)位置
UIViewAnimatingPositionStart //動(dòng)畫(huà)的開(kāi)頭位置
UIViewAnimatingPositionCurrent //動(dòng)畫(huà)當(dāng)前位置
指定 UIViewAnimatingPositionCurrent 以使視圖屬性與其當(dāng)前值保持不變憔维。
示例:我們繼續(xù)之前的例子,這次我們配合 -finishAnimationAtPosition:
方法使用畏邢。
UIViewPropertyAnimator* animator = [UIViewPropertyAnimator runningPropertyAnimatorWithDuration:2.0 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
self.contentView.center = CGPointMake(self.view.center.x+100, self.view.center.y);
} completion:^(UIViewAnimatingPosition finalPosition) {
// 動(dòng)畫(huà)的完成回調(diào)
self.contentView.backgroundColor = UIColor.redColor;
}];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[animator stopAnimation:NO];
// 動(dòng)畫(huà)器的狀態(tài)必須是stopped
if (animator.state==UIViewAnimatingStateStopped) {
[animator finishAnimationAtPosition:UIViewAnimatingPositionCurrent];
}
});
我們發(fā)現(xiàn)业扒,動(dòng)畫(huà)運(yùn)行1秒后停止了,并且背景色被填充為紅色舒萎,這說(shuō)明-finishAnimationAtPosition:
觸發(fā)完成塊凶赁,這一點(diǎn)和之前的例子是不同的。另外逆甜,我們看到視圖停下來(lái)之后就保持在了當(dāng)前位置,這是因?yàn)槲覀兘o的結(jié)束位置就是 Current致板。下圖演示了位置的不同參數(shù)的效果交煞。
交互式動(dòng)畫(huà)
fractionComplete 屬性
UIViewPropertyAnimator 類(lèi)中有一個(gè)fractionComplete
屬性素征,這個(gè)屬性表示當(dāng)前動(dòng)畫(huà)的完成的百分比,并且這個(gè)屬性不是只讀的屬性萝挤,這說(shuō)明我們可以精準(zhǔn)的控制動(dòng)畫(huà)的整個(gè)過(guò)程御毅。利用它,我們可以制作交互式動(dòng)畫(huà)怜珍。交互式動(dòng)畫(huà)的好處是:對(duì)于多個(gè)視圖端蛆、非常復(fù)雜的視圖變化加以控制變得簡(jiǎn)單。
示例:
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIView *blueView;
@property (weak, nonatomic) IBOutlet UIView *redView;
@property (weak, nonatomic) IBOutlet UISlider *slider;
@property (strong, nonatomic) UIViewPropertyAnimator* animator;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 初始化動(dòng)畫(huà)器
self.animator = [[UIViewPropertyAnimator alloc] initWithDuration:2.0 curve:UIViewAnimationCurveLinear animations:^{
// 紅色視圖
CGRect fram = CGRectMake(self.slider.center.x - 50/2.0, self.slider.center.y - 100, 50, 50);
self.redView.frame = fram;
self.redView.transform = CGAffineTransformMakeRotation(M_PI);
self.redView.backgroundColor = UIColor.blueColor;
// 藍(lán)色視圖
self.blueView.frame = fram;
self.blueView.transform = self.redView.transform;
self.blueView.backgroundColor = UIColor.redColor;
}];
[self.slider addTarget:self action:@selector(change:) forControlEvents:UIControlEventValueChanged];
}
-(void)change:(UISlider*)slider{
CGFloat value = slider.value;
// 更改動(dòng)畫(huà)完成度
self.animator.fractionComplete = value;
}
需要注意的是酥泛,在使用fractionComplete
之前今豆,最好調(diào)用-pauseAnimation
暫停當(dāng)前動(dòng)畫(huà),此時(shí)動(dòng)畫(huà)處于活躍狀態(tài)柔袁,但非isRunning
呆躲。
修改動(dòng)畫(huà)
正如前面簡(jiǎn)介中提到過(guò),UIViewPropertyAnimator 可以修改動(dòng)畫(huà)捶索,甚至是在動(dòng)畫(huà)處于運(yùn)行狀態(tài)插掂。我們可以添加多個(gè)動(dòng)畫(huà)塊、完成塊,設(shè)置是暫停掉正在執(zhí)行的動(dòng)畫(huà)辅甥,并且修改它的剩余時(shí)間酝润,這讓我們更加的精準(zhǔn)的控制視圖的動(dòng)畫(huà)行為。
-
-addAnimations:
:為視圖添加動(dòng)畫(huà)塊
我們之前在使用自定義時(shí)間速率對(duì)象
初始化動(dòng)畫(huà)器時(shí)肆氓,曾經(jīng)使用到過(guò)該方法袍祖,此方法可以讓我們對(duì)視圖的動(dòng)畫(huà)追加多個(gè)動(dòng)畫(huà)塊。
示例:我們?yōu)檎谶\(yùn)動(dòng)的視圖添加漸變動(dòng)畫(huà)
UIViewPropertyAnimator* animator = [UIViewPropertyAnimator runningPropertyAnimatorWithDuration:1.0 delay:0 options:UIViewAnimationCurveLinear animations:^{
self.contentView.center = CGPointMake(self.view.center.x+100, self.view.center.y);
} completion:nil];
// 追加動(dòng)畫(huà)塊
[animator addAnimations:^{
self.contentView.backgroundColor = UIColor.redColor;
}];
我們追加的動(dòng)畫(huà)塊會(huì)和其他動(dòng)畫(huà)共享動(dòng)畫(huà)器剩余的時(shí)間谢揪。
示例:延遲追加動(dòng)畫(huà)
為了明顯的看出效果蕉陋,我們給予更長(zhǎng)的動(dòng)畫(huà)時(shí)間,并在運(yùn)行一段時(shí)間后拨扶,追加動(dòng)畫(huà)凳鬓。
UIViewPropertyAnimator* animator = [UIViewPropertyAnimator runningPropertyAnimatorWithDuration:4.0 delay:0 options:UIViewAnimationCurveLinear animations:^{
self.contentView.center = CGPointMake(self.view.center.x+100, self.view.center.y);
} completion:nil];
// 追加動(dòng)畫(huà)塊
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[animator addAnimations:^{
self.contentView.backgroundColor = UIColor.redColor;
}];
});
我們看到2秒后追加的漸變動(dòng)畫(huà)在剩余的2秒內(nèi)完成了漸變效果。
當(dāng)然患民,蘋(píng)果已經(jīng)給出了類(lèi)似的方法缩举,無(wú)需我們主動(dòng)寫(xiě)延遲方法。就像下面的演示匹颤。
-
-addAnimations:delayFactor:
:延遲追加動(dòng)畫(huà)塊
參數(shù)delayFactor
是指時(shí)間因子仅孩,即動(dòng)畫(huà)的進(jìn)度,取值區(qū)間為(0印蓖,1)辽慕。比如,0.5表示動(dòng)畫(huà)執(zhí)行一半的時(shí)候執(zhí)行赦肃。
示例:我們使用該方法完成之前的例子
UIViewPropertyAnimator* animator = [UIViewPropertyAnimator runningPropertyAnimatorWithDuration:4.0 delay:0 options:UIViewAnimationCurveLinear animations:^{
self.contentView.center = CGPointMake(self.view.center.x+100, self.view.center.y);
} completion:nil];
// 延遲追加動(dòng)畫(huà)塊
[animator addAnimations:^{
self.contentView.backgroundColor = UIColor.redColor;
} delayFactor:0.5];
-
-addCompletion:
:追加完成塊
既然動(dòng)畫(huà)塊都可以追加修改溅蛉,那么完成塊也應(yīng)該相應(yīng)的有追加方法呀!
在初始化以動(dòng)畫(huà)器一節(jié)中他宛,我們發(fā)現(xiàn)大部分都是不帶有完成塊回調(diào)的船侧,蘋(píng)果似乎考慮到開(kāi)發(fā)過(guò)程中很少會(huì)關(guān)心動(dòng)畫(huà)的完成事件吧,因此為了方法的簡(jiǎn)潔性厅各,就讓其變成了可選特性镜撩,又或者這樣設(shè)計(jì)會(huì)讓動(dòng)畫(huà)變得更加的靈活,因?yàn)檫@樣讯检,動(dòng)畫(huà)的完成事件就無(wú)需緊跟在初始化方法上了琐鲁。
示例:我們?cè)趧?dòng)畫(huà)執(zhí)行完成時(shí)執(zhí)行一些事情
這里為了方便看到效果,我們就直接來(lái)改變視圖的顏色人灼。
UIViewPropertyAnimator* animator = [[UIViewPropertyAnimator alloc] initWithDuration:1.0 curve:UIViewAnimationCurveLinear animations:^{
self.contentView.center = CGPointMake(self.view.center.x+100, self.view.center.y);
}];
[animator startAnimation];
// 追加完成塊
[animator addCompletion:^(UIViewAnimatingPosition finalPosition) {
self.contentView.backgroundColor = UIColor.redColor;
}];
在【控制動(dòng)畫(huà)】一節(jié)中围段,我們提到過(guò),我們可以調(diào)用-startAnimation
:來(lái)恢復(fù)暫停后的動(dòng)畫(huà)投放,但是這樣做的話(huà)奈泪,動(dòng)畫(huà)的形式依舊是之前設(shè)置好的情況,它并不會(huì)發(fā)生變化。那么涝桅,如果想要暫定動(dòng)畫(huà)后拜姿,執(zhí)行其他時(shí)間速率的動(dòng)畫(huà)該怎么辦呢? UIViewPropertyAnimator 可以讓我們?nèi)我獾目刂苿?dòng)畫(huà)冯遂,必然會(huì)提供該類(lèi)方法蕊肥。
-
-continueAnimationWithTimingParameters:durationFactor:
:暫停后修改動(dòng)畫(huà)方式繼續(xù)執(zhí)行
該類(lèi)方法只會(huì)在調(diào)用-pauseAnimation
方法之后起到作用,此時(shí)的動(dòng)畫(huà)狀態(tài)為蛤肌,活躍但非isRunning
壁却。
參數(shù)durationFactor
是時(shí)間因子,表示動(dòng)畫(huà)的進(jìn)度裸准。通痴苟可以取fractionComplete
屬性。
示例:我們將勻速運(yùn)行中的視圖中途改為彈性運(yùn)動(dòng)
UIViewPropertyAnimator* animator = [[UIViewPropertyAnimator alloc] initWithDuration:2 curve:UIViewAnimationCurveLinear animations:^{
self.contentView.center = CGPointMake(self.view.center.x+100, self.view.center.y);
}];
[animator startAnimation];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 暫停動(dòng)畫(huà)之后
[animator pauseAnimation];
// 暫停動(dòng)畫(huà)之后炒俱,修改動(dòng)畫(huà)時(shí)間速率后繼續(xù)動(dòng)畫(huà)
UISpringTimingParameters* timing = [[UISpringTimingParameters alloc] initWithDampingRatio:0.2];
[animator continueAnimationWithTimingParameters:timing durationFactor:animator.fractionComplete];
});
上圖演示了中途更改的動(dòng)畫(huà)情況盐肃,其中,底下的視圖為參考視圖权悟,即未改變的勻速運(yùn)動(dòng)砸王。
以上就是快速入門(mén)使用的所有教程了,相信經(jīng)過(guò)一系列的介紹之后峦阁,你能夠快速的使用新的動(dòng)畫(huà)方式了处硬。
接下來(lái)的進(jìn)階篇,會(huì)講解一些 UIViewPropertyAnimator 的一些細(xì)節(jié)部分拇派。
進(jìn)階篇
動(dòng)畫(huà)協(xié)議
其實(shí)要介紹 UIViewPropertyAnimator 類(lèi)前,應(yīng)該先介紹其遵循的動(dòng)畫(huà)協(xié)議--UIViewAnimating 和 UIViewImplicitlyAnimating 凿跳。前者是后者的父類(lèi)件豌,我們先來(lái)解釋 UIViewAnimating 協(xié)議。該協(xié)議定義了操作動(dòng)畫(huà)的基本方法控嗜,包括啟動(dòng)茧彤、停止、暫停動(dòng)畫(huà)的能力疆栏。另外還有幾個(gè)屬性用于反映動(dòng)畫(huà)的當(dāng)前狀態(tài)信息曾掂。
UIViewPropertyAnimator 遵循并實(shí)現(xiàn)了 UIViewAnimating 協(xié)議的所有方法,因此我們可以用 UIViewPropertyAnimator 來(lái)實(shí)現(xiàn)動(dòng)畫(huà)的控制壁顶。如果你想在自定義類(lèi)中也遵循此協(xié)議珠洗,最好實(shí)現(xiàn)所有的協(xié)議方法和屬性。
動(dòng)畫(huà)的狀態(tài)
UIViewPropertyAnimator 有著一套完整的狀態(tài)機(jī)制若专。在動(dòng)畫(huà)器處理一組動(dòng)畫(huà)時(shí)许蓖,都會(huì)伴隨著這一系列的動(dòng)畫(huà)狀態(tài)。這些狀態(tài)定義了動(dòng)畫(huà)器的行為,包括它是如何處理變化的膊爪。如果你在實(shí)現(xiàn)自定義動(dòng)畫(huà)器自阱,必須遵循這些狀態(tài)的轉(zhuǎn)換并準(zhǔn)確的更新?tīng)顟B(tài)屬性。下圖顯示了發(fā)生的狀態(tài)和狀態(tài)轉(zhuǎn)換關(guān)系米酬。
Inactive
非活躍狀態(tài)是動(dòng)畫(huà)器的初始狀態(tài)沛豌。每個(gè)新創(chuàng)建的動(dòng)畫(huà)器都會(huì)處于非活躍狀態(tài)下啟動(dòng)。相對(duì)的赃额,動(dòng)畫(huà)正常完成后會(huì)返回到非活躍狀態(tài)加派。
當(dāng)我們調(diào)用-startAnimation
或-pauseAnimation
方法時(shí),此時(shí)動(dòng)畫(huà)器會(huì)變?yōu)?code>Active活躍狀態(tài)爬早。此狀態(tài)下的動(dòng)畫(huà)器正在運(yùn)行或暫停狀態(tài)哼丈。如果是動(dòng)畫(huà)被暫停,我們此時(shí)還可以修改動(dòng)畫(huà)時(shí)間速率曲線(xiàn)筛严,讓后讓其繼續(xù)運(yùn)行到預(yù)期結(jié)束醉旦,結(jié)束后的動(dòng)畫(huà)器狀態(tài)依舊是Inactive
非活躍狀態(tài),等待我們使用一組新的動(dòng)畫(huà)重新配置它桨啃,以便開(kāi)始新的動(dòng)畫(huà)车胡。
當(dāng)我們開(kāi)啟動(dòng)畫(huà)之后,調(diào)用-stopAnimation:
方法會(huì)停止正在運(yùn)行的動(dòng)畫(huà)照瘾,此時(shí)視圖會(huì)被保留在停止的那一刻的值匈棘。此方法的參數(shù)值決定了當(dāng)前的動(dòng)畫(huà)信息是否被擦除。如果參數(shù) withoutFinishing 是 YES析命,則表示擦除當(dāng)前動(dòng)畫(huà)的信息主卫,動(dòng)畫(huà)器進(jìn)入Inactive
狀態(tài),需要注意鹃愤,這種情況下簇搅,動(dòng)畫(huà)器是不會(huì)執(zhí)行完成塊的,換句話(huà)說(shuō)你無(wú)法在完成塊中得到動(dòng)畫(huà)結(jié)束信息软吐,此時(shí)如果你需要知道動(dòng)畫(huà)結(jié)束的事件瘩将,你可以使用 KVO 的方法監(jiān)聽(tīng)屬性isRunning
獲得。如果參數(shù) withoutFinishing 是 NO凹耙,則表示保留當(dāng)前動(dòng)畫(huà)的信息姿现,動(dòng)畫(huà)器進(jìn)入Stopped
狀態(tài),此時(shí)我們可以去完成其他的操作肖抱,如執(zhí)行其他動(dòng)畫(huà)备典。然后我們調(diào)用方法-finishAnimationAtPosition:
以結(jié)束此次動(dòng)畫(huà),動(dòng)畫(huà)器順理成章的進(jìn)入到Inactive
狀態(tài)意述。注意熊经,這情情況下泽艘,動(dòng)畫(huà)器可以順利的執(zhí)行完成塊內(nèi)容。
動(dòng)畫(huà)狀態(tài)的幾個(gè)枚舉:
typedef NS_ENUM(NSInteger, UIViewAnimatingState)
{
UIViewAnimatingStateInactive, // The animation is not executing.
UIViewAnimatingStateActive, // The animation is executing.
UIViewAnimatingStateStopped, // The animation has been stopped and has not transitioned to inactive.
} NS_ENUM_AVAILABLE_IOS(10_0) ;
協(xié)議內(nèi)容
方法
-
-startAnimation
開(kāi)始動(dòng)畫(huà)
不可以在動(dòng)畫(huà)器調(diào)用方法-stopAnimation:
直接結(jié)束動(dòng)畫(huà)后再次調(diào)用-startAnimation
镐依,換句話(huà)說(shuō)匹涮,使用過(guò)程中,出現(xiàn)下面情況會(huì)出錯(cuò):
我們發(fā)現(xiàn)槐壳,在我們-stopAnimation:
指定參數(shù)為 YES時(shí)然低,動(dòng)畫(huà)器狀態(tài)由活躍狀態(tài)Active
轉(zhuǎn)變?yōu)榉腔钴S狀態(tài)Inactive
,此時(shí)再次調(diào)用-startAnimation
時(shí)务唐,系統(tǒng)拋出了異常雳攘。
而我們指定參數(shù)為 NO時(shí),
此時(shí)動(dòng)畫(huà)器狀態(tài)為stopped
枫笛,程序并未出錯(cuò)吨灭。
這一點(diǎn)和官方文檔的說(shuō)明并不一致,目前還不是很清楚原因刑巧。
It is a programmer error to call this method while the state of the animator is set to UIViewAnimatingStateStopped.
??:11-29喧兄,以上結(jié)論基于10.3.2系統(tǒng),但是筆者使用11以上的系統(tǒng)發(fā)現(xiàn)啊楚,結(jié)論和上述相反吠冤,卻和官方文檔一致,即動(dòng)畫(huà)器狀態(tài)為
stopped
下恭理,不能使用-startAnimation
拯辙。這一點(diǎn)讓我更加凌亂了,難道后面的系統(tǒng)修正了颜价?
-
-startAnimationAfterDelay:
延遲后開(kāi)始動(dòng)畫(huà)
上面的開(kāi)啟動(dòng)畫(huà)一樣的注意點(diǎn)同樣適用涯保。(請(qǐng)注意上面 11-29 的說(shuō)明)
另外經(jīng)測(cè)試發(fā)現(xiàn),-pauseAnimation
之后調(diào)用-startAnimationAfterDelay:
會(huì)發(fā)生程序錯(cuò)誤周伦。
-
-pauseAnimation
暫停動(dòng)畫(huà)
暫停動(dòng)畫(huà)后遭赂,可以使用-startAnimation
方法重新恢復(fù)動(dòng)畫(huà),另外你也可以使用協(xié)議UIViewImplicitlyAnimating
中的continueAnimationWithTimingParameters:durationFactor:
恢復(fù)動(dòng)畫(huà)横辆。如果動(dòng)畫(huà)已經(jīng)暫停,則再次調(diào)用-pauseAnimation
不會(huì)執(zhí)行任何操作茄猫。
經(jīng)測(cè)試發(fā)現(xiàn)如果動(dòng)畫(huà)器從未啟動(dòng)過(guò)狈蚤,直接調(diào)用-pauseAnimation
方法,如果緊接著調(diào)用-startAnimation
或者continueAnimationWithTimingParameters:durationFactor:
是無(wú)法恢復(fù)動(dòng)畫(huà)的划纽,之間需要大于千分之一秒的時(shí)間脆侮,就像下面的情況:
無(wú)法恢復(fù)動(dòng)畫(huà)的情況:
[self.animator pauseAnimation];
[self.animator startAnimation];
//[self.animator continueAnimationWithTimingParameters:[[UICubicTimingParameters alloc] initWithAnimationCurve:UIViewAnimationCurveLinear] durationFactor:0.5];
如果之前調(diào)用過(guò)開(kāi)啟動(dòng)畫(huà),則可以恢復(fù)動(dòng)畫(huà)
[self.animator startAnimation];
...
[self.animator pauseAnimation];
[self.animator startAnimation];
//[self.animator continueAnimationWithTimingParameters:[[UICubicTimingParameters alloc] initWithAnimationCurve:UIViewAnimationCurveLinear] durationFactor:0.5];
又或者添加延遲
// 從未開(kāi)啟過(guò)勇劣,暫停動(dòng)畫(huà)
[self.animator pauseAnimation];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.002 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self.animator startAnimation];
// [self.animator continueAnimationWithTimingParameters:[[UICubicTimingParameters alloc] initWithAnimationCurve:UIViewAnimationCurveLinear] durationFactor:0.5];
});
至于為什么會(huì)時(shí)這種情況靖避,官方文檔并未指出潭枣,或許只有蘋(píng)果自己清楚吧。
另外幻捏,官方文檔指出動(dòng)畫(huà)器為stopped
狀態(tài)時(shí)盆犁,調(diào)用-pauseAnimation
會(huì)出現(xiàn)程序錯(cuò)誤,但并沒(méi)有篡九。
??:11-29谐岁,以上結(jié)論基于10.3.2系統(tǒng),使用11以上的系統(tǒng)發(fā)現(xiàn)并不會(huì)出現(xiàn)【無(wú)法啟動(dòng)暫停動(dòng)畫(huà)】的情況榛臼,并且伊佃,動(dòng)畫(huà)器為
stopped
狀態(tài)時(shí),調(diào)用-pauseAnimation
時(shí)沛善,確實(shí)出現(xiàn)程序錯(cuò)誤航揉。
-
-stopAnimation:
停止動(dòng)畫(huà)
需要注意的是,不可以在動(dòng)畫(huà)器狀態(tài)由Active
轉(zhuǎn)為為stopped
的時(shí)候再調(diào)用該方法金刁。下面的使用會(huì)發(fā)生程序錯(cuò)誤:
上圖中的調(diào)用-pauseAnimation
將動(dòng)畫(huà)器轉(zhuǎn)為Active
也會(huì)出現(xiàn)錯(cuò)誤帅涂。
這一點(diǎn),官方文檔卻并未提及胀葱。why漠秋?
-
-finishAnimationAtPosition:
結(jié)束動(dòng)畫(huà)
該方法通常會(huì)和上面的停止方法相結(jié)合,用來(lái)結(jié)束當(dāng)前停止下來(lái)(狀態(tài)為stopped
)動(dòng)畫(huà)順利回到Inactive
狀態(tài)抵屿。經(jīng)測(cè)試庆锦,該方法只認(rèn)stopped
狀態(tài),其他兩個(gè)狀態(tài)都會(huì)發(fā)生錯(cuò)誤轧葛。
屬性
-
fractionComplete
動(dòng)畫(huà)執(zhí)行的進(jìn)度
描述了當(dāng)前動(dòng)畫(huà)的進(jìn)度搂抒,可被更改,當(dāng)動(dòng)畫(huà)處于停止時(shí)尿扯,可配合手勢(shì)等實(shí)現(xiàn)交互式動(dòng)畫(huà)求晶。
-
reversed
是否可以反轉(zhuǎn)動(dòng)畫(huà)
關(guān)于反轉(zhuǎn)動(dòng)畫(huà),目前還未知如果實(shí)現(xiàn)反轉(zhuǎn)動(dòng)畫(huà)衷笋。
state
動(dòng)畫(huà)器的狀態(tài)running
動(dòng)畫(huà)的運(yùn)行狀態(tài)芳杏,支持KVO
修改動(dòng)畫(huà)協(xié)議
UIViewImplicitlyAnimating 繼承自 UIViewAnimating 協(xié)議,在后者協(xié)議的基礎(chǔ)上又添加了一些額外的修改動(dòng)畫(huà)的方法辟宗。而我們使用的 UIViewPropertyAnimator 動(dòng)畫(huà)器就遵循了這個(gè)相對(duì)完善的協(xié)議爵赵,并實(shí)現(xiàn)了所有的方法。
方法
-
-addAnimations:
添加動(dòng)畫(huà)塊
使用此方法可以將新的動(dòng)畫(huà)塊添加到自定義動(dòng)畫(huà)對(duì)象泊脐。新的動(dòng)畫(huà)會(huì)與先前的動(dòng)畫(huà)一起運(yùn)行空幻,并從當(dāng)前時(shí)間開(kāi)始并與任何原始動(dòng)畫(huà)同時(shí)結(jié)束。
-
-addAnimations:delayFactor:
添加延遲動(dòng)畫(huà)塊
同上容客,不過(guò)會(huì)從指定的延遲開(kāi)始并與任何原始動(dòng)畫(huà)同時(shí)結(jié)束秕铛。
參數(shù) delayFactor:用于延遲動(dòng)畫(huà)開(kāi)始的時(shí)間因子约郁。該值必須介于0.0和1.0之間。將此值乘以動(dòng)畫(huà)剩余持續(xù)時(shí)間但两,作為實(shí)際延遲鬓梅。例如,如果值0.5镜遣、動(dòng)畫(huà)器的持續(xù)時(shí)間為2.0己肮,則延遲一秒執(zhí)行動(dòng)畫(huà)。
-
-addCompletion:
添加動(dòng)畫(huà)完成塊
回調(diào)動(dòng)畫(huà)完成的事件悲关,你可以在該 block 中完成其他操作谎僻。
參數(shù) withoutFinishing 有三種,表示最后動(dòng)畫(huà)結(jié)束的位置寓辱。
typedef NS_ENUM(NSInteger, UIViewAnimatingPosition) {
UIViewAnimatingPositionEnd,
UIViewAnimatingPositionStart,
UIViewAnimatingPositionCurrent,
} NS_ENUM_AVAILABLE_IOS(10_0);
如果動(dòng)畫(huà)正常完成結(jié)束艘绍,位置參數(shù)為UIViewAnimatingPositionEnd
,即最終的期望位置秫筏;
如果動(dòng)畫(huà)執(zhí)行過(guò)程中诱鞠,調(diào)用了-stopAnimation:
,并且制定的參數(shù)為 YES这敬,動(dòng)畫(huà)器則不會(huì)調(diào)用完成塊航夺;
如果動(dòng)畫(huà)執(zhí)行過(guò)程中,調(diào)用了-stopAnimation:
崔涂,并且制定的參數(shù)為 NO阳掐,此時(shí)需要調(diào)用finishAnimationAtPosition:
配置結(jié)束動(dòng)畫(huà),此時(shí)完成塊中的位置參數(shù)由方法finishAnimationAtPosition:
決定冷蚂。
-
-continueAnimationWithTimingParameters:durationFactor:
調(diào)整暫停的動(dòng)畫(huà)的時(shí)間速率曲線(xiàn)和持續(xù)時(shí)間
參數(shù) parameters 是指時(shí)間速率曲線(xiàn)缭保,系統(tǒng)提供了兩種,兼容了 UIKit 內(nèi)置的四種時(shí)間速率曲線(xiàn)蝙茶、三次貝塞爾曲線(xiàn)艺骂、彈簧式的彈性動(dòng)畫(huà)。
UICubicTimingParameters
UISpringTimingParameters
參數(shù) durationFactor 是指動(dòng)畫(huà)原始持續(xù)時(shí)間的因子隆夯,取值為(0钳恕,1),將此值乘以動(dòng)畫(huà)的原始持續(xù)時(shí)間蹄衷,作為新的持續(xù)時(shí)間忧额。
UIViewPropertyAnimator* animator = [[UIViewPropertyAnimator alloc] initWithDuration:2 curve:UIViewAnimationCurveLinear animations:^{
self.contentView.center = CGPointMake(self.view.center.x+100, self.view.center.y);
}];
[animator startAnimation];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[animator pauseAnimation];
[animator continueAnimationWithTimingParameters:[[UICubicTimingParameters alloc] initWithAnimationCurve:UIViewAnimationCurveLinear] durationFactor:animator.fractionComplete];
});
如果我們將 durationFactor 傳遞為當(dāng)前動(dòng)畫(huà)器的進(jìn)度值 fractionComplete ,你會(huì)發(fā)現(xiàn)執(zhí)行的動(dòng)畫(huà)并沒(méi)有什么變化宦芦,這是因?yàn)?fractionComplete 的值乘以原始持續(xù)時(shí)間就等于動(dòng)畫(huà)剩余的時(shí)間。
但是我們將值放大轴脐,比 fractionComplete 的值要大调卑,那么動(dòng)畫(huà)的剩余時(shí)間就會(huì)被拉長(zhǎng)抡砂,剩下的動(dòng)畫(huà)會(huì)在新的時(shí)間內(nèi)完成。
示例:我們將動(dòng)畫(huà)1秒后恬涧,將剩余的時(shí)間縮短為0.1倍
UIViewPropertyAnimator* animator = [[UIViewPropertyAnimator alloc] initWithDuration:2 curve:UIViewAnimationCurveLinear animations:^{
self.contentView.center = CGPointMake(self.view.center.x+100, self.view.center.y);
}];
[animator startAnimation];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[animator pauseAnimation];
[animator continueAnimationWithTimingParameters:[[UICubicTimingParameters alloc] initWithAnimationCurve:UIViewAnimationCurveLinear] durationFactor:0.1];
});
當(dāng)前就像之前介紹的注益,你也可以改換當(dāng)前動(dòng)畫(huà)的時(shí)間速率曲線(xiàn),或者更換為彈性動(dòng)畫(huà)溯捆。
動(dòng)畫(huà)器
介紹完 UIViewPropertyAnimator 的兩種協(xié)議之后丑搔,我們來(lái)看下 UIViewPropertyAnimator 中的一些其小細(xì)節(jié)。
三次貝塞爾曲線(xiàn)
在構(gòu)建動(dòng)畫(huà)器的方法中提揍,有一個(gè)之前我們一提而過(guò)的方法:
-initWithDuration:controlPoint1:controlPoint2:animations:
這個(gè)方法可以讓我們自定義時(shí)間速率曲線(xiàn)啤月,采用的是三次貝塞爾曲線(xiàn),可能有些人并不清楚什么是三次貝塞爾曲線(xiàn)劳跃。三次貝塞爾曲線(xiàn)在繪制圖形時(shí)經(jīng)常出現(xiàn)谎仲,是有起點(diǎn)、終點(diǎn)以及兩個(gè)控制點(diǎn)產(chǎn)生的曲線(xiàn)刨仑。文字描述比較抽象郑诺,我們來(lái)看下圖:
該曲線(xiàn)的起點(diǎn)為(0,0)杉武,其終點(diǎn)為(1辙诞,1)。point1 和 point2 參數(shù)是定義生成的貝塞爾曲線(xiàn)形狀的控制點(diǎn)轻抱。其中飞涂,起點(diǎn)和控制點(diǎn)1的連線(xiàn)為曲線(xiàn)的切線(xiàn),終點(diǎn)和控制點(diǎn)2的連線(xiàn)也是曲線(xiàn)的切線(xiàn)十拣,控制點(diǎn)1和控制點(diǎn)2的連寫(xiě)也是曲線(xiàn)的切線(xiàn)封拧,這樣夭问,產(chǎn)生的曲線(xiàn)就是三次貝塞爾曲線(xiàn)缰趋。
該曲線(xiàn)的斜率定義了動(dòng)畫(huà)的不同時(shí)間速率捧杉,斜率越大秘血,速度越快,斜率越小速度越慢灰粮。上圖顯示了一個(gè)速率曲線(xiàn)仔涩,其中動(dòng)畫(huà)快速啟動(dòng)并快速完成粘舟,但在中間部分運(yùn)行得相對(duì)較慢佩研。
屬性
-
duration
只讀
動(dòng)畫(huà)的持續(xù)時(shí)間旬薯,只有在初始化動(dòng)畫(huà)器時(shí)指定該值适秩,稍后添加的動(dòng)畫(huà)僅在剩余的時(shí)間內(nèi)運(yùn)行秽荞。剩余時(shí)間由公式(1.0 - fractionComplete)* 持續(xù)時(shí)間確定蚂会。
-
delay
只讀
延遲動(dòng)畫(huà)時(shí)間,默認(rèn)值為0趁猴。如果要為此屬性設(shè)置值儡司,啟動(dòng)動(dòng)畫(huà)時(shí)則需要使用startAnimationAfterDelay:
方法
-
timingParameters
只讀
描述速度的曲線(xiàn)捕犬,和duration一樣,只有在初始化 animator 指定該值碉碉」噶福可以使用此屬性稍后獲取這些參數(shù)蜡吧。
interruptible
動(dòng)畫(huà)中是否可被打斷占键。當(dāng)此屬性的值為 YES 時(shí)畔乙,我們可以使用-pauseAnimation
和-stopAnimation:
方法來(lái)中斷動(dòng)畫(huà)并進(jìn)行更改。當(dāng)此屬性的值為 NO 時(shí)氮帐,在調(diào)用startAnimation方法后,動(dòng)畫(huà)將運(yùn)行至完成(并且不會(huì)中斷)楞艾。
如果使用動(dòng)畫(huà)器來(lái)實(shí)現(xiàn)可中斷的視圖控制器轉(zhuǎn)換硫眯,則此屬性必須為 YES择同。
userInteractionEnabled
動(dòng)畫(huà)中用戶(hù)是否可交互敲才。默認(rèn)值為 YES紧武。當(dāng)此屬性的值為 YES 時(shí)阻星,觸摸事件將正常傳遞給視圖妥箕,否則在動(dòng)畫(huà)持續(xù)時(shí)間內(nèi)會(huì)忽略用戶(hù)的觸摸事件畦幢。
manualHitTestingEnabled
動(dòng)畫(huà)中點(diǎn)擊測(cè)試的能力呛讲。默認(rèn)為 NO贝搁。
scrubsLinearly
暫停的動(dòng)畫(huà)是否使用線(xiàn)性擦除或者使用指定的時(shí)間速率曲線(xiàn)雷逆。iOS11之后可用。
pausesOnCompletion
動(dòng)畫(huà)完成后是否保持活動(dòng)狀態(tài)往产。默認(rèn)值為 NO仿村。iOS11之后可用蔼囊。
當(dāng)此屬性的值為 YES 時(shí)畏鼓,動(dòng)畫(huà)器完成后動(dòng)畫(huà)后將保持Active
狀態(tài)云矫,并且不會(huì)執(zhí)行完成塊让禀。此時(shí)我們可以撤消動(dòng)畫(huà)巡揍。當(dāng)此屬性的值為 NO 時(shí)吼肥,動(dòng)畫(huà)完成后缀皱,動(dòng)畫(huà)器執(zhí)行完成塊,自動(dòng)轉(zhuǎn)換為Inactive
狀態(tài)表箭,從而結(jié)束動(dòng)畫(huà)免钻。
注:由于 YES 的情況下极舔,動(dòng)畫(huà)器并且不會(huì)執(zhí)行完成塊拆魏,因此如果你想要知道動(dòng)畫(huà)的結(jié)束事件渤刃,你需要監(jiān)聽(tīng)動(dòng)畫(huà)器的running
屬性卖子。
補(bǔ)充
- 設(shè)置同一可動(dòng)畫(huà)屬性
-addAnimations:
方法可以讓我們添加多個(gè)屬性動(dòng)畫(huà)塊洋闽,那么喊递,如果兩個(gè)或多個(gè)動(dòng)畫(huà)需要同時(shí)改變相同的屬性會(huì)發(fā)生什么呢骚勘?蘋(píng)果采用的是“后者優(yōu)先”原則俏讹。即:后添加的動(dòng)畫(huà)效果會(huì)覆蓋之前的動(dòng)畫(huà)效果泽疆。但有趣的是殉疼,這將導(dǎo)致卡頓瓢娜,因?yàn)樾枰M合新舊動(dòng)畫(huà)眠砾,在舊動(dòng)畫(huà)淡出的同時(shí)會(huì)隱約看見(jiàn)新動(dòng)畫(huà)褒颈。
示例:
UIViewPropertyAnimator* animator = [UIViewPropertyAnimator runningPropertyAnimatorWithDuration:1.0 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
self.contentView.transform = CGAffineTransformMakeScale(1.5, 1.5);
[animator addAnimations:^{
self.contentView.transform = CGAffineTransformMakeScale(0.5, 0.5);
}];
我們發(fā)現(xiàn)谷丸,后添加的縮小為0.5的動(dòng)畫(huà)效果覆蓋了之前的放大為1.5的動(dòng)畫(huà)效果淤井。但這似乎看不出所為卡頓的效果币狠,那我們來(lái)看下填充背景色會(huì)發(fā)生什么漩绵。
UIViewPropertyAnimator* animator = [UIViewPropertyAnimator runningPropertyAnimatorWithDuration:1.0 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
self.contentView.backgroundColor = UIColor.redColor;
} completion:nil];
[animator addAnimations:^{
self.contentView.backgroundColor = UIColor.yellowColor;
}];
該示例中宝踪,視圖的最初顏色為藍(lán)色瘩燥,在第一個(gè)動(dòng)畫(huà)塊中厉膀,我們將其設(shè)置為紅色服鹅,后又設(shè)置為黃色企软。在該動(dòng)畫(huà)運(yùn)行過(guò)程中仗哨,我們發(fā)現(xiàn)藻治,視圖立刻被設(shè)置為紅色桩卵,然后由紅色漸變?yōu)辄S色雏节。因此钩乍,在多個(gè)動(dòng)畫(huà)塊中設(shè)置同一個(gè)動(dòng)畫(huà)屬性并不可控寥粹,我們應(yīng)該盡可能的避免這種情況的出現(xiàn)涝涤。
總結(jié)
UIViewPropertyAnimator 類(lèi)讓我們能夠精準(zhǔn)的控制視圖動(dòng)畫(huà)的每個(gè)細(xì)節(jié)阔拳。我們可以使用該類(lèi)完成各種動(dòng)畫(huà)的設(shè)置糊肠,中途修改動(dòng)畫(huà)货裹,甚至可以便捷的完成交互性的動(dòng)畫(huà)弧圆,這徹底改變了我們?cè)O(shè)置視圖動(dòng)畫(huà)的習(xí)慣墓阀,這些改變令人驚喜萬(wàn)分斯撮。
在進(jìn)階篇中勿锅,我們發(fā)現(xiàn)了很多異常的情況溢十,并且在不同的系統(tǒng)上有著不同的表現(xiàn)张弛,甚至是完全相反的情況吞鸭,這一點(diǎn)讓人非常的疑惑刻剥,筆者猜想可能是蘋(píng)果在 iOS11 系統(tǒng)之后改變了 UIViewPropertyAnimator 的一些實(shí)現(xiàn)細(xì)節(jié)部分造虏,導(dǎo)致了前后不一致的情況陶珠,但是在這種情況下背率,想要使用該類(lèi)需要異常謹(jǐn)慎寝姿。
但是饵筑,不能夠因噎廢食根资,如果我們開(kāi)發(fā)過(guò)程中能夠注意到這些異常的情況玄帕,避免這些異常操作裤纹,UIViewPropertyAnimator 不失為一個(gè)較為良好的動(dòng)畫(huà)類(lèi)鹰椒。
根據(jù)之前的問(wèn)題,有幾點(diǎn)建議:
創(chuàng)建完動(dòng)畫(huà)器之后奸汇,請(qǐng)使用
-startAnimation
和-startAnimationAfterDelay:
方法開(kāi)啟動(dòng)畫(huà)茫蛹,或者直接使用+ runningPropertyAnimatorWithDuration:delay:options:animations:completion:
在
stopped
情況下婴洼,請(qǐng)配合-finishAnimationAtPosition:
方法結(jié)束后續(xù)動(dòng)畫(huà)柬采,而非其他方法在暫停動(dòng)畫(huà)的情況下粉捻,請(qǐng)使用
-startAnimation
和-continueAnimationWithTimingParameters:durationFactor:
方法恢復(fù)動(dòng)畫(huà)祟霍,可能的話(huà)沸呐,請(qǐng)保證動(dòng)畫(huà)是由運(yùn)行中暫停的崭添,或者延遲大于千分之秒的時(shí)間恢復(fù)動(dòng)畫(huà)