百思不得姐框架(二)

来源:互联网 发布:淘宝怎么登陆不了 编辑:程序博客网 时间:2024/04/30 00:36

一 该部分框架效果图和实现思路

框架二的效果图:

框架效果图

实现思路:

—- 1> 先完善tabBar(主要是自定义)
—- 2> 再完善导航条
—- 3> 其次完善屏幕侧滑(主要是全屏侧滑功能)

二 抽取分类(设置到插件中)

1 抽取分类的思想: 实现复用

—-> 1.1 上部分代码中,我们需要设置tabBar中图片成未被渲染的格式,因此我们抽取了一个分类,用分类里面的方法实现了效果.
—-> 分类代码:
//传入一张图片的名称返回一张未被渲染的图片+ (UIImage *)originalWithImage:(NSString *)imageName{    UIImage *image = [UIImage imageNamed:imageName];    return [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];}

2 问题:虽然抽取了分类,但是我们是不是想在用分类设置图片的时候,也能有插件提示功能呢?

设置插件功能图:(图一)

这里写图片描述

具体的设置思路:<—>见下图

2.1 按住option,点击桌面的左上角,找到前往,点击资源库
图一:

这里写图片描述

图二:

这里写图片描述

图三:

这里写图片描述

图四:

这里写图片描述

图五:

这里写图片描述

图六:

这里写图片描述

图七:

这里写图片描述

最后:找到插件的位置,具体做法就是先command + c 然后command + v 赋值个item,然后将图七中的改为自己的分类方法就可以.

三 问题一

1 问题: 选中的图片中,配图的文字被渲染了(图片不被渲染我们用分类解决了)
2 实现思路:
—-> 1> 通过获取到全局的tabBar
—-> 2> 再通过字典来包装设置字体颜色和字体的大小
3 在自定义的tabBarController控制器中设置选中字体的颜色不被渲染(全程序只需要设置一次)–>选中状态
4 通过拿到全局的tabBarItem去设置按钮的字体大小(由整个app的效果图知道,字体需要加粗)

具体代码:

#pragma mark - 设置标题的字体不被渲染(该方法全程序只会来一次)+ (void)load{    //获取全局的tabBar    UITabBarItem *tabBar = [UITabBarItem appearance];    //创建可变字典    NSMutableDictionary *dict = [NSMutableDictionary dictionary];    //设置文字的颜色    dict[NSegroundColorAttributeName] = [UIColor blackColor];    //设置字体    [tabBar setTitleTextAttributes:dict forState:UIControlStateSelected];    NSMutableDictionary *dict1 = [NSMutableDictionary dictionary];    //设置文字的大小    dict1[NSFontAttributeName] = [UIFont boldSystemFontOfSize:13];    //设置字体大小    [tabBar setTitleTextAttributes:dict1 forState:UIControlStateNormal];}
5 发布按钮显示不出来—>发布按钮的图片比较大,显示出来就会有问题
—-> 5.1 让正常状态下的图片也不被渲染(能达到效果)
nav2.tabBarItem.image = [UIImage originalWithImage:@"tabBar_publish_icon"];
—-> 5.2 设置对应的控制器的tabBarItem,通过设置图片的内边距来实现(通过测试也不符合条件:原因是选中时候高亮,但是不选中的时候就会恢复状态)–>很明显是高亮状态
publish.tabBarItem.imageInsets = UIEdgeInsetsMake(7, 0, -7, 0);

四 自定义tabBar

1 为了解决tabBar的问题,我们自定义tabBar(继承系统的UITabBar)

见图:

这里写图片描述

2 修改tabBar内部子控件位置

3 把系统的tabBar替换为自己的tabBar(只需要创建一次)–(KVC)

具体实现代码:
#pragma mark - 运用自定义的tabBar- (void)setUpTabBar{    //创建自定义tabBar    XFJTabBar *tabBar = [[XFJTabBar alloc] init];    //KVC赋值    [self setValue:tabBar forKey:@"tabBar"];}

4 重写layoutSubViews(布局tabBar中的子控件)

4.1 调整内部子控件的位置(遍历所有的子控件,然后判断子控件的类型,将中间的按钮位置空出来)

注意部分: 通过打印tabBar的子控件的类型,我们知道了按钮的类型是—> UITabBarButton这种类型的

