一個(gè)play方法實(shí)現(xiàn)全屏炫酷倒計(jì)時(shí)的小demo

今天實(shí)現(xiàn)了下全屏倒計(jì)時(shí)的小demo并且簡單的封裝了一下,保證了其封裝性和擴(kuò)展性。只需在你的工程中倒入#import "WZBCountdownLabel.h",在需要開始倒計(jì)時(shí)的地方使用[WZBCountdownLabel play];即可!
先看效果:

**全屏動(dòng)畫效果**
**全屏動(dòng)畫效果**

其實(shí)功能本身很簡單,就是動(dòng)畫改變label的文字,然而我覺得封裝很重要,我見過一個(gè)界面十幾個(gè)功能,代碼幾千行,我覺得這樣很不好,一來其它人看你代碼的時(shí)候會(huì)暈頭轉(zhuǎn)向,找不著東南西北,二來不利于代碼的維護(hù)和擴(kuò)展。

而我在項(xiàng)目中往往會(huì)把一個(gè)界面的功能分為幾大類,然后分模塊實(shí)現(xiàn)這些功能,外部只需要提供幾個(gè)簡單的方法就可以實(shí)現(xiàn),這樣能夠很大程度上簡化代碼,幾千行的控制器只剩幾百行甚至幾十行,這樣是不是很爽!

有人可能會(huì)說,你這倒計(jì)時(shí)3秒,不符合我的需求,我要5秒怎么辦?簡單!只需要用這個(gè)方法[WZBCountdownLabel playWithNumber:5];。

有人可能會(huì)說,你這還不能滿足我的需求,我要在5秒之后顯示一個(gè)文字,怎么辦?簡單!只需要用這個(gè)方法[WZBCountdownLabel playWithNumber:5 endTitle:@"GO!"];

有人可能會(huì)說,你這還不能滿足我的需求,我要在5秒文字顯示完成之后做一些其它操作,怎么辦?簡單!我提供了兩種方法通知控制器,沒錯(cuò),代理和block。首先簽訂協(xié)議讓控制器成為此label的代理,因?yàn)橐恢庇玫念惙椒?,所以綁定代理同樣是提供一個(gè)類方法:[WZBCountdownLabel addDelegate:self];然后實(shí)現(xiàn)代理方法即可:

- (void)countdownSuccess:(WZBCountdownLabel *)label {
    // do something
}

block是這樣用的:

[WZBCountdownLabel setCountdownSuccessBlock:^(WZBCountdownLabel *label) {
        // countdown success
}];

有人可能還會(huì)說,這樣還是不能滿足我的需求,我想要在開始動(dòng)畫的時(shí)候做些事情。這個(gè)監(jiān)聽也是有的:
block

[WZBCountdownLabel addCountdownBeginBlock:^(WZBCountdownLabel *label) {
        // countdown begin
    }];

delegate

- (void)countdownBegin:(WZBCountdownLabel *)label {
    NSLog(@"delegateBegin");
}

需要注意的是:為了順利執(zhí)行,block和代理的綁定,必須要放在play方法的前面,不然會(huì)監(jiān)聽不到

最后,我提供了一個(gè)方法可以一行代碼實(shí)現(xiàn)以上所有功能,look me:

/*
     * return WZBCountdownLabel對(duì)象
     * number : 倒計(jì)時(shí)開始的數(shù)字
     * endTitle : 結(jié)束語
     * begin : 倒計(jì)時(shí)開始的回調(diào)
     * success : 倒計(jì)時(shí)成功的回調(diào)
     */
    [WZBCountdownLabel playWithNumber:5 endTitle:@"GO" begin:^(WZBCountdownLabel *label) {
        NSLog(@"blockBegin");
    } success:^(WZBCountdownLabel *label) {
        NSLog(@"blockSuccess");
    }];

下面簡單講下我的實(shí)現(xiàn)部分

+ (instancetype)play {
    return [self playWithNumber:0];
}

+ (instancetype)playWithNumber:(NSInteger)number {
    return [self playWithNumber:number endTitle:nil];
}

+ (instancetype)playWithNumber:(NSInteger)number endTitle:(NSString *)endTitle {
    return [self playWithNumber:number endTitle:endTitle success:nil];
}

+ (instancetype)playWithNumber:(NSInteger)number success:(CountdownSuccessBlock)success {
    return [self playWithNumber:number endTitle:nil success:success];
}

上面這幾個(gè)方法最終都會(huì)走到下邊這個(gè)方法,核心代碼

