iOS 关于tabBar的几处笔记

级别: ★☆☆☆☆
标签:「iOS」「状态栏」「导航栏」
作者: dac_1033
审校: QiShare团队


1. 创建一个带tabBar的App

一般项目中的App界面框架结构,如下:

本例中创建了一个QiTabBarController继承于UITabBarController,并作为window的rootViewController,则在QiTabBarController中写以下代码即可实现上面所述结构。

 AppDelegate.m 中代码
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    QiTabBarController *tabBarController = [[QiTabBarController alloc] init];
    _window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    [_window setBackgroundColor:[UIColor whiteColor]];
    [_window setRootViewController:tabBarController];
    [_window makeKeyAndVisible];
    
    return YES;
}


 QiTabBarController.m 中代码
#import "QiTabBarController.h"
#import "QiNavigationController.h"
#import "FirstController.h"
#import "SecondController.h"

@interface QiTabBarController ()

@end

@implementation QiTabBarController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self setupChildControllers];
}

- (void)setupChildControllers {
    
    FirstController *first = [[FirstController alloc] init];
    QiNavigationController *firstNav = [[QiNavigationController alloc] initWithRootViewController:first];
    firstNav.tabBarItem.title = @"FirTab";
    firstNav.tabBarItem.image = [[UIImage imageNamed:@"tab_team_normal"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    firstNav.tabBarItem.selectedImage = [[UIImage imageNamed:@"tab_team_50"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    
    SecondController *second = [[SecondController alloc] init];
    QiNavigationController *secondNav = [[QiNavigationController alloc] initWithRootViewController:second];
    secondNav.tabBarItem.title = @"SecTab";
    secondNav.tabBarItem.image = [[UIImage imageNamed:@"tab_mine_normal"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    secondNav.tabBarItem.selectedImage = [[UIImage imageNamed:@"tab_mine_50"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    
    self.viewControllers = @[firstNav, secondNav, thirdNav, fourthNav, fifthNav, sixthNav];
}

@end
复制代码

如果App设计有底部标签栏(UITabBar),我们可以通过Xcode的调试功能“Debug View Hierarchy”看到UITabBar的结构。

当tabBar中的UITabItem个数超过5个时,tabBar右侧会出现一个more按钮,点击more按钮进入一个名为more的controller,点击展示出来的其他tabItem即可可进入相应的controller。

其中,名为more的controller导航栏右侧有edit按钮,点击进入后,可拖动编辑tabBar中所示的tab顺序。在拖动编辑tabBar中所示的tab顺序时,系统会自动调用UITabBarDelegate中的相应方法(如果需要,可在QiTabBarController中直接实现UITabBarDelegate协议方法):

- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item; // called when a new view is selected by the user (but not programatically)

/* called when user shows or dismisses customize sheet. you can use the 'willEnd' to set up what appears underneath. 
 changed is YES if there was some change to which items are visible or which order they appear. If selectedItem is no longer visible, 
 it will be set to nil.
 */

- (void)tabBar:(UITabBar *)tabBar willBeginCustomizingItems:(NSArray<UITabBarItem *> *)items __TVOS_PROHIBITED;                     // called before customize sheet is shown. items is current item list
- (void)tabBar:(UITabBar *)tabBar didBeginCustomizingItems:(NSArray<UITabBarItem *> *)items __TVOS_PROHIBITED;                      // called after customize sheet is shown. items is current item list
- (void)tabBar:(UITabBar *)tabBar willEndCustomizingItems:(NSArray<UITabBarItem *> *)items changed:(BOOL)changed __TVOS_PROHIBITED; // called before customize sheet is hidden. items is new item list
- (void)tabBar:(UITabBar *)tabBar didEndCustomizingItems:(NSArray<UITabBarItem *> *)items changed:(BOOL)changed __TVOS_PROHIBITED;  // called after customize sheet is hidden. items is new item list
复制代码
2. 设置tabBar的样式
  • 设置tabBar的基本样式 在普通的项目中,一般只需要修改tabBar中每个item展示的图片icon和title及item的位置,或item中icon与title的间隔。
- (void)setTabBarStyle {
    
    //去掉TabBar顶部的线
    UITabBar *tabBar = self.tabBar;
    [tabBar setShadowImage:[UIImage new]];
    [tabBar setBackgroundImage:[UIImage new]];
    tabBar.translucent = NO;

    for (UITabBarItem *item in self.tabBar.items) {
        // 设置UITabBarItem中title样式
        [item setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor lightGrayColor]} forState:UIControlStateNormal];
        [item setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor darkGrayColor]} forState:UIControlStateSelected];

        // 设置UITabBarItem中按钮大小,及img与title间距
        [item setImageInsets:UIEdgeInsetsMake(-5, 0, 5, 0)];
    }
}
复制代码
  • 自定义tabBar按钮动画 一般常见的tabBar按钮动画有两种:点击时icon缩小放大动画,icon像.gif型图片一样的动画。

需求看起来很简单,我们应该已经有了思路,首先,我们应该找到这个当前我们要操作的这个tabBarBtn, 在QiTabBarController中实现UITabBarControllerDelegate方法,其中可以监听到tabBar上的点击动作:

- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
    
    NSInteger index = [tabBarController.childViewControllers indexOfObject:viewController];
    
    UIButton *tabBarBtn = tabBarController.tabBar.subviews[index+1];
    UIImageView *imageView = tabBarBtn.subviews.firstObject;
    
    // 我们把动画加到这个imageView上,即可实现动画效果

    // ......

    return YES;
}
复制代码

在本文实例中,我们只设置了两个tab项,第一个tabBarBtn使用.gif型动画,第二个tabBarBtn使用缩小放大动画,整个QiTabBarController实现代码如下:

#import "QiTabBarController.h"
#import "QiNavigationController.h"
#import "FirstController.h"
#import "SecondController.h"

@interface QiTabBarController () <UITabBarControllerDelegate>

@property (strong, nonatomic) NSMutableArray<UIImage *> *imgArr;

@end

@implementation QiTabBarController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self setupChildControllers];
    [self setTabBarStyle];
    [self initImages];
}

- (void)setupChildControllers {
    
    self.view.backgroundColor = [UIColor whiteColor];
    self.delegate = self;
    
    FirstController *first = [[FirstController alloc] init];
    QiNavigationController *firstNav = [[QiNavigationController alloc] initWithRootViewController:first];
    firstNav.tabBarItem.title = @"FirTab";
    firstNav.tabBarItem.image = [[UIImage imageNamed:@"tab_team_normal"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    firstNav.tabBarItem.selectedImage = [[UIImage imageNamed:@"tab_team_50"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    
    SecondController *second = [[SecondController alloc] init];
    QiNavigationController *secondNav = [[QiNavigationController alloc] initWithRootViewController:second];
    secondNav.tabBarItem.title = @"SecTab";
    secondNav.tabBarItem.image = [[UIImage imageNamed:@"tab_mine_normal"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    secondNav.tabBarItem.selectedImage = [[UIImage imageNamed:@"tab_mine_50"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    
    self.viewControllers = @[firstNav, secondNav];
}

- (void)setTabBarStyle {
    
    //去掉TabBar顶部的线
    UITabBar *tabBar = self.tabBar;
    [tabBar setShadowImage:[UIImage new]];
    [tabBar setBackgroundImage:[UIImage new]];
    tabBar.translucent = NO;

    for (UITabBarItem *item in self.tabBar.items) {
        // 设置UITabBarItem中title样式
        [item setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor lightGrayColor]} forState:UIControlStateNormal];
        [item setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor darkGrayColor]} forState:UIControlStateSelected];

        // 设置UITabBarItem中按钮大小,及img与title间距
        [item setImageInsets:UIEdgeInsetsMake(-3, 0, 3, 0)];
    }
}

- (void)initImages {
    
    _imgArr = [NSMutableArray array];
    for (int i=0; i<51; i++) {
        NSString *name = [NSString stringWithFormat:@"tab_team_%02d", i];
        UIImage *image = [UIImage imageNamed:name];
        [_imgArr addObject:image];
    }
}

- (CAAnimation *)getCustomAnimation {
    
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    //速度控制函数,控制动画运行的节奏
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    animation.duration = 0.2;
    animation.repeatCount = 1;
    animation.autoreverses = YES;
    animation.fromValue = [NSNumber numberWithFloat:0.7];
    animation.toValue = [NSNumber numberWithFloat:1.2];
    
    return animation;
}

#pragma mark - UITabBarControllerDelegate

- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
    
    NSInteger index = [tabBarController.childViewControllers indexOfObject:viewController];
    
    UIButton *tabBarBtn = tabBarController.tabBar.subviews[index+1];
    UIImageView *imageView = tabBarBtn.subviews.firstObject;
    
    if (index == 0) {
        [imageView stopAnimating];
        imageView.animationImages = _imgArr;
        imageView.animationRepeatCount = 1;
        imageView.animationDuration = 0.7;
        [imageView startAnimating];
    } else {
        static NSString *tabBarBtnAnimationKey = @"tabBarBtnAnimationKey";
        [imageView.layer removeAnimationForKey:tabBarBtnAnimationKey];
        [imageView.layer addAnimation:[self getCustomAnimation] forKey:tabBarBtnAnimationKey];
    }
    
    return YES;
}

@end
复制代码

我们可在getCustomAnimation中定义其他类型的动画,来满足不同需求。
工程源码GitHub地址


小编微信:可加并拉入《QiShare技术交流群》。

关注我们的途径有:
QiShare(简书)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公众号)

推荐文章:
算法小专栏:谈谈大O表示法
iOS UIWebView、WKWebView注入Cookie
Cookie简介
iOS 图标&启动图生成器(一)
算法小专栏:“D&C思想”与“快速排序”
奇舞周刊

转载于:https://juejin.im/post/5cd0043de51d453ae11053ff

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值