最近有這樣一個需求:
table的第一行高亮,第一行用完以后刪掉,第二行成為第一行萝喘,并高亮惑折。
大致效果是這樣的:
中間這部分是隨便扯一扯的,想看實現(xiàn)恬吕,直接跳到 實現(xiàn)方案
收到這個需求,覺得很簡單:
- 刪除第一行
- 將第二行滾到頂
- 刷新新的第一行
前兩步,很簡單遣臼,一行代碼搞定:
[table deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]]
withRowAnimation:UITableViewRowAnimationTop];
cell被delete之后,新的cell上來并不會刷新拾并,所以需要手動更新下揍堰。
但是這個刷新時機(jī)遇到點小坑:
直接寫
直接執(zhí)行刪除和reload這兩行代碼蚌讼,delete的動畫效果是需要時間的,但是后邊reload又是立即執(zhí)行的个榕,總體出來的效果不理想篡石,放棄。
after -> scrollViewDelegate
既然直接寫不能實現(xiàn)效果西采,就想需要在動畫結(jié)束之后凰萨,再執(zhí)行后續(xù)操作。首先想到的就是scrollView的delegate械馆。
點進(jìn)去delegate胖眷,有這幾個方法:
scrollViewDidEndDecelerating:
在WillBeginDecelerating
的注釋中寫著
"called on finger up as we are moving",也就是手動才會觸發(fā)霹崎。不能用珊搀。scrollViewDidEndScrollingAnimation:
這個方法的注釋里也寫著"called when setContentOffset/scrollRectVisible:animated: finishes.",而table的rowAnimation也不會觸發(fā)尾菇,不能用.其他的代理方法也沒有完美匹配的境析。
tricky方法
既然table和scroll的代理里沒有明確給出回調(diào)的方法,那么就用一些替代方法派诬。
- 比如說劳淆,dispatch_after 0.5s 執(zhí)行結(jié)束后的刷新。
- 通過scroll滾動到相應(yīng)的位置判斷動畫已經(jīng)結(jié)束默赂。
- 等等等等
作為一個有追求的工程師沛鸵,肯定是要去尋找真正的解決方案。
解決思路
刪除cell調(diào)用的方法是:
- (void)deleteRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths
withRowAnimation:(UITableViewRowAnimation)animation;
顧名思義缆八,這是帶有動畫的曲掰。。奈辰。
順著這個思路栏妖,嘗試去給animation相關(guān)的方法打斷點。
通過斷點發(fā)現(xiàn):在delete的過程中冯挎,執(zhí)行了
[UIView(Animation) commitAnimations]
知道了rowAnimation底哥,那么給這個animation加個回調(diào)就行了。
首先想到的就是Core Animation的transaction房官≈夯眨看官方文檔:
CATransaction allows you to override default animation properties that are set for animatable properties. You can customize duration, timing function, whether changes to properties trigger animations, and provide a handler that informs you when all animations from the transaction group are completed.
最后一句的意思就是可以回調(diào)了。
而且官方還給了個demo翰守,大意是這個begin()和commit()可以嵌套孵奶,先commit內(nèi)側(cè)動畫,再commit外側(cè)動畫蜡峰。
實現(xiàn)方案
其實具體實現(xiàn)非常簡單:
[CATransaction begin];
[CATransaction setCompletionBlock:^{
[_mainTable reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]]
withRowAnimation:UITableViewRowAnimationNone];
}];
[_mainTable deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]]
withRowAnimation:UITableViewRowAnimationTop];
[CATransaction commit];
為了方便下次使用了袁,封裝了一個tableview的category
- (void)ym_animatAction:(void(^)(UITableView *table))action
complete:(void(^)(UITableView *table))callback {
[CATransaction begin];
[CATransaction setCompletionBlock:^{
callback(self);
}];
action(self);
[CATransaction commit];
}
使用時直接調(diào)用即可
[_mainTable ym_animatAction:^(UITableView *table) {
<#animat code#>
} complete:^(UITableView *table) {
<#complete code#>
}];
one more thing
這里使用CATransaction來處理這個動畫朗恳,只是一個比較簡潔的做法。
同理载绿,也有很多其他思路:比如說從UIView的setAnimationDidStopSelector:
方法入手粥诫。以后有機(jī)會再來研究。
最后崭庸,上面的代碼寫了一個demo怀浆,在 GitHub