iOS 7自定义后退button

我想使用自定义后退button。 在iOS 6中,一切都是完美的,但iOS 7是奇怪的。

 [[UIBarButtonItem appearance] setBackButtonBackgroundImage:[[UIImage imageNamed:@"back_button_normal"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 12.0, 0, 12.0)] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; 

首先,它没有iOS 7的箭头,也没有背景图片。

(俄语区域)

初始状态

那么,如果按下背景图片button就会出现。 另外我有背景图像设置为UIControlStateHighlighted状态,当你按住button高亮显示的图像也出现。 一旦按下任何后退button,所有后退button都有背景图像。

一旦按下

但! 如果您显示模式视图控制器,请closures它,然后按任何视图控制器 – iOS 7箭头将出现在每个后退button。

我使用DP5。 这是一个UIKit的错误?

PS另外我试图手动创build返回button,使用UIBarButtonItem ,设置背景图像,然后self.navigationItem.backBarButtonItem = barButtonItem; 没有帮助。 然后,我试图将背景图像设置为禁用状态,并更改我的酒吧button项目的启用属性,也没有帮助。

在这里输入图像说明

这不是一个错误,这是如何Back button在iOS 7中看起来。例如:

在这里输入图像说明

您可能应该为您的应用程序使用新的概念,而不是在iOS 7中设置后退button的背景图像。

如果你仍然希望你回来button有相同的看起来在iOS6比你应该手动创build这些后退button:

 - (void)loadView { [super loadView]; UIButton *backButton = [[UIButton alloc] initWithFrame: CGRectMake(0, 0, 60.0f, 30.0f)]; UIImage *backImage = [[UIImage imageNamed:@"back_button_normal.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 12.0f, 0, 12.0f)]; [backButton setBackgroundImage:backImage forState:UIControlStateNormal]; [backButton setTitle:@"Back" forState:UIControlStateNormal]; [backButton addTarget:self action:@selector(popBack) forControlEvents:UIControlEventTouchUpInside]; UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton]; self.navigationItem.leftBarButtonItem = backButtonItem; } -(void) popBack { [self.navigationController popViewControllerAnimated:YES]; } 

编辑 :不要打破滑动手势 ( 这是一个来源)

 self.navigationController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)self; 

第一次推送时没有出现的自定义背景图像在iOS 7 GM中已经修复。

要隐藏标准背面指示器,请使用以下代码

 if ([UINavigationBar instancesRespondToSelector:@selector(setBackIndicatorImage:)]) { // iOS 7 [navigationBarAppearance setBackIndicatorImage:[UIImage imageNamed:@"transparent_1px"]]; [navigationBarAppearance setBackIndicatorTransitionMaskImage:[UIImage imageNamed:@"transparent_1px"]]; } 

据我所知,最初没有出现的自定义背景图像在iOS7 GM或最终版本中并未修复。 我看到了同样的问题。 它似乎是一个苹果的bug; 苹果使用的私人视图在初始显示时并不需要setNeedsDisplay调用。 做任何事情导致这个调用应该解决它 – 就像按下它(这可能会改变内部状态,所以它调用setNeedsDisplay本身),或带来一个模式(这可能会强制重新显示整个视图层次结构viewWillAppear:call)。

使用leftBarItems也可以,但是这可能会导致现有代码的很多维护问题(一些屏幕可能有自己的左边的项目,例如,当它们被设置为零时,它们将恢复原始的返回项目)。

如上所述,理想情况下,您可以在iOS7上更改为无边框外观,这意味着该错误并不明显(因为没有背景图像)。 对于一些iOS6 / iOS7的转换情况,这可能是困难的(很多屏幕,和/或需要支持较旧的iOS版本一段时间,太难以实现两个外观,而且没有其他的变化)。 如果是这样的话,下面的补丁应该可以工作:

 #import <objc/runtime.h> @implementation UINavigationBar (BackButtonDisplayFix) + (void)load { if ([UIDevice currentDevice].systemVersion.intValue >= 7) { /* * We first try to simply add an override version of didAddSubview: to the class. If it * fails, that means that the class already has its own override implementation of the method * (which we are expecting in this case), so use a method-swap version instead. */ Method didAddMethod = class_getInstanceMethod(self, @selector(_displaybugfixsuper_didAddSubview:)); if (!class_addMethod(self, @selector(didAddSubview:), method_getImplementation(didAddMethod), method_getTypeEncoding(didAddMethod))) { Method existMethod = class_getInstanceMethod(self, @selector(didAddSubview:)); Method replacement = class_getInstanceMethod(self, @selector(_displaybugfix_didAddSubview:)); method_exchangeImplementations(existMethod, replacement); } } } - (void)_displaybugfixsuper_didAddSubview:(UIView *)subview { [super didAddSubview:subview]; [subview setNeedsDisplay]; } - (void)_displaybugfix_didAddSubview:(UIView *)subview { [self _displaybugfix_didAddSubview:subview]; // calls the existing method [subview setNeedsDisplay]; } @end 

注意:UINavigationBar当前有重写的方法,所以我期望使用method_exchangeImplementations风格。 为了安全起见,我只是添加了其他的东西,以防苹果改变他们的代码 我们可能会自己走向无边界,但我确实发现这种方法至less可以作为一种select(直到更彻底的UI提升)。

附加说明:这个错误在iOS 7.1中似乎已经修复。 因此,如果运行> = 7.0和<7.1,修补程序可以被调整为仅安装方法。

有一个更好的解决scheme,不涉及方法swizzling。

您需要在您的应用程序的某处添加UINavigationViewControllerDelegate方法。

 - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated { dispatch_async(dispatch_get_main_queue(), ^{ [[navigationController.navigationBar subviews] makeObjectsPerformSelector:@selector(setNeedsDisplay)]; }); 

}

我的解决scheme是iOS 7及以上。

首先,使默认后退button不可见。

 self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil]; 

然后,使用自定义图像设置后退button的默认backIndicatorImage

 [UINavigationBar appearance].backIndicatorImage = [[UIImage imageNamed:@"topbar_icon_back_n.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; [UINavigationBar appearance].backIndicatorTransitionMaskImage = [[UIImage imageNamed:@"topbar_icon_back_p.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; 

在这一点上,使自定义的UINavigationBar调整_UINavigationBarBackIndicatorView其中包含上述backIndicatorImage

 const CGPoint SANavigationBarOffset = {-8, 11.5}; @implementation SANavigationBar - (void)layoutSubviews { [super layoutSubviews]; // set back button position NSArray *classNamesToReposition = @[@"_UINavigationBarBackIndicatorView"]; for (UIView *view in [self subviews]) { if ([classNamesToReposition containsObject:NSStringFromClass([view class])]) { CGRect frame = [view frame]; frame.origin.x = 0; frame.origin.y = 0; [view setFrame:frame]; } } } @end 

然后,将其设置为我的导航栏

 // set custom NavagationBar for back button position [self.navigationController setValue:[[SANavigationBar alloc] init] forKey:@"navigationBar"]; 

在下面的ios7中添加button作为导航项目

  UIButton *btnAdd = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 60, 30)]; [btnAdd setContentMode:UIViewContentModeScaleAspectFit]; [btnAdd setBackgroundImage:[UIImage imageNamed:@"back.png"] forState:UIControlStateNormal]; [btnAdd addTarget:self action:@selector(backButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; UIBarButtonItem *btnAdd = [[UIBarButtonItem alloc] initWithCustomView:imView]; self.navigationItem.rightBarButtonItem = btnAdd; 

使用Swift你可以添加一个扩展:

 extension UIViewController: UIGestureRecognizerDelegate { func popBack() { self.navigationController?.popViewControllerAnimated(true) } func enableCustomBackButtom() { self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: UIImage(named: "icon-back"), style: UIBarButtonItemStyle.Plain, target: self, action:"popBack") self.navigationController?.interactivePopGestureRecognizer.delegate = self } } 

并在你的UIViewController使用像这样:

 self.enableCustomBackButtom() 

我只是提供了与iOS6相同的行为(注意navigationBar是UINavigationBar),请确保navigationBar有一个topItem

 UINavigationItem *topItemNavigation = [navigationBar topItem]; UIBarButtonItem *barButtonTopItemNavigation = [[UIBarButtonItem alloc] initWithTitle:topItemNavigation.title style:UIBarButtonItemStyleBordered target:nil action:nil]; [barButtonTopItemNavigation setBackButtonBackgroundImage:YOUR_IMAGE_BACKGROUND forState:UIControlStateNormal barMetrics:UIBarMetricsDefault ]; [topItemNavigation setBackBarButtonItem: barButtonTopItemNavigation]; } 

我的解决scheme是在UINavigationItem上写一个类别。 这是iOS7。

 - (void)mdSetCustomBackButton:(UINavigationController *)navigationController { MDBackButton *backButton = [[MDBackButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 44.0, 44.0) navigationController:navigationController]; [backButton addTarget:self action:@selector(popBack:) forControlEvents:UIControlEventTouchUpInside]; UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton]; [self setLeftBarButtonItem:barButtonItem]; [navigationController.interactivePopGestureRecognizer setDelegate:(id<UIGestureRecognizerDelegate>)self]; } - (void)popBack:(MDBackButton *)sender { [sender.navigationController popViewControllerAnimated:YES]; } 

和子类UIButton添加一个UINavigationController属性(popup并设置向后滑动的代理)。

 @property (nonatomic, weak) UINavigationController *navigationController; @implementation MDBackButton - (id)initWithFrame:(CGRect)frame navigationController:(UINavigationController *)navigationController { self = [super initWithFrame:frame]; if(self){ _navigationController = navigationController; [self setImage:[UIImage imageNamed:@"back_button"] forState:UIControlStateNormal]; } return self; } 

这对我是工作的:

 - (void)setCustomNavigationBackButton { self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil]; UIImage *myIcon = [self imageWithImage:[UIImage imageNamed:@"backbutton.png"] scaledToSize:CGSizeMake(20, 20)]; self.navigationController.navigationBar.backIndicatorImage = myIcon; self.navigationController.navigationBar.backIndicatorTransitionMaskImage = myIcon; } - (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize { //UIGraphicsBeginImageContext(newSize); // In next line, pass 0.0 to use the current device's pixel scaling factor (and thus account for Retina resolution). // Pass 1.0 to force exact pixel size. UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0); [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; } 

另外,自定义颜色的自定义字体:

 //self.navigationController.navigationBar.tintColor = [UIColor whiteColor]; [[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil] setTitleTextAttributes: @{NSForegroundColorAttributeName:[UIColor whiteColor], NSFontAttributeName:[UIFont fontWithName:@"Signika-Bold" size:20]} forState:UIControlStateNormal]; 

参考: https : //stackoverflow.com/a/2658801/1371949

我使用下面这些代码,这在iOS 8的作品

 UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; button.translatesAutoresizingMaskIntoConstraints = NO; button.exclusiveTouch = YES; button.titleLabel.font = [UIFont systemFontOfSize:14.0]; [button setTitleColor:kWhiteColor forState:UIControlStateNormal]; [button setTitleColor:[UIColor colorWithRed:1/255.0 green:36/255.0 blue:60/255.0 alpha:1.0] forState:UIControlStateHighlighted]; [button setTitle:@"Back" forState:UIControlStateNormal]; [button setImage:[UIImage imageNamed:@"barbutton_back"] forState:UIControlStateNormal]; [button setImageEdgeInsets:UIEdgeInsetsMake(1.0, 0.0, 0.0, 0.0)]; CGSize fontSize = [button.titleLabel sizeThatFits:CGSizeMake(100.0, 30.0)]; button.frame = CGRectMake(0.0, 0.0, button.imageView.image.size.width+fontSize.width, 30.0); UIBarButtonItem *barbtn = [[UIBarButtonItem alloc] initWithCustomView:button]; //fix iOS 7 left margin UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; negativeSpacer.width = -10; self.navigationItem.leftBarButtonItems = [NSArray arrayWithObjects:negativeSpacer,barbtn, nil]; 
 -(void) viewWillAppear:(BOOL)animated { UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; [btn setFrame:CGRectMake(0, 0, 30, 44)]; [btn setImage:[UIImage imageNamed:@"btnBack.png"] forState:UIControlStateNormal]; [btn addTarget:self action:@selector(PopToView) forControlEvents:UIControlEventTouchUpInside]; UIBarButtonItem *btnBack = [[UIBarButtonItem alloc] initWithCustomView:btn]; [btnBack setTintColor:[UIColor whiteColor]]; [[self.navigationController navigationItem] setLeftBarButtonItem:btnBack]; }