62 votes

Le guide de disposition supérieur du contrôleur de navigation n'est pas respecté avec la transition personnalisée

Version courte:

J'ai un problème avec mise en page automatique haut de page lorsqu'il est utilisé conjointement avec la coutume de transition et d' UINavigationController dans iOS7. Plus précisément, la contrainte entre le haut guide de présentation et l'affichage de texte n'est pas mis à l'honneur. Quelqu'un a rencontré ce problème?


Version longue:

J'ai une scène qui a définir sans ambiguïté des contraintes (haut, bas, gauche et droite) qui rend une vue comme ça:

right

Mais quand je l'utilise avec une transition personnalisée sur la manette de navigation, en haut de contrainte pour le haut de la page semble éteint et le rendu est comme suit, comme si la page était en haut de l'écran, plutôt qu'en bas de la manette de navigation:

wrong

Il semble que le "haut de page" avec la manette de navigation est de se confondre en employant la transition personnalisée. Le reste de l'contraintes sont appliquées correctement. Et si j'ai faites pivoter l'appareil et faites-le pivoter de nouveau, tout est soudain rendu correctement, de sorte qu'il ne semble pas être n'est pas une question que les contraintes ne sont pas définis correctement. De même, lorsque j'éteins mon custom de transition, les points de vue s'afficher correctement.

Ayant dit que, _autolayoutTrace est signalé que le UILayoutGuide objets souffrent d' AMBIGUOUS LAYOUT, quand je le lance:

(lldb) po [[UIWindow keyWindow] _autolayoutTrace]

Mais ces repères de mise en page sont toujours signalés comme ambigu chaque fois que je les regarde, même si j'ai veillé à ce qu'il ne manque aucun des contraintes (j'ai fait le coutumier de la sélection de la vue-contrôleur, et en choisissant "Ajouter manquant contraintes de vue-contrôleur" ou en sélectionnant toutes les commandes et faire de même pour eux).

En termes de la façon dont justement je suis en train de faire la transition, j'ai spécifié un objet conforme à l' UIViewControllerAnimatedTransitioning dans la animationControllerForOperation méthode:

- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                  animationControllerForOperation:(UINavigationControllerOperation)operation
                                               fromViewController:(UIViewController*)fromVC
                                                 toViewController:(UIViewController*)toVC
{
    if (operation == UINavigationControllerOperationPush)
        return [[PushAnimator alloc] init];

    return nil;
}

Et

@implementation PushAnimator

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
    return 0.5;
}

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
    UIViewController* toViewController   = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

    [[transitionContext containerView] addSubview:toViewController.view];
    CGFloat width = fromViewController.view.frame.size.width;

    toViewController.view.transform = CGAffineTransformMakeTranslation(width, 0);

    [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
        fromViewController.view.transform = CGAffineTransformMakeTranslation(-width / 2.0, 0);
        toViewController.view.transform = CGAffineTransformIdentity;
    } completion:^(BOOL finished) {
        fromViewController.view.transform = CGAffineTransformIdentity;
        [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
    }];
}

@end

J'ai aussi fait une version de ce qui précède, le réglage de l' frame de la vue plutôt que de l' transform, avec le même résultat.

J'ai aussi essayé manuellement, assurez-vous que les contraintes sont ré-appliqué en appelant layoutIfNeeded. J'ai aussi essayé de setNeedsUpdateConstraints, setNeedsLayout, etc.

Bas de la ligne, quelqu'un a réussi à marier transition personnalisée de la manette de navigation avec des contraintes d'utilisation haut de page?

10voto

Jasper Kuperus Points 89

Je me suis battu avec exactement le même problème. Mettre cela dans le viewDidLoad de mon toViewController m'a vraiment aidé:

 self.edgesForExtendedLayout = UIRectEdgeNone;
 

Cela n'a pas résolu tous mes problèmes et je cherche toujours une meilleure approche, mais cela a certainement facilité les choses.

3voto

hpique Points 23090

@Rob mentionné, topLayoutGuide n'est pas fiable lors de l'utilisation de transitions personnalisées en UINavigationController. J'ai travaillé autour de cela, en utilisant ma propre mise en page du guide. Vous pouvez voir le code en action dans ce projet de démonstration. Faits saillants:

