我有一个UINavigationController
我可以推送几个视图。在其中一个视图的viewDidLoad
内,我想将self.navigationItem.backBarButtonItem
设置为自定义视图(基于自定义图像)。我不知道为什么,但似乎没有用。相反,我得到标准的“后退”按钮。
UIButton *backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 63, 30)];
[backButton setImage:[UIImage imageNamed:@"back_OFF.png"] forState:UIControlStateNormal];
[backButton setImage:[UIImage imageNamed:@"back_ON.png"] forState:UIControlStateSelected];
UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
self.navigationItem.backBarButtonItem = backButtonItem;
[backButtonItem release];
[backButton release];
我测试了一个标准的标题,它的工作原理。上面的代码出了什么问题?
self.navigationItem.backBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:@"Prout" style:UIBarButtonItemStyleDone target:nil action:nil] autorelease];
感谢您提供任何帮助。
答案 0 :(得分:27)
从iOS5开始,我们有一个使用UIAppearance protocol定制几乎所有控件的外观的优秀新方法,即[UIBarButtonItem appearance]
。外观代理允许您创建应用程序范围内的控件外观更改。下面是使用外观代理创建的自定义后退按钮的示例。
使用下面的示例代码创建一个后退按钮,其中包含正常和突出显示状态的自定义图像。从appDelegate的application:didFinishLaunchingWithOptions:
- (void) customizeAppearance {
UIImage *i1 = [[UIImage imageNamed:@"custom_backButton_30px"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 6)];
UIImage *i2 = [[UIImage imageNamed:@"custom_backButton_24px"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 6)];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:i1
forState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:i2
forState:UIControlStateNormal
barMetrics:UIBarMetricsLandscapePhone];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:i1
forState:UIControlStateHighlighted
barMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:i2
forState:UIControlStateHighlighted
barMetrics:UIBarMetricsLandscapePhone];
}
这只是一个简单的例子。通常,您可能希望为正常和突出显示(按下)状态设置单独的图像。
如果您有兴趣自定义其他控件的外观,可以在此处找到一些很好的示例:http://ios.biomsoft.com/2011/10/13/user-interface-customization-in-ios-5/
答案 1 :(得分:19)
我非常确定backBarButtonItem
是一个只读属性。不要修改backBarButtonItem
,而是尝试设置自定义leftBarButtonItem
并隐藏backBarButtonItem
:
self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:@"Prout" style:UIBarButtonItemStyleDone target:nil action:nil] autorelease];
self.navigationItem.hidesBackButton = YES;
您还需要确保连接自定义按钮以在UINavigationBar
上调用后退操作。
答案 2 :(得分:15)
我无法使用自定义视图和UIBarButtonItem
创建合适的setBackBarButtonItem
。
这是我发现的解决方案:让net UINavigationControllerDelegate
处理所有事情!这里的诀窍是调用popViewControllerAnimated:
的{{1}}方法,这样您就不必创建任何自定义方法。
viewController.navigationController
答案 3 :(得分:10)
如果您的最终目标是简单地替换用于后退按钮的图像,则可以在iOS 5.0中使用的UIBarButtonItem上使用新方法:
setBackButtonBackgroundImage:forState:barMetrics:
这是一个简单的示例,为您应用中的所有后退按钮设置自定义背景图片:
UIImage *toolbarBackButtonBackgroundPortrait = [[UIImage imageNamed:@"toolbarBackButtonPortrait"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 17, 0, 6)];
UIImage *toolbarBackButtonBackgroundLandscape = [[UIImage imageNamed:@"toolbarBackButtonLandscape"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 17, 0, 6)];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:toolbarBackButtonBackgroundPortrait forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:toolbarBackButtonBackgroundLandscape forState:UIControlStateNormal barMetrics:UIBarMetricsLandscapePhone];
答案 4 :(得分:6)
我愿意打赌,这是Apple的一个错误,因为我遇到了同样的问题。原因是我可以显示自定义UIBarButtonItem
,但仅当我不尝试使用initWithCustomView:
方法时。根据API,导航控制器在按下新视图控制器时检查以下内容:
我的情况(以及你的情况)是2.我指定代码完全与您的相同(即创建UIButton
,为各种设置image
属性状态,创建UIBarButtonItem
,使用UIButton
初始化它,然后将我当前的视图控制器的backBarButtonItem
属性设置为UIBarButtonItem
);然而,当我稍后推动我的视图控制器时,我的导航控制器的左侧没有显示任何内容。奇怪的是,我可以单击“后退”按钮所在的位置,然后弹出视图控制器。
有趣的是,如果我使用UIBarButtonItem
方法而不是initWithTitle:style:target:action:
方法创建initWithCustomView:
,则会显示带有自定义标题的自定义按钮。此外,正如特拉维斯所说,使用leftBarButtonItem
属性可以正常工作。但是,我宁愿遵守认可的逻辑,通过为当前视图控制器指定“后退”按钮 - 稍后在按下新视图控制器时显示 - 而不是为下一个视图控制器创建左按钮可以说,它应该不关心与它之前的视图控制器有关的任何事情。 : - \
答案 5 :(得分:5)
在使用navigationController推送viewController之前设置backBarButtonItem
之前。在backBarButtonItem
中设置viewDidLoad
不起作用。
说我有MyTableViewController。当用户点击特定行时,我想使用navigationController推送AnotherViewController。代码看起来像这样:
// in MyTableViewController's tableView:didSelectRowAtIndexPath method...
UIBarButtonItem *backButton = [[UIBarButtonItem alloc]
initWithImage:[UIImage imageNamed:@"yourImage.png"]
style:UIBarButtonItemStyleBordered
target:nil
action:nil];
self.navigationItem.backBarButtonItem = backButton;
[backButton release];
[self.navigationController pushViewController:anotherViewController];
当显示anotherViewController时,导航栏中的后退按钮将具有@"yourImage.png"
和默认后退按钮样式(矩形箭头)。另请注意,将nil
作为target
传递是合适的。按钮的行为类似于后退按钮。
答案 6 :(得分:2)
即使已经回答,这对我有用:
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"backArrow.png"] style:UIBarButtonItemStyleBordered target:nil action:nil];
self.navigationItem.backBarButtonItem = backButton;
[backButton release];
BTW:即使在iOS4中使用initWithCustomView初始化我的后退按钮:对我来说也不起作用。 ;(
答案 7 :(得分:2)
我customView
上的navigationItem.backBarButtonItem
也遇到了问题。我怀疑它可能只是SDK中的b0rked。
虽然这里列出的解决方法确实有效,但我提出了一个更优雅的解决方案:它仍然使用navigationItem.leftBarButtonItem
,但是会自动为您处理(不再需要'儿童' '查看控制器需要了解有关'父母'的任何信息和/或手动设置navigationItem.leftBarButtonItem
)。
首先,让某些课程成为您感兴趣的后退按钮的UINavigationControllerDelegate
的{{1}}。然后,在此课程中,设置类似以下UINavigationController
委托的内容方法:
willShowViewController
我还有一些问题;似乎-(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
// reference to view controller stack
NSArray *viewControllers = [ navigationController viewControllers ];
if( [ viewControllers count ] > 1 ){
// the view controller we'll be linking to
UIViewController *backViewController = [ viewControllers objectAtIndex: [ viewControllers count ] - 2 ];
// create custom UIBarButtonItem
UIBarButtonItem *leftButton = [[ UIBarButtonItem alloc ] initWithCustomView: someCustomView ];
// set it as the leftBarButtonItem on the incoming viewcontroller
viewController.navigationItem.leftBarButtonItem = leftButton;
// tidy up
[ leftButton release ];
}
}
和UIBarButtonItem.action
在UIBarButtonItem.target
时无效。所以,你留下了一个实际上没有返回的自定义后退按钮。我会在您的自定义视图中回复触摸作为读者的练习(我使用了UIButton),但您需要将此方法添加到您的委托类中:
navigationItem.leftBarButtonItem
并在点击自定义视图时将其连接起来。
答案 8 :(得分:1)
backBarButtonItem不是只读的 属性。我不确定它为什么会这样 太奇怪了,以上是有效的 (如果不太理想)解决方法。
它表现得很奇怪,因为设置vc的backBarButtonItem不会改变vc导航项的外观 - 相反,它会更改指向BACK的按钮到vc。请参阅Apple FMI的updating the navigation bar。
那说我自己没有运气好运。如果你环顾这个网站,你会发现一些线程建议放置代码非常类似于你在调用之前已经拥有的代码,以便在堆栈上推送新视图。我在那里运气不错,但遗憾的是在使用自定义图像方面没有。
答案 9 :(得分:1)
navigationController的backBarButtonItem设置在您试图影响其标题的项目上。
即。在第1页的视图控制器中,比如,viewdidLoad:
self.title = @"Page 1 of 4";
self.navigationItem.backBarButtonItem =
[[[UIBarButtonItem alloc] initWithTitle:@"Page 1"
style:UIBarButtonItemStyleBordered
target:nil
action:nil] autorelease];
你不会在第2页中覆盖它。
UINavigationItem的文档:backBarButtonItem清楚地说明了这一点:
当此项目是后面的项目时 导航栏 - 当它是下一个 顶部项目下面的项目 - 它可能是 表示为后退按钮 导航栏。使用此属性 指定后退按钮。目标 和后栏按钮项的操作 你设定应该是零。默认 value是一个显示的条形按钮项 导航项目的标题。
答案 10 :(得分:1)
这就是我用箭头而不是通常的文字创建自定义方形后退按钮的方法。
我只是为我的UINavigationController设置了一个委托。我使用app委托,因为窗口根视图控制器是我想要控制的UINavigationController。
所以AppDelegate.m(ARC):
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
((UINavigationController*)_window.rootViewController).delegate = self;
return YES;
}
#pragma mark - UINavigationControllerDelegate
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if(navigationController.viewControllers.count > 1) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:[UIImage imageNamed:@"back-arrow.png"] forState:UIControlStateNormal];
[button setBackgroundColor:[UIColor grayColor]];
button.frame = CGRectMake(0, 0, 44, 44);
viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
[button addEventHandler:^(id sender) {
[navigationController popViewControllerAnimated:YES];
} forControlEvents:UIControlEventTouchUpInside];
}
}
我正在使用BlocksKit来捕捉按钮点击事件。这样的东西很方便,但你也可以使用常规的addTarget:action:forControlEvents:method
答案 11 :(得分:0)
我想我找到了解决方法。 只需在上一个控制器上导航项目上设置按钮(您想要返回的那个)
所以,如果我有一个根控制器 我推了第二个控制器,想要自定义后退按钮,然后我应该执行以下操作:
self.navigationItem.backBarButtonItem = [[[UIBarButtonItem alloc]
initWithImage:[UIImage imageNamed:@"ico.png"] style:UIBarButtonItemStyleBordered
target:nil action:nil] autorelease];
其中self是根视图控制器而不是第二个。
答案 12 :(得分:0)
我的逻辑:
第3步非常重要。我认为模拟“返回”最干净的方法就是利用UINavigationController的方法(popViewControllerAnimated :)。所以,我只是将这个动作添加到我正在推动的viewController的navigationController中(viewControllerToPush),如下所示:
[navItemButton addTarget:viewControllerToPush.navigationController action:@selector(popViewControllerAnimated:) forControlEvents:UIControlEventTouchUpInside];
示例:
UIViewController *viewControllerToPush = [[UIViewController alloc] init];
UIImage *navImage = [UIImage imageNamed:@"your_back_button_image"];
UIButton *navItemButton = [UIButton buttonWithType:UIButtonTypeCustom];
[navItemButton setImage:navImage forState:UIControlStateNormal];
[navItemButton setImage:navImage forState:UIControlStateHighlighted];
[navItemButton setFrame:CGRectMake(0, 0, navImage.size.width, navImage.size.height)];
[navItemButton addTarget:viewControllerToPush.navigationController action:@selector(popViewControllerAnimated:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:navItemButton];
viewControllerToPush.navigationItem.leftBarButtonItem = barButtonItem;
viewControllerToPush.navigationItem.hidesBackButton = YES;
[self.navigationController pushViewController:viewControllerToPush animated:YES];
答案 13 :(得分:0)
您可以使用leftBarButtonItem而不是后退按钮项。要删除默认的后退按钮项,请将其设置为nil,如下所示;
navigationController?.navigationBar.backIndicatorImage = nil
navigationController?.navigationBar.backIndicatorTransitionMaskImage = nil
let button = UIButton.init(type: .custom)
button.imageView?.contentMode = UIViewContentMode.scaleAspectFit
button.setImage(UIImage.init(named: "top_back"), for: UIControlState.normal)
button.frame = CGRect.init(x: 0, y: 0, width: 75, height: 50)
button.addTarget(self, action: #selector(handleBackButton), for: .touchUpInside)
let barButton = UIBarButtonItem.init(customView: button)
self.navigationItem.leftBarButtonItem = barButton