iOS 旋轉(zhuǎn)倒計(jì)時(shí)解決方案

產(chǎn)品中需要使用到一個(gè)帶旋轉(zhuǎn)動(dòng)畫的倒計(jì)時(shí)按鈕拷恨。但在開發(fā)過程中產(chǎn)生了兩個(gè)新的需求。一谢肾、APP進(jìn)入后臺時(shí)倒計(jì)時(shí)暫停,返回前臺繼續(xù)倒計(jì)時(shí)小泉。二芦疏、在倒計(jì)時(shí)未結(jié)束的時(shí)候冕杠,移除該頁面,此Button自動(dòng)dealloc掉酸茴。(如果不dealloc分预,等到動(dòng)畫完成后由系統(tǒng)去dealloc,會(huì)觸發(fā)此動(dòng)畫結(jié)束的回調(diào)薪捍,執(zhí)行回調(diào)中的方法笼痹,而此時(shí)該頁面已經(jīng)移除了,會(huì)引起各種問題酪穿。)

那么先擺一下我踩的坑凳干,最后給上我自己的解決方案。(如果有直接想看最終方案的童鞋被济,可到文尾救赐,有傳送門。)

第一種思路只磷,使用Animation解決经磅。

這是最先想到的方法,使用貝塞爾曲線畫一個(gè)圓钮追,再用CABaseAnimation做倒計(jì)時(shí)動(dòng)畫预厌。實(shí)現(xiàn)細(xì)節(jié)我這邊就不貼代碼了,網(wǎng)上有很多這樣的代碼元媚。
說一下這樣解決的一個(gè)問題轧叽。使用CABaseAnimation做動(dòng)畫,我們很自然的使用

- (void)animationDidStop:(CAAnimation*)anim finished:(BOOL)flag {
    //執(zhí)行動(dòng)畫結(jié)束回調(diào)  
}

來截獲動(dòng)畫結(jié)束時(shí)的回調(diào)惠毁,再傳遞到外層給做各種結(jié)束處理犹芹。但這樣處理就會(huì)引發(fā)我一開始說的第一個(gè)問題,在APP進(jìn)入后臺時(shí)鞠绰,系統(tǒng)會(huì)自動(dòng)remove掉所有的Animation腰埂,就會(huì)觸發(fā) animationDidStop 這個(gè)函數(shù),而此時(shí)我們并不需要觸發(fā)它蜈膨。再而返回前臺后屿笼,這個(gè)動(dòng)畫就結(jié)束了。
我嘗試了一些解決方法翁巍,在回到前臺是重新開始動(dòng)畫等驴一。但都沒有很好的解決這個(gè)問題。

第二種思路灶壶,重繪圓環(huán)肝断。

不使用Animation,就只能自己定義NSTimer來實(shí)現(xiàn)該功能。核心代碼如下

self.progressValue = 0;
timer = [NSTimer at_scheduledTimerWithTimeInterval:0.03 block:^{    
    if (floor(self.progressValue) > 1.0f) {
        if (timer) {
            [timer invalidate];
            timer = nil;
        }
        return;
    } else {
        frontFillBezierPath = [UIBezierPath bezierPathWithArcCenter:center radius:(CGRectGetWidth(wSelf.bounds)-progressStrokeWidth)/2.f startAngle:-M_PI_2 endAngle:(2*M_PI)*self.progressValue-M_PI_2 clockwise:YES];
        frontFillLayer.path = frontFillBezierPath.CGPath;
    }
    self.progressValue+=(0.03/2);   
} repeats:YES];

該方案的核心就是每0.03秒重繪一次貝塞爾曲線的圓弧胸懈,由于人的視覺殘留現(xiàn)象担扑,形成一個(gè)連續(xù)的動(dòng)畫。雖然這樣對圓環(huán)的暫停趣钱,重啟更加方便涌献。也解決了文章開始第一條說的問題,但由于每0.03秒需要重繪一次首有,比較消耗CPU燕垃。如果每0.1s執(zhí)行一次,就無法形成連續(xù)的動(dòng)畫井联。一般每秒要24-25幀卜壕,人眼才能覺得不卡頓。

第三種思路低矮,利用strokeEnd自帶的動(dòng)畫屬性印叁。

CALayer有兩個(gè)屬性strokeStart和strokeEnd,分別表示起始位置和結(jié)束為止军掂,默認(rèn)支持動(dòng)畫轮蜕,這兩個(gè)屬性的值在0~1之間。strokeStart=0.1f; strokeEnd=0.7f則顯示如下圖所示蝗锥。

圖片來自網(wǎng)絡(luò)(侵刪)

通過改變strokeEnd屬性的值來實(shí)現(xiàn)倒計(jì)時(shí)的動(dòng)畫效果跃洛,核心代碼如下:

CGFloat timeInterval = 0.1f;
CGFloat percent = 1.0f/(duration/timeInterval);

__weak typeof(self) weakSelf = self;
self.timer = [NSTimer at_scheduledTimerWithTimeInterval:timeInterval repeats:YES block:^(NSTimer * _Nonnull timer) {
    if (weakSelf.frontFillLayer.strokeEnd >= 1) {
        [weakSelf stop];
    } else {
        weakSelf.frontFillLayer.strokeEnd += percent;
        if (block) {
            block(weakSelf.frontFillLayer.strokeEnd * duration);
        }
    }
}];

有一點(diǎn)需要注意,strokeStart默認(rèn)的起始位置為3點(diǎn)鐘方向终议。如果想改變起始位置為12點(diǎn)鐘方向汇竭,把strokeStart設(shè)為-0.25是沒有效果的。(它的取值范圍是0-1)只需要一開始畫貝塞爾曲線時(shí)穴张,將起始位置設(shè)為-M_PI_2细燎。

self.frontFillBezierPath = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:-M_PI_2 endAngle:1.5*M_PI clockwise:YES];

另外在dealloc時(shí),手動(dòng)銷毀定時(shí)器皂甘,就解決了文章開頭說的第二個(gè)問題了玻驻。

最后給上Demo地址,傳送門偿枕。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末璧瞬,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子渐夸,更是在濱河造成了極大的恐慌嗤锉,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件墓塌,死亡現(xiàn)場離奇詭異瘟忱,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)酷誓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進(jìn)店門披坏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來态坦,“玉大人伞梯,你說我怎么就攤上這事谜诫。” “怎么了三热?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵铸豁,是天一觀的道長。 經(jīng)常有香客問我菊碟,道長节芥,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任逆害,我火速辦了婚禮头镊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘魄幕。我一直安慰自己相艇,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布纯陨。 她就那樣靜靜地躺著坛芽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪翼抠。 梳的紋絲不亂的頭發(fā)上咙轩,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天,我揣著相機(jī)與錄音机久,去河邊找鬼臭墨。 笑死,一個(gè)胖子當(dāng)著我的面吹牛膘盖,可吹牛的內(nèi)容都是我干的胧弛。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼侠畔,長吁一口氣:“原來是場噩夢啊……” “哼结缚!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起软棺,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤红竭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后喘落,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體茵宪,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年瘦棋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了稀火。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,650評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡赌朋,死狀恐怖凰狞,靈堂內(nèi)的尸體忽然破棺而出篇裁,到底是詐尸還是另有隱情,我是刑警寧澤赡若,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布达布,位于F島的核電站,受9級特大地震影響逾冬,放射性物質(zhì)發(fā)生泄漏黍聂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一粉渠、第九天 我趴在偏房一處隱蔽的房頂上張望分冈。 院中可真熱鬧,春花似錦霸株、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至扰路,卻和暖如春尤溜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背汗唱。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工宫莱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人哩罪。 一個(gè)月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓授霸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親际插。 傳聞我的和親對象是個(gè)殘疾皇子碘耳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評論 2 349