自定義tabbar, 中間凸起, 點(diǎn)擊圖片放大

常見的三種自定義tabBar

效果圖

1
2

Demo 下載地址: ZYCustomTabBar 覺得有用的話, 請(qǐng)給一個(gè)star

demo里面有三種自定義方式

實(shí)現(xiàn)思路

  1. UITabBarItem可以看做是一種特殊的button, 可以創(chuàng)建自定義的button
  2. 創(chuàng)建自定義的ZYTabBarViewController繼承UITabBarController
  3. 創(chuàng)建一個(gè)繼承自UITabBar的實(shí)體類ZYTabbar
  4. 通過按鈕的點(diǎn)擊事件,設(shè)置代理
  • typeOne: 實(shí)現(xiàn)中間只有圖片的tabBar
#pragma mark - custom method
// 初始化所有的子控制器
- (void)setupAllChildViewControllers {
    // 1.ONE
    UIViewController *one = [[UIViewController alloc] init];
    one.view.backgroundColor = [UIColor whiteColor];
    [self addChildViewController:one  title:@"首頁" imageName:@"tabbar_news" selectedImageName:@"tabbar_news_hl"];
    
    // 2.TWO
    UIViewController *two = [[UIViewController alloc] init];
    two.view.backgroundColor = [UIColor magentaColor];
    [self addChildViewController:two title:@"圖片" imageName:@"tabbar_picture" selectedImageName:@"tabbar_picture_hl"];
    
  
    if (self.tabBarType == typeOne) {
        // 2.publishButton
        UIViewController *publish = [[UIViewController alloc] init];
        publish.view.backgroundColor = [UIColor blueColor];
        two.view.backgroundColor = [UIColor magentaColor];
        [self addChildViewController:publish title:@"publish" imageName:@"tabbar_write" selectedImageName:@"tabbar_write"];
    }
    
    // 3.THREE
    UIViewController *three = [[UIViewController alloc] init];
    three.view.backgroundColor = [UIColor cyanColor];
    [self addChildViewController:three title:@"精華" imageName:@"tabbar_video" selectedImageName:@"tabbar_video_hl"];
    
    // 4.FOUR
    UIViewController *four = [[UIViewController alloc] init];
    four.view.backgroundColor = [UIColor yellowColor];
    [self addChildViewController:four title:@"我的" imageName:@"tabbar_setting" selectedImageName:@"tabbar_setting_hl"];
}


/**
 *  初始化一個(gè)子控制器
 *
 *  @param childVc           需要初始化的子控制器
 *  @param title             標(biāo)題
 *  @param imageName         圖標(biāo)
 *  @param selectedImageName 選中的圖標(biāo)
 */
