tabBar動(dòng)畫實(shí)現(xiàn) -- UITabBarItem翻轉(zhuǎn)

前言

最近根據(jù)產(chǎn)品的需求趾唱,要求實(shí)現(xiàn)tabBar的動(dòng)畫,自己之前做過類似的站欺,純自定義tabBar來加載想要的動(dòng)畫姨夹。這次的需求里還添加了一個(gè)plusButton,類似閑魚的tabBar
閑魚

所以基于CYLTabBarController實(shí)現(xiàn)了更加方便定制的tabBar矾策,然后加上自己的動(dòng)畫效果磷账。最后的效果如下(當(dāng)然,這是參考Demo):

效果圖

先簡單介紹一下CYLTabBarController的使用

  • 由于需要手動(dòng)修改一些方法贾虽,所以不建議使用cocoapods逃糟,而是手動(dòng)集成
    代碼結(jié)構(gòu)
  • 接下來初始化TabBarController,這里參考CYLTabBarController采取Config的方式。
    CYLTabBarControllerConfig.h
    image

    CYLTabBarControllerConfig.m
    image
    image
    image
    image

    這里只顯示了部分绰咽,詳細(xì)的請(qǐng)參考Demo蛉抓。
  • 自定義PlusButton。
    image

    需要繼承CYLPlusButton剃诅,以及添加協(xié)議CYLPlusButtonSubclassing巷送。定制想要的樣式。

  • AppDelegate中矛辕。
    image

(方便大家直接可以看笑跛,所以這里放的是截圖,代碼在Demo里都有)

接下來講述一下動(dòng)畫的定制聊品。

翻轉(zhuǎn)動(dòng)畫

我們想要實(shí)現(xiàn)的效果是水平翻轉(zhuǎn)動(dòng)畫飞蹂。簡單而言,對(duì)于實(shí)現(xiàn)翻轉(zhuǎn)動(dòng)畫翻屈,方式有很多陈哑。

使用Pop

Facebook的Pop動(dòng)畫是很強(qiáng)大的,遇到想要實(shí)現(xiàn)動(dòng)畫的地方第一反應(yīng)就是它伸眶。

    POPBasicAnimation *rotateAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerRotationY];
    rotateAnimation.fromValue = @(0);
    rotateAnimation.toValue = @(M_PI * 2);
    rotateAnimation.duration = 0.6; // 0.5 0.3
    [view.layer pop_addAnimation:rotateAnimation forKey:@"layerRotateAnimation"];
    [rotateAnimation setCompletionBlock:^(POPAnimation *animation, BOOL finished) {
        if (finished) {
            [UIView animateWithDuration:0.3 animations:^{
            // Pop 選擇動(dòng)畫有時(shí)會(huì)發(fā)生動(dòng)畫停止的時(shí)候位置有稍微偏移的情況惊窖,所以最好在動(dòng)畫結(jié)束后恢復(fù)一下
                view.transform = CGAffineTransformIdentity;
            } completion:nil];
        }
        
    }];
  

使用CABasicAnimation

系統(tǒng)動(dòng)畫,比較直接厘贼,這里同樣也可以使用關(guān)鍵幀動(dòng)畫界酒,可以做得更加自然一點(diǎn)

    CABasicAnimation *rotateAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
    
    // 設(shè)定動(dòng)畫選項(xiàng)
    rotateAnimation.duration = 1.2; // 持續(xù)時(shí)間
    rotateAnimation.repeatCount = 1; // 重復(fù)次數(shù)
    
    // 設(shè)定旋轉(zhuǎn)角度
    rotateAnimation.fromValue = @(0); // 起始角度
    rotateAnimation.toValue = @(M_PI * 2); // 終止角度
    
    [view.layer addAnimation:rotateAnimation forKey:@"rotateAnimation"];
    

使用transform動(dòng)畫

[UIView animateWithDuration:0.32 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
        view.layer.transform = CATransform3DMakeRotation(M_PI, 0, 1, 0);
    } completion:nil];
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [UIView animateWithDuration:0.70 delay:0 usingSpringWithDamping:1 initialSpringVelocity:0.2 options:UIViewAnimationOptionCurveEaseOut animations:^{
            view.layer.transform = CATransform3DMakeRotation(2 * M_PI, 0, 1, 0);
        } completion:nil];
    });

我采用的是第三種,其他二者都是可以的嘴秸。之所以寫得有點(diǎn)繁瑣是為了看起來更加自然一點(diǎn)毁欣。

tabBar中添加動(dòng)畫

tabBar的自定義過程中我采取了CYLTabBarController的,另外還可以完全自定義岳掐,完全自定義的話凭疮,所有的tabBarItem都是自定義的Button,動(dòng)畫直接在event中添加即可串述,這里就不詳述执解,有興趣的話可以私下交流一下。

這里來講述CYLTabBarController的tabBar動(dòng)畫剖煌。
在CYLTabBar中的

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;

