自定义返回指示器图像和 iOS 11

Posted

技术标签:

【中文标题】自定义返回指示器图像和 iOS 11【英文标题】:Custom back indicator image and iOS 11 【发布时间】:2017-09-13 09:01:31 【问题描述】:

我在我的应用程序中使用了自定义后退按钮。这个自定义后退按钮全局设置如下:

    UINavigationBar.appearance().backIndicatorImage = UIImage(named: "Back").withRenderingMode(.alwaysOriginal)
    UINavigationBar.appearance().backIndicatorTransitionMaskImage = UIImage(asset: .back).withRenderingMode(.alwaysOriginal)

ios 11 之前,此代码可以解决问题,但现在在 iOS 11 中,按钮不再垂直居中,如下所示:

我可以将后退按钮图像的高度更改为 44,但这会在 iOS

编辑:

原来,正如banxii1988所说,问题是由setBackButtonTitlePositionAdjustment引起的,当值故意将标题移到可见屏幕之外时。这是一种避免删除每个视图控制器中的后退按钮标题的技巧。我决定删除这个 hack,我做了正确的事:

    将故事板中的后退按钮项设置为" "。 在没有关联故事板的每个视图控制器中,我设置 backBarButtonItem 以编程方式 navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)

请注意,您在视图控制器中看到的后退按钮标题是在导航堆栈中的前一个标题中设置的。

【问题讨论】:

我有同样的问题,在我用 View Debugging 检查它之后。我发现这是因为我们在 BackButtonTitlePositionAdjustment 中使用了一些技巧来隐藏 backButtonTitle。所以 1)navigationItem.title 是必需的,后面的 Indicator 有约束,2)删除棘手的偏移 【参考方案1】:

1) 删除 PositionAdjustment(如果有)。比如

  bap.setBackButtonTitlePositionAdjustment(UIOffset(horizontal: 0, vertical: -64), for: .default)

2) 检查 nav stack 中的前一个 ViewController 是否有标题

【讨论】:

【参考方案2】:

我觉得这个方法还可以!对我有用。

if(@available(iOS 11, *)) 
    [[UIBarButtonItem appearance] setTitleTextAttributes:@NSForegroundColorAttributeName: [UIColor clearColor] forState:UIControlStateNormal];
    [[UIBarButtonItem appearance] setTitleTextAttributes:@NSForegroundColorAttributeName: [UIColor clearColor] forState:UIControlStateHighlighted];

 else 
    [[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(-60, -60) forBarMetrics:UIBarMetricsDefault];

【讨论】:

这是唯一对我有用的解决方案,因为我在整个应用程序中都使用了视图控制器的标题。我无法删除标题,因为我会失去功能。只是将文本设置为清晰有效。谢谢。 唯一需要注意的是按钮文本(如“取消”)在分享到其他应用(电子邮件、消息等)时是透明的(透明颜色),如果需要分享功能则翻转颜色: 我的解决方案将影响所有 barButtonItems 的标题。标题的文本颜色将被清除,例如:rightBarButtonItem,leftBarButtonItem。 @asanli 的解决方案效果很好。但是,当滑动手势缓慢返回时,您可以看到“偏移屏幕标题”【参考方案3】:

对于无法解决的任何人:

1) 在你的项目中(cmd+shift+f)搜索“setBackButtonTitle”,你会发现如下代码:

[[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[xController class]]] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -60) forBarMetrics:UIBarMetricsDefault];

2) 用这个改变上面的代码:

[[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[xController class]]] setBackButtonTitlePositionAdjustment:UIOffsetMake(-200, 0) forBarMetrics:UIBarMetricsDefault];

从 iOS 11 开始,上面的代码我们用来隐藏后退按钮标题,将后退按钮连同标题本身一起移动。但是,如果您只是水平移动后退按钮的标题,则一切正常,并且没有回退。

【讨论】:

这个对我有用。应该是一个可接受的答案【参考方案4】:

此解决方案适用于 iOS 9、10 和 11

    var backButtonImage: UIImage = UIImage(named: "backButton")!
    UINavigationBar.appearance().backIndicatorImage = backButtonImage
    UINavigationBar.appearance().backIndicatorTransitionMaskImage = backButtonImage

    if #available(iOS 11, *) 
        UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffsetMake(-300, 0), for:UIBarMetrics.default)
     else 
        UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffsetMake(0, -200), for:UIBarMetrics.default)
    

【讨论】:

【参考方案5】:

经过多次尝试和失败,这对我们适用于 iOS 11:

[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(-200, -5) forBarMetrics:UIBarMetricsDefault];

诀窍是将 x 轴上的“后退”文本向后移动很多,并在 y 轴上移动一点,因为setBackButtonTitlePositionAdjustment 原来对图像和文本都有影响。

但是,我们不知道这个解决方案能工作多久,它可能会被 Apple 随时“修复”

【讨论】:

【参考方案6】:

我会推荐方法调配来解决它,我已经在我的一些项目中使用了这个解决方案,它工作正常。

1 - 创建UIViewController 的类别。

2- 导入#import <objc/runtime.h>

3-粘贴以下方法

#import "UIViewController+Extras.h"
#import <objc/runtime.h>
@implementation UIViewController (Extras)

+ (void)load 
    static dispatch_once_t once_token;
    dispatch_once(&once_token,  ^
        SEL viewDidLoadSelector = @selector(viewDidLoad);
        SEL viewDidLoadModifyBackButtonSelector = @selector(modifyBackButton_viewDidLoad);
        Method originalMethod = class_getInstanceMethod(self, viewDidLoadSelector);
        Method extendedMethod = class_getInstanceMethod(self, viewDidLoadModifyBackButtonSelector);
        method_exchangeImplementations(originalMethod, extendedMethod);
    );


- (void)modifyBackButton_viewDidLoad 
    [self modifyBackButton_viewDidLoad];
    self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:self.navigationItem.backBarButtonItem.style target:nil action:nil];


@end

【讨论】:

【参考方案7】:
if(@available(iOS 11, *)) 
    [[UIBarButtonItem appearance] setTitleTextAttributes:@NSForegroundColorAttributeName: [UIColor clearColor] forState:UIControlStateNormal];
    [[UIBarButtonItem appearance] setTitleTextAttributes:@NSForegroundColorAttributeName: [UIColor clearColor] forState:UIControlStateHighlighted];

 else 
    [[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(-60, -60) forBarMetrics:UIBarMetricsDefault];

@Tonin 的上述解决方案有效,但唯一的问题是导航栏左按钮文本(如“取消”)在共享到其他应用程序(电子邮件、消息等)时是透明的(清除颜色),如果需要翻转颜色分享功能:

UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:@[title, URL] applicationActivities:nil];
[activityViewController setCompletionWithItemsHandler:^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) 
     // set clear color when back from share
     [[UIBarButtonItem appearance] setTitleTextAttributes:@NSForegroundColorAttributeName: [UIColor clearColor] forState:UIControlStateNormal];
];
[self presentViewController:activityViewController animated:YES completion:^
     // set white color when share to other app 
     [[UIBarButtonItem appearance] setTitleTextAttributes:@NSForegroundColorAttributeName: [UIColor whiteColor] forState:UIControlStateNormal];
];

【讨论】:

【参考方案8】:

适用于 SWIFT 3+

     if #available(iOS 11, *) 
            UIBarButtonItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.clear], for: .normal)
            UIBarButtonItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.clear], for: .highlighted)
      else 
            UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffsetMake(0,
-60), for:UIBarMetrics.default)
        

【讨论】:

这种方式也会从右键中移除颜色。【参考方案9】:

1.

extension UINavigationController 
    func pushViewC(_ viewController: UIViewController, animated: Bool) 
        viewController.navigationItem.leftBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "return").withRenderingMode(.alwaysOriginal), style: .plain, target: navigationController, action: #selector(popViewController(animated:)))
        pushViewController(viewController, animated: animated)
    

2.使用pushViewC代替pushViewController

navigationController?.pushViewC(otherVC, animated: true)

【讨论】:

以上是关于自定义返回指示器图像和 iOS 11的主要内容,如果未能解决你的问题,请参考以下文章

iOS 7 中的自定义后退指示器图像未垂直居中

LabVIEW设计自定义指示灯和按钮控件

带有自定义图像的活动指示器

我需要在 TableView 中创建基于图像的自定义附件类型的示例代码

iOS 8 自定义键盘自动布局键

自定义 TableView 滚动指示器 (iOS)