最近項目中有一個需求是需要手動點擊相機對焦,這里由於相機對焦部分需要一個類似於系統對焦框一樣的縮放動畫,同時動畫時長為0.3秒,因此這里就有一個很普遍的需求,如果用戶在0.3秒內繼續點擊對焦會怎么樣?
動畫部分代碼很簡單,如下:
self.transform = CGAffineTransformMakeScale(2.0f, 2.0f);
[UIView animateWithDuration:0.3f delay:0.0f options:UIViewAnimationOptionCurveLinear
animations:^{
self.transform = CGAffineTransformIdentity;
}
completion:^(BOOL finished){
if (finished) {
[self hideFocus];
}
}];
對焦框在0.3秒內進行兩倍縮小到正常尺寸的一個動畫,之后隱藏。
舊代碼分析
以前的代碼在這部分的處理大致是這樣的,
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(touchFocus:) object:_touches];
UITouch *touch = [_touches anyObject];
CGPoint touchPoint = [touch locationInView:self.view];
[self performSelector:@selector(touchFocus:) withObject: touches afterDelay:0.3f];
- (void)touchFocus:(NSSet *)touches {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(touchFocus:) object:touches];
// 以下為具體對焦框顯示部分
...
}
可以看出,代碼邏輯大致為,截獲屏幕點擊事件,之后加入一個0.3秒的延時方法,如果用戶0.3秒內再次點擊對焦,則取消上一次的對焦事件;否則,執行對焦框動畫。
這個邏輯看似解決了用戶快速點擊對焦的問題,實際上如果用戶真正快速點擊屏幕時,會出現一個很奇怪的現象,就是對焦框始終存在,並且不會變換位置,等到停止點擊屏幕后,對焦框才會響應最新的觸控位置進行動畫,另一個問題就是對焦始終存在遲滯感,因為點擊屏幕后需要等待0.3秒才能看到動畫。
解決方案
那么有什么更好的辦法呢?系統難道沒有提供終止動畫的接口嘛?當然不是,其實只需要在用戶再次點擊屏幕時候調用[_focusView.layer removeAllAnimations];
即可,其中具體的 view 為正在做動畫的 view。
這樣做還有另外一個好處,再也不需要煩人的滯后感了,屏幕對焦始終跟手,同時直接終止動畫,里面的 completion 都會照常調用,不存在副作用,很好地解決了這個問題。
新引入問題
最近遇到了一個新引入的問題,發現對焦框無法隱藏,經過調查,問題出在這里:
if (finished) {
[self hideFocus];
}
如果是直接使用removeAllAnimations
接口停止動畫的話,此處的finished
參數有可能返回 NO,導致這段代碼產生問題,所以這里如果中止動畫,則需要重新進行判定。
總結
- 學會了
removeAllAnimations
接口用法
盡管這個是很基礎的系統 API 調用,但是我之前一直都不知道,在此記錄下來,希望能給予其他人些許幫助。