添加位置如下:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    BOOL canNotResponseEvent = self.hidden || (self.alpha <= 0.01f) || (self.userInteractionEnabled == NO);
    if (canNotResponseEvent) {
        return nil;
    }
    if (!CYLExternPlusButton && ![self pointInside:point withEvent:event]) {
        return nil;
    }
    if (CYLExternPlusButton) {
        CGRect plusButtonFrame = self.plusButton.frame;
        BOOL isInPlusButtonFrame = CGRectContainsPoint(plusButtonFrame, point);
        if (!isInPlusButtonFrame && (point.y < 0) ) {
            return nil;
        }
        if (isInPlusButtonFrame) {
            self.times ++;
            if (self.times % 2 == 0) {
            // 這里添加動(dòng)畫
                [self addRotateAnimationOnPlusButton];
            }
            return CYLExternPlusButton;
        }
    }
    NSArray *tabBarButtons = self.tabBarButtonArray;
    if (self.tabBarButtonArray.count == 0) {
        tabBarButtons = [self tabBarButtonFromTabBarSubviews:self.subviews];
    }
    for (NSUInteger index = 0; index < tabBarButtons.count; index++) {
        UIView *selectedTabBarButton = tabBarButtons[index];
        CGRect selectedTabBarButtonFrame = selectedTabBarButton.frame;
        if (CGRectContainsPoint(selectedTabBarButtonFrame, point)) {
            self.times ++;
            if (self.times % 2 == 1) {
            // 這里添加動(dòng)畫
                [self addRotateAnimation:selectedTabBarButton];
            }
            return selectedTabBarButton;
        }
    }
    return nil;
}

動(dòng)畫 上述兩個(gè)位置加的動(dòng)畫實(shí)現(xiàn)一樣材鹦,區(qū)分開來方便分開定制

- (void)addRotateAnimationOnPlusButton {
    // 這里動(dòng)畫
    [UIView animateWithDuration:0.32 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
        _plusButton.layer.transform = CATransform3DMakeRotation(M_PI, 0, 1, 0);
    } completion:nil];
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [UIView animateWithDuration:0.70 delay:0 usingSpringWithDamping:1 initialSpringVelocity:0.2 options:UIViewAnimationOptionCurveEaseOut animations:^{
            _plusButton.layer.transform = CATransform3DMakeRotation(2 * M_PI, 0, 1, 0);
        } completion:nil];
    });
}

由于hit的響應(yīng)比較頻繁逝淹,所以采取了折半耕姊。

重要提示

在設(shè)置tabBar的過程中,如果沒有設(shè)置背景圖片栅葡,即為透明的話茉兰,動(dòng)畫是正常的。但是如果為了需要設(shè)置了背景圖片欣簇,比如:

[[UITabBar appearance] setBackgroundImage:[UIImage imageNamed:@"tab_bar"]];

那么動(dòng)畫會(huì)有明顯的異常规脸。

異常效果

很明顯的異常坯约。這個(gè)問題我想了挺長時(shí)間,開始一直以為是我動(dòng)畫方法的問題莫鸭,所以嘗試了很多動(dòng)畫闹丐,但都一樣。最后和別人討論了一下問題的原因被因,弄了個(gè)解決方法卿拴。
背景與按鈕圖片處于同一層次,當(dāng)按鈕圖片旋轉(zhuǎn)時(shí)梨与,轉(zhuǎn)軸就在背景圖上堕花,所以會(huì)有一部分在背景圖之下 所以會(huì)有一半被遮住的情況出現(xiàn)。

兩個(gè)在同一圖層粥鞋,所以動(dòng)畫出現(xiàn)了異常缘挽。那么如何解決呢?

  • 可以自定義UIimageView放在tabBar上代替tabBarItem呻粹,然后將imageView.layer.zPosition = 最大圖片寬度
  • 找到tabbar中放置圖片的imageView壕曼,調(diào)整zPosition

我這里采取了第一種方法。

for (UIView *tabBarButton in self.tabBar.subviews) {
        tabBarButton.layer.zPosition = 65.f / 2;//最大圖片寬度的一半
    }

還有一點(diǎn)等浊,這個(gè)設(shè)置需要放在TabBarViewController的viewWillAppear方法中

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    for (UIView *tabBarButton in self.tabBar.subviews) {
        tabBarButton.layer.zPosition = 65.f / 2;//最大圖片寬度的一半
    }
}

為了定制方便窝稿,建議大家繼承CYLTabBarController,使用自己的凿掂,添加功能伴榔,以及這個(gè)設(shè)置。

詳情參考Demo庄萎,希望大家指出我的不足以及改進(jìn)之處踪少,共同學(xué)習(xí)進(jìn)步

附github地址:
https://github.com/hllGitHub/CYLTabBarController
也可以加入群:(139852091)Demo不用寫,說就行 一起交流糠涛。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末援奢,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子忍捡,更是在濱河造成了極大的恐慌集漾,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件砸脊,死亡現(xiàn)場離奇詭異具篇,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)凌埂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門驱显,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事埃疫『技澹” “怎么了夷陋?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我疆股,道長贯卦,這世上最難降的妖魔是什么麸粮? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任汉操,我火速辦了婚禮,結(jié)果婚禮上鹰霍,老公的妹妹穿的比我還像新娘闻鉴。我一直安慰自己,他們只是感情好茂洒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布孟岛。 她就那樣靜靜地躺著,像睡著了一般督勺。 火紅的嫁衣襯著肌膚如雪渠羞。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天智哀,我揣著相機(jī)與錄音次询,去河邊找鬼。 笑死瓷叫,一個(gè)胖子當(dāng)著我的面吹牛屯吊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播摹菠,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼盒卸,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了次氨?” 一聲冷哼從身側(cè)響起蔽介,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎煮寡,沒想到半個(gè)月后虹蓄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡幸撕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年薇组,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片杈帐。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡体箕,死狀恐怖专钉,靈堂內(nèi)的尸體忽然破棺而出挑童,到底是詐尸還是另有隱情累铅,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布站叼,位于F島的核電站娃兽,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏尽楔。R本人自食惡果不足惜投储,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望阔馋。 院中可真熱鬧玛荞,春花似錦、人聲如沸呕寝。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽下梢。三九已至客蹋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間孽江,已是汗流浹背讶坯。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留岗屏,地道東北人辆琅。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像这刷,于是被迫代替她去往敵國和親涎跨。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

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