web-dev-qa-db-fra.com

Image d'indicateur de dos personnalisé et iOS 11

J'utilise un bouton de retour personnalisé dans mon application. Ce bouton de retour personnalisé est défini globalement comme ceci:

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

Avant iOS 11, ce code faisait l'affaire, mais maintenant dans iOS 11, le bouton n'est plus centré verticalement, comme vous pouvez le voir ici:

 enter image description here

Je pouvais modifier la hauteur de l'image du bouton de retour à 44, mais cela se briserait sous iOS <11. Je pourrais également utiliser deux images différentes, mais je recherchais quelque chose de plus net, comme un moyen de centrer verticalement l'image à l'arrière bouton contenant la vue.

MODIFIER:

Il s'avère que, comme l'a dit banxii1988, le problème est dû à setBackButtonTitlePositionAdjustment lorsque les valeurs déplacent délibérément le titre en dehors de l'écran visible. C'était un hack pour éviter de supprimer le titre du bouton de retour dans chaque contrôleur de vue. J'ai décidé de supprimer ce hack et j'ai fait ce qu'il fallait:

  1. définissez le bouton de retour dans le storyboard sur " ".
  2. dans chaque contrôleur de vue sans storyboard associé, je règle la backBarButtonItem par programmation navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)

Notez que le titre du bouton Précédent que vous voyez dans un contrôleur de vue est défini dans le précédent dans la pile de navigation.

21
Luca Torella

1) enlevez PositionAdjustment s'il y en a. tel que

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

2) vérifier si le précédent ViewController dans la pile de navigation a un titre

9
banxi1988

Je pense que cette méthode est ok! C'est utile pour moi.

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];
}
12
Tonin

Pour ceux qui ne pourraient pas le résoudre:

1) Dans votre projet (cmd + shift + f), recherchez "setBackButtonTitle", vous trouverez un code comme ci-dessous:

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

2) Changer le code ci-dessus avec celui-ci:

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

Depuis iOS 11, le code ci-dessus sert à masquer les titres des boutons, le bouton précédent et le titre lui-même. Cependant, si vous déplacez simplement le titre du bouton de retour horizontalement, tout fonctionne correctement et il n'y a pas de tirage en arrière.

12
asanli

Cette solution fonctionne pour moi pour iOS 9, 10 et 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)
    }
4
Eugene

Après plusieurs tentatives et échecs, cela a fonctionné pour nous pour iOS 11:

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

L'astuce consistait à déplacer le texte "Retour" sur l'axe des abscisses, et un peu sur l'axe des ordonnées, car setBackButtonTitlePositionAdjustment s'est avéré affecter à la fois l'image et le texte.

Cependant, nous ne savons pas combien de temps cette solution fonctionnera, elle pourrait être "réparée" par Apple à tout moment

3
effochka

je recommanderais la méthode swizzling pour le résoudre, j'ai utilisé cette solution dans certains de mes projets et cela fonctionne bien.

1 - créer une catégorie de UIViewController.

2- importer #import <objc/runtime.h>.

3- coller la méthode suivante

#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
1
Mortgy
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];
}

La solution ci-dessus de @Tonin fonctionne, mais le seul souci est que le texte du bouton gauche de la barre de navigation (comme "Annuler") est transparent (couleur claire) lorsqu'il est partagé avec une autre application (email, message, etc.) 

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];
}];
1
Yao Li

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. utiliser pushViewC au lieu de pushViewController

navigationController?.pushViewC(otherVC, animated: true)
0
BaQiWL

POUR 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)
        }
0
MANISH PATHAK