- (void)addChildViewController:(UIViewController *)childVc title:(NSString *)title imageName:(NSString *)imageName selectedImageName:(NSString *)selectedImageName {
    // 1.設(shè)置控制器的屬性
    childVc.title = title;
    // 設(shè)置圖標(biāo)
    childVc.tabBarItem.image = [[UIImage imageNamed:imageName] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    // 設(shè)置選中的圖標(biāo)
    childVc.tabBarItem.selectedImage = [[UIImage imageNamed:selectedImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    [childVc.tabBarItem setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor redColor],NSFontAttributeName:[UIFont systemFontOfSize:13.f]} forState:UIControlStateSelected];

    //方式一 (self.tabBarType == typeOne) 只有圖片沒有文字tabbar
    if ([title isEqualToString:@"publish"]) {
        //tabBar圖片居中顯示,不顯示文字
        childVc.title = @"";
        childVc.tabBarItem.imageInsets = UIEdgeInsetsMake(5, 0, -5, 0);
    }
    // 2.包裝一個(gè)導(dǎo)航控制器
    ZYNavigationVc *nav = [[ZYNavigationVc alloc] initWithRootViewController:childVc];
    [self addChildViewController:nav];
}

Demo里面的三種方式是采用枚舉來區(qū)分的

#import <UIKit/UIKit.h>
typedef NS_ENUM(NSInteger, TabBarType) {
    typeOne = 0,
    typeTwo = 1,
    typeThree = 2
};
@interface ZYTabBarViewController : UITabBarController
@property (nonatomic, assign) TabBarType tabBarType;
@end

typeOne 需要添加的代碼

if (self.tabBarType == typeOne) { UIViewController *publish = [[UIViewController alloc] init]; publish.view.backgroundColor = [UIColor blueColor]; two.view.backgroundColor = [UIColor magentaColor]; [self addChildViewController:publish title:@"publish" imageName:@"tabbar_write" selectedImageName:@"tabbar_write"]; }

//方式一 (self.tabBarType == typeOne) 只有圖片沒有文字tabbar if ([title isEqualToString:@"publish"]) { //tabBar圖片居中顯示刚梭,不顯示文字 childVc.title = @""; childVc.tabBarItem.imageInsets = UIEdgeInsetsMake(5, 0, -5, 0); }

typeOne實(shí)現(xiàn)思路:

這是一種投機(jī)取巧的方式, 主要是把title設(shè)置為@"", 在設(shè)置圖片的偏移

typeTwo實(shí)現(xiàn)思路:

通過自定義UITabBar
.m文件核心代碼:

- (void)layoutSubviews {
    [super layoutSubviews];
    //按鈕的尺寸
    CGFloat buttonW = self.frame.size.width/5.0;
    CGFloat buttonH = self.frame.size.height;
    
    self.publishButton.center = CGPointMake(self.frame.size.width * 0.5, buttonH * 0.5);
    //中間凸起tabBar
    if (_isCircle) {
        self.publishButton.center = CGPointMake(self.frame.size.width * 0.5, self.frame.size.height/2.0 - 20);
        self.label.center = CGPointMake(self.publishButton.center.x, CGRectGetMaxY(self.publishButton.frame)+10);
    }
    //按鈕索引
    NSInteger tabbarIndex = 0;
    for (UIView * subview in self.subviews) {
        if ([subview isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
            subview.frame = CGRectMake(tabbarIndex * buttonW, 0, buttonW, buttonH);
            tabbarIndex ++;
            //把中間的按鈕位置預(yù)留出來
            if (tabbarIndex == 2) {
                tabbarIndex ++;
            }
        }
    }
}
- (void)publishClick {
    if ([self.ZYDelegate respondsToSelector:@selector(tabBarDidClickPlusButton)]) {
        [self.ZYDelegate tabBarDidClickPlusButton];
    }
}

在自定義的ZYTabBarViewController利用kvc替換系統(tǒng)的tabBar, 這里的self.tabBarType == typeTwo 就是表示第二種自定義tabBar

 ZYTabbar * tabbar = [[ZYTabbar alloc] init];
    tabbar.ZYDelegate = self;
    self.delegate = self;
    //注意:因?yàn)槭窍到y(tǒng)的tabBar是readonly的窝剖,所以用KVC方法替換
    if (self.tabBarType == typeTwo) {
        [self setValue:tabbar forKey:@"tabBar"];
    }else if (self.tabBarType == typeThree) {
        tabbar.isCircle = YES;
        [self setValue:tabbar forKey:@"tabBar"];
    }
    [self setupAllChildViewControllers];

typeThree實(shí)現(xiàn)思路:

typeTwo基本一致, 就是把自定義button的背景圖片以及位置移動(dòng)一下.并設(shè)置label的位置

代碼如下:

#pragma mark -- setter 
- (void)setIsCircle:(BOOL)isCircle {
    _isCircle = isCircle;
    if (isCircle) {
        [self.publishButton setBackgroundImage:[UIImage imageNamed:@"post_normal"] forState:UIControlStateNormal];
        [self.publishButton setBackgroundImage:[UIImage imageNamed:@"post_normal"] forState:UIControlStateHighlighted];
        self.publishButton.center = CGPointMake(self.frame.size.width * 0.5, self.frame.size.height/2.0 - 20);
        self.label.center = CGPointMake(self.publishButton.center.x, CGRectGetMaxY(self.publishButton.frame)+10);
        [self addSubview:self.label];
    }
}

這里在ZYTabbar聲明一個(gè)isCircle主要是為了區(qū)分方式二和方式三, 并實(shí)現(xiàn)isCircle的setter方法, 來修改button的背景圖片, 由于layoutSubviews這個(gè)方法是在isCirclesetter方法之后調(diào)用的, 所以我們還需要在layoutSubviews這個(gè)方法內(nèi)部修改button, label的位置

- (void)layoutSubviews {
    [super layoutSubviews];
    //按鈕的尺寸
    CGFloat buttonW = self.frame.size.width/5.0;
    CGFloat buttonH = self.frame.size.height;
    
    self.publishButton.center = CGPointMake(self.frame.size.width * 0.5, buttonH * 0.5);
    //中間凸起tabBar
    if (_isCircle) {
        self.publishButton.center = CGPointMake(self.frame.size.width * 0.5, self.frame.size.height/2.0 - 20);
        self.label.center = CGPointMake(self.publishButton.center.x, CGRectGetMaxY(self.publishButton.frame)+10);
    }
    //按鈕索引
    NSInteger tabbarIndex = 0;
    for (UIView * subview in self.subviews) {
        if ([subview isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
            subview.frame = CGRectMake(tabbarIndex * buttonW, 0, buttonW, buttonH);
            tabbarIndex ++;
            //把中間的按鈕位置預(yù)留出來
            if (tabbarIndex == 2) {
                tabbarIndex ++;
            }
        }
    }
}

到這里差不多demo里面的三種自定義tabBar已經(jīng)說完了.
最后說一下點(diǎn)擊tabBar的動(dòng)畫效果, 代碼如下:

- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item {
    NSMutableArray * tabbarArr = [NSMutableArray array];
    NSInteger index = [self.tabBar.items indexOfObject:item];
 
    for (UIView *subview in tabBar.subviews) {
        if ([subview isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
            [tabbarArr addObject:subview];
        }
    }
    
    UIView * tabbarBtn = tabbarArr[index];
    for (UIView * imgV in tabbarBtn.subviews) {
        if ([imgV isKindOfClass:NSClassFromString(@"UITabBarSwappableImageView")]) {
           
            CABasicAnimation*pulse = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
            pulse.timingFunction= [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
            pulse.duration = 0.2;
            pulse.repeatCount= 1;
            pulse.autoreverses= YES;
            pulse.fromValue= [NSNumber numberWithFloat:0.7];
            pulse.toValue= [NSNumber numberWithFloat:1.3];
            [imgV.layer
             addAnimation:pulse forKey:nil];
        }
    }
}

這里主要是實(shí)現(xiàn)UITabBarDelegate的代理方法來實(shí)現(xiàn)的, 需要注意的一點(diǎn)就是我們不需要再聲明 self.tabBar.delegate = self, 因?yàn)槲乙呀?jīng)實(shí)現(xiàn)了UITabBarController的代理, 具體的原因我也不是很清楚, 想了解更多的話, 還是去找度娘

到這里已經(jīng)全部說完了, 樓主語言表達(dá)能力, 技術(shù)有限! 有說的不對(duì)的地方還請(qǐng)小伙伴們速速提出, 謝謝!!!
參考文獻(xiàn): 自定義TabBar(在tabBar中有一個(gè)弧形的凸起)
作者: JSOfJackChen
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末先紫,一起剝皮案震驚了整個(gè)濱河市衩茸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌藐窄,老刑警劉巖资昧,帶你破解...
    沈念sama閱讀 221,430評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異荆忍,居然都是意外死亡格带,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門刹枉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來践惑,“玉大人,你說我怎么就攤上這事嘶卧《酰” “怎么了?”我有些...
    開封第一講書人閱讀 167,834評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵芥吟,是天一觀的道長侦铜。 經(jīng)常有香客問我,道長钟鸵,這世上最難降的妖魔是什么钉稍? 我笑而不...
    開封第一講書人閱讀 59,543評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮棺耍,結(jié)果婚禮上贡未,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好俊卤,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評(píng)論 6 397
  • 文/花漫 我一把揭開白布嫩挤。 她就那樣靜靜地躺著,像睡著了一般消恍。 火紅的嫁衣襯著肌膚如雪岂昭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,196評(píng)論 1 308
  • 那天狠怨,我揣著相機(jī)與錄音约啊,去河邊找鬼。 笑死佣赖,一個(gè)胖子當(dāng)著我的面吹牛恰矩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播憎蛤,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼枢里,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了蹂午?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,671評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤彬碱,失蹤者是張志新(化名)和其女友劉穎豆胸,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體巷疼,經(jīng)...
    沈念sama閱讀 46,221評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡晚胡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了嚼沿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片估盘。...
    茶點(diǎn)故事閱讀 40,444評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖骡尽,靈堂內(nèi)的尸體忽然破棺而出遣妥,到底是詐尸還是另有隱情,我是刑警寧澤攀细,帶...
    沈念sama閱讀 36,134評(píng)論 5 350
  • 正文 年R本政府宣布箫踩,位于F島的核電站,受9級(jí)特大地震影響谭贪,放射性物質(zhì)發(fā)生泄漏境钟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評(píng)論 3 333
  • 文/蒙蒙 一俭识、第九天 我趴在偏房一處隱蔽的房頂上張望慨削。 院中可真熱鬧,春花似錦、人聲如沸缚态。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽猿规。三九已至衷快,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間姨俩,已是汗流浹背蘸拔。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留环葵,地道東北人调窍。 一個(gè)月前我還...
    沈念sama閱讀 48,837評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像张遭,于是被迫代替她去往敵國和親邓萨。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評(píng)論 2 359

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