// // PYBaseViewController.m // Food // // Created by ko1o on 2019/7/16. // Copyright © 2019年 ko1o. All rights reserved. // #import "PYBaseViewController.h" #import "UIViewController+BXYStatefulViewController.h" #import "UIImage+Extender.h" #import #import "UINavigationController+FDFullscreenPopGesture.h" @interface PYBaseViewController () @property (nonatomic, strong) UIImage *backupNavgationBarShadowImage; @property (nonatomic, assign) BOOL hasLoadedStateful; @property (nonatomic, weak) UIViewController * mt_previousVC; @property (nonatomic, assign) BOOL isViewAppear; @property (nonatomic, assign) BOOL isTrackPageEnded; @property (nonatomic, assign) BOOL stopLoading; @property (nonatomic, strong) UIView *maskView; @end @implementation PYBaseViewController //MARK: - QM - (instancetype)init { if (self = [super init]) { if ([QMUIHelper.visibleViewController.navigationController isKindOfClass:NSClassFromString(@"THNavigationController")]) { //兼容QMUIKit self.hidesBottomBarWhenPushed = YES; } } return self; } //MARK: - Other - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) { self.extendedLayoutIncludesOpaqueBars = YES; if (![self isSupportFullScreenLayout]) { self.edgesForExtendedLayout = UIRectEdgeNone; // self.automaticallyAdjustsScrollViewInsets = NO; } self.mt_translucent = NO; self.mt_nav_barTintColor = [UIColor whiteColor]; self.mt_nav_tintColor = [UIColor blackColor]; self.mt_barStyle = UIBarStyleDefault; } return self; } - (UIStatusBarStyle)preferredStatusBarStyle { if (self.mt_barStyle == UIBarStyleBlack) { return UIStatusBarStyleLightContent; } return UIStatusBarStyleLightContent; } - (BOOL)isSupportContentScrollView { return NO; } - (BOOL)isSupportShare { return NO; } - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; self.bxy_loadingView.centerY = self.bxy_errorView.centerY = self.bxy_emptyView.centerY = self.view.height * 0.5; self.bxy_emptyView.userInteractionEnabled = NO; self.bxy_errorView.userInteractionEnabled = NO; } - (BOOL)canBack { return YES; } - (BOOL)fd_interactivePopDisabled { if (![self canBack]) { return YES; } if ([MTAlertView hasAlertViewShowing]) { // 当前显示AlertView禁用 return YES; } return _fd_interactivePopDisabled; } - (void)viewDidLoad { [super viewDidLoad]; //配置页面状态view if ([self mt_shouldSetupStateful] && self.hasLoadedStateful) { [self bxy_setupInitialViewState]; } self.view.backgroundColor = BG_COLOR; self.maskView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds]; self.maskView.backgroundColor = UIColor.blackColor; WeakSelf(self); [self.maskView addTapWithAction:^{ [weakself.view endEditing:YES]; }]; if ([self mt_shouldSetupStateful]) { self.bxy_loadingView = [[MTStatefulBaseView alloc] initWithFrame:CGRectZero type:MTStatefulViewTypeLoading delegate:self]; self.bxy_emptyView = [[MTStatefulBaseView alloc] initWithFrame:CGRectZero type:MTStatefulViewTypeEmpty delegate:self]; self.bxy_errorView = [[MTStatefulBaseView alloc] initWithFrame:CGRectZero type:MTStatefulViewTypeError delegate:self]; } if (self.preferredStatusBarStyle == UIStatusBarStyleLightContent) { self.mt_barStyle = UIBarStyleBlack; } else { self.mt_barStyle = UIBarStyleDefault; } if ([self isSupportContentScrollView]) { self.contentScrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; self.contentScrollView.backgroundColor = [UIColor clearColor]; self.contentScrollView.showsVerticalScrollIndicator = YES; self.contentScrollView.alwaysBounceVertical = YES; [self.view addSubview:self.contentScrollView]; self.contentScrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; // if ([[[UIDevice currentDevice] systemVersion] floatValue] <= 11.0) { // self.contentScrollView.y = NAVIGATION_BAR_HEIGHT; // self.contentScrollView.height = self.view.height - self.contentScrollView.y; // } } if (self.navigationController.childViewControllers.count > 1) { UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithImage:ImageNamed(@"TH_back_black") style:UIBarButtonItemStyleDone target:self action:@selector(back)]; self.navigationItem.leftBarButtonItem = backItem; } if (![self canBack]) { self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:[UIView new]]; } [self.navigationController setModalPresentationStyle:UIModalPresentationFullScreen]; self.mt_prefersNavigationBarShadowHidden = YES; if ([self mt_nagationBarTransparent]) { self.mt_translucent = YES; self.extendedLayoutIncludesOpaqueBars = YES; } if ([self isSupportShare]) { self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:ImageNamed(@"share") style:UIBarButtonItemStyleDone target:self action:@selector(shareDidClick)]; } // if (self.mt_prefersNavigationBarShadowHidden) { // self.navigationController.navigationBar.shadowImage = [UIImage new]; // } } #pragma mark - UITextFieldDelegate - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField { if ([textField.inputView isKindOfClass:NSClassFromString(@"MTPickerView")]) { textField.tintColor = UIColor.clearColor; [self showMaskView]; } else { [IQKeyboardManager sharedManager].enableAutoToolbar = NO; } return YES; } - (BOOL)textFieldShouldEndEditing:(UITextField *)textField { if ([textField.inputView isKindOfClass:NSClassFromString(@"MTPickerView")]) { [self hideMaskView]; } return YES; } - (void)showMaskView { [IQKeyboardManager sharedManager].enableAutoToolbar = NO; [self.view.window addSubview:self.maskView]; self.maskView.alpha = 0.0; [self.view.window bringSubviewToFront:self.maskView]; [UIView animateWithDuration:0.25 animations:^{ self.maskView.alpha = 0.3; }]; } - (void)hideMaskView { [UIView animateWithDuration:0.25 animations:^{ self.maskView.alpha = 0.0; } completion:^(BOOL finished) { [IQKeyboardManager sharedManager].enableAutoToolbar = NO; }]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [self.view endEditing:animated]; self.isViewAppear = NO; } - (void)back { [self.navigationController popViewControllerAnimated:YES]; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesBegan:touches withEvent:event]; [self.view endEditing:YES]; } - (BOOL)mt_nagationBarTransparent { if (self.title.length > 0) { // 有文本 return NO; } return _mt_nagationBarTransparent; } - (BOOL)isSupportFullScreenLayout { return YES; } - (UIModalPresentationStyle)modalPresentationStyle { return UIModalPresentationFullScreen; } //配置是否显示loading empty error 页面提示 - (BOOL)mt_shouldSetupStateful { return YES; } - (NSString *)emptyTips { return @"空空无也~"; } - (BOOL)mt_hasContentForStateful { return self.stopLoading; } - (void)mt_startStatefulLoading:(BOOL)animated { if ([self mt_shouldSetupStateful]) { self.hasLoadedStateful = YES; dispatch_async(dispatch_get_main_queue(), ^{ [self bxy_startLoading:animated completion:^{ ; }]; }); } } - (void)mt_endStatefulLoading:(BOOL)animated error:(NSError *)error { if ([self mt_shouldSetupStateful]) { [self bxy_endLoading:animated error:error completion:^{ ; }]; } } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; if (![self isNavigationBarHidden]) { [self.navigationController setNavigationBarHidden:NO animated:animated]; } [self mt_applyAppearanceToNavigationBar:self.navigationController.navigationBar]; } - (BOOL)enableAutoToolbar { return YES; } - (BOOL)isNavigationBarHidden { return NO; } - (void)viewDidAppear:(BOOL)animated { //当前页面的源VC,往前回溯一级 UIViewController *mt_previousViewController; NSInteger index = [self.navigationController.viewControllers indexOfObject:self]; if (index != NSNotFound && index >= 1) { mt_previousViewController = [self.navigationController.viewControllers objectAtIndex:index -1]; } if (self.parentViewController && !mt_previousViewController) { //被其他vc 承载 UIViewController * parent = self.parentViewController; index = [parent.navigationController.viewControllers indexOfObject:parent]; if (index != NSNotFound && index >= 1) { mt_previousViewController = [parent.navigationController.viewControllers objectAtIndex:index -1]; } } if (!mt_previousViewController) { mt_previousViewController = self.presentingViewController; } self.mt_previousVC = mt_previousViewController; [super viewDidAppear:animated]; self.isViewAppear = YES; [self.navigationController setNavigationBarHidden:[self isNavigationBarHidden] animated:NO]; [IQKeyboardManager sharedManager].enableAutoToolbar = [self enableAutoToolbar]; [self mt_applyAppearanceToNavigationBar:self.navigationController.navigationBar]; } - (void)startLoading { self.stopLoading = NO; [self mt_startStatefulLoading:NO]; } - (void)endLoading:(NSError *)error { self.stopLoading = YES; [self mt_endStatefulLoading:NO error:error]; } #pragma mark - StatefulViewControllerProtocol /** * Return true if content is available in your controller. * * - returns: true if there is content available in your controller. */ - (BOOL)hasContent { return [self mt_hasContentForStateful]; } /** * This method is called if an error occurred, but `hasContent` returned true. * You would typically display an unobstrusive error message that is easily dismissable * for the user to continue browsing content. * * - parameter error: The error that occurred */ - (void)handleErrorWhenContentAvailable:(NSError *)error { } #pragma mark - MTStatefulBaseViewDelegate - (MTStatefulConfigItem *)statefulConfigItemForStatefulViewType:(MTStatefulViewType)statefulViewType { MTStatefulConfigItem *item = [MTStatefulConfigItem new]; WeakSelf(self); if (statefulViewType == MTStatefulViewTypeEmpty) { MTStatefulConfigItem *item = [[MTStatefulConfigItem alloc] init]; item.statefulTitle = [self emptyTips]; return item; } // else // if (statefulViewType == MTStatefulViewTypeError) { // StrongSelf(self); // MTStatefulConfigItem *item = [[MTStatefulConfigItem alloc] init]; // item.statefulTitle = @"哎哟!网络异常,请稍后…"; // item.shouldShowErrorRefresh = YES; // item.didClickedRefreshBlock = self.didClickedRefreshBlock; // return item; // } item.shouldShowErrorRefresh = NO; return item; } @end @interface UIViewControllerMTAppearance : NSObject @property (nonatomic, assign) BOOL mt_translucent; @property (nonatomic, assign) BOOL mt_prefersNavigationBarShadowHidden; @property (nonatomic, strong) UIColor * mt_nav_barTintColor; @property (nonatomic, strong) UIColor * mt_navbarBackgroundImageColor; @property (nonatomic, strong) UIColor * mt_nav_tintColor; @property (nonatomic, strong) NSDictionary * mt_titleTextAttributes; @property (nonatomic, assign) UIBarStyle mt_barStyle; @property (nonatomic, strong) UIImage * mt_navbarBackgroundImage; @end @implementation UIViewControllerMTAppearance @end @interface UIViewController (MTAppearanceInner) @property (nonatomic, strong) UIViewControllerMTAppearance *mtAppearance; @end @implementation UIViewController (MTAppearance) @dynamic mt_translucent; @dynamic mt_prefersNavigationBarShadowHidden; @dynamic mt_nav_barTintColor; @dynamic mt_navbarBackgroundImageColor; @dynamic mt_nav_tintColor; @dynamic mt_titleTextAttributes; @dynamic mt_navbarBackgroundImage; - (BOOL)mt_translucent { return self.mtAppearance.mt_translucent; } - (void)setMt_translucent:(BOOL)mt_translucent { self.mtAppearance.mt_translucent = mt_translucent; } - (UIViewControllerMTAppearance *)mtAppearance { UIViewControllerMTAppearance *mtAppearance = objc_getAssociatedObject(self, _cmd); if (!mtAppearance) { mtAppearance = [UIViewControllerMTAppearance new]; objc_setAssociatedObject(self, _cmd, mtAppearance, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } return mtAppearance; } - (id)forwardingTargetForSelector:(SEL)sel { if ([self.mtAppearance respondsToSelector:sel]) { return self.mtAppearance; } return nil; } - (void)mt_applyAppearanceToNavigationBar:(UINavigationBar *) navigationBar { UIViewController * vc = self; navigationBar.translucent = vc.mt_translucent; UIImage *barBackgroundImage = [UIImage new]; if (vc.mt_navbarBackgroundImageColor) { UIImage *barImage = vc.mt_navbarBackgroundImageColor == [UIColor clearColor] ? [UIImage new] : [UIImage imageWithColor:vc.mt_navbarBackgroundImageColor size:CGSizeMake(10, 10)] ; barBackgroundImage = barImage; } [navigationBar setBackgroundImage:barBackgroundImage forBarMetrics:UIBarMetricsDefault]; if (vc.mt_navbarBackgroundImage) { [navigationBar setBackgroundImage:vc.mt_navbarBackgroundImage forBarMetrics:UIBarMetricsDefault]; } vc.mt_nav_barTintColor = [self preferredStatusBarStyle] == UIStatusBarStyleLightContent ? COLOR_WITH_RGB(0x15112D) : [UIColor whiteColor]; navigationBar.barStyle = vc.mt_barStyle; navigationBar.barTintColor = vc.mt_nav_barTintColor; UIColor *tintColor = [self preferredStatusBarStyle] == UIStatusBarStyleLightContent ? UIColor.whiteColor : TITLE_COLOR; navigationBar.tintColor = tintColor; navigationBar.titleTextAttributes = vc.mt_titleTextAttributes ?: @{NSFontAttributeName : MT_FONT_MEDIUM_SIZE(15), NSForegroundColorAttributeName : tintColor}; navigationBar.shadowImage = [vc mt_prefersNavigationBarShadowHidden] ? [UIImage new] : nil ; // navigationBar.shadowImage = [UIImage imageWithColor:[UIColor colorWithWhite:1.0 alpha:0.1] size:CGSizeMake(SCREEN_WIDTH, 0.5)]; if (@available(iOS 15.0, *)) { UINavigationBarAppearance *barApp = [UINavigationBarAppearance new]; barApp.backgroundColor = navigationBar.barTintColor; barApp.titleTextAttributes = navigationBar.titleTextAttributes; barApp.shadowImage = navigationBar.shadowImage; barApp.shadowColor = [UIColor clearColor]; barApp.backgroundImage = barBackgroundImage; self.navigationController.navigationBar.translucent = [self mt_translucent]; if ([self mt_translucent]) { // 设置透明导航栏 [barApp configureWithTransparentBackground]; } else { barApp.backgroundImage = [UIImage imageWithColor:navigationBar.barTintColor size:navigationBar.size]; } self.navigationController.navigationBar.scrollEdgeAppearance = barApp; self.navigationController.navigationBar.standardAppearance = barApp; } } @end