IOS导航栏的问题
天蓬老师
天蓬老师 2017-04-17 17:39:37
0
5
456

ios 两个状态栏 背景图片不一样 push过去正常显示
返回(pop)回来,当前的背景图变成了push过去的那个导航栏的背景图片.
用图片演示:
1.这是控制器A:

2.设置push过去的控制器B:

3.点击返回后的控制器A:

为什么控制器A的导航栏的背景图片变成了控制器B的?如何修改?

代码奉上:
自定义控制器的所有代码:

#import "LMSNavigationController.h"

@interface LMSNavigationController ()

@end

@implementation LMSNavigationController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.navigationBar setTitleTextAttributes:
  @{NSFontAttributeName:[UIFont systemFontOfSize:16]}];
}


/**
 * 在这个方法中拦截所有push进来的控制器
 */
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    if (self.childViewControllers.count > 0) {
        // 如果push进来的不是第一个控制器
        UIButton *leftBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        [leftBtn setImage:[UIImage imageNamed:@"nav-back.png"] forState:UIControlStateNormal];
        [leftBtn setImage:[UIImage imageNamed:@"nav-back-hi.png"] forState:UIControlStateHighlighted];
        leftBtn.frame = CGRectMake(0, 0, 30, 30);
        [leftBtn addTarget:self action:@selector(popViewControllerAnimated:) forControlEvents:UIControlEventTouchUpInside];
        viewController.navigationItem.leftBarButtonItem  = [[UIBarButtonItem alloc]initWithCustomView:leftBtn];
        // 隐藏tabbar
        viewController.hidesBottomBarWhenPushed = YES;
    }
    
    //把导航栏底部的横线去掉
    [self.navigationBar setShadowImage:[UIImage new]];
    
    // 这句super的push要放在后面, 让viewController可以覆盖上面设置的leftBarButtonItem
    // 意思是,我们任然可以重新在push控制器的viewDidLoad方法中设置导航栏的leftBarButtonItem,如果设置了就会覆盖在push方法中设置的“返回”按钮,因为 [super push....]会加载push的控制器执行viewDidLoad方法。
    [super pushViewController:viewController animated:animated];
}



- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

控制器A关键代码:

- (void)viewDidLoad {
    [super viewDidLoad];
    //导航栏透明背景(nav-clearcolor-image是一张透明的图片)
    [self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"nav-clearcolor-image"] forBarMetrics:UIBarMetricsDefault];
    //把导航栏底部的横线去掉
    [self.navigationController.navigationBar setShadowImage:[UIImage new]];
    //不显示文字
    self.navigationItem.title = nil;
}

控制器B关键代码:

- (void)viewDidLoad {
    [super viewDidLoad];
    UILabel *titleLabel = [[UILabel alloc]init];
    titleLabel.text = @"push过来的控制器";
    titleLabel.textColor = TitleTextColor;
    [titleLabel sizeToFit];
    self.navigationItem.titleView = titleLabel;
}
天蓬老师
天蓬老师

欢迎选择我的课程,让我们一起见证您的进步~~

répondre à tous(5)
伊谢尔伦

Il s'agit d'une question sur le cycle de vie de UINavigationController (en supposant que votre LMSNavigationController soit sa sous-classe) et UIViewController (ci-après dénommé VC). . .


Version simple de la réponse

Changer de VC AviewDidLoad en viewWillAppear .
(Il existe une meilleure méthode ci-dessous.)

Version compliquée (pas si compliquée...)

Regardons d'abord comment le document décrit viewDidLoad :

Appelé après le chargement de la vue du contrôleur en mémoire.

Cette méthode sera appelée lorsque la vue VC sera chargée en mémoire. Le VC B pop ne remplit pas les conditions pour appeler les VC A viewDidLoad en sortant. L'explication est la suivante :

UINavigationController maintient une pile VC, et vous push et pop exploitez cette pile lorsque vous utilisez ces VC.

Lorsque

push il créera un nouveau VC et le poussera sur la pile, qui est votre VC B Au cours de ce processus, ce nouveau VC B est lié subit le processus d'ajout à la mémoire, et view est appelé. viewDidLoadVC B est au sommet de la pile et devient . topViewControllerVC A n'est plus en haut de la pile, mais est toujours sur la pile, et son view associé est toujours en mémoire . Lorsque le popVC B s'éteint, le de la vue associée au VC A n'est plus appelé. viewDidLoad

Alors

pushComment s'appelle-t-on exactement ? pop

Photo ci-dessus

Figure 1-5 Messages envoyés lors des changements de pile


Source de l'image : Surveillance des modifications apportées à la section Pile de navigation de la documentation du contrôleur de navigation

Surveillance des modifications apportées à la pile de navigation

Surveillance des modifications apportées à la pile de navigation

Prenons

pushVC B sortant comme exemple :

  1. VC B En tant que contrôleur de vue le plus haut actuel, son est appelé en premier viewWillDispear

    Le
  2. de
  3. VC A s'appelle viewWillAppear

  4. de UINavigationControllerDelegate s'appelle navigationController:willShowViewController:animated:

  5. Animation de transition (terminée ? Peu clair)

    Le
  6. de
  7. VC B s'appelle viewDidDispear

    Le
  8. de
  9. VC A s'appelle viewDidAppear

  10. de UINavigationControllerDelegate s'appelle navigationController:didShowViewController:animated:

En résumé, les de VC AviewDidLoad peuvent être remplacés par viewWillAppear.

Cependant, je pense personnellement qu'une meilleure façon est de diviser les deux viewDidLoad et de réécrire la logique dans les UINavigationControllerDelegate de navigationController:willShowViewController:animated:. Vous pouvez résoudre le besoin de modifier l’image d’arrière-plan en un seul endroit.

Fin.


Mettre à jour, utilisez UINavigationControllerDelegate comme mentionné ci-dessus :

    func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
        if self.childViewControllers.count > 1 {
            navigationController.navigationBar.setBackgroundImage(UIImage(named: "a"), forBarMetrics: .Default)
        } else {
            navigationController.navigationBar.setBackgroundImage(UIImage(named: "b"), forBarMetrics: .Default)
        }
    }

viewWillAppear Je l'ai aussi essayé, c'est exactement le même que celui-ci, aucun cadre noir n'apparaît. En ce qui concerne cette question, ces deux lieux répondent à vos exigences. Choisissez simplement ce que vous aimez.

Le contrôleur de navigation fourni avec le système a déjà fait ce qu'il devait faire avant le début de l'animation, il n'y aura donc pas de chargement d'image avant la moitié de l'animation. Le pire, c'est que l'animation sera bloquée quelques secondes avant de démarrer, et elle ne démarrera qu'après son chargement.

Votre contrôleur de navigation est personnalisé. Vérifiez la partie personnalisée pour voir s'il y a des boîtes noires causées par des problèmes.

(Aussi... je ne vois toujours pas où l'image de fond a été modifiée. Ce n'est pas l'image du bouton qui a été modifiée sur la première manette)

巴扎黑

Tous les VC sous nav partagent la même navBar
Vous avez modifié la navBar en entrant dans B
mais ne l'avez pas modifiée en quittant B

小葫芦

Vous disposez de deux contrôleurs de barre de navigation (pop). La barre de navigation renvoyée est la même que la barre de navigation actuelle. Vous devez créer un proxy et réaffecter la valeur. (Mais c'est plus gênant)

阿神

Vous devez avoir modifié la couleur ou l'image de la barre de navigation en B

阿神

Essayez à nouveau de définir l'image d'arrière-plan de vc dans la méthode viewWillAppear de A

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal