一 基本搭建
main->UIApplicationMain底层实现
- 1.创建UIApplication对象
- 2.创建UIApplication对象代理
- 3.开启主运行循环,保持程序一直运行
- 4.加载info.plist文件,判断下是否指定main
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
- 手动创建 storyboard
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 1.创建窗口
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
// 2.创建窗口的跟控制器
// 创建tabBarVc
UITabBarController *tabBarVc = [[UITabBarController alloc] init];
// 设置窗口的根控制器
self.window.rootViewController = tabBarVc;
// 3.让窗口显示
[self.window makeKeyAndVisible];
return YES;
}
二 自定义 tabBar
#pragma mark - 添加所有子控制器
- (void)setUpAllChildViewController
{
// 购彩大厅
XMGHallViewController *hall = [[XMGHallViewController alloc] init];
hall.view.backgroundColor = [UIColor redColor];
// 添加一个子控制器
[self setUpOneChildViewController:hall image:[UIImage imageNamed:@"TabBar_LotteryHall_new"] selImage:[UIImage imageNamed:@"TabBar_LotteryHall_selected_new"]];
// 竞技场
XMGArenaViewController *arena = [[XMGArenaViewController alloc] init];
arena.view.backgroundColor = [UIColor purpleColor];
[self setUpOneChildViewController:arena image:[UIImage imageNamed:@"TabBar_Arena_new"] selImage:[UIImage imageNamed:@"TabBar_Arena_selected_new"]];
……
- 抽取相似方法代码
#pragma mark - 添加一个子控件
- (void)setUpOneChildViewController:(UIViewController *)vc image:(UIImage *)image selImage:(UIImage *)selImage
{
// 设置tabBarButton的图片,tabBarButton的内容由对应的子控制器的tabBarItem
vc.tabBarItem.image = image;
vc.tabBarItem.selectedImage = selImage;
[self addChildViewController:vc];
}
- 自定义tabBar
#pragma mark - 自定义tabBar
- (void)setUpTabBar
{
// 1.移除系统的tabBar,移除系统自带的tabBarButton
[self.tabBar removeFromSuperview];
// 2.添加自己的tabBar
XMGTabBar *tabBar = [[XMGTabBar alloc] init];
tabBar.delegate = self;
// tabBar按钮的个数,由tabBar子控制器个数决定
// tabBar.count = (int)self.childViewControllers.count;
// 传对应子控制器的tabBarItem数组
tabBar.items = self.items;
tabBar.backgroundColor = [UIColor greenColor];
tabBar.frame = self.tabBar.frame;
[self.view addSubview:tabBar];
}
- 封装自定义tabBar
- (void)setItems:(NSArray *)items
{
_items = items;
for (UITabBarItem *item in items) {
UIButton *btn = [XMGTabBarButton buttonWithType:UIButtonTypeCustom];
// 设置内容
[btn setBackgroundImage:item.image forState:UIControlStateNormal];
[btn setBackgroundImage:item.selectedImage forState:UIControlStateSelected];
[btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchDown];
btn.tag = self.subviews.count;
if (self.subviews.count == 0) {
[self btnClick:btn];
}
[self addSubview:btn];
}
}
- 每次选中一个逻辑
- (void)btnClick:(UIButton *)btn
{
_selBtn.selected = NO;
btn.selected = YES;
_selBtn = btn;
// 通知代理点击了哪个角标的按钮
if ([_delegate respondsToSelector:@selector(tabBar:didClickBtn:)]) {
[_delegate tabBar:self didClickBtn:btn.tag];
}
}
- (void)layoutSubviews
{
[super layoutSubviews];
int count = (int)self.subviews.count;
CGFloat btnW = self.bounds.size.width / count;
CGFloat btnH = self.bounds.size.height;
CGFloat btnY = 0;
CGFloat btnX = 0;
// 布局按钮的位置
for (int i = 0; i < count; i++) {
UIButton *btn = self.subviews[i];
btnX = i * btnW;
btn.frame = CGRectMake(btnX, btnY, btnW, btnH);
}
}
- 按钮取消高亮状态
- 自定义按钮 XMGTabBarButton
- (void)setHighlighted:(BOOL)highlighted
{
}
- 点击 button 通知代理切换控制器 view
@class XMGTabBar;
@protocol XMGTabBarDelgate <NSObject>
@optional
- (void)tabBar:(XMGTabBar *)tabBar didClickBtn:(NSInteger)index;
@end
@interface XMGTabBar : UIView
/** items:UITabBarItem模型 */
@property (nonatomic, strong) NSArray *items;
@property (nonatomic, weak) id<XMGTabBarDelgate> delegate;
@end
- 仿系统实现 tabBar 代理方法
#pragma mark -XMGTabBarDelgate方法
// 当点击tabBar上的条的时候调用
- (void)tabBar:(XMGTabBar *)tabBar didClickBtn:(NSInteger)index
{
// 切换界面
self.selectedIndex = index;
}
三 设置导航条内容
#pragma mark - 添加一个子控制器,并且设置对应的内容
- (void)setUpOneChildViewController:(UIViewController *)vc image:(UIImage *)image selImage:(UIImage *)selImage title:(NSString *)title
{
// 设置导航条
vc.navigationItem.title = title;
// 设置tabBarButton的图片,tabBarButton的内容由对应的子控制器的tabBarItem
vc.tabBarItem.image = image;
vc.tabBarItem.selectedImage = selImage;
// 保存对应子控制器的UITabBarItem
[self.items addObject:vc.tabBarItem];
// 如果想要一个控制器既展示自己的view,同时想增加一个导航条,直接包装成导航控制器
// 包装成导航控制器
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
// 设置导航条背景图片,必须填UIBarMetricsDefault
// 使用UIBarMetricsDefault,导航控制器的子控制器view的尺寸不包括导航条部分
[nav.navigationBar setBackgroundImage:[UIImage imageNamed:@"NavBar64"] forBarMetrics:UIBarMetricsDefault];
// 设置导航条文字颜色
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
// 设置颜色
dict[NSForegroundColorAttributeName] = [UIColor whiteColor];
dict[NSFontAttributeName] = [UIFont boldSystemFontOfSize:22];
[nav.navigationBar setTitleTextAttributes:dict];
[self addChildViewController:nav];
}
四 自定义导航控制器
- initialize方法(初始化一次)
- 创建了5个导航控制器,会创建5次,需要只设置一次
// 当前类或者它的子类第一次使用的时候调用
// 初始化一个类
+ (void)initialize
{
// 设置导航条的背景,文字颜色
// 谁用我的导航控制器,只设置使用自己导航控制器下的导航条
// 获取整个app里所有导航条外观的标志(通常开发不用,强制性大)
// UINavigationBar *bar = [UINavigationBar appearance];
// 获取当前类下的导航条
// self指向->XMGNavigationController
UINavigationBar *bar = [UINavigationBar appearanceWhenContainedIn:self, nil];
// Do any additional setup after loading the view.
// 设置导航条背景图片,必须填UIBarMetricsDefault
// 使用UIBarMetricsDefault,导航控制器的子控制器view的尺寸不包括导航条部分
[bar setBackgroundImage:[UIImage imageNamed:@"NavBar64"] forBarMetrics:UIBarMetricsDefault];
// 设置导航条文字颜色
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
// 设置颜色
dict[NSForegroundColorAttributeName] = [UIColor whiteColor];
dict[NSFontAttributeName] = [UIFont boldSystemFontOfSize:22];
[bar setTitleTextAttributes:dict];
}
五 导航条TabBar item设置
- 购彩大厅左侧图标
- (void)viewDidLoad {
[super viewDidLoad];
// 不让图片被渲染封装方法
UIImage *image = [UIImage imageWithOriginRenderingName:@"CS50_activity_image"];
// 原始代码如下:
// UIImage *image = [UIImage imageNamed:@"CS50_activity_image"];
// image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
// 设置导航条左边按钮
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStyleDone target:self action:@selector(activity)];
}
- 图片不被渲染分类方法 UIImage+Image.h
+ (instancetype)imageWithOriginRenderingName:(NSString *)imageName
{
UIImage *image = [UIImage imageNamed:imageName];
return [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
}
- 蒙板效果XMGCover
#define XMGKeyWindow [UIApplication sharedApplication].keyWindow
+ (void)show
{
XMGCover *cover = [[self alloc] init];
cover.frame = XMGKeyWindow.bounds;
cover.backgroundColor = [UIColor blackColor];
cover.alpha = 0.5;
// 获取主窗口
[XMGKeyWindow addSubview:cover];
}
+ (void)hide
{
// 隐藏蒙板
for (UIView *childView in XMGKeyWindow.subviews) {
if ([childView isKindOfClass:self]) { // 是蒙板
[childView removeFromSuperview];
}
}
}
// 点击活动按钮的时候调用
- (void)activity
{
// 弹出蒙板,
// 只要以后想要把一个控件显示在最外边,就添加到窗口,提供一个show方法
[XMGCover show];
// 弹出pop菜单
XMGPopMenu *menu = [XMGPopMenu showInPoint:self.view.center];
menu.delegate = self;
}
#pragma mark - XMGPopMenuDelegate
// 点击菜单上关闭按钮的时候就会调用
- (void)popMenuDidClickCloseMenu:(XMGPopMenu *)menu
{
[UIView animateWithDuration:0 animations:nil completion:^(BOOL finished) {
}];
// 定义移动完成的block,保存移动完成的代码
void (^completion)() = ^{
// 当移动完成的时候,把蒙板消失
[XMGCover hide];
};
// block精髓:可以当做参数去用。
// 菜单移动到某个位置,并且缩放。
[menu hideInPoint:CGPointMake(44, 44) completion:completion];
}
- 用代理监听关闭按钮
- (IBAction)close:(id)sender {
// 通知代理做事情,告诉代理点击了关闭
if ([_delegate respondsToSelector:@selector(popMenuDidClickCloseMenu:)]) {
[_delegate popMenuDidClickCloseMenu:self];
}
}
// 隐藏
- (void)hideInPoint:(CGPoint)point completion:(void (^)())completion
{
[UIView animateWithDuration:.5 animations:^{
self.center = point;
// 直接修改父控件的尺寸,是不会影响子控件
// self.bounds = CGRectMake(0, 0, 1, 1);
// 如果设置0,控件直接缩放为0,没有动画,如果想要动画,搞一个最小值
self.transform = CGAffineTransformMakeScale(0.01, 0.01);
} completion:^(BOOL finished) {
[self removeFromSuperview];
if (completion) {
completion();
}
}];
}
- 实现代理方法
#pragma mark - XMGPopMenuDelegate
// 点击菜单上关闭按钮的时候就会调用
- (void)popMenuDidClickCloseMenu:(XMGPopMenu *)menu
{
[UIView animateWithDuration:0 animations:nil completion:^(BOOL finished) {
}];
// 定义移动完成的block,保存移动完成的代码
void (^completion)() = ^{
// 当移动完成的时候,把蒙板消失
[XMGCover hide];
};
// 菜单移动到某个位置,并且缩放。
[menu hideInPoint:CGPointMake(44, 44) completion:completion];
}
六 block
- 定义 block
- void(^)() : block类型
void(^block)() = ^(){
// 保存代码
};
- 起别名
// name: block类型的别名
typedef void(^MyBlock)();
// 调用block,才会执行block里面代码
block();
七 抽取 UIView分类
- pch 文件
- 存储一些公用的宏,公用的分类
设置 pch 路径
#ifdef __OBJC__
#define XMGKeyWindow [UIApplication sharedApplication].keyWindow
#import "UIImage+Image.h"
#import "UIView+Frame.h"
#endif
- UIView+Frame.h 分类
@property在分类里面只会自动生成get,set方法,并不会生成下划线的成员属性
- 封装宽、高、x、y
- (CGFloat)width
{
return self.frame.size.width;
}
- (void)setWidth:(CGFloat)width
{
CGRect frame = self.frame;
frame.size.width = width;
self.frame = frame;
}
…… ……