百思不得姐框架(二)
来源:互联网 发布:淘宝怎么登陆不了 编辑:程序博客网 时间: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
- 百思不得姐框架(二)
- 百思不得姐框架(一)
- 精度解析百思不得姐流行框架之精华版
- 《百思不得姐》
- 百思不得姐
- 百思不得姐项目详细知识点(二)
- 二.BeautifulSoup多线程下载百思不得姐图片
- 百思不得姐项目学习总结
- 02-百思不得姐(第二天)
- 03-百思不得姐(第三天)
- 04-百思不得姐(第四天)
- 02百思不得姐设置TabBar
- 03百思不得姐appearance使用
- 06-百思不得姐(第六天)
- 百思不得姐自定义TabBar
- 07-百思不得姐(第七天)
- 09-百思不得姐(第九天)
- iOS 高仿《百思不得姐》
- mysql:sql-mode
- android基础点击事件的四种写法和数据的存储方式
- Dubbo构建问题
- 程序员必知的8大排序(四)-------归并排序,基数排序(java实现)
- AngularJS路由实例(uiRoute、ngRoute)
- 百思不得姐框架(二)
- 互联网协议入门(1)
- ASP.NET MVC:自定义 Route 生成小写 Url
- Linux技术——gdb调试基础
- Java并发:await/wait 与sleep、yield间的区别
- 作业——在线学习Android课程之第五周
- HDU 5630 Rikka with Chess(翻棋子)
- 一、Android源码分析01-Ubuntu14.04系统Android源码下载
- #include<string>与#include<string.h>的区别