你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> 【iOS】彩色TabBar切換動畫實現

【iOS】彩色TabBar切換動畫實現

編輯:IOS開發基礎

無意間看到一個彩色TabBar切換的設計圖,感覺很不錯,有空就把他實現了。

環境信息

  • Mac OS X 10.10.4

  • Xcode 6.4

  • iOS 8.4

效果圖:

1.gif

源碼下載地址:

https://github.com/saitjr/TColorfulTabBar.git

一、實現分析

看到這個彩色切換效果的時候,我第一個反應就是在TabBar上有一個彩色的View,然後每個色塊的顯示都是通過mask來顯示的。最終,我的具體實現也是根據這個思路來的。

1. 設計思想

為了減少侵入性(耦合),我采取的是繼承UITabBar來實現,所以要集成的時候,只需要將系統的TabBar換成我寫的TColorfulTabBar就可以了。

2. 視圖層級圖

blob.png

二、效果實現

1. 添加彩色視圖colorfulView

TColorfulTabBar.m

- (void)setupColorView {
    
    // 初始化彩色視圖,並將它加在tabbar上
    UIView *colorView = [[UIView alloc] initWithFrame:self.bounds];
    [self addSubview:colorView];
    self.colorfulView = colorView;
    
    // 彩色視圖的五種顏色,這是一個UIColor數組,
    NSArray *colors = self.itemColors;
    CGFloat itemWidth = self.bounds.size.width / self.itemCount;
    
    for (int i = 0; i < self.itemCount; i ++) {
        
        UIView *view = [[UIView alloc] initWithFrame:CGRectMake(itemWidth * i, 0, itemWidth, self.bounds.size.height)]; 
        view.backgroundColor = colors[i]; 
        [self.colorfulView addSubview:view]; 
    } 
}

2. 添加彩色視圖的遮罩colorfulMaskView

之所以這裡的遮罩使用的是UIView而不是CAShapeLayer或者CALayer,原因如下:

  • 遮罩是矩形,沒必要使用路徑,所以不用CAShapeLayer

  • 通過設計圖可以看到,在位移動畫之前,有一個遮罩單向變寬(向左或向右)的效果。如果使用CALayer,那麼改變bounds的時候,是雙向改變,想要單向就必須加錨點,太麻煩

  • 如果使用UIView,那麼向右變寬只需要x不變,width變長就行;向左變寬只需要x-value,width+value就行,要方便的多

  • 最後一點就是在做動畫的時候,Layer要用到CABaseAnimation,然而UIView使用UIView的Animation就行

在設置遮罩的時候,將colorfulMaskView的layer設置為colorfulView的mask就可以了。

代碼實現如下:

TColorfulTabBar.m

- (void)setupMaskLayer {
    
    // 獲取每個item的寬度
    CGFloat itemWidth = self.bounds.size.width / self.itemCount;
    
    // 初始化colorMaskView,並將colorMaskView的layer設置成彩色視圖的遮罩
    UIView *colorMaskView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, itemWidth, self.bounds.size.height)];
    colorMaskView.backgroundColor = [UIColor blackColor];
    self.colorfulMaskView = colorMaskView;
    self.colorfulView.layer.mask = self.colorfulMaskView.layer;
}

3. 設置代理,獲取當前點擊的下標

UITabBar並沒有獲取點擊下標的接口,但是UITabBarDelegate有,這個協議默認被UITabBarController遵守。為了降低耦合性,采用UITabBar自己獲取下標,所以,需要UITabBar自己實現自己的delegate。

值得注意的是,不能在UITabBar的初始化方法中去設置self.delegate = self,因為即使設置了,也會被UITabBarController覆蓋。最終解決方案是當UITabBar加載到父視圖上是,在修改delegate為self。

- (void)didMoveToSuperview {
    [super didMoveToSuperview];
    self.delegate = self;
}

因為每次的移動位置與方向都和上次的下標與這次的下標有關,所以需要使用到屬性來記錄這兩個下標的值。

- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item {
    
    NSInteger index = [self.items indexOfObject:item];
    self.fromeIndex = self.toIndex;
    self.toIndex = index;
    // 拿到下標以後執行動畫
    [self animation];
}

4. 移動遮罩,顯示不同的色塊

在做動畫的時候,需要考慮到效果的平滑性。整個動畫有兩個動畫組成,一個是寬度放大的動畫,一個是縮小到原來大小和位移動畫。整個動畫是EaseInOut的效果,所以拆開來看,就應該第一個動畫EaseIn,第二個動畫EaseOut。

一圖勝千言:

blob.png

- (void)animation {
    
    CGFloat itemWidth = self.bounds.size.width / self.itemCount;
    // 為了效果看起來更平滑,所以根據兩次下標的差值來計算需要放大的距離
    CGFloat extraWidth = ABS(self.toIndex - self.fromeIndex) * itemWidth / 4;
    
    // 放大的大小
    CGRect scaleFrame = CGRectMake(self.colorfulMaskView.x, 0, itemWidth + extraWidth, self.bounds.size.height);
    // 最終大的大小與位置
    CGRect toFrame = CGRectMake(self.toIndex * itemWidth, 0, itemWidth, self.bounds.size.height);
    
    // 如果是向左移動,那修改x軸的坐標
    if (self.fromeIndex > self.toIndex) {
        
        scaleFrame = CGRectMake(self.colorfulMaskView.x - extraWidth, 0, itemWidth + extraWidth, self.bounds.size.height);
    }
    
    // 兩個動畫加起來是一個EaseInOut的效果,所以第一個動畫就應該是EaseIn,第二個動畫是EaseOut
    // 先進行放大
    [UIView animateWithDuration:ANIMATION_DURATION delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
        
        self.colorfulMaskView.frame = scaleFrame;
    } completion:^(BOOL finished) {
        
        // 再進行縮小和位移
        [UIView animateWithDuration:ANIMATION_DURATION delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
            
            self.colorfulMaskView.frame = toFrame;
        } completion:NULL];
    }];
}


  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved