项目搭建

1.新建一个微博的项目,去掉屏幕旋转

2.设置屏幕方向-->只有竖向

3.使用代码构建UI,不使用storyboard

4.配置图标AppIcon和LaunchImage

将微博资料的相关素材拉到AppIcon和LaunchImage中,并将除了AppIcon和LaunchImage其它图片也全部拉到images.xcassets中。

项目布局

1、项目分层。为了让在Finder中显示跟Xcode中显示都是分层效果,首先在Finder中建文件目录,再拉到xcode中。

2.添加导航及控制器

思路:

(1)创建一个集成UITabBarController的类作为window的rootViewController

(2)由于中间有一个特殊的+加按钮,需要重写(KVC)导航控制器类来重新布局

AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{ //1.创建窗口
self.window=[[UIWindow alloc] init];
self.window.frame=[UIScreen mainScreen].bounds; //2.设置根控制器
self.window.rootViewController=[[UYTabBarViewController alloc] init]; //显示窗口
[self.window makeKeyAndVisible];
return YES;
}

Weibo-Prefix.pch :为了下面方便测试,我们在全局宏命令中定义随机色及RGB颜色

// RGB颜色
#define HWColor(r, g, b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1.0] // 随机色
#define HWRandomColor HWColor(arc4random_uniform(256), arc4random_uniform(256), arc4random_uniform(256))

UYTabBarViewController:

#import "UYTabBarViewController.h"
#import "UYHomeViewController.h"
#import "UYMessageCenterViewController.h"
#import "UYProfileViewController.h"
#import "UYDiscoverViewController.h"
#import "UYTabBar.h" @interface UYTabBarViewController () @end @implementation UYTabBarViewController - (void)viewDidLoad
{
[super viewDidLoad]; // 1.初始化子控制器
UYHomeViewController *home = [[UYHomeViewController alloc] init];
[self addChildVc:home title:@"首页" image:@"tabbar_home" selectedImage:@"tabbar_home_selected"]; UYMessageCenterViewController *messageCenter = [[UYMessageCenterViewController alloc] init];
[self addChildVc:messageCenter title:@"消息" image:@"tabbar_message_center" selectedImage:@"tabbar_message_center_selected"]; UYDiscoverViewController *discover = [[UYDiscoverViewController alloc] init];
[self addChildVc:discover title:@"发现" image:@"tabbar_discover" selectedImage:@"tabbar_discover_selected"]; UYProfileViewController *profile = [[UYProfileViewController alloc] init];
[self addChildVc:profile title:@"我" image:@"tabbar_profile" selectedImage:@"tabbar_profile_selected"]; // 2.更换系统自带的tabbar,由于tabbar是realonly,因此使用KVC来重写。如果没有特殊的导航布局,去掉这下面这部分代码即可。
// UYTabBar *tabBar = [[UYTabBar alloc] init];
// tabBar.delegate = self;
// [self setValue:tabBar forKeyPath:@"tabBar"];
} /**
* 添加一个子控制器
*
* @param childVc 子控制器
* @param title 标题
* @param image 图片
* @param selectedImage 选中的图片
*/
- (void)addChildVc:(UIViewController *)childVc title:(NSString *)title image:(NSString *)image selectedImage:(NSString *)selectedImage
{
// 设置子控制器的文字
childVc.title = title; // 同时设置tabbar和navigationBar的文字 // 设置子控制器的图片
childVc.tabBarItem.image = [UIImage imageNamed:image];
childVc.tabBarItem.selectedImage = [[UIImage imageNamed:selectedImage]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; // 设置文字的样式
NSMutableDictionary *textAttrs = [NSMutableDictionary dictionary];
textAttrs[NSForegroundColorAttributeName] = HWColor(123, 123, 123);
NSMutableDictionary *selectTextAttrs = [NSMutableDictionary dictionary];
selectTextAttrs[NSForegroundColorAttributeName] = [UIColor orangeColor];
[childVc.tabBarItem setTitleTextAttributes:textAttrs forState:UIControlStateNormal];
[childVc.tabBarItem setTitleTextAttributes:selectTextAttrs forState:UIControlStateSelected]; // 先给外面传进来的小控制器 包装 一个导航控制器
//HWNavigationController *nav = [[HWNavigationController alloc] initWithRootViewController:childVc];
// 添加为子控制器
[self addChildViewController:childVc];
} @end

运行后,效果如下:

从上面的效果可以看到,我们还需要设置顶部导航控制器:

思路:

  1. 每个tab的controller上包装了一个UINavigationController.
  2. 进入非NavigationController的rootViewController的时候,隐藏底部的TabBar
  3. 重写pushViewController方法,当push的时候隐藏TabBar #mark:此方法可以作用与所有的非rootViewController,非常好用

1.创建一个集成UIBarButtonItem的分类,用来创建使用UIButton作为按钮图标的item

#import "UIBarButtonItem+Extension.h"

@implementation UIBarButtonItem (Extension)

+ (instancetype) itemWithImage:(NSString *) imageName hightlightedImage:(NSString *) highlightedImageName target:(id)target selector:(SEL)selector {
UIBarButtonItem *item = [[self alloc] init]; // 创建按钮
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *image = [UIImage imageNamed:imageName];
[button setImage:image forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:highlightedImageName] forState:UIControlStateHighlighted]; // 一定要设置frame,才能显示
button.frame = CGRectMake(0, 0, image.size.width, image.size.height); // 设置事件
[button addTarget:target action:selector forControlEvents:UIControlEventTouchUpInside]; item.customView = button;
return item;
} @end
2.UINavigationController:
#import "UYNavigationController.h"

@interface UYNavigationController ()

@end

@implementation UYNavigationController

+ (void)initialize
{
// 设置整个项目所有item的主题样式
UIBarButtonItem *item = [UIBarButtonItem appearance]; // 设置普通状态
// key:NS****AttributeName
NSMutableDictionary *textAttrs = [NSMutableDictionary dictionary];
textAttrs[NSForegroundColorAttributeName] = [UIColor orangeColor];
textAttrs[NSFontAttributeName] = [UIFont systemFontOfSize:13];
[item setTitleTextAttributes:textAttrs forState:UIControlStateNormal]; // 设置不可用状态
NSMutableDictionary *disableTextAttrs = [NSMutableDictionary dictionary];
disableTextAttrs[NSForegroundColorAttributeName] = [UIColor colorWithRed:0.6 green:0.6 blue:0.6 alpha:0.7];
disableTextAttrs[NSFontAttributeName] = [UIFont systemFontOfSize:13];
[item setTitleTextAttributes:disableTextAttrs forState:UIControlStateDisabled];
} - (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
} /**
* 重写这个方法目的:能够拦截所有push进来的控制器
*
* @param viewController 即将push进来的控制器
*/
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if (self.viewControllers.count > 0) { // 这时push进来的控制器viewController,不是第一个子控制器(不是根控制器)
/* 自动显示和隐藏tabbar */
viewController.hidesBottomBarWhenPushed = YES;
    //左边    
    self.navigationItem.leftBarButtonItem = [HVWBarButtonItem itemWithImage:@"navigationbar_friendsearch" hightlightedImage:@"navigationbar_friendsearch_highlighted" target:self selector:@selector(searchFriend)];
    // 右边按钮
    self.navigationItem.rightBarButtonItem = [HVWBarButtonItem itemWithImage:@"navigationbar_pop" hightlightedImage:@"navigationbar_pop_highlighted" target:self selector:@selector(pop)];
}
[super pushViewController:viewController animated:animated]; } 

- (void)back { 
#warning 这里要用self,不是self.navigationController
// 因为self本来就是一个导航控制器,self.navigationController这里是nil的
[self popViewControllerAnimated:YES];
} - (void)more {
[self popToRootViewControllerAnimated:YES];
} @end

效果如下:

自定义TabBar,把特殊+按钮添加上来

需要反注释掉UYTabBarViewController部分代码:

    // 2.更换系统自带的tabbar,由于tabbar是realonly,因此使用KVC来重写。如果没有特殊的导航布局,去掉这下面这部分代码即可。
UYTabBar *tabBar = [[UYTabBar alloc] init];
tabBar.delegate = self;
[self setValue:tabBar forKeyPath:@"tabBar"];

UYTabBar 中,在layoutSubviews重新对四个底部TabBar进行位置调整,并给+号按钮增加点击事件:

UYTabBar.h

#import <UIKit/UIKit.h>
@class UYTabBar; #warning 因为UYTabBar继承自UITabBar,所以称为UYTabBar的代理,也必须实现UITabBar的代理协议
@protocol UYTabBarDelegate <UITabBarDelegate>
@optional
- (void)tabBarDidClickPlusButton:(UYTabBar *)tabBar;
@end @interface UYTabBar : UITabBar
@property (nonatomic, weak) id<UYTabBarDelegate> delegate;
@end

UYTabBar.m

#import "UYTabBar.h"

@interface UYTabBar()
@property(nonatomic,weak) UIButton *plusBtn;
@end @implementation UYTabBar - (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// 添加一个+号按钮 到tabbar中
UIButton *plusBtn = [[UIButton alloc] init];
//设置背影
[plusBtn setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button"] forState:UIControlStateNormal];
[plusBtn setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button_highlighted"] forState:UIControlStateHighlighted];
//增加+号图片
[plusBtn setImage:[UIImage imageNamed:@"tabbar_compose_icon_add"] forState:UIControlStateNormal];
[plusBtn setImage:[UIImage imageNamed:@"tabbar_compose_icon_add_highlighted"] forState:UIControlStateHighlighted];
plusBtn.size = plusBtn.currentBackgroundImage.size;
[plusBtn addTarget:self action:@selector(plusClick) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:plusBtn];
self.plusBtn = plusBtn;
}
return self;
} /**
* 加号按钮点击
*/
- (void)plusClick
{
// 通知代理
if ([self.delegate respondsToSelector:@selector(tabBarDidClickPlusButton:)]) {
[self.delegate tabBarDidClickPlusButton:self];
}
} - (void)layoutSubviews
{
#warning [super layoutSubviews] 一定要调用
[super layoutSubviews]; // 1.设置加号按钮的位置
self.plusBtn.centerX = self.width * 0.5;
self.plusBtn.centerY = self.height * 0.5; // 2.设置其他tabbarButton的位置和尺寸
CGFloat tabbarButtonW = self.width / 5;
CGFloat tabbarButtonIndex = 0;
for (UIView *child in self.subviews) {
Class class = NSClassFromString(@"UITabBarButton");
if ([child isKindOfClass:class]) {
// 设置宽度
child.width = tabbarButtonW;
// 设置x
child.x = tabbarButtonIndex * tabbarButtonW; // 增加索引
tabbarButtonIndex++;
if (tabbarButtonIndex == 2) {
tabbarButtonIndex++;
}
}
}
} @end

效果如下:

添加导航栏按钮

需要给各个Tab还有其下的页面添加左右导航栏按钮
由于该方法经常被使用到,自定义一个分类UIBarButtonItem
UIBarButtonItem.h
@interface UIBarButtonItem (Extension)
+ (UIBarButtonItem *)itemWithTarget:(id)target action:(SEL)action image:(NSString *)image highImage:(NSString *)highImage;
@end

UIBarButtonItem.m

@implementation UIBarButtonItem (Extension)
/**
* 创建一个item
*
* @param target 点击item后调用哪个对象的方法
* @param action 点击item后调用target的哪个方法
* @param image 图片
* @param highImage 高亮的图片
*
* @return 创建完的item
*/
+ (UIBarButtonItem *)itemWithTarget:(id)target action:(SEL)action image:(NSString *)image highImage:(NSString *)highImage
{
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
// 设置图片
[btn setBackgroundImage:[UIImage imageNamed:image] forState:UIControlStateNormal];
[btn setBackgroundImage:[UIImage imageNamed:highImage] forState:UIControlStateHighlighted];
// 设置尺寸
btn.size = btn.currentBackgroundImage.size;
return [[UIBarButtonItem alloc] initWithCustomView:btn];
}
@end

在HWNavigationController.m方法pushViewController下,增加

/**
* 重写这个方法目的:能够拦截所有push进来的控制器
*
* @param viewController 即将push进来的控制器
*/
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if (self.viewControllers.count > 0) { // 这时push进来的控制器viewController,不是第一个子控制器(不是根控制器)
/* 自动显示和隐藏tabbar */
viewController.hidesBottomBarWhenPushed = YES; /* 设置导航栏上面的内容 */
// 设置左边的返回按钮
viewController.navigationItem.leftBarButtonItem = [UIBarButtonItem itemWithTarget:self action:@selector(back) image:@"navigationbar_back" highImage:@"navigationbar_back_highlighted"]; // 设置右边的更多按钮
viewController.navigationItem.rightBarButtonItem = [UIBarButtonItem itemWithTarget:self action:@selector(more) image:@"navigationbar_more" highImage:@"navigationbar_more_highlighted"];
} [super pushViewController:viewController animated:animated];
}

新建一个测试页UYTest1ViewController

首页UYHomeViewController.m

- (void)viewDidLoad
{
[super viewDidLoad]; /* 设置导航栏上面的内容 */
self.navigationItem.leftBarButtonItem = [UIBarButtonItem itemWithTarget:self action:@selector(friendSearch) image:@"navigationbar_friendsearch" highImage:@"navigationbar_friendsearch_highlighted"]; self.navigationItem.rightBarButtonItem = [UIBarButtonItem itemWithTarget:self action:@selector(pop) image:@"navigationbar_pop" highImage:@"navigationbar_pop_highlighted"];
} - (void)friendSearch
{
NSLog(@"friendSearch");
} - (void)pop
{
//NSLog(@"pop");
UYTest1ViewController *test1 = [[UYTest1ViewController alloc] init];
test1.title = @"测试1控制器";
[self.navigationController pushViewController:test1 animated:YES]; }

效果:

添加自定义日志输出

日志输出,如果直接使用NSLog,在发布程序后,会比较耗性能。因此,我们只在调试的时候,才需要日志输出。

在pch文件里添加debug模式下的log函数

// 测试用log
#ifdef DEBUG
#define UYLog(...) NSLog(__VA_ARGS__)
#else
#define UYLog(...)
#endif

使用宏定义的log函数,只有在debug模式下才会转化成为NSLog,release的时候会转为空

 /** 寻找朋友按钮事件 */
- (void) searchFriend {
UYLog(@"searchFriend");
}

这里可以修改运行模式:

发布的程序,是Archive模式,是Release

iOS框架搭建(MVC,自定义TabBar)--微博搭建为例的更多相关文章

  1. weex 项目开发(四)项目框架搭建 及 自定义 TabBar 组件

    1.安装  路由模块  及  状态管理模块 npm install vue-router --save npm install vuex --save 2.自定义  TabBar  组件 src / ...

  2. iOS开发笔记_4自定义TabBar

    新博客:http://www.liuchendi.com 好多APP都使用的是自定义的TabBar,那这个功能应该如何实现呢?首先应该解决的问题就是,加载NavigationController的时候 ...

  3. [angularjs] MVC + Web API + AngularJs 搭建简单的 CURD 框架

    MVC + Web API + AngularJs 搭建简单的 CURD 框架 GitHub 地址:https://github.com/liqingwen2015/Wen.MvcSinglePage ...

  4. 基于Gin+Gorm框架搭建MVC模式的Go语言后端系统

    文/朱季谦 环境准备:安装Gin与Gorm 本文搭建准备环境:Gin+Gorm+MySql. Gin是Go语言的一套WEB框架,在学习一种陌生语言的陌生框架,最好的方式,就是用我们熟悉的思维去学.作为 ...

  5. 如何搭建MVC + EF 框架

    1.搭建MVC框架 1.1 VS2010:需要安装WPI 安装 ASP.NET MVC 4 和Visual Studio 2010 系统必备组件 如果上述链接无法打开,请访问:http://www.a ...

  6. VS2017创建一个 ASP.NET Core2.0 应用,并搭建 MVC 框架

    https://testerhome.com/topics/11747 1.使用最新版本的VS2017,并安装.NET Core2.0中相关开发工具   2.打开VS2017,点击文件-新建-项目,选 ...

  7. 【ASP.NET Core】- 搭建MVC框架

    1.使用最新版本的VS2017,并安装.NET Core2.0中相关开发工具   2.打开VS2017,点击文件-新建-项目,选择.NET Core中的ASP.NET Core Web 应用程序   ...

  8. [iOS微博项目 - 1.6] - 自定义TabBar

    A.自定义TabBar 1.需求 控制TabBar内的item的文本颜色(普通状态.被选中状态要和图标一致).背景(普通状态.被选中状态均为透明) 重新设置TabBar内的item位置,为下一步在Ta ...

  9. AJ学IOS 之微博项目实战(4)微博自定义tabBar中间的添加按钮

    AJ分享,必须精品 一:效果图 自定义tabBar实现最下面中间的添加按钮 二:思路 首先在自己的tabBarController中把系统的tabBar设置成自己的tabBar(NYTabBar),这 ...