Une catégorie pour la mise en page personnalisée guides:

@implementation UIViewController (hp_layoutGuideFix)

- (BOOL)hp_usesTopLayoutGuideInConstraints
{
    return NO;
}

- (id<UILayoutSupport>)hp_topLayoutGuide
{
    id<UILayoutSupport> object = objc_getAssociatedObject(self, @selector(hp_topLayoutGuide));
    return object ? : self.topLayoutGuide;
}

- (void)setHp_topLayoutGuide:(id<UILayoutSupport>)hp_topLayoutGuide
{
    HPLayoutSupport *object = objc_getAssociatedObject(self, @selector(hp_topLayoutGuide));
    if (object != nil && self.hp_usesTopLayoutGuideInConstraints)
    {
        [object removeFromSuperview];
    }
    HPLayoutSupport *layoutGuide = [[HPLayoutSupport alloc] initWithLength:hp_topLayoutGuide.length];
    if (self.hp_usesTopLayoutGuideInConstraints)
    {
        [self.view addSubview:layoutGuide];
    }
    objc_setAssociatedObject(self, @selector(hp_topLayoutGuide), layoutGuide, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end

HPLayoutSupport est la classe qui va agir comme un guide de présentation de l'. Il a un UIView sous-classe pour éviter les collisions (je me demande pourquoi ce n'est pas une partie de l' UILayoutSupport interface).

@implementation HPLayoutSupport {
    CGFloat _length;
}

- (id)initWithLength:(CGFloat)length
{
    self = [super init];
    if (self)
    {
        self.translatesAutoresizingMaskIntoConstraints = NO;
        self.userInteractionEnabled = NO;
        _length = length;
    }
    return self;
}

- (CGSize)intrinsicContentSize
{
    return CGSizeMake(1, _length);
}

- (CGFloat)length
{
    return _length;
}

@end

L' UINavigationControllerDelegate qui est responsable de "fixer" le guide de présentation de l'avant de la transition:

- (id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                   animationControllerForOperation:(UINavigationControllerOperation)operation
                                                fromViewController:(UIViewController *)fromVC
                                                  toViewController:(UIViewController *)toVC
{
    toVC.hp_topLayoutGuide = fromVC.hp_topLayoutGuide;
    id <UIViewControllerAnimatedTransitioning> animator;
    // Initialise animator
    return animator;
}

Enfin, l' UIViewController utilise hp_topLayoutGuide au lieu de topLayoutGuide dans la les contraintes, et indique ce en substituant hp_usesTopLayoutGuideInConstraints:

- (void)updateViewConstraints
{
    [super updateViewConstraints];
    id<UILayoutSupport> topLayoutGuide = self.hp_topLayoutGuide;
    // Example constraint
    NSDictionary *views = NSDictionaryOfVariableBindings(_imageView, _dateLabel, topLayoutGuide);
    NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[topLayoutGuide][_imageView(240)]-8-[_dateLabel]" options:NSLayoutFormatAlignAllCenterX metrics:nil views:views];
    [self.view addConstraints:constraints];
}

- (BOOL)hp_usesTopLayoutGuideInConstraints
{
    return YES;
}

Espérons que cela aide.

2voto

Yusuf terzi Points 51

j'ai trouvé le chemin. Commencez par décocher la propriété "Étendre les bords" du contrôleur. après que la barre de navigation devienne de couleur sombre. Ajoutez une vue au contrôleur et définissez LayoutConstraint -100 en haut et en bas. Ensuite, définissez la propriété clipsubview de la vue (pour l’effet de navigation dans la barre de navigation). Mon anglais sory sory pour ça. :)

1voto

stringCode Points 744

J'ai eu le même problème, j'ai fini par implémenter ma propre vue de guide topLayout et par lui imposer des contraintes plutôt que par topLayoutGuide. Pas idéal. Ne la postez ici que dans le cas où quelqu'un est bloqué et à la recherche d'une solution rapide pour le hacky http://www.github.com/stringcode86/SCTopLayoutGuide

0voto

vivek Points 398

essayez:

 self.edgesforextendedlayout=UIRectEdgeNone
 

Ou simplement définir opaque sur la barre de navigation et définir l’image ou la couleur de fond sur barre de navigation

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X