cdts/xdts-ios 3/TreeHole/CYHResetCode/CYH/QMUIKit/QMUIComponents/NavigationBarTransition/UINavigationController+NavigationBarTransition.m

614 lines
35 KiB
Mathematica
Raw Normal View History

2023-07-27 09:20:00 +08:00
/**
* Tencent is pleased to support the open source community by making QMUI_iOS available.
* Copyright (C) 2016-2021 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
*/
//
// UINavigationController+NavigationBarTransition.m
// qmui
//
// Created by QMUI Team on 16/2/22.
//
#import "UINavigationController+NavigationBarTransition.h"
#import "QMUINavigationController.h"
#import "QMUICore.h"
#import "UINavigationController+QMUI.h"
#import "UIImage+QMUI.h"
#import "UIViewController+QMUI.h"
#import "UINavigationBar+Transition.h"
#import "QMUINavigationTitleView.h"
#import "UINavigationBar+QMUI.h"
#import "UINavigationBar+QMUIBarProtocol.h"
#import "UIView+QMUI.h"
#import "QMUILog.h"
/**
* <b>NavigationBarTransition</b>UIViewController
* @see UINavigationController+NavigationBarTransition.h
*/
@interface UIViewController (NavigationBarTransition)
@property(nonatomic, assign) BOOL qmuinb_shouldShowTransitionBar;
/// 仿navBarnavBar
@property(nonatomic, strong) _QMUITransitionNavigationBar *transitionNavigationBar;
/// navBar
@property(nonatomic, assign) BOOL prefersNavigationBarBackgroundViewHidden;
/// containerView
@property(nonatomic, strong) UIColor *originContainerViewBackgroundColor;
@end
@interface UILabel (NavigationBarTransition)
@property(nonatomic, strong) UIColor *qmui_specifiedTextColor;
@end
@implementation UILabel (NavigationBarTransition)
QMUISynthesizeIdStrongProperty(qmui_specifiedTextColor, setQmui_specifiedTextColor)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
OverrideImplementation(NSClassFromString(@"UIButtonLabel"), @selector(setAttributedText:), ^id(__unsafe_unretained Class originClass, SEL originCMD, IMP (^originalIMPProvider)(void)) {
return ^(UILabel *selfObject, NSAttributedString *attributedText) {
if (selfObject.qmui_specifiedTextColor) {
NSMutableAttributedString *mutableAttributedText = [attributedText isKindOfClass:NSMutableAttributedString.class] ? attributedText : [attributedText mutableCopy];
[mutableAttributedText addAttributes:@{ NSForegroundColorAttributeName : selfObject.qmui_specifiedTextColor} range:NSMakeRange(0, mutableAttributedText.length)];
attributedText = mutableAttributedText;
}
void (*originSelectorIMP)(id, SEL, NSAttributedString *);
originSelectorIMP = (void (*)(id, SEL, NSAttributedString *))originalIMPProvider();
originSelectorIMP(selfObject, originCMD, attributedText);
};
});
});
}
@end
@implementation UINavigationBar (NavigationBarTransition)
/// Label
- (UILabel *)qmui_backButtonLabel {
__block UILabel *backButtonLabel = nil;
[self.qmui_contentView.subviews enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(__kindof UIView * _Nonnull subview, NSUInteger idx, BOOL * _Nonnull stop) {
if ([subview isKindOfClass:NSClassFromString(@"_UIButtonBarButton")]) {
UIButton *titleButton = [subview valueForKeyPath:@"visualProvider.titleButton"];
backButtonLabel = titleButton.titleLabel;
*stop = YES;
}
}];
return backButtonLabel;
}
@end
@implementation UIViewController (NavigationBarTransition)
#pragma mark -
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
ExtendImplementationOfVoidMethodWithoutArguments([UINavigationController class], @selector(qmui_didInitialize), ^(UINavigationController *selfObject) {
[selfObject qmui_addNavigationActionDidChangeBlock:^(QMUINavigationAction action, BOOL animated, __kindof UINavigationController * _Nullable weakNavigationController, __kindof UIViewController * _Nullable appearingViewController, NSArray<__kindof UIViewController *> * _Nullable disappearingViewControllers) {
//
UIViewController *disappearingViewController = disappearingViewControllers.lastObject;
if (!appearingViewController || !disappearingViewController) {
return;
}
switch (action) {
case QMUINavigationActionDidPush:
case QMUINavigationActionWillPop:
case QMUINavigationActionWillSet: {
BOOL shouldCustomNavigationBarTransition =
[weakNavigationController shouldCustomTransitionAutomaticallyForOperation:UINavigationControllerOperationPush firstViewController:disappearingViewController secondViewController:appearingViewController];
if (shouldCustomNavigationBarTransition) {
disappearingViewController.qmuinb_shouldShowTransitionBar = YES;
appearingViewController.qmuinb_shouldShowTransitionBar = YES;
// vc bar setNavigationBarHidden:
// https://github.com/Tencent/QMUI_iOS/issues/1335
weakNavigationController.navigationBar.qmuinb_copyStylesToBar = appearingViewController.transitionNavigationBar;
}
}
break;
case QMUINavigationActionPushCompleted:
case QMUINavigationActionPopCompleted:
case QMUINavigationActionSetCompleted: {
disappearingViewController.qmuinb_shouldShowTransitionBar = NO;
appearingViewController.qmuinb_shouldShowTransitionBar = NO;
weakNavigationController.navigationBar.qmuinb_copyStylesToBar = nil;
}
break;
default:
break;
}
}];
});
OverrideImplementation([UINavigationController class], @selector(setNavigationBarHidden:animated:), ^id(__unsafe_unretained Class originClass, SEL originCMD, IMP (^originalIMPProvider)(void)) {
return ^(UINavigationController *selfObject, BOOL hidden, BOOL animated) {
// call super
void (*originSelectorIMP)(id, SEL, BOOL, BOOL);
originSelectorIMP = (void (*)(id, SEL, BOOL, BOOL))originalIMPProvider();
originSelectorIMP(selfObject, originCMD, hidden, animated);
if ((selfObject.qmui_isPushing || selfObject.qmui_isPopping) && selfObject.topViewController.qmuinb_shouldShowTransitionBar) {
if (hidden) {
[selfObject.topViewController removeTransitionNavigationBar];
} else {
[selfObject.topViewController addTransitionNavigationBarAndBindNavigationBar:YES];
}
}
};
});
OverrideImplementation([UIViewController class], @selector(viewWillAppear:), ^id(__unsafe_unretained Class originClass, SEL originCMD, IMP (^originalIMPProvider)(void)) {
return ^(UIViewController *selfObject, BOOL firstArgv) {
//
[selfObject renderNavigationBarStyleAnimated:firstArgv];
// call super
void (*originSelectorIMP)(id, SEL, BOOL);
originSelectorIMP = (void (*)(id, SEL, BOOL))originalIMPProvider();
originSelectorIMP(selfObject, originCMD, firstArgv);
};
});
OverrideImplementation([UIViewController class], @selector(viewWillLayoutSubviews), ^id(__unsafe_unretained Class originClass, SEL originCMD, IMP (^originalIMPProvider)(void)) {
return ^(UIViewController *selfObject) {
if (selfObject.transitionNavigationBar) {
[selfObject layoutTransitionNavigationBar];
}
// call super
void (*originSelectorIMP)(id, SEL);
originSelectorIMP = (void (*)(id, SEL))originalIMPProvider();
originSelectorIMP(selfObject, originCMD);
};
});
// UISearchController push bug
// https://github.com/Tencent/QMUI_iOS/issues/479
// _navigationControllerWillShowViewController:
SEL selector = NSSelectorFromString([NSString stringWithFormat:@"_%@%@:", @"navigationController", @"WillShowViewController"]);
QMUIAssert([[UISearchController class] instancesRespondToSelector:selector], @"UIViewController (NavigationBarTransition)", @"iOS 版本更新导致 UISearchController 无法响应方法 %@", NSStringFromSelector(selector));
OverrideImplementation([UISearchController class], selector, ^id(__unsafe_unretained Class originClass, SEL originCMD, IMP (^originalIMPProvider)(void)) {
return ^(UISearchController *selfObject, NSNotification *firstArgv) {
UIViewController *nextViewController = firstArgv.userInfo[@"UINavigationControllerNextVisibleViewController"];
if (![nextViewController canCustomNavigationBarTransitionIfBarHiddenable]) {
void (*originSelectorIMP)(id, SEL, NSNotification *);
originSelectorIMP = (void (*)(id, SEL, NSNotification *))originalIMPProvider();
originSelectorIMP(selfObject, originCMD, firstArgv);
}
};
});
if (@available(iOS 15.0, *)) {
// - [UINavigationBar didMoveToWindow]
OverrideImplementation([UINavigationBar class], @selector(didMoveToWindow), ^id(__unsafe_unretained Class originClass, SEL originCMD, IMP (^originalIMPProvider)(void)) {
return ^(UINavigationBar *selfObject) {
// call super
void (*originSelectorIMP)(id, SEL);
originSelectorIMP = (void (*)(id, SEL))originalIMPProvider();
originSelectorIMP(selfObject, originCMD);
// renderNavigationBarStyleAnimated: window UIAppearance renderNavigationBarAppearanceAnimated: window
// https://github.com/Tencent/QMUI_iOS/issues/1437
if (selfObject.window) {
UINavigationController *nav = (UINavigationController *)selfObject.qmui_viewController;
if (![nav isKindOfClass:UINavigationController.class]) return;
UIViewController *topViewController = nav.topViewController;
if (topViewController.qmui_visibleState & QMUIViewControllerVisible) {// visibleState UINavigationController didMoveToWindow topViewController viewWillAppear: visibleState viewWillAppear:
[topViewController renderNavigationBarAppearanceAnimated:NO];
}
}
};
});
}
});
}
- (void)addTransitionNavigationBarAndBindNavigationBar:(BOOL)shouldBind {
// add navigationBarHidden push/pop viewWillLayoutSubviews navigationBarHidden bar
if (!self.qmuinb_shouldShowTransitionBar || self.transitionNavigationBar || !self.navigationController.navigationBar || self.navigationController.navigationBarHidden) {
return;
}
_QMUITransitionNavigationBar *customBar = [[_QMUITransitionNavigationBar alloc] init];
self.transitionNavigationBar = customBar;
// iOS 15 bar add UIAppearance runloop standardAppearance UIAppearance didMoveToWindow UIAppearance add
// push pop
// iOS 14
#ifdef IOS15_SDK_ALLOWED
if (@available(iOS 15.0, *)) {
if (self.navigationController.qmui_navigationAction == QMUINavigationActionDidPush) {
customBar.shouldPreventAppearance = YES;
}
}
#endif
[self.view addSubview:customBar];
customBar.originalNavigationBar = self.navigationController.navigationBar;// bar bar copy
if (shouldBind) {
self.navigationController.navigationBar.qmuinb_copyStylesToBar = customBar;
}
[self layoutTransitionNavigationBar];
}
- (void)removeTransitionNavigationBar {
if (self.transitionNavigationBar) {
[self.transitionNavigationBar removeFromSuperview];
self.transitionNavigationBar = nil;
id <UIViewControllerTransitionCoordinator> transitionCoordinator = self.transitionCoordinator;
if (self.navigationController.navigationBar.translucent && self.originContainerViewBackgroundColor) {
[transitionCoordinator containerView].backgroundColor = self.originContainerViewBackgroundColor;
}
}
}
- (void)layoutTransitionNavigationBar {
if (self.isViewLoaded && self.navigationController) {
UIView *backgroundView = self.navigationController.navigationBar.qmui_backgroundView;
CGRect rect = [backgroundView.superview convertRect:backgroundView.frame toView:self.view];
self.transitionNavigationBar.frame = CGRectSetX(rect, 0);// push/pop x 112-112
[self.view bringSubviewToFront:self.transitionNavigationBar];// subviews
}
}
#pragma mark -
// viewController
- (void)renderNavigationBarStyleAnimated:(BOOL)animated {
// UINavigationController viewController custom containerViewController childViewController
if (![self.navigationController.viewControllers containsObject:self]) {
return;
}
if (![self conformsToProtocol:@protocol(QMUINavigationControllerAppearanceDelegate)]) {
return;
}
// vc 使
UIViewController<QMUINavigationControllerAppearanceDelegate> *vc = (UIViewController<QMUINavigationControllerAppearanceDelegate> *)self;
UINavigationController *navigationController = vc.navigationController;
// /
if ([vc canCustomNavigationBarTransitionIfBarHiddenable]) {
if ([vc hideNavigationBarWhenTransitioning]) {
if (!navigationController.isNavigationBarHidden) {
[navigationController setNavigationBarHidden:YES animated:animated];
}
} else {
if (navigationController.isNavigationBarHidden) {
[navigationController setNavigationBarHidden:NO animated:animated];
}
}
}
// window UIAppearance UINavigationBar (QMUI) navigationBar.standardAppearance App
// https://github.com/Tencent/QMUI_iOS/issues/1437
if (@available(iOS 15.0, *)) {
if (!navigationController.navigationBar.window) {
return;
}
}
[self renderNavigationBarAppearanceAnimated:animated];
}
//
- (void)renderNavigationBarAppearanceAnimated:(BOOL)animated {
// UINavigationController viewController custom containerViewController childViewController
if (![self.navigationController.viewControllers containsObject:self]) {
return;
}
if (![self conformsToProtocol:@protocol(QMUINavigationControllerAppearanceDelegate)]) {
return;
}
// vc 使
UIViewController<QMUINavigationControllerAppearanceDelegate> *vc = (UIViewController<QMUINavigationControllerAppearanceDelegate> *)self;
UINavigationController *navigationController = vc.navigationController;
//
if ([vc respondsToSelector:@selector(qmui_navigationBarBarTintColor)]) {
UIColor *barTintColor = [vc qmui_navigationBarBarTintColor];
navigationController.navigationBar.barTintColor = barTintColor;
} else if (QMUICMIActivated) {
navigationController.navigationBar.barTintColor = UINavigationBar.qmui_appearanceConfigured.barTintColor;
}
//
if ([vc respondsToSelector:@selector(qmui_navigationBarBackgroundImage)]) {
UIImage *backgroundImage = [vc qmui_navigationBarBackgroundImage];
[navigationController.navigationBar setBackgroundImage:backgroundImage forBarMetrics:UIBarMetricsDefault];
} else if (QMUICMIActivated) {
[navigationController.navigationBar setBackgroundImage:[UINavigationBar.qmui_appearanceConfigured backgroundImageForBarMetrics:UIBarMetricsDefault] forBarMetrics:UIBarMetricsDefault];
}
// style
if ([vc respondsToSelector:@selector(qmui_navigationBarStyle)]) {
UIBarStyle barStyle = [vc qmui_navigationBarStyle];
navigationController.navigationBar.barStyle = barStyle;
} else if (QMUICMIActivated) {
navigationController.navigationBar.barStyle = UINavigationBar.qmui_appearanceConfigured.barStyle;
}
// 线
if ([vc respondsToSelector:@selector(qmui_navigationBarShadowImage)]) {
navigationController.navigationBar.shadowImage = [vc qmui_navigationBarShadowImage];
} else if (QMUICMIActivated) {
navigationController.navigationBar.shadowImage = NavBarShadowImage;
}
//
UIColor *tintColor =
[vc respondsToSelector:@selector(qmui_navigationBarTintColor)] ? [vc qmui_navigationBarTintColor] :
QMUICMIActivated ? NavBarTintColor : nil;
if (tintColor) {
// https://github.com/Tencent/QMUI_iOS/issues/654
// navigationBar.tintColor iOS 10 tintColor animateAlongsideTransition iOS 11 navigationBar.tintColor
// topViewController backButtonLabel navBar tintColor
if (navigationController.qmui_isPopping) {
UILabel *backButtonLabel = navigationController.navigationBar.qmui_backButtonLabel;
if (backButtonLabel) {
backButtonLabel.qmui_specifiedTextColor = backButtonLabel.textColor;
[vc qmui_animateAlongsideTransition:nil completion:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
backButtonLabel.qmui_specifiedTextColor = nil;
}];
}
}
[vc qmui_animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
navigationController.navigationBar.tintColor = tintColor;
} completion:nil];
}
// iOS 13 title viewWillAppear iOS 12 popViewController
// iOS 12 使 titleView viewWillAppear navigationBar.titleTextAttributes push pop pop titleTextAttributes did pop
// titleView title
[vc renderNavigationBarTitleAppearanceAnimated:animated];
}
//
- (void)renderNavigationBarTitleAppearanceAnimated:(BOOL)animated {
// UINavigationController viewController custom containerViewController childViewController
if (![self.navigationController.viewControllers containsObject:self]) {
return;
}
if (![self conformsToProtocol:@protocol(QMUINavigationControllerAppearanceDelegate)]) {
return;
}
// vc 使
UIViewController<QMUINavigationControllerAppearanceDelegate> *vc = (UIViewController<QMUINavigationControllerAppearanceDelegate> *)self;
UINavigationController *navigationController = vc.navigationController;
// title
if ([vc respondsToSelector:@selector(qmui_titleViewTintColor)]) {
UIColor *tintColor = [vc qmui_titleViewTintColor];
if ([vc.navigationItem.titleView isKindOfClass:QMUINavigationTitleView.class]) {
((QMUINavigationTitleView *)vc.navigationItem.titleView).tintColor = tintColor;
} else if (!vc.navigationItem.titleView) {
NSMutableDictionary<NSAttributedStringKey, id> *titleTextAttributes = (navigationController.navigationBar.titleTextAttributes ?: @{}).mutableCopy;
titleTextAttributes[NSForegroundColorAttributeName] = tintColor;
navigationController.navigationBar.titleTextAttributes = titleTextAttributes.copy;
} else {
// navigationItem.titleView
}
} else if (QMUICMIActivated) {
UIColor *tintColor = NavBarTitleColor;
if ([vc.navigationItem.titleView isKindOfClass:QMUINavigationTitleView.class]) {
((QMUINavigationTitleView *)vc.navigationItem.titleView).tintColor = tintColor;
} else if (!vc.navigationItem.titleView) {
NSMutableDictionary<NSAttributedStringKey, id> *titleTextAttributes = (navigationController.navigationBar.titleTextAttributes ?: @{}).mutableCopy;
titleTextAttributes[NSForegroundColorAttributeName] = tintColor;
navigationController.navigationBar.titleTextAttributes = titleTextAttributes.copy;
} else {
// navigationItem.titleView
}
}
}
- (BOOL)respondCustomNavigationBarTransitionIfBarHiddenable {
BOOL respondIfBarHiddenable = NO;
// UISearchController navigationBar QMUI bar
if ([self.presentedViewController isKindOfClass:[UISearchController class]] && ((UISearchController *)self.presentedViewController).hidesNavigationBarDuringPresentation) {
return NO;
}
if ([self conformsToProtocol:@protocol(QMUICustomNavigationBarTransitionDelegate)]) {
UIViewController<QMUICustomNavigationBarTransitionDelegate> *vc = (UIViewController<QMUICustomNavigationBarTransitionDelegate> *)self;
if ([vc respondsToSelector:@selector(shouldCustomizeNavigationBarTransitionIfHideable)]) {
respondIfBarHiddenable = YES;
}
}
return respondIfBarHiddenable;
}
- (BOOL)respondCustomNavigationBarTransitionWithBarHiddenState {
BOOL respondWithBarHidden = NO;
if ([self conformsToProtocol:@protocol(QMUICustomNavigationBarTransitionDelegate)]) {
UIViewController<QMUICustomNavigationBarTransitionDelegate> *vc = (UIViewController<QMUICustomNavigationBarTransitionDelegate> *)self;
if ([vc respondsToSelector:@selector(preferredNavigationBarHidden)]) {
respondWithBarHidden = YES;
}
}
return respondWithBarHidden;
}
- (BOOL)canCustomNavigationBarTransitionIfBarHiddenable {
if ([self respondCustomNavigationBarTransitionIfBarHiddenable]) {
UIViewController<QMUICustomNavigationBarTransitionDelegate> *vc = (UIViewController<QMUICustomNavigationBarTransitionDelegate> *)self;
return [vc shouldCustomizeNavigationBarTransitionIfHideable];
}
return NO;
}
- (BOOL)hideNavigationBarWhenTransitioning {
if ([self respondCustomNavigationBarTransitionWithBarHiddenState]) {
UIViewController<QMUICustomNavigationBarTransitionDelegate> *vc = (UIViewController<QMUICustomNavigationBarTransitionDelegate> *)self;
BOOL hidden = [vc preferredNavigationBarHidden];
return hidden;
}
return NO;
}
- (BOOL)shouldCustomTransitionAutomaticallyForOperation:(UINavigationControllerOperation)operation firstViewController:(UIViewController *)viewController1 secondViewController:(UIViewController *)viewController2 {
UIViewController<QMUINavigationControllerDelegate> *vc1 = (UIViewController<QMUINavigationControllerDelegate> *)viewController1;
UIViewController<QMUINavigationControllerDelegate> *vc2 = (UIViewController<QMUINavigationControllerDelegate> *)viewController2;
if (![vc1 conformsToProtocol:@protocol(QMUINavigationControllerDelegate)] || ![vc2 conformsToProtocol:@protocol(QMUINavigationControllerDelegate)]) {
return NO;// QMUI
}
BOOL vc1Clips = vc1.isViewLoaded && vc1.view.clipsToBounds && vc1.qmui_navigationBarMaxYInViewCoordinator < NavigationContentTopConstant;
BOOL vc2Clips = vc2.isViewLoaded && vc2.view.clipsToBounds && vc2.qmui_navigationBarMaxYInViewCoordinator < NavigationContentTopConstant;
if (vc1Clips || vc2Clips) {
QMUILogWarn(@"UINavigationController (NavigationBarTransition)", @"因界面布局原因导致无法优化导航栏动画vc1 = %@maxY1 = %.0f, vc2 = %@maxY2 = %.0f", vc1, vc1.qmui_navigationBarMaxYInViewCoordinator, vc2, vc2.qmui_navigationBarMaxYInViewCoordinator);
return NO;// navigationBar
}
if ([vc1.navigationController.delegate respondsToSelector:@selector(navigationController:animationControllerForOperation:fromViewController:toViewController:)]) {
//
BOOL a = [vc1 respondsToSelector:@selector(shouldCustomizeNavigationBarTransitionIfUsingCustomTransitionForOperation:fromViewController:toViewController:)] ? [vc1 shouldCustomizeNavigationBarTransitionIfUsingCustomTransitionForOperation:operation fromViewController:vc1 toViewController:vc2] : NO;
BOOL b = [vc2 respondsToSelector:@selector(shouldCustomizeNavigationBarTransitionIfUsingCustomTransitionForOperation:fromViewController:toViewController:)] ? [vc2 shouldCustomizeNavigationBarTransitionIfUsingCustomTransitionForOperation:operation fromViewController:vc1 toViewController:vc2] : NO;
if (!a && !b) {
return NO;
}
}
if ([vc1 respondsToSelector:@selector(customNavigationBarTransitionKey)] || [vc2 respondsToSelector:@selector(customNavigationBarTransitionKey)]) {
NSString *key1 = [vc1 respondsToSelector:@selector(customNavigationBarTransitionKey)] ? [vc1 customNavigationBarTransitionKey] : nil;
NSString *key2 = [vc2 respondsToSelector:@selector(customNavigationBarTransitionKey)] ? [vc2 customNavigationBarTransitionKey] : nil;
BOOL result = (key1 || key2) && ![key1 isEqualToString:key2];
return result;
}
if (!AutomaticCustomNavigationBarTransitionStyle) {
return NO;
}
UIImage *bg1 = [vc1 respondsToSelector:@selector(qmui_navigationBarBackgroundImage)] ? [vc1 qmui_navigationBarBackgroundImage] : [UINavigationBar.qmui_appearanceConfigured backgroundImageForBarMetrics:UIBarMetricsDefault];
UIImage *bg2 = [vc2 respondsToSelector:@selector(qmui_navigationBarBackgroundImage)] ? [vc2 qmui_navigationBarBackgroundImage] : [UINavigationBar.qmui_appearanceConfigured backgroundImageForBarMetrics:UIBarMetricsDefault];
if (bg1 || bg2) {
if (!bg1 || !bg2) {
return YES;//
}
if (![bg1.qmui_averageColor isEqual:bg2.qmui_averageColor]) {
return YES;//
}
}
// backgroundImage barTintColorbarStyle backgroundImage
if (!bg1 && !bg2) {
UIColor *barTintColor1 = [vc1 respondsToSelector:@selector(qmui_navigationBarBarTintColor)] ? [vc1 qmui_navigationBarBarTintColor] : UINavigationBar.qmui_appearanceConfigured.barTintColor;
UIColor *barTintColor2 = [vc2 respondsToSelector:@selector(qmui_navigationBarBarTintColor)] ? [vc2 qmui_navigationBarBarTintColor] : UINavigationBar.qmui_appearanceConfigured.barTintColor;
if (barTintColor1 || barTintColor2) {
if (!barTintColor1 || !barTintColor2) {
return YES;
}
if (![barTintColor1 isEqual:barTintColor2]) {
return YES;
}
}
UIBarStyle barStyle1 = [vc1 respondsToSelector:@selector(qmui_navigationBarStyle)] ? [vc1 qmui_navigationBarStyle] : UINavigationBar.qmui_appearanceConfigured.barStyle;
UIBarStyle barStyle2 = [vc2 respondsToSelector:@selector(qmui_navigationBarStyle)] ? [vc2 qmui_navigationBarStyle] : UINavigationBar.qmui_appearanceConfigured.barStyle;
if (barStyle1 != barStyle2) {
return YES;
}
}
UIImage *shadowImage1 = [vc1 respondsToSelector:@selector(qmui_navigationBarShadowImage)] ? [vc1 qmui_navigationBarShadowImage] : (vc1.navigationController.navigationBar ? vc1.navigationController.navigationBar.shadowImage : (QMUICMIActivated ? NavBarShadowImage : nil));
UIImage *shadowImage2 = [vc2 respondsToSelector:@selector(qmui_navigationBarShadowImage)] ? [vc2 qmui_navigationBarShadowImage] : (vc2.navigationController.navigationBar ? vc2.navigationController.navigationBar.shadowImage : (QMUICMIActivated ? NavBarShadowImage : nil));
if (shadowImage1 || shadowImage2) {
if (!shadowImage1 || !shadowImage2) {
return YES;
}
if (![shadowImage1.qmui_averageColor isEqual:shadowImage2.qmui_averageColor]) {
return YES;
}
}
return NO;
}
- (UIColor *)containerViewBackgroundColor {
if ([self conformsToProtocol:@protocol(QMUICustomNavigationBarTransitionDelegate)]) {
UIViewController<QMUICustomNavigationBarTransitionDelegate> *vc = (UIViewController<QMUICustomNavigationBarTransitionDelegate> *)self;
if ([vc respondsToSelector:@selector(containerViewBackgroundColorWhenTransitioning)]) {
return [vc containerViewBackgroundColorWhenTransitioning];
}
}
return self.isViewLoaded && self.view.backgroundColor ? self.view.backgroundColor : UIColorWhite;
}
#pragma mark - Setter / Getter
QMUISynthesizeIdStrongProperty(transitionNavigationBar, setTransitionNavigationBar)
QMUISynthesizeIdStrongProperty(originContainerViewBackgroundColor, setOriginContainerViewBackgroundColor)
static char kAssociatedObjectKey_backgroundViewHidden;
- (void)setPrefersNavigationBarBackgroundViewHidden:(BOOL)prefersNavigationBarBackgroundViewHidden {
// navBar navBar backgroundView backgroundView mask
if (prefersNavigationBarBackgroundViewHidden) {
self.navigationController.navigationBar.qmui_backgroundView.layer.mask = [CALayer layer];
} else {
self.navigationController.navigationBar.qmui_backgroundView.layer.mask = nil;
}
objc_setAssociatedObject(self, &kAssociatedObjectKey_backgroundViewHidden, @(prefersNavigationBarBackgroundViewHidden), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)prefersNavigationBarBackgroundViewHidden {
return [((NSNumber *)objc_getAssociatedObject(self, &kAssociatedObjectKey_backgroundViewHidden)) boolValue];
}
static char kAssociatedObjectKey_shouldShowTransitionBar;
- (void)setQmuinb_shouldShowTransitionBar:(BOOL)shouldShowTransitionBar {
objc_setAssociatedObject(self, &kAssociatedObjectKey_shouldShowTransitionBar, @(shouldShowTransitionBar), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
if (shouldShowTransitionBar) {
[self addTransitionNavigationBarAndBindNavigationBar:NO];// bar vc
self.prefersNavigationBarBackgroundViewHidden = YES;
} else {
[self removeTransitionNavigationBar];
// childViewController
if ([self.navigationController.viewControllers containsObject:self]) {
self.prefersNavigationBarBackgroundViewHidden = NO;
}
}
}
- (BOOL)qmuinb_shouldShowTransitionBar {
return [((NSNumber *)objc_getAssociatedObject(self, &kAssociatedObjectKey_shouldShowTransitionBar)) boolValue];
}
@end