最近看到一個(gè)UI設(shè)計(jì)效果圖辟宗,自己嘗試做了一下碗硬,代碼最好還是去github上下載下來看吧:
源碼下載地址:https://github.com/DMDavid/DMSubmitView
最近封裝了一下,使用的話可以
pod 'DMSubmitView'
初步設(shè)計(jì)思路
這個(gè)submit動(dòng)畫可以分開為3部分設(shè)計(jì):
-
按鈕形變部分:
這部分按鈕逐漸縮小自身的寬度绵咱,當(dāng)自身寬度與高度相等時(shí)碘饼,則停止形變。
2.圓環(huán)部分:
這部分沒啥好說的,現(xiàn)在APP上很多l(xiāng)oading的效果艾恼,基本都是這樣的住涉。主要就是2個(gè)圖層,下面圖層是灰色的钠绍,上面的綠色圖層作為subLayer覆蓋在灰色圖層上面秆吵。
3.完成部分:
這是這個(gè)效果的最后部分,即從一個(gè)圓逐漸還原成原來按鈕的大小樣式五慈。然后上面做一個(gè)圖層動(dòng)畫纳寂,畫一個(gè)“對(duì)號(hào)”。
代碼實(shí)現(xiàn)
清楚了基本思路后泻拦,就可以著手?jǐn)]代碼了毙芜。
你可以全部使用圖層來實(shí)現(xiàn),上面效果争拐。但正所謂條條大路通羅馬腋粥,這邊提供的方法可做參考,如果有更好的方法設(shè)計(jì)架曹,歡迎與我交流隘冲。
1.第一部分設(shè)計(jì)實(shí)現(xiàn):
這里我仍然使用button作為點(diǎn)擊的submit按鈕,當(dāng)然你也可以使用其他方法設(shè)計(jì)绑雄。接下來創(chuàng)建一個(gè)label來展示文字展辞,為什么不使用button自帶的textLabel?是因?yàn)槿绻褂胋utton自帶的label的話万牺,執(zhí)行動(dòng)畫后自帶label大小也在改變罗珍,不是特別方便。當(dāng)然脚粟,還是那句話覆旱,你也可以封裝一個(gè)button。
之后核无,我們的層級(jí)關(guān)系應(yīng)該如下圖所示:
這里注意:藍(lán)色為我們的submitView扣唱,紅色為btn,淺藍(lán)為label团南。
而button和label的父視圖都為藍(lán)色的submitView噪沙。
將按鈕設(shè)計(jì)為圓角:
self.submitButton.layer.cornerRadius=self.submitButton.bounds.size.height/2;
self.submitButton.layer.masksToBounds = YES;
沒什么好說的
在按鈕的點(diǎn)擊事件里面,去做一個(gè)讓按鈕寬度縮小的動(dòng)畫已慢,使用UIView 的隱式動(dòng)畫曲聂,隱藏label,另外讓按鈕背景色逐漸變白佑惠,并給它添加邊境寬度朋腋,顏色設(shè)為灰色齐疙。實(shí)現(xiàn)這個(gè)效果:
按鈕點(diǎn)擊事件:
- (void)submitBtnClick:(UIButton *)submitBtn {
//縮小動(dòng)畫
[self scaleLayerAnimtaion];
[UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
//隱藏按鈕
self.showLabel.alpha = 0;
self.submitButton.backgroundColor = [UIColor whiteColor];
self.submitButton.layer.borderWidth = 2;
self.submitButton.layer.borderColor = [UIColor colorWithRed:172.0/255.0 green:172.0/255.0 blue:172.0/255.0 alpha:1].CGColor;
} completion:^(BOOL finished) {
self.submitButton.hidden = YES;
[self drawProgressLayer];
}];
}
//縮放動(dòng)畫
- (void)scaleLayerAnimtaion {
CABasicAnimation *anima = [CABasicAnimation animation];
anima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
anima.duration = 1.;
anima.keyPath = @"bounds";
anima.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, _originRect.size.height, _originRect.size.height)];
anima.removedOnCompletion = NO;
anima.fillMode = kCAFillModeForwards;
[self.submitButton.layer addAnimation:anima forKey:nil];
}
注意: 這里UIView隱式動(dòng)畫的duration的時(shí)間應(yīng)該和scaleLayerAnimation的duration相同,否則動(dòng)畫會(huì)出現(xiàn)不圓潤的情況旭咽。
如果一切順利贞奋,你會(huì)看到下面效果:
2.第二部分設(shè)計(jì)實(shí)現(xiàn):
這里我們已經(jīng)完成了讓按鈕變成一個(gè)圓環(huán)啦。接下來穷绵,其實(shí)你也可以直接使用button的圖層轿塔,在它上面創(chuàng)建一個(gè)綠色環(huán)形圖層,執(zhí)行一個(gè)動(dòng)畫仲墨,做出loading的效果勾缭。當(dāng)然實(shí)現(xiàn)的方法很多,我這里使用的是讓這個(gè)button隱藏目养,自己重新創(chuàng)建一個(gè)灰色圖層俩由,它的大小樣式都和button形變后的效果一樣,只不過隱式動(dòng)畫比較快癌蚁,難以區(qū)分幻梯,我們?cè)趧?dòng)畫完成block回調(diào)里面創(chuàng)建這個(gè)圖層。
- (void)submitBtnClick:(UIButton *)submitBtn {
//縮小動(dòng)畫
[self scaleLayerAnimtaion];
[UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
//隱藏按鈕
self.showLabel.alpha = 0;
self.submitButton.backgroundColor = [UIColor whiteColor];
self.submitButton.layer.borderWidth = 2;
self.submitButton.layer.borderColor = [UIColor colorWithRed:172.0/255.0 green:172.0/255.0 blue:172.0/255.0 alpha:1].CGColor;
} completion:^(BOOL finished) {
//mark - 在這里實(shí)現(xiàn)完成block后的操作!
self.submitButton.hidden = YES;
[self drawProgressLayer];
}];
}
//進(jìn)度環(huán)動(dòng)畫
-(void) drawProgressLayer { //方法實(shí)現(xiàn):
_viewCenter = (CGPoint){self.bounds.size.width/2, self.bounds.size.height/2};
//1. 背景環(huán)
backProgressLayer = [CAShapeLayer layer];
backProgressLayer.strokeColor = changedBgColor.CGColor;
backProgressLayer.fillColor = [UIColor whiteColor].CGColor;
backProgressLayer.lineCap = kCALineCapRound;
backProgressLayer.lineJoin = kCALineJoinBevel;
backProgressLayer.lineWidth = 2;
UIBezierPath *backProgressCircle = [UIBezierPath bezierPath];
[backProgressCircle addArcWithCenter:_viewCenter radius:self.bounds.size.height/2 startAngle:-M_PI_2 endAngle:M_PI_2 * 3 clockwise:YES];
backProgressLayer.path = backProgressCircle.CGPath;
[self.layer addSublayer:backProgressLayer];
//2. 圓環(huán)
CAShapeLayer *progressLayer = [CAShapeLayer layer];
progressLayer.strokeColor = btnColor.CGColor;
progressLayer.fillColor = [UIColor whiteColor].CGColor;
progressLayer.lineCap = kCALineCapRound;
progressLayer.lineJoin = kCALineJoinBevel;
progressLayer.lineWidth = 4.0;
progressLayer.strokeEnd = 0.0;
UIBezierPath *progressCircle = [UIBezierPath bezierPath];
[progressCircle addArcWithCenter:_viewCenter radius:self.bounds.size.height/2 startAngle:-M_PI_2 endAngle:M_PI_2 * 3 clockwise:YES];
progressLayer.path = progressCircle.CGPath;
[backProgressLayer addSublayer:progressLayer];
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
pathAnimation.duration = 3.0;
pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
pathAnimation.fromValue = [NSNumber numberWithFloat:0.0];
pathAnimation.toValue = [NSNumber numberWithFloat:1.0f];
pathAnimation.removedOnCompletion = NO;
pathAnimation.fillMode = kCAFillModeForwards;
[progressLayer addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
}
如果一切OK努释,你會(huì)看到下面效果圖:
擴(kuò)展:
這里畫的進(jìn)度控制碘梢,你可以提供參數(shù)進(jìn)行控制。如伐蒂,當(dāng)一個(gè)progressRatio達(dá)到20%時(shí)候煞躬,讓layer的bezierPath endAngle:這個(gè)參數(shù)為1/5 * (M_PI*2),或者動(dòng)畫的進(jìn)度定死饿自,讓進(jìn)度條執(zhí)行幀動(dòng)畫先到20%汰翠,然后到60%,最后是否完成通過一個(gè)bool來控制昭雌,如果false則提示,如果true健田,則完成最后的環(huán)形合并烛卧。你可以自定義一個(gè)layer,提供一個(gè)方法傳入progressFloat妓局,之后你在下載回調(diào)方法里面調(diào)用layer的drawRect:inContent方法总放,來重繪達(dá)到效果。
這里自己實(shí)現(xiàn)下載進(jìn)度效果使用的是NSURLSession好爬,了解請(qǐng)看源碼
3.第三部分設(shè)計(jì)實(shí)現(xiàn):
其實(shí)這里基本已經(jīng)效果已經(jīng)出來了局雄,這里使用一個(gè)GCD延遲執(zhí)行。當(dāng)然你也可以使用NSTimer存炮,CADisplayLink來實(shí)現(xiàn)炬搭。
注意:這里的時(shí)間應(yīng)該是和上面的CABaseAnimation動(dòng)畫時(shí)間一致蜈漓。
按鈕回復(fù)原來形狀
- (void)expandLayerAnimation { //方法實(shí)現(xiàn):
[backProgressLayer removeFromSuperlayer];//移除之前圖層
[_submitButton setShowSubmitButton];//顯示按鈕
[_showLabel showLabelAnimation];//執(zhí)行對(duì)號(hào)動(dòng)畫
//按鈕擴(kuò)充動(dòng)畫
CABasicAnimation *anima = [CABasicAnimation animation];
anima.duration = 1.;
anima.keyPath = @"bounds";
anima.toValue = [NSValue valueWithCGRect:_originRect];
anima.removedOnCompletion = NO;
anima.fillMode = kCAFillModeForwards;
[self.submitButton.layer addAnimation:anima forKey:nil];
}
- (void)showLabelAnimation {
self.text = @"";
[self creatCompleteAnimation];
[UIView animateWithDuration:1.0 animations:^{
self.alpha = 1;
}];
}
- (void)creatCompleteAnimation {
CGPoint centerPoint = (CGPoint){self.bounds.size.width/2, self.bounds.size.height/2 + 5};
CGFloat margin = 10;
CAShapeLayer *completeLayer = [CAShapeLayer layer];
completeLayer.fillColor = [UIColor clearColor].CGColor;
completeLayer.strokeColor = [UIColor whiteColor].CGColor;
completeLayer.lineCap = kCALineJoinRound;
completeLayer.lineJoin = kCALineJoinRound;
completeLayer.lineWidth = 4;
UIBezierPath *completePath = [UIBezierPath bezierPath];
[completePath moveToPoint:CGPointMake(centerPoint.x - margin, centerPoint.y)];
[completePath addLineToPoint:CGPointMake(centerPoint.x - 5, centerPoint.y + margin - 5)];
[completePath addLineToPoint:CGPointMake(centerPoint.x + margin, centerPoint.y - margin)];
completeLayer.path = completePath.CGPath;
[self.layer addSublayer:completeLayer];
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
pathAnimation.duration = 1.0;
pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
pathAnimation.fromValue = [NSNumber numberWithFloat:0.0];
pathAnimation.toValue = [NSNumber numberWithFloat:1.0f];
pathAnimation.removedOnCompletion = NO;
pathAnimation.fillMode = kCAFillModeForwards;
[completeLayer addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
}
最終效果:
因?yàn)闀r(shí)間關(guān)系,代碼和功能實(shí)現(xiàn)還有很多地方?jīng)]有完善宫盔,這里只是希望大家互相分享能夠起到共同進(jìn)步的目的融虽。歡迎指出不足,大家共同交流進(jìn)步灼芭。