iOS 一個(gè)提交按鈕形變動(dòng)畫設(shè)計(jì)思路

最近看到一個(gè)UI設(shè)計(jì)效果圖辟宗,自己嘗試做了一下碗硬,代碼最好還是去github上下載下來看吧:

1504118-622ed4419554c027.gif

源碼下載地址:https://github.com/DMDavid/DMSubmitView
最近封裝了一下,使用的話可以

pod 'DMSubmitView'

初步設(shè)計(jì)思路

這個(gè)submit動(dòng)畫可以分開為3部分設(shè)計(jì):

  1. 按鈕形變部分:


    0FF8334F-87CA-4178-8109-B47920A51F70.jpg

這部分按鈕逐漸縮小自身的寬度绵咱,當(dāng)自身寬度與高度相等時(shí)碘饼,則停止形變。

2.圓環(huán)部分:


6E5CE458-AB61-48C8-8E09-7115030C3A40.jpg

這部分沒啥好說的,現(xiàn)在APP上很多l(xiāng)oading的效果艾恼,基本都是這樣的住涉。主要就是2個(gè)圖層,下面圖層是灰色的钠绍,上面的綠色圖層作為subLayer覆蓋在灰色圖層上面秆吵。

3.完成部分:


CC7C6A13-C7C1-4F26-AF5E-0A112454706C.jpg

這是這個(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)該如下圖所示:


370F910E-B93D-4BF3-903C-591013FE1B20.png

這里注意:藍(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è)效果:


Paste_Image.png

按鈕點(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ì)看到下面效果:


part1111.gif
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ì)看到下面效果圖:


part22222.gif
擴(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)炬搭。

Paste_Image.png

注意:這里的時(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"];
}

最終效果:

finishPart.gif

因?yàn)闀r(shí)間關(guān)系,代碼和功能實(shí)現(xiàn)還有很多地方?jīng)]有完善宫盔,這里只是希望大家互相分享能夠起到共同進(jìn)步的目的融虽。歡迎指出不足,大家共同交流進(jìn)步灼芭。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末有额,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子彼绷,更是在濱河造成了極大的恐慌巍佑,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寄悯,死亡現(xiàn)場離奇詭異萤衰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)热某,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門腻菇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人昔馋,你說我怎么就攤上這事筹吐。” “怎么了秘遏?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵丘薛,是天一觀的道長。 經(jīng)常有香客問我邦危,道長洋侨,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任倦蚪,我火速辦了婚禮黔衡,結(jié)果婚禮上晴楔,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好蹦肴,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布起宽。 她就那樣靜靜地躺著震桶,像睡著了一般尖奔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上沪悲,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天获洲,我揣著相機(jī)與錄音,去河邊找鬼殿如。 笑死贡珊,一個(gè)胖子當(dāng)著我的面吹牛最爬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播飞崖,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼烂叔,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了固歪?” 一聲冷哼從身側(cè)響起蒜鸡,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎牢裳,沒想到半個(gè)月后逢防,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蒲讯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年忘朝,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片判帮。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡局嘁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出晦墙,到底是詐尸還是另有隱情悦昵,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布晌畅,位于F島的核電站但指,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏抗楔。R本人自食惡果不足惜棋凳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望连躏。 院中可真熱鬧剩岳,春花似錦、人聲如沸入热。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽才顿。三九已至,卻和暖如春尤蒿,著一層夾襖步出監(jiān)牢的瞬間郑气,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來泰國打工腰池, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留尾组,地道東北人忙芒。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像讳侨,于是被迫代替她去往敵國和親呵萨。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容