如何在没有标题的 iOS 7 及更高版本中自定义导航返回按钮? (即只有箭头)
self.navigationItem.leftBarButtonItem = self.editButtonItem;
我只是想知道他们是否有任何 self.backButtonItem;
或者
像这样的东西?
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemBACK
target:self action:@selector(back)];
这实际上很容易,这就是我所做的:
目标 C
// Set this in every view controller so that the back button displays back instead of the root view controller name
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
斯威夫特 2
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)
斯威夫特 3
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
将此行放入正在推送到堆栈的视图控制器(前一个视图控制器)中。新推的视图控制器后退按钮现在将显示您为 initWithTitle 放置的任何内容,在本例中为空字符串。
我找到了一种使用 iOS 单箭头制作后退按钮的简单方法。
假设您有一个导航控制器从 ViewB 到 ViewA。在 IB 中,选择 ViewA 的导航栏,您应该会看到以下选项:Title、Prompt 和 Back Button。
ViewA 导航栏选项
https://i.stack.imgur.com/NaKPy.png
诀窍是在前一个视图控制器(视图 A)的选项中选择您的命运视图控制器后退按钮标题(视图 B)。如果您没有填写“Back Button”选项,iOS 会自动将标题“Back”与前一个视图控制器的标题放在一起。因此,您需要用一个空格填充此选项。
在“返回按钮”选项中填充空格
https://i.stack.imgur.com/Jeu7o.png
结果:
https://i.stack.imgur.com/DYcuS.png
Back Button
设置为单个空格字符(即 ViewA 和 ViewB)时才有效
只需使用图像!
OBJ-C:
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"Icon-Back"]
style:UIBarButtonItemStylePlain
target:self.navigationController
action:@selector(popViewControllerAnimated:)];
self.navigationItem.leftBarButtonItem = backButton;
}
斯威夫特 4:
let backBTN = UIBarButtonItem(image: UIImage(named: "Back"),
style: .plain,
target: navigationController,
action: #selector(UINavigationController.popViewController(animated:)))
navigationItem.leftBarButtonItem = backBTN
navigationController?.interactivePopGestureRecognizer?.delegate = self
图标返回.png
https://i.stack.imgur.com/RsIpj.png
图标-Back@2x.png
https://i.stack.imgur.com/dM1qs.png
图标-Back@3x.png
https://i.stack.imgur.com/J6hHE.png
navigationController?.interactivePopGestureRecognizer?.delegate = self
可以保持向后滑动手势
iOS7 有新的界面规则,所以在推送 UIView 时最好至少保留后退箭头。以编程方式更改“后退”文本非常容易。只需在推送视图之前添加此代码(或者如果您使用 StoryBoards,则为 prepareForSegue):
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
self.navigationItem.backBarButtonItem=[[UIBarButtonItem alloc] initWithTitle:@"NEW TITLE" style:UIBarButtonItemStylePlain target:nil action:nil];
}
这将更改默认的“后退”文本,但会保留 iOS7 样式的后退箭头。您还可以在推送视图之前更改后退箭头的色调颜色:
- (void)viewDidLoad{
//NavBar background color:
self.navigationController.navigationBar.barTintColor=[UIColor redColor];
//NavBar tint color for elements:
self.navigationController.navigationBar.tintColor=[UIColor whiteColor];
}
希望这对你有帮助!
你不需要做太多的事情。您可以通过情节提要本身实现相同的目的。
只需转到根导航控制器并留出空间。请记住,不要对您想要没有标题的后退按钮的控制器,而是对根导航控制器。
https://i.stack.imgur.com/O79p4.png
虽然 Kyle Begeman's answer 完全可以解决问题,但在每个可能的视图控制器中都有这段代码是很烦人的。我最终得到了一个简单的 UINavigationItem
类别。当心,这里有龙!对不起,我的意思是,混乱:
#import <objc/runtime.h>
@implementation UINavigationItem (ArrowBackButton)
static char kArrowBackButtonKey;
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Method m1 = class_getInstanceMethod(self, @selector(backBarButtonItem));
Method m2 = class_getInstanceMethod(self, @selector(arrowBackButton_backBarButtonItem));
method_exchangeImplementations(m1, m2);
});
}
- (UIBarButtonItem *)arrowBackButton_backBarButtonItem {
UIBarButtonItem *item = [self arrowBackButton_backBarButtonItem];
if (item) {
return item;
}
item = objc_getAssociatedObject(self, &kArrowBackButtonKey);
if (!item) {
item = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStyleBordered target:nil action:NULL];
objc_setAssociatedObject(self, &kArrowBackButtonKey, item, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return item;
}
@end
[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(-1000, -1000) forBarMetrics:UIBarMetricsDefault];
(source) - 可能不太优雅,但 swizzling 感觉有点矫枉过正
UINavigationItem
自己的方法,不涉及继承。并且 _cmd
不太可能参与吸气剂。无论如何,这是一个好点。所以你们,如果你的项目中有这么多 swizzling helpers 中的任何一个,请确保你也在这里使用它。
这可行,但它会删除前一个项目的标题,即使你弹回它:
self.navigationController.navigationBar.topItem.title = @"";
只需在推送的视图控制器的 viewDidLoad
上设置此属性。
viewWillAppear
上设置了推送 VC 的标题,因此它始终设置正确。
编辑:2014-04-09:当我获得声誉时,我感到很抱歉,因为我不再使用这个技巧了。我推荐凯尔的回答。另请注意,self.navigationItem.backBarButtonItem
的 self
不是显示后退按钮的视图控制器,而是要返回的上一个视图控制器。
如果你不需要前一个视图控制器的标题文本,只需用空白字符串填充标题即可;
self.navigationItem.title = @"";
[self.navigationController pushViewController:viewController animated:YES];
这将防止在推送的视图控制器上显示带有雪佛龙的“后退”。
编辑:即使您使用非空白标题文本,在 viewWillAppear:
中设置前一个视图控制器的标题也有效,除了视图控制器弹出时标题可能会闪烁。我认为“推特应用程序”似乎做了更微妙的破解来避免闪烁。
这就是我的做法,也是最简单、最有效、最清晰的做法。
如果嵌入在 Navigation Controller
上,则此方法有效
斯威夫特 3
在 viewDidLoad
中,我将此添加到视图控制器中,您希望后退按钮只是箭头。
if let topItem = self.navigationController?.navigationBar.topItem {
topItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
}
这与@Kyle Begeman 的回答的不同之处在于您在视图控制器上调用它,您希望后退按钮只是箭头,而不是在推送堆栈视图控制器上。
您无法以您想要的方式访问导航 backButtonItem,您需要创建自己的后退按钮,如下所示:
- (void)loadView
{
[super loadView];
UIButton *backButton = [[UIButton alloc] initWithFrame: CGRectMake(0, 0, 44.0f, 30.0f)];
[backButton setImage:[UIImage imageNamed:@"back.png"] forState:UIControlStateNormal];
[backButton addTarget:self action:@selector(popVC) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
}
当然:
- (void) popVC{
[self.navigationController popViewControllerAnimated:YES];
}
目标:将 UINavigationBar
上的所有后退按钮自定义为白色图标
步骤: 1.在AppDelete的“didFinishLaunchingWithOptions”方法中:
UIImage *backBtnIcon = [UIImage imageNamed:@"navBackBtn"];
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
[UINavigationBar appearance].tintColor = [UIColor whiteColor];
[UINavigationBar appearance].backIndicatorImage = backBtnIcon;
[UINavigationBar appearance].backIndicatorTransitionMaskImage = backBtnIcon;
}else{
UIImage *backButtonImage = [backBtnIcon resizableImageWithCapInsets:UIEdgeInsetsMake(0, backBtnIcon.size.width - 1, 0, 0)];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -backButtonImage.size.height*2) forBarMetrics:UIBarMetricsDefault];
}
2.在普通超ViewController
类的viewDidLoad
方法中:
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@""
style:UIBarButtonItemStylePlain
target:nil
action:nil];
[self.navigationItem setBackBarButtonItem:backItem];
}else{
//do nothing
}
斯威夫特 4
对于那些希望创建自定义后退按钮以及删除其标题的人,请在推动新按钮的视图控制器中使用以下代码:
self.navigationController?.navigationBar.backIndicatorImage = UIImage(named: "close")
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = UIImage(named: "close")
self.navigationItem?.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
要获得更普遍的用途,请执行以下操作:
创建通用函数如下: func addCustomizedBackBtn(navigationController: UINavigationController?, navigationItem: UINavigationItem?) { navigationController?.navigationBar.backIndicatorImage = UIImage(named: "close") navigationController?.navigationBar.backIndicatorTransitionMaskImage = UIImage(named: "close" ) navigationItem?.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) } 然后在视图控制器中使用如下: addCustomizedBackBtn(navigationController: self.navigationController, navigationItem: self.navigationItem )
iOS6 的简单 hack 也适用于 iOS7:
[UIBarButtonItem.appearance setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -60) forBarMetrics:UIBarMetricsDefault];
编辑:不要使用这个黑客。详情见评论。
你可以用这个。只需添加一个 UIButton
作为 UIBarButtonItem
的自定义视图,这对我来说非常有效。
试试下面的代码
self.navigationItem.leftBarButtonItem=[self backButton];
- (UIBarButtonItem *)backButton
{
UIImage *image = [UIImage imageNamed:@"back-btn.png"];
CGRect buttonFrame = CGRectMake(0, 0, image.size.width, image.size.height);
UIButton *button = [[UIButton alloc] initWithFrame:buttonFrame];
[button addTarget:self action:@selector(backButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[button setImage:image forState:UIControlStateNormal];
UIBarButtonItem *item= [[UIBarButtonItem alloc] initWithCustomView:button];
return item;
}
为根视图控制器创建一个具有所需标题的 UILabel
,并将其分配给视图控制器的 navigationItem.titleView
。
现在将标题设置为空字符串,您按下的下一个视图控制器将有一个没有文本的后退按钮。
self.navigationItem.titleView = titleLabel; //Assuming you've created titleLabel above
self.title = @"";
// add left bar button item
try this code:
- (void)viewDidLoad
{
[super viewDidLoad];
UIImage* image_back = [UIImage imageNamed:@"your_leftarrowImage.png"];
CGRect backframe = CGRectMake(250, 9, 15,21);
UIButton *backbutton = [[UIButton alloc] initWithFrame:backframe];
[backbutton setBackgroundImage:image_back forState:UIControlStateNormal];
[backbutton addTarget:self action:@selector(Btn_back:)
forControlEvents:UIControlEventTouchUpInside];
[backbutton setShowsTouchWhenHighlighted:YES];
UIBarButtonItem *backbarbutton =[[UIBarButtonItem alloc] initWithCustomView:backbutton];
self.navigationItem.leftBarButtonItem=backbarbutton;
[backbutton release];
}
-(IBAction)Btn_back:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
所有的答案都不能解决问题。在每个视图控制器中设置后退按钮标题并且向标题添加偏移量仍然会使下一个视图控制器标题向右移动是不可接受的。
这是使用方法 swizzling 的方法,只需为 UINavigationItem 创建新的扩展
import UIKit
extension UINavigationItem {
public override class func initialize() {
struct Static {
static var token: dispatch_once_t = 0
}
// make sure this isn't a subclass
if self !== UINavigationItem.self {
return
}
dispatch_once(&Static.token) {
let originalSelector = Selector("backBarButtonItem")
let swizzledSelector = #selector(UINavigationItem.noTitleBackBarButtonItem)
let originalMethod = class_getInstanceMethod(self, originalSelector)
let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
if didAddMethod {
class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
} else {
method_exchangeImplementations(originalMethod, swizzledMethod)
}
}
}
// MARK: - Method Swizzling
struct AssociatedKeys {
static var ArrowBackButtonKey = "noTitleArrowBackButtonKey"
}
func noTitleBackBarButtonItem() -> UIBarButtonItem? {
if let item = self.noTitleBackBarButtonItem() {
return item
}
if let item = objc_getAssociatedObject(self, &AssociatedKeys.ArrowBackButtonKey) as? UIBarButtonItem {
return item
} else {
let newItem = UIBarButtonItem(title: " ", style: UIBarButtonItemStyle.Plain, target: nil, action: nil)
objc_setAssociatedObject(self, &AssociatedKeys.ArrowBackButtonKey, newItem as UIBarButtonItem?, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return newItem
}
}
}
我在 viewDidLoad 中应用了以下代码,它可以工作:
// this will set the back button title
self.navigationController.navigationBar.topItem.title = @"Test";
// this line set the back button and default icon color
//[[self.navigationController.navigationBar.subviews lastObject] setTintColor:[UIColor blackColor]];
this line change the back default icon to your custom icon
[[self.navigationController.navigationBar.subviews lastObject] setTintColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"menuicon"]]];
只是为了更新我使用矢量图标
您可以继承 UINavigationController,将自身设置为委托,并在委托方法 navigationController:willShowViewController:animated:
中设置 backBarButtonItem
@interface Custom_NavigationController : UINavigationController <UINavigationControllerDelegate>
@end
@implementation Custom_NavigationController
- (void)viewDidLoad
{
[super viewDidLoad];
self.delegate = self;
}
#pragma mark - UINavigationControllerDelegate
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
viewController.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
}
@end
将标题设置为空
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStyleDone target:self action:@selector(handleBack:)];
[backButton setTintColor:Color_WHITE];
[self.navigationItem setBackBarButtonItem:backButton];
换回图片
UIImage *backImg = [[UIImage imageNamed:@"ic_back_white"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
[UINavigationBar appearance].backIndicatorImage = backImg;
[UINavigationBar appearance].backIndicatorTransitionMaskImage = backImg;
检查这个答案
How to change the UINavigationController back button name?
将 title
文本设置为 string
,并带有一个空格,如下所示
title = " "
没有足够的声誉来添加评论:)
自 iOS 5 左右以来,我一直在使用此解决方案,没有任何问题。我制作了一个实用函数,我在视图控制器中调用它。您需要在 viewDidLoad 或之后的任何时候执行此操作。
void updateBackButtonTextForViewController(UIViewController *viewController, NSString *text)
{
if(! viewController.navigationItem.backBarButtonItem)
{
viewController.navigationItem.backBarButtonItem =
[[UIBarButtonItem alloc] initWithTitle:text
style:UIBarButtonItemStylePlain
target:nil action:nil];
}
else
{
viewController.navigationItem.backBarButtonItem.title = text;
}
}
在某些情况下,导航项可能已经存在,在其他情况下需要创建。这在不影响导航项标题的情况下解决了这两种情况。它允许您通过简单地传入 @""
来删除标题。
对我有用的唯一方法是:
navigationController?.navigationBar.backItem?.title = ""
更新:
当我将 segue 动画标志更改为 true (之前是 false )时,对我有用的唯一方法是:
navigationController?.navigationBar.topItem?.title = ""
如果您在导航控制器中嵌入了两个 ViewController(FirstVC, SecondVC),并且您希望 SecondVC 中只有后退箭头。
你可以试试这个在 FirstVC 的 ViewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)
}
然后当你推入 SecondVC 时,你会看到只有后退箭头
如果你设置了 NavigationBar 的 tintColor,添加一个自定义的没有标题的后退按钮图像,该 tint 颜色将反映图像颜色。请按照这个苹果文档链接。
UINavigationItem *navItem = [[UINavigationItem alloc] init];
navBar.tintColor = self.tintColor;
UIImage *myImage = [UIImage imageNamed:@"left_arrow.png"];
myImage = [myImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
UIBarButtonItem *leftButton = [[UIBarButtonItem alloc] initWithImage:myImage style:UIBarButtonItemStylePlain target:self action:@selector(cancelButtonFunction:)];
navItem.leftBarButtonItem = leftButton;
navBar.items = @[ navItem ];
我写了一个扩展来使这更容易:
extension UIViewController {
/// Convenience for setting the back button, which will be used on any view controller that this one pushes onto the stack
@objc var backButtonTitle: String? {
get {
return navigationItem.backBarButtonItem?.title
}
set {
if let existingBackBarButtonItem = navigationItem.backBarButtonItem {
existingBackBarButtonItem.title = newValue
}
else {
let newNavigationItem = UIBarButtonItem(title: newValue, style:.plain, target: nil, action: nil)
navigationItem.backBarButtonItem = newNavigationItem
}
}
}
}
您可以在 viewWillDisappear 上将当前 ViewController 的标题更改为 @"",并在它即将再次显示时将标题重新设置为之前的任何内容。
-(void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.title = @"Previous Title";
}
-(void) viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
self.title = @"";
}
将 backItem.title = "" 更改为使用 topItem.title = ""
设置 navigationItem.hidesBackButton = true & navigationItem.leftBarButtonItem 将失去返回手势
请记住,我们必须创建 2 个背面图像的实例
我的解决方案将更改图像并保持后退手势:
navigationController?.navigationBar.backIndicatorImage = UIImage(named: "back")
navigationController?.navigationBar.backIndicatorTransitionMaskImage = UIImage(named: "back")
navigationController?.navigationBar.topItem?.title = ""
在第一个 ViewController 的 prepareForSegue: 方法中,您将该视图标题设置为 @"",因此当推送下一个视图时,它将显示上一个 ViewController 标题,即 @""。
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
self.navigationItem.title = @" ";
}
唯一的问题是,当您点击返回按钮时,您之前的视图将没有标题,因此您可以在 viewWillAppear 上再次添加它:
-(void)viewWillAppear:(BOOL)animated{
self.navigationItem.title = @"First View Title";
}
我不太喜欢这个解决方案,但它有效,我没有找到其他方法来做到这一点。
要添加到上面的 Thomas C's answer,有时放置一个空格不起作用,您必须不断添加空格。
https://i.stack.imgur.com/IoL2t.png
当您在“导航项”下看到“条形按钮项-”时,您就知道您成功了。那在文档大纲中(编辑器->显示文档大纲)。看到上图后,可以删掉几个空格,看看还能不能用。
不定期副业成功案例分享
prepareForSegue
中,它工作得很好。