+ (instancetype)playWithNumber:(NSInteger)number endTitle:(NSString *)endTitle begin:(CountdownBeginBlock)begin success:(CountdownSuccessBlock)success {
    // isAnimationing 用來判斷目前是否在動(dòng)畫
    if (isAnimationing) return nil;
    WZBCountdownLabel *label = [WZBCountdownLabel share];
    label.hidden = NO;
    // 給全局屬性賦值
    // 默認(rèn)三秒
    label.number = 3;
    if (number && number > 0) label.number = number;
    if (endTitle) label.endTitle = endTitle;
    if (success) label.countdownSuccessBlock = success;
    if (begin) label.countdownBeginBlock = begin;
    
    [self setupLabelBase:label];
    
    // 動(dòng)畫倒計(jì)時(shí)部分
    [self scaleActionWithBeginBlock:begin andSuccessBlock:success label:label];
    return label;
}

// 動(dòng)畫倒計(jì)時(shí)部分
+ (void)scaleActionWithBeginBlock:(CountdownBeginBlock)begin andSuccessBlock:(CountdownSuccessBlock)success label:(WZBCountdownLabel *)label {
    if (!isAnimationing) { // 如果不在動(dòng)畫才走開始的代理和block
        if (begin) begin(label);
        if ([label.delegate respondsToSelector:@selector(countdownBegin:)]) [label.delegate countdownBegin:label];
    }
    // 這個(gè)判斷用來表示有沒有結(jié)束語
    if (label.number >= (label.endTitle ? 0 : 1)) {
        isAnimationing = YES;
        label.text = label.number == 0 ? label.endTitle : [NSString stringWithFormat:@"%zd", label.number];
        [UIView animateWithDuration:1 animations:^{
            label.transform = CGAffineTransformIdentity;
            label.alpha = 1;
        } completion:^(BOOL finished) {
            if (finished) {
                label.number--;
                label.alpha = 0;
                label.transform = CGAffineTransformScale(label.transform, 10, 10);
                [self scaleActionWithBeginBlock:begin andSuccessBlock:success label:label];
            }
        }];
    } else {
        // 調(diào)用倒計(jì)時(shí)完成的代理和block
        if ([label.delegate respondsToSelector:@selector(countdownSuccess:)]) [label.delegate countdownSuccess:label];

        if (success) success(label);
        [self hidden];
    }
}

本demo中的label并不是加在window上的,因?yàn)槲野l(fā)現(xiàn)這樣會(huì)有問題。就是在動(dòng)畫還未結(jié)束的時(shí)候,界面跳轉(zhuǎn)了,我想大多需求是需要隱藏這個(gè)倒計(jì)時(shí)的,但如果加在window上label不會(huì)隱藏。所以我選擇把label加在當(dāng)前控制器的view上

/// 這個(gè)方法是拿到當(dāng)前正在顯示的控制器,不管是push進(jìn)去的,還是present進(jìn)去的都能拿到,相信很多項(xiàng)目會(huì)用到。拿去不謝!
- (UIViewController *)getVisibleViewControllerFrom:(UIViewController*)vc {
    if ([vc isKindOfClass:[UINavigationController class]]) {
        return [self getVisibleViewControllerFrom:[((UINavigationController*) vc) visibleViewController]];
    }else if ([vc isKindOfClass:[UITabBarController class]]){
        return [self getVisibleViewControllerFrom:[((UITabBarController*) vc) selectedViewController]];
    } else {
        if (vc.presentedViewController) {
            return [self getVisibleViewControllerFrom:vc.presentedViewController];
        } else {
            return vc;
        }
    }
}

最后, demo在這
如果喜歡我的文章,記得點(diǎn)擊喜歡或者關(guān)注我哦!

您還可以加入我們的群,大家庭期待您的加入!

我們的社區(qū)
我們的社區(qū)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,562評(píng)論 19 139
  • 上篇寫了一篇實(shí)現(xiàn)全屏倒計(jì)時(shí)的demo,今天寫的這篇是對(duì)上篇的擴(kuò)展,還沒看過上篇的這里是通道:一個(gè)play方法實(shí)現(xiàn)全...
    雜霧無塵閱讀 2,623評(píng)論 10 19
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,040評(píng)論 25 709
  • skt的崛起確實(shí)順應(yīng)了一個(gè)時(shí)代的潮流,可是,這是為什么?或者可以說,為什么是skt?我們站在現(xiàn)在,站在一個(gè)已知的結(jié)...
    懶貓奇遇記閱讀 329評(píng)論 0 0
  • 這幾天,一直籌謀著,在畫畫一百幅之際,說點(diǎn)什么,寫點(diǎn)什么。 于我而言,畫畫不是簡單的會(huì)了這么簡單,在這個(gè)過程中,有...
    修煉佛心閱讀 1,304評(píng)論 1 5

友情鏈接更多精彩內(nèi)容