仿iOS通知欄刪除按鈕
最近變懶了,通知欄很久都不清除了,清除的時(shí)候看到了刪除的動(dòng)畫,覺(jué)得還可以,而且也想將學(xué)過(guò)的layer和view層的動(dòng)畫都復(fù)習(xí)一遍,順便做點(diǎn)demo練練手,就先從他開(kāi)始了。

分析

我們觀察到這個(gè)按鈕最開(kāi)始是圓形,中間有2條垂直且傾斜的線,然后點(diǎn)擊之后,十字(姑且叫十字,哈哈)會(huì)向左邊移動(dòng),且逐漸虛化消失,然后蹦跶出來(lái)2個(gè)字,也是有淺到深,而且仔細(xì)觀察會(huì)發(fā)現(xiàn),字的出現(xiàn)是先右邊出現(xiàn),然后左邊出現(xiàn)的,而且有點(diǎn)震動(dòng)的動(dòng)畫。分析之后其實(shí)該動(dòng)畫很簡(jiǎn)單,就是一個(gè)位移和透明度漸變動(dòng)畫,加上字的顯現(xiàn)。
動(dòng)起來(lái)
創(chuàng)建初始狀態(tài)

首先,我們來(lái)寫上2條互相交叉的線,
CALayer *vertical = [CALayer layer];;
vertical.backgroundColor = [UIColor blackColor].CGColor;
vertical.frame = CGRectMake(self.bounds.size.height/2,(self.bounds.size.height - width)/2, 1, width);
CALayer *horizontal = [CALayer layer];;
horizontal.backgroundColor = [UIColor blackColor].CGColor;
horizontal.frame = CGRectMake((self.bounds.size.height - width)/2, self.bounds.size.height/2, width, 1);
分別命名為vertical何horizontal,代表豎直和水平方向的線。
且分別算出2條線的frame,這個(gè)沒(méi)難度,這里的width是高度一半的平方和求根
CGFloat width = sqrtf(pow(self.bounds.size.height/2, 2)*2);,
因?yàn)楹竺孢@2條線都是一起運(yùn)動(dòng)的,所以現(xiàn)在將他們加到一個(gè)layer上,直接對(duì)該layer添加動(dòng)畫即可。
CALayer *containtLayer = [CALayer layer];
[containtLayer addSublayer:vertical];
[containtLayer addSublayer:horizontal];
containtLayer.frame = CGRectMake(0, 0, self.bounds.size.height, self.bounds.size.height);
containtLayer.transform = CATransform3DMakeRotation((M_PI*45)/180, 0, 0, 1);
self.containtLayer = containtLayer;
[self.layer addSublayer:containtLayer];
細(xì)心的同學(xué)應(yīng)該發(fā)現(xiàn)了中間出現(xiàn)了一個(gè)3D的東西還有M_PI這些東西。這個(gè)其實(shí)就是控制整個(gè)layer的傾斜的,向左或者向右偏移45度其實(shí)都可以。
這樣,一個(gè)傾斜的十字就做出來(lái)了,然后就是點(diǎn)擊事件。
點(diǎn)擊動(dòng)畫
按鈕點(diǎn)擊之后,按鈕會(huì)向左移動(dòng),并且變寬,但是高度和cornerRadius不變(這里我使用的是:)
self.layer.cornerRadius = self.frame.size.height/2;
self.clipsToBounds = YES;)
這種做法,這會(huì)導(dǎo)致離屏渲染,但是我們這兒就1個(gè)view,姑且不管他),控制view的動(dòng)畫我采用的是UIView的動(dòng)畫,直接改變self的frame.
[UIView animateWithDuration:animationTime animations:^{
if (self.style == CCButtonStyleLeftToRight) {
self.frame = CGRectMake(self.originalFrame.origin.x, self.originalFrame.origin.y, self.originalFrame.size.width, self.originalFrame.size.height);
}else{
self.frame = CGRectMake(self.originalFrame.origin.x, self.originalFrame.origin.y, self.originalFrame.size.width, self.originalFrame.size.height);
}
}];
我定義了2種樣式,向左和向右的。
然后是十字的動(dòng)畫。
直接采用CABasicAnimation,設(shè)置transform、transform.translation.x和opacity,然后添加到CAAnimationGroup,一起進(jìn)行動(dòng)畫,在動(dòng)畫之后,保持動(dòng)畫的樣子,不要回到開(kāi)始。
transformGroup.removedOnCompletion = NO;
transformGroup.fillMode=kCAFillModeForwards;
文字
這兒的文字我采用CATextLayer進(jìn)行顯示,但是用textlayer就有一個(gè)問(wèn)題,就是它默認(rèn)是豎直向上的,并不是居中,所以就會(huì)導(dǎo)致顯示出來(lái)的文字靠上,目前來(lái)說(shuō)我并沒(méi)有找到有什么好方法,我采用寫死的,寫到居中((⊙﹏⊙)b)。
CATextLayer和UILabel還會(huì)有一點(diǎn)區(qū)別的,它的字體用的是CFTypeRef
/* The font to use, currently may be either a CTFontRef, a CGFontRef,
* or a string naming the font. Defaults to the Helvetica font. Only
* used when the `string' property is not an NSAttributedString. */
但是這個(gè)類可以從UIFont中獲取到,可以看出其實(shí)是可以用CTFontRef、CGFontRef或者直接是字體名的;并且可以看出,只有不是NSAttributedString才會(huì)有用。
添加到self.layer之后,需要將opacity置為0,開(kāi)始并不現(xiàn)實(shí),然后再點(diǎn)擊之后顯示出來(lái),改變opacity為1。而且還要控制放大縮小的動(dòng)畫。
CAKeyframeAnimation *scale = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
scale.values = @[[NSValue valueWithCATransform3D:CATransform3DMakeScale(0, 0, 0)], [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.5, 0.5, 0)],
[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.25, 1.25, 0)],
[NSValue valueWithCATransform3D:CATransform3DMakeScale(1, 1, 0)]];
CABasicAnimation *opacity = [CABasicAnimation animationWithKeyPath:@"opacity"];
opacity.fromValue = [NSNumber numberWithFloat:0];
opacity.toValue = [NSNumber numberWithFloat:1];
大小需要先放大到1.25倍,然后再縮小到原來(lái)大小。
寫完代碼后,動(dòng)畫就是這樣的:

其他
基本這個(gè)動(dòng)畫的點(diǎn)就是這么多。還有一點(diǎn)就是,點(diǎn)擊其他地方,按鈕需要縮小回來(lái),這里采用的是對(duì)Windows寫的一個(gè)分類,劫持響應(yīng)者鏈,然后發(fā)送通知。
結(jié)尾
基本這次就是這些,干貨并不多或者沒(méi)有((⊙﹏⊙)b),后面還會(huì)到dribbble上面去找一點(diǎn)好看的動(dòng)畫來(lái)做,其實(shí)做動(dòng)畫還是很簡(jiǎn)單,主要是分解成很多小動(dòng)畫來(lái)找思路。
好了,這次的demo放在github上,有興趣的可以看看。