iOS 7自定义后退按钮
我想使用自定义后退按钮。在iOS 6中,一切都很完美,但iOS 7却很奇怪iOS 7自定义后退按钮,ios,cocoa-touch,ios7,xcode5,Ios,Cocoa Touch,Ios7,Xcode5,我想使用自定义后退按钮。在iOS 6中,一切都很完美,但iOS 7却很奇怪 [[UIBarButtonItem appearance] setBackButtonBackgroundImage:[[UIImage imageNamed:@"back_button_normal"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 12.0, 0, 12.0)] forState:UIControlStateNormal barMetrics:UIBa
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:[[UIImage imageNamed:@"back_button_normal"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 12.0, 0, 12.0)] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
首先,它没有iOS 7箭头和背景图像
(俄语地区)
然后,如果按下按钮,将显示背景图像。我还为UIControlStateHighlighted
状态设置了背景图像,当按住按钮时,高亮显示的图像也会出现。按下任何后退按钮后,所有后退按钮都有背景图像
但是!如果显示模式视图控制器,请将其关闭,然后按下任何视图控制器-ios7
箭头将出现在每个后退按钮上
我使用DP5。这是一个UIKit错误吗
PS我还尝试手动创建后退按钮,使用UIBarButtonItem
,将背景图像设置为它,然后self.navigationItem.backBarButtonItem=barButtonItem代码>没有帮助。
然后我尝试将背景图像设置为禁用状态,并更改我的工具栏按钮项的enabled属性,但也没有帮助
这不是一个bug,这是iOS 7中后退按钮的外观。例如:
您可能应该在应用程序中使用新概念,而不是在iOS 7中为后退按钮设置背景图像
如果您仍然希望后退按钮与iOS6中的相同,那么您可能应该手动创建这些后退按钮:
- (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.interactiveepgpgestureerecognizer.delegate=(id)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或final中没有修复。我看到了同样的问题。这似乎是一个Apple错误;Apple使用的私有视图在初始显示时根本没有得到setNeedsDisplay调用。对它做任何导致调用的操作都应该修复它——就像pre一样打开它(这可能会更改内部状态,以便它自己调用setNeedsDisplay),或者打开一个模式(这可能会强制在下一个视图上重新显示整个视图层次结构:call)
使用leftBarItems也可以工作,但这可能会导致现有代码的许多维护问题(例如,一些屏幕可能有自己的左侧项,期望当设置回nil时,它们会恢复原始的back项)
如前所述,理想情况下,您可以在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(BackButtonDisplayFix)
+(空)荷载
{
如果([UIDevice currentDevice].systemVersion.intValue>=7)
{
/*
*我们首先尝试简单地向类添加didAddSubview:的覆盖版本
*失败,这意味着该类已经拥有自己的方法重写实现
*(我们在本例中希望如此),因此请改用方法交换版本。
*/
Method didAddMethod=class_getInstanceMethod(self,@selector(_displaybugfixsuper_didAddSubview:);
如果(!class_addMethod(self,@selector(didAddSubview:),
方法_getImplementation(didAddMethod),
方法\u getTypeEncoding(didAddMethod)))
{
方法existMethod=class_getInstanceMethod(self,@selector(didAddSubview:);
方法替换=class_getInstanceMethod(self,@selector(_displaybugfix_didAddSubview:);
方法交换实施(现有方法,替换);
}
}
}
-(无效)_displaybugfixsuper_didAddSubview:(UIView*)子视图
{
[超级添加子视图:子视图];
[子视图设置需要显示];
}
-(无效)\u displaybugfix\u didAddSubview:(UIView*)子视图
{
[self _displaybugfix_didAddSubview:subview];//调用现有方法
[子视图设置需要显示];
}
@结束
注意:UINavigationBar目前确实有一个对所讨论方法的覆盖,所以我希望使用方法交换实现风格。为了安全起见,我刚刚添加了其他东西,以防苹果更改其代码。我们自己可能会去无边界,但我确实发现这种方法可以作为一种选择(直到更彻底的UI升级)至少
附加说明:此错误似乎在iOS 7.1中已修复。因此,该修补程序可能被限制为仅在运行>=7.0和<7.1时安装这些方法。在iOS 7中添加按钮作为导航项,如下所示
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;
有一个更好的解决方案,它不涉及方法切换
您需要在应用程序中的某个位置添加UINavigationViewControllerDelegate方法
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
dispatch_async(dispatch_get_main_queue(), ^{
[[navigationController.navigationBar subviews] makeObjectsPerformSelector:@selector(setNeedsDisplay)];
});
}我只是提供了与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];
}
我的解决方案是在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];
}
我的解决方案适用于iOS 7及以上版本
首先,使默认的后退按钮不可见
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
然后,使用自定义图像设置后退按钮的默认backindicatormage
[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
,用于调整的大小\u UINavigationBarBackIndicatorView
,其中包含上述背景指示符号图像
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"];
这是我的工作:
- (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];
参考资料:使用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()
我用这些c
//self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil] setTitleTextAttributes:
@{NSForegroundColorAttributeName:[UIColor whiteColor],
NSFontAttributeName:[UIFont fontWithName:@"Signika-Bold" size:20]}
forState:UIControlStateNormal];
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
}
}
self.enableCustomBackButtom()
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];