MyUINavigationController.m 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. //
  2. // MyUINavigationController.m
  3. // jiaPeiC
  4. //
  5. // Created by Echopentakill on 16/12/13.
  6. // Copyright © 2016年 JCZ. All rights reserved.
  7. //
  8. #import "MyUINavigationController.h"
  9. @interface MyUINavigationController ()<UINavigationControllerDelegate, UIGestureRecognizerDelegate>
  10. @end
  11. @implementation MyUINavigationController
  12. // 第一次使用这个类调用一次
  13. + (void)initialize {
  14. // 2.设置UINavigationBar的主题
  15. [self rq_setupNavigationBarTheme];
  16. // 3.设置UIBarButtonItem的主题
  17. [self rq_setupBarButtonItemTheme];
  18. }
  19. - (void)viewDidLoad {
  20. [super viewDidLoad];
  21. __weak MyUINavigationController *weakSelf = self;
  22. if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
  23. {
  24. self.interactivePopGestureRecognizer.delegate = weakSelf;
  25. self.delegate = weakSelf;
  26. }
  27. }
  28. /**
  29. * 设置UINavigationBarTheme的主题
  30. */
  31. + (void)rq_setupNavigationBarTheme {
  32. UINavigationBar *appearance = [UINavigationBar appearance];
  33. /// 设置背景
  34. //!!!: 必须设置为透明 不然布局有问题 ios8以下 会崩溃/ 如果iOS8以下 请再_setup里面 设置透明 self.navigationBar.translucent = YES;
  35. [appearance setTranslucent:YES]; /// 必须设置YES
  36. // 设置导航栏的样式
  37. [appearance setBarStyle:UIBarStyleDefault];
  38. //设置导航栏文字按钮的渲染色
  39. [appearance setTintColor:RQColorFromHexString(@"#333333")];
  40. // 设置导航栏的背景渲染色
  41. [appearance setBarTintColor:RQMianColor];
  42. // 设置文字属性
  43. NSMutableDictionary *textAttrs = [NSMutableDictionary dictionary];
  44. textAttrs[NSFontAttributeName] = [UIFont fontWithName:@"Helvetica-Bold" size:17.f];
  45. textAttrs[NSForegroundColorAttributeName] = RQColorFromHexString(@"#ffffff");
  46. // UIOffsetZero是结构体, 只要包装成NSValue对象, 才能放进字典\数组中
  47. NSShadow *shadow = [[NSShadow alloc] init];
  48. shadow.shadowOffset = CGSizeZero;
  49. textAttrs[NSShadowAttributeName] = shadow;
  50. [appearance setTitleTextAttributes:textAttrs];
  51. /// 去掉导航栏的阴影图片
  52. [appearance setShadowImage:[UIImage new]];
  53. [appearance setBackgroundImage:[UIImage yy_imageWithColor:RQMianColor] forBarMetrics:UIBarMetricsDefault];
  54. }
  55. /**
  56. * 设置UIBarButtonItem的主题
  57. */
  58. + (void)rq_setupBarButtonItemTheme {
  59. // 通过appearance对象能修改整个项目中所有UIBarButtonItem的样式
  60. UIBarButtonItem *appearance = [UIBarButtonItem appearance];
  61. CGFloat fontSize = 16.0f;
  62. /**设置文字属性**/
  63. // 设置普通状态的文字属性
  64. NSMutableDictionary *textAttrs = [NSMutableDictionary dictionary];
  65. textAttrs[NSForegroundColorAttributeName] = [UIColor whiteColor];
  66. textAttrs[NSFontAttributeName] = [UIFont systemFontOfSize:fontSize];
  67. NSShadow *shadow = [[NSShadow alloc] init];
  68. shadow.shadowOffset = CGSizeZero;
  69. textAttrs[NSShadowAttributeName] = shadow;
  70. [appearance setTitleTextAttributes:textAttrs forState:UIControlStateNormal];
  71. // 设置高亮状态的文字属性
  72. NSMutableDictionary *highTextAttrs = [NSMutableDictionary dictionaryWithDictionary:textAttrs];
  73. highTextAttrs[NSForegroundColorAttributeName] = [[UIColor whiteColor] colorWithAlphaComponent:.5f];
  74. [appearance setTitleTextAttributes:highTextAttrs forState:UIControlStateHighlighted];
  75. // 设置不可用状态(disable)的文字属性
  76. NSMutableDictionary *disableTextAttrs = [NSMutableDictionary dictionaryWithDictionary:textAttrs];
  77. disableTextAttrs[NSForegroundColorAttributeName] = [[UIColor whiteColor] colorWithAlphaComponent:.5f];
  78. [appearance setTitleTextAttributes:disableTextAttrs forState:UIControlStateDisabled];
  79. }
  80. //在转场/过渡的时候禁用 interactivePopGestureRecognizer当用户在转场的时候触发一个后退手势,则各种事件又凑一块了.导航栈内又成了混乱的.我的解决办法是,转场效果的过程中禁用手势识别,当新的视图控制器加载完成后再启用.再次建议使用UINavigationController的子类操作
  81. -(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
  82. {
  83. if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
  84. self.interactivePopGestureRecognizer.enabled = NO;
  85. [super pushViewController:viewController animated:animated];
  86. }
  87. #pragma mark UINavigationControllerDelegate
  88. - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
  89. {
  90. // Enable the gesture again once the new controller is shown
  91. if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
  92. self.interactivePopGestureRecognizer.enabled = YES;
  93. }
  94. //
  95. //解决左滑手势冲突和不灵敏的问题
  96. -(UIViewController *)popViewControllerAnimated:(BOOL)animated {
  97. return [super popViewControllerAnimated:YES];
  98. }
  99. #pragma mark UIGestureRecognizerDelegate
  100. - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
  101. if ([self.childViewControllers count] == 1) {
  102. return NO;
  103. }
  104. return YES;
  105. }
  106. // 我们差不多能猜到是因为手势冲突导致的,那我们就先让 ViewController 同时接受多个手势吧
  107. - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
  108. return YES;
  109. }
  110. //运行试一试,两个问题同时解决,不过又发现了新问题,手指在滑动的时候,被 pop 的 ViewController 中的 UIScrollView 会跟着一起滚动,这个效果看起来就很怪(知乎日报现在就是这样的效果),而且也不是原始的滑动返回应有的效果,那么就让我们继续用代码来解决吧
  111. - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
  112. {
  113. return [gestureRecognizer isKindOfClass:UIScreenEdgePanGestureRecognizer.class];
  114. }
  115. - (void)didReceiveMemoryWarning {
  116. [super didReceiveMemoryWarning];
  117. // Dispose of any resources that can be recreated.
  118. }
  119. /*
  120. #pragma mark - Navigation
  121. // In a storyboard-based application, you will often want to do a little preparation before navigation
  122. - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
  123. // Get the new view controller using [segue destinationViewController].
  124. // Pass the selected object to the new view controller.
  125. }
  126. */
  127. @end