代码详见:
#pragma mark - 布局子控件- (void)layoutSubviews{    [super layoutSubviews];    //获取子控件的总数    NSInteger count = self.items.count + 1;    //设置按钮的尺寸的属性    CGFloat buttonX = 0;    CGFloat buttonY = 0;    CGFloat buttonW = self.XFJ_Width / count;    CGFloat buttonH = self.XFJ_height;    NSInteger i= 0;    //遍历    for (UIView *button in self.subviews) {        //判断为该种类型的时候才进行下面        if ([button isKindOfClass:NSClassFromString(@"UITabBarButton")]) {            if (i == 2) {                i = i + 1;            }            //按钮的X值            buttonX = i * buttonW;            //按钮的尺寸            button.frame = CGRectMake(buttonX, buttonY, buttonW, buttonH);            i ++;        }    }    //设置发布按钮的饿摆放位置    self.plusButton.center = CGPointMake(self.XFJ_Width * 0.5, self.XFJ_height * 0.5);}
4.2 懒加载(通过懒加载创建发布按钮,然后在内部设置属性)—>由于只需要创建一次,所以用懒加载实现
#pragma mark - 懒加载- (UIButton *)plusButton{    if (_plusButton == nil) {        //创建按钮        UIButton *plusButton = [UIButton buttonWithType:UIButtonTypeCustom];        //设置按钮的图片(平常状态)        [plusButton setImage:[UIImage imageNamed:@"tabBar_publish_icon"] forState:UIControlStateNormal];        //高亮状态        [plusButton setImage:[UIImage imageNamed:@"tabBar_publish_click_icon"] forState:UIControlStateHighlighted];        //赋值        self.plusButton = plusButton;        //自适应        [plusButton sizeToFit];        [self addSubview:plusButton];    }    return _plusButton;}

五 问题二

问题: 我们很多时候需要在外界直接修改控件的尺寸,但是传统的写法太麻烦.

解决办法:创建分类,在外界直接修改X,Y,width,Height的时候,能直接点出来

代码块一 :
@property CGFloat XFJ_x;@property CGFloat XFJ_y;@property CGFloat XFJ_Width;@property CGFloat XFJ_height;
代码块二(在分类的内部实现了尺寸的修改,外面直接就可以点出来用):
- (void)setXFJ_x:(CGFloat)XFJ_x{    CGRect frame = self.frame;    frame.origin.x = XFJ_x;    self.frame = frame;}- (CGFloat)XFJ_x{    return self.frame.origin.x;}

六 PCH文件

1 创建一个PCH文件(注意命名方式:和工程名一样),将全程序都需要的用到的文件都放到里面–>prefix

—-> PCH文件的实现思路:将pch文件中的代码,全部都拷贝一个到每个文件中,然后编译.

2 具体PCH配置:

详见图一:

这里写图片描述

详见图二:(注意文件的路径)

这里写图片描述

七 精华模块导航条的内容

1 导航条左边的按钮图片(封装一个分类)—->封装原因:我们想直接通过传入两张图,直接返回一个设置好的UIBarButtonItem对象.

