[iOS]系统UITabBarController详解及自定义
来源:互联网 发布:怎样测试端口是否打开 编辑:程序博客网 时间:2024/06/10 17:07
对于UITabBarController, 大家都不陌生, 但是有时候又不那么的熟悉, 下面就来再认识一下这个熟悉的陌生人.
以下使用微信的tabBar图标;
一. 系统UITabBarController基本使用
1.1 基本用法
UITabBarController的使用, 其实很简单, 这里直接给出相应代码:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. // 初始化UITabBarController实例对象 UITabBarController *tabBar = [[UITabBarController alloc]init]; // 创建子控制器 UIViewController *vc1 = [[UIViewController alloc]init]; vc1.view.backgroundColor = [UIColor redColor]; // 设置标题 vc1.tabBarItem.title = @"微信"; // 设置选中状态的图片 vc1.tabBarItem.selectedImage = [UIImage imageNamed:@"tabbar_mainframeHL"]; // 设置未选中状态的图片 vc1.tabBarItem.image = [UIImage imageNamed:@"tabbar_mainframe"] ; // 设置右上角显示数字(例如: 未读消息数目) vc1.tabBarItem.badgeValue = @"100"; // 右上角数字背景色 vc1.tabBarItem.badgeColor = [UIColor greenColor]; UIViewController *vc2 = [[UIViewController alloc]init]; vc2.view.backgroundColor = [UIColor orangeColor]; vc2.tabBarItem.title = @"联系人"; vc2.tabBarItem.selectedImage = [UIImage imageNamed:@"tabbar_contactsHL"]; vc2.tabBarItem.image = [UIImage imageNamed:@"tabbar_contacts"]; UIViewController *vc3 = [[UIViewController alloc]init]; vc3.view.backgroundColor = [UIColor cyanColor]; vc3.tabBarItem.title = @"发现"; vc3.tabBarItem.image = [UIImage imageNamed:@"tabbar_discover"]; vc3.tabBarItem.selectedImage = [UIImage imageNamed:@"tabbar_discoverHL"]; UIViewController *vc4 = [[UIViewController alloc]init]; vc4.view.backgroundColor = [UIColor whiteColor]; vc4.tabBarItem.title = @"我"; vc4.tabBarItem.image = [UIImage imageNamed:@"tabbar_me"]; vc4.tabBarItem.selectedImage = [UIImage imageNamed:@"tabbar_meHL"]; // 添加子视图到tabbar tabBar.viewControllers = @[vc1, vc2, vc3, vc4]; // 设置为window跟视图 self.window.rootViewController = tabBar; return YES;}
以上代码直接写在xxAppDelegate.m的上面这个方法里即可;
效果如下:
注意:这里使用的是微信的图标, 是绿色的, 设置完后变成了蓝色, 而且上面也没有设置选中及未选中文字的颜色, 这里都被默认设置了, 最主要的是没有显示我原先图标的颜色.( 这样美工是不同意的 ��).
1.2. 显示原图
根据上面的问题, 我们先来看看图标的问题, 为了不被系统渲染成蓝色, 这里我们在设置各个控制器的选中和未选中的图标的时候, 调用一下UIImage的这个方法即可imageWithRenderingMode:
// 设置选中状态的图片 vc1.tabBarItem.selectedImage = [[UIImage imageNamed:@"tabbar_mainframeHL"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; // 设置未选中状态的图片 vc1.tabBarItem.image = [[UIImage imageNamed:@"tabbar_mainframe"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
这样就能正确显示我们原先的图片了;
1.3 修改文字颜色
但是文字的颜色并不是我们需要的, 我们可以通过下面的方法, 来修改文字的颜色:
// 未选中状态下文字颜色 [vc1.tabBarItem setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor redColor]} forState:UIControlStateNormal];// 选中状态下的文字颜色 [vc1.tabBarItem setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor blueColor]} forState:UIControlStateSelected];
这是设置选中和未选中状态下的标题属性, 效果如下:
这里我只是修改了前两个控制器的文字, 后面的还是用的默认的.
上面是修改按钮标题的文字属性, 按钮右上角的角标的文字属性, 可使用下面的方法来修改:
// 未选中状态下的角标文字颜色[vc1.tabBarItem setBadgeTextAttributes:@{NSForegroundColorAttributeName: [UIColor blackColor]} forState:UIControlStateNormal];// 选中状态下的角标文字颜色 [vc1.tabBarItem setBadgeTextAttributes:@{NSForegroundColorAttributeName: [UIColor orangeColor]} forState:UIControlStateSelected];
以上就是系统自带UITabBarController及相关属性的设置, 对于图标规则的需求基本都能满足, 如果还有其他的需求, 系统不能满足的, 就只能自定义了.
二. 自定义tabBarController
对于自定义的tabBar, 我们一般还是定义为UITabBarController的子类:
@interface LZTabBarController : UITabBarController
这样我们可以借助UITabBarController的一些属性和方法, 例如切换控制器; 不用再去写切换的逻辑;
实际上, 我们说的自定义的tabBar, 对数情况下是自定义的底部的tabBar; 所以, 我们的重点是来设置底部视图的实现.
我们自定义的时候, 一般有两种选择:
- 一种是, 隐藏掉系统的tabBar, 完全重新布局;
- 另一种是, 使用系统的tabBar, 但是自定义tabBarItem
不管是哪一种, 都需要自定义一个tabBarItem, 所以, 先来看看怎么定义这个tabBarItem;
2.1 自定义item –LZTabBarItem
这个类, 主要做的是布局item, 及响应点击事件
我们定义一个类* LZTabBarItem*, 继承自UIView, .h声明文件如下:
//// LZTabBarItem.h// LZTabBarController//// Created by Artron_LQQ on 2016/12/12.// Copyright © 2016年 Artup. All rights reserved.//@protocol LZTabBarItemDelegate;@interface LZTabBarItem : UIView@property (nonatomic, copy) NSString *icon;@property (nonatomic, copy) NSString *title;@property (nonatomic, strong) UIColor *titleColor;@property (nonatomic, assign) id <LZTabBarItemDelegate> delegate;@end@protocol LZTabBarItemDelegate <NSObject>- (void)tabBarItem:(LZTabBarItem *)item didSelectIndex:(NSInteger)index;@end
这里使用代理来回调点击事件; .m实现如下:
//// LZTabBarItem.m// LZTabBarController//// Created by Artron_LQQ on 2016/12/12.// Copyright © 2016年 Artup. All rights reserved.//#import "LZTabBarItem.h"static NSInteger defaultTag = 100000;@interface LZTabBarItem ()@property (nonatomic, strong)UIImageView *iconImageView;@property (nonatomic, strong)UILabel *titleLabel;@end@implementation LZTabBarItem- (instancetype)init { self = [super init]; if (self) { self.userInteractionEnabled = YES; UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(itemClicked:)]; [self addGestureRecognizer:tap]; } return self;}// 重写setTag方法- (void)setTag:(NSInteger)tag { [super setTag:tag + defaultTag];}- (UIImageView *)iconImageView { if (_iconImageView == nil) { _iconImageView = [[UIImageView alloc]init]; _iconImageView.contentMode = UIViewContentModeScaleAspectFit; [self addSubview:_iconImageView]; } return _iconImageView;}- (UILabel *)titleLabel { if (_titleLabel == nil) { _titleLabel = [[UILabel alloc]init]; _titleLabel.textAlignment = NSTextAlignmentCenter; _titleLabel.font = [UIFont systemFontOfSize:10]; _titleLabel.numberOfLines = 0; _titleLabel.textColor = [UIColor grayColor]; [self addSubview:_titleLabel]; } return _titleLabel;}- (void)setIcon:(NSString *)icon { _icon = icon; self.iconImageView.image = [UIImage imageNamed:icon];}- (void)setTitle:(NSString *)title { _title = title; self.titleLabel.text = title;}- (void)setTitleColor:(UIColor *)titleColor { _titleColor = titleColor; self.titleLabel.textColor = titleColor;}- (void)layoutSubviews { [super layoutSubviews]; CGFloat space = 6.0; if (self.icon.length > 0 && self.title.length > 0) { CGFloat iconHeight = (CGRectGetHeight(self.frame) - space * 3)*2/3.0 ; self.iconImageView.frame = CGRectMake(space, space, CGRectGetWidth(self.frame) - 2 * space, iconHeight); self.titleLabel.frame = CGRectMake(space, CGRectGetMaxY(self.iconImageView.frame) + space, CGRectGetWidth(self.frame) - 2*space, iconHeight/2.0); } else if (self.icon.length > 0) { self.iconImageView.frame = CGRectMake(2, 2, CGRectGetWidth(self.frame) - 4, CGRectGetHeight(self.frame) - 4); } else if (self.title.length > 0) { self.titleLabel.frame = CGRectMake(2, CGRectGetHeight(self.frame) - 22, CGRectGetWidth(self.frame) - 4, 20); }}- (void)itemClicked:(UITapGestureRecognizer *)tap { if (self.delegate && [self.delegate respondsToSelector:@selector(tabBarItem:didSelectIndex:)]) { [self.delegate tabBarItem:self didSelectIndex:self.tag - defaultTag]; }}/*// Only override drawRect: if you perform custom drawing.// An empty implementation adversely affects performance during animation.- (void)drawRect:(CGRect)rect { // Drawing code}*/@end
其实, 很简单, 只是添加了一个imageView, 一个label, 和一个单击手势来响应点击事件. 这里我是在* layoutSubviews*方法里来布局子视图的, 这样当视图frame改变的时候, 其子视图会做相应的调整;
这样,tabBarItem的自定义就完成了,接下来就是自定义tabBar;
tabBar的定义, 有两种方法:
- 一个是继承自UIView, 完全自定义;
- 一个是继承自UITabBar;
2.2 继承自UIView
先来看一下继承自UIView, 完全自定义的方法:
//// LZTabBar.h// LZTabBarController//// Created by Artron_LQQ on 2016/12/12.// Copyright © 2016年 Artup. All rights reserved.//#import <UIKit/UIKit.h>@class LZTabBarItem;@protocol LZTabBarDelegate;@interface LZTabBar : UIView@property (nonatomic, strong)NSArray<LZTabBarItem *> *items;@property (nonatomic, assign)id <LZTabBarDelegate> delegate;@end@protocol LZTabBarDelegate <NSObject>- (void)tabBar:(LZTabBar *)tab didSelectItem:(LZTabBarItem *)item atIndex:(NSInteger)index ;@end
这里是.h文件内容, 其属性比较简单, 只设置了delegate和items;
.m的实现如下:
//// LZTabBar.m// LZTabBarController//// Created by Artron_LQQ on 2016/12/12.// Copyright © 2016年 Artup. All rights reserved.//#import "LZTabBar.h"#import "LZTabBarItem.h"@interface LZTabBar ()<LZTabBarItemDelegate>@property (nonatomic, strong) UIVisualEffectView *effectView;@property (nonatomic, strong) UIView *topLine;@end@implementation LZTabBar- (instancetype)init { self = [super init]; if (self) { self.backgroundColor = [UIColor whiteColor]; } return self;}- (UIView *)topLine { if (_topLine == nil) { _topLine = [[UIView alloc]init]; _topLine.backgroundColor = [UIColor grayColor]; [self addSubview:_topLine]; } return _topLine;}- (UIVisualEffectView *)effectView { if (_effectView == nil) { UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; _effectView = [[UIVisualEffectView alloc] initWithEffect:effect]; _effectView.alpha = 1.0; [self addSubview:_effectView]; } return _effectView;}- (void)layoutSubviews { [super layoutSubviews]; self.effectView.frame = self.bounds; [self setupItems]; self.topLine.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), 0.6);}- (void)setupItems { CGFloat width = CGRectGetWidth(self.frame)/self.items.count; CGFloat height = CGRectGetHeight(self.frame); for (int i = 0; i < self.items.count; i++) { LZTabBarItem *item = [self.items objectAtIndex:i]; item.frame = CGRectMake(i*width, 0, width, height); [self addSubview:item]; item.delegate = self; }}- (void)tabBarItem:(LZTabBarItem *)item didSelectIndex:(NSInteger)index { if (self.delegate && [self.delegate respondsToSelector:@selector(tabBar:didSelectItem:atIndex:)]) { [self.delegate tabBar:self didSelectItem:item atIndex:index]; }}/*// Only override drawRect: if you perform custom drawing.// An empty implementation adversely affects performance during animation.- (void)drawRect:(CGRect)rect { // Drawing code}*/@end
这个类的主要作用是: 布局各个item, 在tabBar的位置, 及tabBar的一些内容.
接下来, 就是定义LZTabBarController了;
2.3 自定义LZTabBarController
这个类的主要作用是: 提供数据源, 绘制底部tabBar, 及关联viewController;
在提供数据的时候, 我单独设置了一个类类储存这些数据, 而没有直接设置为* LZTabBarController*的属性:
#pragma mark - LZTabBarConfig@interface LZTabBarConfig : NSObject/** 控制器数组, 必须设置 */@property (nonatomic, strong) NSArray *viewControllers;/** item标题数组, 选择设置 */@property (nonatomic, strong) NSArray *titles;/** 是否是导航, 默认 YES */@property (nonatomic, assign) BOOL isNavigation;/** 选中状态下的图片数组 */@property (nonatomic, strong) NSArray *selectedImages;/** 正常状态下的图片数组 */@property (nonatomic, strong) NSArray *normalImages;/** 选中状态下的标题颜色 默认: red */@property (nonatomic, strong) UIColor *selectedColor;/** 正常状态下的标题颜色 默认: gray */@property (nonatomic, strong) UIColor *normalColor;@end
提供数据源的时候, 只需要配置这个config即可;
其.m文件, 只是设置了一些默认值:
@implementation LZTabBarConfig- (instancetype)init { self = [super init]; if (self) { _isNavigation = YES; _normalColor = [UIColor grayColor]; _selectedColor = [UIColor redColor]; } return self;}@end
下面, 回到* LZTabBarController*, 其.h的声明, 就简洁许多:
#import <UIKit/UIKit.h>@class LZTabBarConfig;typedef LZTabBarConfig*(^tabBarBlock)(LZTabBarConfig *config);@interface LZTabBarController : UITabBarController/** 是否可用自动旋转屏幕 */@property (nonatomic, assign) BOOL isAutoRotation;/** 创建tabBarController @param block 配置创建tabBarController所需的参数 @return 返回tabBarController实例对象 */+ (instancetype)createTabBarController:(tabBarBlock)block;/** 获取当前的tabBarController实例, 实例创建后可通过此方法获取当前实例 @return 返回tabBarController实例对象 */+ (instancetype)defaultTabBarController;/** 隐藏底部tabBar的方法 @param isAnimation 是否需要动画 */- (void)hiddenTabBarWithAnimation:(BOOL)isAnimation;/** 显示底部tabBar的方法 @param isAnimation 是否需要动画 */- (void)showTabBarWithAnimation:(BOOL)isAnimation;@end
只是提供了创建的方法, 及获取当前实例和隐藏/显示底部tabBar的方法;
.m中的实现:
//// LZTabBarController.m// LZTabBarController//// Created by Artron_LQQ on 2016/12/12.// Copyright © 2016年 Artup. All rights reserved.//#import "LZTabBarController.h"#import "LZTabBar.h"static CGFloat lzTabBarHeight = 49.0;@interface LZTabBarController ()<LZTabBarDelegate>@property (nonatomic, strong) LZTabBar *customTabBar;@property (nonatomic, strong) LZTabBarConfig *config;@end@implementation LZTabBarController- (LZTabBar *)customTabBar { if (_customTabBar == nil) { _customTabBar = [[LZTabBar alloc]init]; _customTabBar.delegate = self; } return _customTabBar;}+ (instancetype)createTabBarController:(tabBarBlock)block { static dispatch_once_t onceToken; static LZTabBarController *tabBar; dispatch_once(&onceToken, ^{ tabBar = [[LZTabBarController alloc]initWithBlock:block]; }); return tabBar;}+ (instancetype)defaultTabBarController { return [LZTabBarController createTabBarController:nil];}- (void)hiddenTabBarWithAnimation:(BOOL)isAnimation { if (isAnimation) { [UIView animateWithDuration:0.2 animations:^{ self.customTabBar.alpha = 0; }]; } else { self.customTabBar.alpha = 0; }}- (void)showTabBarWithAnimation:(BOOL)isAnimation { if (isAnimation) { [UIView animateWithDuration:0.2 animations:^{ self.customTabBar.alpha = 1.0; }]; } else { self.customTabBar.alpha = 1.0; }}- (instancetype)initWithBlock:(tabBarBlock)block { self = [super init]; if (self) { LZTabBarConfig *config = [[LZTabBarConfig alloc]init]; NSAssert(block, @"Param in zhe function, can not be nil"); if (block) { _config = block(config); } NSAssert(_config.viewControllers, @"Param 'viewControllers' in the 'config', can not be nil"); [self setupViewControllers]; [self setupTabBar]; _isAutoRotation = YES; } return self;}- (void)setupViewControllers { if (_config.isNavigation) { NSMutableArray *vcs = [NSMutableArray arrayWithCapacity:_config.viewControllers.count]; for (UIViewController *vc in _config.viewControllers) { if (![vc isKindOfClass:[UINavigationController class]]) { UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:vc]; [vcs addObject:nav]; } else { [vcs addObject:vc]; } } self.viewControllers = [vcs copy]; } else { self.viewControllers = [_config.viewControllers copy]; }}- (void)setupTabBar { NSMutableArray *items = [NSMutableArray array]; for (int i = 0; i < _config.viewControllers.count; i++) { LZTabBarItem *item = [[LZTabBarItem alloc]init]; if (i == 0) { item.icon = _config.selectedImages[i]; if (_config.titles.count > 0) { item.titleColor = _config.selectedColor; } } else { item.icon = _config.normalImages[i]; if (_config.titles.count > 0) { item.titleColor = _config.normalColor; } } if (i < _config.titles.count) { item.title = _config.titles[i]; } [items addObject:item]; item.tag = i; } // 隐藏掉系统的tabBar self.tabBar.hidden = YES; self.customTabBar.items = [items copy]; self.customTabBar.frame = CGRectMake(0, CGRectGetHeight(self.view.frame) - lzTabBarHeight, CGRectGetWidth(self.view.frame), lzTabBarHeight); [self.view addSubview:self.customTabBar];}- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.view.backgroundColor = [UIColor whiteColor]; self.selectedIndex = 0;}#pragma mark - LZTabBarDelegate- (void)tabBar:(LZTabBar *)tab didSelectItem:(LZTabBarItem *)item atIndex:(NSInteger)index { NSMutableArray *items = [NSMutableArray arrayWithCapacity:0]; for (UIView *view in tab.subviews) { if ([view isKindOfClass:[LZTabBarItem class]]) { [items addObject:view]; } } for (int i = 0; i < items.count; i++) { UIView *view = items[i]; if ([view isKindOfClass:[LZTabBarItem class]]) { LZTabBarItem *item = (LZTabBarItem *)view; item.icon = self.config.normalImages[i]; if (self.config.titles.count > 0) { item.titleColor = _config.normalColor; } } } item.icon = self.config.selectedImages[index]; if (self.config.titles.count > 0) { item.titleColor = self.config.selectedColor; } self.selectedIndex = index;}// 屏幕旋转时调整tabbar- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator { [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; self.customTabBar.frame = CGRectMake(0, size.height - lzTabBarHeight, size.width, lzTabBarHeight);}- (BOOL)shouldAutorotate { return self.isAutoRotation;}- (UIInterfaceOrientationMask)supportedInterfaceOrientations { if (self.isAutoRotation) { return UIInterfaceOrientationMaskAllButUpsideDown; } else { return UIInterfaceOrientationMaskPortrait; }}- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}/*#pragma mark - Navigation// In a storyboard-based application, you will often want to do a little preparation before navigation- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller.}*/@end
这里主要的其实就是, * setupTabBar*方法
和* LZTabBarDelegate*的代理方法tabBar:(LZTabBar )tab didSelectItem:(LZTabBarItem )item atIndex:(NSInteger)index, 需要处理一些状态的转换;
到此, 第一种的自定义就结束了, 效果如下:
需要注意的是:
因为我们自定义了tabBar , 所以控制器的属性hidesBottomBarWhenPushed 就失去效果了, 解决的方法可以是在合适的地方来调用隐藏/显示的方法;
如果, 还想使用系统的* hidesBottomBarWhenPushed*效果, 可在使用的时候, 调整一下方法:一般, 我们是直接将tabBarController作为window的rootvc, 然后在其子控制器分别加上导航, 我们可以做如下调整:
将tabBar作为UINavigationController的rootvc, 然后把这个导航作为window的rootvc:
// 为了能够使用hidesBottomBarWhenPushed, 不直接把tabBar设置为window的跟视图, 而是设置为导航的rootvc, 然后把导航设置为window的跟视图 // 这样, 在子控制器上就不用再添加导航了, 即设置: config.isNavigation = NO; UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:tab];// 打开hidesBottomBarWhenPushed nav.hidesBottomBarWhenPushed = YES; self.window.rootViewController = nav;
这样做, 需要注意的是, 其子控制器就不用再添加导航了.
这样, 就会有上面Gif的效果;
demo地址: LZTabBarController
2.4 继承自UITabBar
继承自UITabBar的方式, 与继承自UIView, 主要的区别是LZTabBar的内容, 其他如LZTabBarItem 和LZTabBarController相关逻辑都是一样的;
#import <UIKit/UIKit.h>@class LZTabBarItem;@protocol LZTabBarDelegate;@interface LZTabBar : UITabBar@property (nonatomic, strong)NSArray<LZTabBarItem *> *lzItems;@property (nonatomic, assign)id <LZTabBarDelegate> lzDelegate;@end@protocol LZTabBarDelegate <NSObject>- (void)tabBar:(LZTabBar *)tab didSelectItem:(LZTabBarItem *)item atIndex:(NSInteger)index ;@end
.m的实现中, 主要是将系统的item移除掉, 然后添加上自定义的item:
#import "LZTabBar.h"@interface LZTabBar ()<LZTabBarItemDelegate>@end@implementation LZTabBar- (instancetype)init { self = [super init]; if (self) { self.backgroundColor = [UIColor whiteColor]; } return self;}- (void)layoutSubviews { [super layoutSubviews]; // 移除系统的tabBarItem Class class = NSClassFromString(@"UITabBarButton"); for (UIView *item in self.subviews) { if ([item isKindOfClass:class]) { [item removeFromSuperview]; } } // 设置自定义的tabBarItem [self setupItems];}- (void)setupItems { CGFloat width = CGRectGetWidth(self.frame)/self.items.count; CGFloat height = CGRectGetHeight(self.frame); for (int i = 0; i < self.lzItems.count; i++) { LZTabBarItem *item = [self.lzItems objectAtIndex:i]; item.frame = CGRectMake(i*width, 0, width, height); [self addSubview:item]; item.delegate = self; }}- (void)tabBarItem:(LZTabBarItem *)item didSelectIndex:(NSInteger)index { if (self.lzDelegate && [self.lzDelegate respondsToSelector:@selector(tabBar:didSelectItem:atIndex:)]) { [self.lzDelegate tabBar:self didSelectItem:item atIndex:index]; }}/*// Only override drawRect: if you perform custom drawing.// An empty implementation adversely affects performance during animation.- (void)drawRect:(CGRect)rect { // Drawing code}*/@end
其最终的效果是一样的, 只不过我们可以在执行push操作的时候使用控制器的* hidesBottomBarWhenPushed*属性来隐藏底部的tabBar;
(完)
- [iOS]系统UITabBarController详解及自定义
- iOS UITabBarController tabbar 自定义 详解
- UITabBarController详解(三)自定义UITabBarController
- IOS自定义UITabBarController
- iOS--自定义UITabBarController
- iOS-自定义 UITabBarController
- iOS--UITabbarController自定义
- iOS 自定义UITabBarController
- iOS - Swift 自定义UITabBarController
- ios开发之自定义UITabBarController
- iOS 自定义UINavigationController和UITabBarController
- iOS UITabBarController 的 UITabBar 自定义
- ios开发--UITabBarController使用详解
- ios开发--UITabBarController使用详解
- iOS自定义控件 - 自定义UITabBarController中的TabBar
- iOS 自定义UITabBarController以及UITabBar的分析
- [IOS开发] 高度自定义 UITabBarController, 支持StoryBoard
- iOS 自定义UITabbarController中的item (swift)
- java-2016-12-17
- 使用intent调用手机自带搜索功能搜索内容
- TelephonyManager(电话管理器)
- 你的项目和大作只差一个插件的距离!
- CentOS 6.6系统安装配置图文教程
- [iOS]系统UITabBarController详解及自定义
- 十进制转化为二进制与十六进制显示(汇编程序)
- Shell—运算符
- Java中IO与NIO
- Linux centos系统shell命令汇总(更新中)
- BroadcastReceiver学习之路(01)之普通广播及广播简介
- 《ANSI Common Lisp》学习笔记
- 如何从官网下载jdk
- 常用日期工具类