项目实战 网易彩票1

一 基本搭建

  • 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;
}
…… ……
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值