—-> 写在分类中的代码:
+ (UIBarButtonItem *)itemWithImage:(UIImage *)image heightImage:(UIImage *)heighImage target:(id)target action:(SEL)action{    //创建按钮    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];    //设置按钮图片    [button setImage:image forState:UIControlStateNormal];    //高亮状态    [button setImage:heighImage forState:UIControlStateHighlighted];        //设置按钮的尺寸    [button sizeToFit];    //按钮的点击事件    [button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];    //返回一个设置好的按钮    return [[UIBarButtonItem alloc ]initWithCustomView:button];}
—-> 设置左边图片:
- (void)setUpNavBar{    //左边的样式    UIBarButtonItem *item = [UIBarButtonItem itemWithImage:[UIImage imageNamed:@"nav_item_game_icon"] heightImage:[UIImage imageNamed:@"nav_item_game_click_icon"] target:self action:@selector(game)];
—-> 设置右边的图片:
//右边的样式    UIBarButtonItem *item1 = [UIBarButtonItem itemWithImage:[UIImage imageNamed:@"navigationButtonRandom"] heightImage:[UIImage imageNamed:@"navigationButtonRandomClick"] target:self action:@selector(task)];    self.navigationItem.rightBarButtonItem = item1;
—-> 设置标题(注意:导航条的标题是一张图片)
#pragma mark - 设置导航条标题- (void)setUpNavTitle{    UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"MainTitle"]];    self.navigationItem.titleView = imageView;}

2 是不是所有的类都能拿到全局的外观?

解答: 不是,只有遵守了UIAppearance协议就可以通过appearance获取全局外观.

3 设置全局导航条的背景图片和显示的字体

具体代码:
//获取全局的导航条    UINavigationBar *navBar = [UINavigationBar appearance];    //设置背景图片    [navBar setBackgroundImage:[UIImage imageNamed:@"navigationbarBackgroundWhite"] forBarMetrics:UIBarMetricsDefault];    //设置字体    NSMutableDictionary *dict = [NSMutableDictionary dictionary];    dict[NSFontAttributeName] = [UIFont boldSystemFontOfSize:20];    [navBar setTitleTextAttributes:dict];

八 bug

ios8会出现的bug:把短信界面导航条改了,联系人界面会出现黑的.

九 跳转设置

1 自定义设置控制器(UITableViewController)

这里写图片描述

2 控制器”我”导航条右侧的图片

#pragma mark - 添加控制器我的右边的图片- (void)setImageWithRight{    //控制器右边的图片    UIBarButtonItem *item1 = [UIBarButtonItem itemWithImage:[UIImage imageNamed:@"mine-moon-icon"] heightImage:[UIImage imageNamed:@"mine-moon-icon-click"] target:self action:@selector(moon)];    UIBarButtonItem *item2 = [UIBarButtonItem itemWithImage:[UIImage imageNamed:@"mine-setting-icon"] heightImage:[UIImage imageNamed:@"mine-setting-icon-click"] target:self action:@selector(setting)];    //设置右边的图片    self.navigationItem.rightBarButtonItems = @[item2,item1];  }

3 跳转到设置界面

#pragma mark - 点击事件的实现(setting)- (void)setting{    NSLog(@"setting");    //创建跳转控制器    XFJSettingViewController *setting = [[XFJSettingViewController alloc] init];    //在push之前隐藏底部的tabBar    setting.hidesBottomBarWhenPushed = YES;    //跳转控制器    [self.navigationController pushViewController:setting animated:YES];}

4 跳转后出现的问题:

—-> 4.1 底部条没有隐藏
//在push之前隐藏底部的tabBar    setting.hidesBottomBarWhenPushed = YES;
—-> 4.2 返回按钮样式(一定要在有内容的前提下,才能设置内边距)

5 设置全局返回按钮(重写push方法)

#pragma mark - 重写push方法- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{    NSLog(@"%@",self.interactivePopGestureRecognizer);    //判断,只有是分根控制器才能返回    if (self.childViewControllers.count > 0) {        //创建按钮        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];        //设置按钮没有点击的图片        [button setImage:[UIImage imageNamed:@"navigationButtonReturn"] forState:UIControlStateNormal];        //设置按钮点击后的图片        [button setImage:[UIImage imageNamed:@"navigationButtonReturnClick"] forState:UIControlStateHighlighted];        //设置返回按钮字样        [button setTitle:@"返回" forState:UIControlStateNormal];        //设置返回按钮的标题的正常样式        [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];        //设置返回按钮的标题的点击样式        [button setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];        //设置按钮的尺寸        [button sizeToFit];        //设置按钮的监听方法        [button addTarget:self action:@selector(backBtn) forControlEvents:UIControlEventTouchUpInside];        //设置返回按钮与左边的距离        button.contentEdgeInsets = UIEdgeInsetsMake(0, -10, 0, 0);        //添加按钮        viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];    }    [super pushViewController:viewController animated:animated];}

十 重写push方法出现的bug—>系统的滑动返回功能失效了

1 解决办法: 清空代理—->会出现bug(假死状态:程序一直在跑,但是界面死了)
2 假死原因:在根控制器下,滑动返回,不应该在根控制器的view上滑动返回
3 解决办法:把自己设置为手势的代理,实现代理方法,判断,如果是根控制器,让手势没有效果(是否触发手势的代理方法)

代码块一:

self.interactivePopGestureRecognizer.delegate = self;

代码块二:

#pragma mark - 代理方法- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{    //只有当导航控制器的子控制器的数量大于1的时候,才能侧滑    return self.childViewControllers.count > 1;}

十一 全屏滑动

1 分析:为什么导航控制器的滑动手势只能边缘滑动?

2 通过打印出代理的类型和action的方法,我们可以添加一个全屏滑动的功能,但是需要设置手势的代理,否则在根控制器的时候,又会出现假死的状态.

—->打印出系统侧滑功能的代理(红色部分是代理需要调用的方法)
<UIScreenEdgePanGestureRecognizer: 0x7fe5b2493980; state = Possible; delaysTouchesBegan = YES; view = <UILayoutContainerView 0x7fe5b24920d0>; target= <(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7fe5b2493860>)>>
—-> 代码块一:
#pragma mark - 添加全屏侧滑功能- (void)setWithScreenPan{    //创建手势    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self.interactivePopGestureRecognizer.delegate action:@selector(handleNavigationTransition:)];    //添加手势    [self.view addGestureRecognizer:pan];    //设置代理为自己    pan.delegate = self;}
代码块二:
//添加手势    [self setWithScreenPan];    //清空代理,但是必须是在添加手势之后    self.interactivePopGestureRecognizer.enabled = NO;

十二 总结

1 该部分是有关tabBar和导航条的设置,里面涉及到自定义.设置好了系统的返回功能,但是由于重写而产生的一系列问题.里面已经涉及到了所有情况的解决思路,可能有一些不是很完整.后期我将一一解决.

2 今天只是框架二 ,明天我将为大家讲解后面的部分,大家有什么问题,麻烦留言,谢谢!!!!

2 0
原创粉丝点击