随机推荐

  1. 负载均衡手段之DNS轮询

    大多数域名注册商都支持对统一主机添加多条A记录,这就是DNS轮询,DNS服务器将解析请求按照A记录的顺序,随机分配到不同的IP上,这样就完成了简单的负载均衡.下图的例子是:有3台联通服务器.3台电信服 ...

  2. 神奇的 routing mesh - 每天5分钟玩转 Docker 容器技术(100)

    接上一节案例,当我们访问任何节点的 8080 端口时,swarm 内部的 load balancer 会将请求转发给 web_server 其中的一个副本. 这就是 routing mesh 的作用. ...

  3. 【C#入门教案-02】用记事本编写第一个C#程序-Hello World

    02-用记事本编写第一个C#程序-Hello World 广东职业技术学院  欧浩源 [1]进行.NET程序开发的最基本环境配备 .NET Framework + 代码编辑工具(记事本或Noetpad ...

  4. ##7.Dashboard web管理界面-- openstack pike

    ##7.Dashboard web管理界面 openstack pike 安装 目录汇总 http://www.cnblogs.com/elvi/p/7613861.html ##.Dashboard ...

  5. iOS 视频播放方式整理

    初衷 多媒体这整个系列的文章自己也准备好开始整理了,先从视频音频最简单也是最常用的播放出发慢慢的往下深究,探索到底层的编码解码等等,这篇文章就从视频的播放这个最简单的说起. iOS的视频播放方式有几种 ...

  6. pku 1061 青蛙的约会 扩展欧几里得

    青蛙的约会Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 120482 Accepted: 25449Description 两只青 ...

  7. linux内核模块编程实例

    linux内核模块编程实例 学号:201400814125 班级:计科141 姓名:刘建伟 1.确定本机虚拟机中的Ubuntu下Linux的版本 通过使用命令uname -a/uname -r/una ...

  8. 项目实战11—企业级nosql数据库应用与实战-redis的主从和集群

    企业级nosql数据库应用与实战-redis 环境背景:随着互联网2.0时代的发展,越来越多的公司更加注重用户体验和互动,这些公司的平台上会出现越来越多方便用户操作和选择的新功能,如优惠券发放.抢红包 ...

  9. js 消抖(debounce)与节流(throttle)

    前言 故事发生在与大创的又一次撕逼(日常)中,我方坚定的认为:作为社会主义接班人,节流与消抖的界限是明显的,是不容混肴的,是不可侵犯的!对方辩友坚持地觉得:界限是模糊的,行为是暧昧的,性别是可以忽视的 ...

  10. Android中相机和相冊使用分析

    Android中相机和相冊使用分析 欢迎转载,但请尊重原创(文章来自不易,转载请标明转载出处,谢谢) 在手机应用程序中,使用自带的相机拍照以及相冊选择喜欢的图片是最常见只是的用户需求,那么怎么合理使用 ...