如何使用自定义视图为UINavigationController创buildbackBarButtomItem
我有一个UINavigationController
我推几个意见。 里面viewDidLoad
为这些意见之一,我想设置self.navigationItem.backBarButtonItem
自定义视图(基于自定义图像)。 我不知道为什么,但似乎没有工作。 相反,我得到标准的“后退”button。
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];
我testing了一个标准的标题,它的工作。 上面的代码有什么问题?
self.navigationItem.backBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:@"Prout" style:UIBarButtonItemStyleDone target:nil action:nil] autorelease];
感谢您的任何帮助。
我很确定backBarButtonItem
是一个只读属性。 而不是修改backBarButtonItem
,尝试设置一个自定义的leftBarButtonItem
并隐藏backBarButtonItem
:
self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:@"Prout" style:UIBarButtonItemStyleDone target:nil action:nil] autorelease]; self.navigationItem.hidesBackButton = YES;
您还需要确保连接自定义button以调用UINavigationBar
上的后退动作。
从iOS5开始,我们有一个很好的新方法来定制使用UIAppearance协议的任何控件的外观 ,即[UIBarButtonItem appearance]
。 外观代理允许您创build应用程序范围的控件外观变化。 以下是使用外观代理创build的自定义后退button的示例。
使用下面的示例代码来创build一个带正常图像和高亮状态的自定义图像的后退button。 从你的appDelegate的application:didFinishLaunchingWithOptions:
调用以下方法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]; }
这只是一个简单的例子。 通常情况下,您需要为正常和突出显示(按下)状态提供单独的图像。
如果你有兴趣定制其他控件的外观,一些很好的例子可以在这里find: http : //ios.biomsoft.com/2011/10/13/user-interface-customization-in-ios-5/
我从来没有能够创build具有自定义视图和setBackBarButtonItem
适当的setBackBarButtonItem
。
这里是我find的解决scheme:让净UINavigationControllerDelegate
处理一切! 这里的技巧是调用popViewControllerAnimated:
方法,所以你不必创build任何自定义的方法。
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated { if([navigationController.viewControllers count ] > 1) { UIView *backButtonView = [[UIView alloc] initWithFrame:CGRectMake(0,0,70,35)]; UIButton *myBackButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain]; [myBackButton setFrame:CGRectMake(0,0,70,35)]; [myBackButton setImage:[UIImage imageNamed:@"back.png"] forState:UIControlStateNormal]; [myBackButton setEnabled:YES]; [myBackButton addTarget:viewController.navigationController action:@selector(popViewControllerAnimated:) forControlEvents:UIControlEventTouchUpInside]; [backButtonView addSubview:myBackButton]; [myBackButton release]; UIBarButtonItem* backButton = [[UIBarButtonItem alloc] initWithCustomView:backButtonView]; viewController.navigationItem.leftBarButtonItem = backButton; [backButtonView release]; [backButton release]; } }
如果您的最终目标是简单地replace用于后退button的图像,则可以在iOS 5.0中提供的UIBarButtonItem上使用新的方法:
setBackButtonBackgroundImage:forState:barMetrics:
Apple文档: http : //developer.apple.com/library/ios/#documentation/UIKit/Reference/UIBarButtonItem_Class/Reference/Reference.html
下面是一个简单的例子,为您的应用中的所有后退button设置自定义背景图片:
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];
我敢打赌,这是苹果的一个错误,因为我遇到了完全相同的问题。 原因是我可以得到一个自定义的UIBarButtonItem
出现,但只有当我不尝试使用initWithCustomView:
方法。 根据API,导航控制器在推送新视图控制器时检查以下内容:
- 如果新的顶层视图控制器具有自定义左栏button项目,则显示该项目。 要指定自定义左栏button项目,请设置视图控制器导航项目的leftBarButtonItem属性。
- 如果顶级视图控制器没有自定义的左栏button项目,但前一个视图控制器的导航项目在其backBarButtonItem属性中具有有效项目,则导航栏会显示该项目。
- 如果一个视图控制器没有指定一个自定义栏button项目,则使用一个默认的后退button,其标题被设置为前一个视图控制器的title属性的值,即视图控制器向下一级堆栈。 (如果导航堆栈中只有一个视图控制器,则不显示后退button。)
我的情况(以及你的)是2.我指定代码完全一样的你(即,创build一个UIButton
,设置其各种状态的image
属性,创build一个UIBarButtonItem
,用UIButton
初始化,然后设置我当前的视图控制器backBarButtonItem
属性到UIBarButtonItem
); 但是,当我稍后推动我的视图控制器,在我的导航控制器的左侧什么也没有显示。 奇怪的是,我可以点击“返回”button,并popup视图控制器。
有趣的是,如果我使用initWithTitle:style:target:action:
方法而不是initWithCustomView:
方法创build一个UIBarButtonItem
,它将显示一个带有自定义标题的自定义button。 另外,正如Travis所说的,使用leftBarButtonItem
属性可以正常工作。 我宁愿遵守被批准的逻辑,但是,通过指定当前视图控制器的“返回”button – 稍后当新的视图控制器被按下时显示 – 而不是为下一个视图控制器创build左button,可以说,这不应该涉及任何与之前的视图控制器有关。 : – \
在使用backBarButtonItem
推送backBarButtonItem
之前设置backBarButtonItem
。 在viewDidLoad
中设置backBarButtonItem
不起作用。
说我有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];
当显示@"yourImage.png"
,导航栏中的后退button将具有@"yourImage.png"
和默认后退button样式(矩形箭头)。 还要注意,可以通过nil
作为target
。 该button的行为像后退button。
即使已经回答了这个工作对我来说:
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"backArrow.png"] style:UIBarButtonItemStyleBordered target:nil action:nil]; self.navigationItem.backBarButtonItem = backButton; [backButton release];
顺便说一句:即使在iOS4初始化我的后退buttoninitWithCustomView:没有为我工作。 (
我也一直在navigationItem.backBarButtonItem
customView
问题。 我怀疑它可能只是在SDK中。
虽然这里列出的解决方法确实起作用,但我已经想出了一个更优雅的解决scheme:它仍然使用navigationItem.leftBarButtonItem
,但自动为您自动处理(不再需要“子”视图控制器来需要知道他们的“父母”的任何事情和/或手动设置navigationItem.leftBarButtonItem
)。
首先,让一些类成为UINavigationControllerDelegate
的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
不工作时,它是一个navigationItem.leftBarButtonItem
。 所以,你剩下一个自定义的后退button,实际上并没有回去。 我会留下回应你的自定义视图作为练习阅读器(我用UIButton),但你需要添加这个方法到你的委托类:
-(void)onDummyBackButtonTapped{ [ someNavigationController popViewControllerAnimated: YES ]; }
并在您的自定义视图被点击时将其挂接起来。
backBarButtonItem不是只读属性。 我不确定为什么它performance得如此奇怪,以上是一个有效的(如果不太理想的)解决方法。
它的行为很奇怪,因为设置vc的backBarButtonItem不会改变任何关于vc导航项目的外观 – 相反,它会改变指向BACK的button到vc。 请参阅从Apple FMI 更新导航栏 。
这就是说我没有太多的运气让自己工作。 如果你浏览一下这个网站,你会发现一些线程,这些线程会提示代码非常类似于在调用堆栈的新视图之前已经有的代码。 我有一些运气,但不幸的是,当涉及到使用自定义图像。
导航控制器的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说明了这一点:
当这个项目是导航栏的后面项目时(当它是最上面的项目下面的下一个项目时),它可以被表示为导航栏上的后退button。 使用此属性来指定后退button。 你设定的后面条button项的目标和动作应该是零。 默认值是显示导航项目标题的栏button项目。
这是我如何使用箭头而不是通常的文本创build自定义方块后退button。
我只是为我的UINavigationController设置一个委托。 我使用的应用程序委托,因为窗口的根视图控制器是我想控制的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来捕捉button点击事件。 对于像这样的东西非常方便,但是你也可以使用常规的addTarget:action:forControlEvents:方法
我想我find了解决scheme。 只需在前一个控制器上的导航项目上设置button(您想要返回的那个button)
所以如果我有例如一个根控制器,我推第二个控制器,并想定制后退button,那么我应该做到以下几点:
self.navigationItem.backBarButtonItem = [[[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"ico.png"] style:UIBarButtonItemStyleBordered target:nil action:nil] autorelease];
自我是根视图控制器,而不是第二个。
我的逻辑:
- 创build一个自定义button(又名自定义视图子类)
- 使用自定义button/视图初始化一个barbutton项目
- 添加一个动作,让我们“回到”我们以前的视图控制器
- 将左栏button项目设置为您创build的此自定义栏button项目
- 隐藏您要推送的视图控制器的后面条button项目
第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];
您可以使用leftBarButtonItem而不是后退button项目。 并删除默认后退button项目设置为零如下;
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