web-dev-qa-db-fra.com

Comment ajuster le point d'ancrage d'une couche CAL lorsque la mise en page automatique est utilisée?

Remarque : La situation a évolué depuis la réponse à cette question. voir ici pour un bon aperçu récent.


Avant la mise en page automatique, vous pouvez modifier le point d'ancrage d'un calque de vue sans déplacer la vue en stockant le cadre, en définissant le point d'ancrage et en restaurant le cadre.

Dans un monde de mise en page automatique, nous ne définissons plus les images, mais les contraintes ne semblent pas devoir permettre d'ajuster la position d'une vue à l'endroit souhaité. Vous pouvez pirater les contraintes pour repositionner votre vue, mais lors d'une rotation ou d'un autre événement de redimensionnement, elles deviennent à nouveau invalides.

L'idée lumineuse suivante ne fonctionne pas car elle crée une "association non valide d'attributs de présentation (gauche et largeur)":

layerView.layer.anchorPoint = CGPointMake(1.0, 0.5);
// Some other size-related constraints here which all work fine...
[self.view addConstraint:
    [NSLayoutConstraint constraintWithItem:layerView
                                 attribute:NSLayoutAttributeLeft
                                 relatedBy:NSLayoutRelationEqual 
                                    toItem:layerView 
                                 attribute:NSLayoutAttributeWidth 
                                multiplier:0.5 
                                  constant:20.0]];

Mon intention ici était de définir le bord gauche de layerView, la vue avec le point d'ancrage ajusté, à la moitié de sa largeur plus 20 (la distance que je veux insérer à partir du bord gauche de la vue supérieure).

Est-il possible de changer le point d'ancrage, sans changer l'emplacement d'une vue, dans une vue mise en page avec une mise en page automatique? Dois-je utiliser des valeurs codées en dur et éditer la contrainte à chaque rotation? J'espère que non.

Je dois modifier le point d'ancrage afin que, lorsque j'applique une transformation à la vue, j'obtienne l'effet visuel correct.

157
jrturton

[EDIT: Avertissement: La totalité de la discussion sera probablement dépassée ou au moins fortement atténuée par iOS 8, qui risque de ne plus commettre l’erreur de déclencher la présentation au moment de l’application d’une transformation de vue.]

Autolayout vs View Transforms

L'autolayout ne fonctionne pas du tout avec les transformations de vue. Autant que je sache, la raison en est que vous n'êtes pas censé jouer avec le cadre d'une vue comportant une transformation (autre que la transformation d'identité par défaut) - mais c'est exactement ce que fait l'autolayout. Autolayout fonctionne comme suit: dans layoutSubviews, le moteur d’exécution vire à travers toutes les contraintes et définit les cadres de toutes les vues en conséquence.

En d'autres termes, les contraintes ne sont pas magiques; ils ne sont qu'une liste de choses à faire. layoutSubviews est l'endroit où la liste de tâches est effectuée. Et cela se fait en définissant des cadres.

Je ne peux pas aider à considérer cela comme un bug. Si j'applique cette transformation à une vue:

v.transform = CGAffineTransformMakeScale(0.5,0.5);

Je m'attends à voir la vue apparaître avec son centre au même endroit qu'auparavant et à la moitié de sa taille. Mais selon ses contraintes, cela peut ne pas être ce que je vois du tout.

[En fait, il y a une deuxième surprise ici: appliquer une transformation à une vue déclenche immédiatement la mise en page. Cela me semble être un autre bug. Ou peut-être que c'est le cœur du premier bug. Ce à quoi je m'attendrais, c’est d’être capable de nous en sortir avec une transformation au moins jusqu’à la mise en page, par exemple. l'appareil est pivoté - de la même manière que je peux m'en tirer avec une animation d'image jusqu'au moment de la présentation. Mais en réalité, le temps d’agencement est immédiat, ce qui semble faux.]

Solution 1: pas de contrainte

Une solution actuelle consiste à supprimer toutes les contraintes qui l’affectent si je veux appliquer une transformation semi-permanente à une vue (et non pas simplement l’agiter temporairement). Malheureusement, cela entraîne généralement la disparition de la vue de l'écran, car l'autolayout existe toujours et il n'y a plus de contrainte pour nous dire où placer la vue. Donc, en plus de supprimer les contraintes, je règle le translatesAutoresizingMaskIntoConstraints de la vue sur YES. La vue fonctionne maintenant à l’ancienne, sans être affectée par le autolayout. (Il est affecté par autolayout, évidemment, mais les contraintes de masque autoresizing implicites font que son comportement est identique à ce qu'il était avant autolayout.)

Solution 2: utilisez uniquement les contraintes appropriées

Si cela semble un peu radical, une autre solution consiste à définir les contraintes pour qu’elles fonctionnent correctement avec la transformation voulue. Si une vue est dimensionnée uniquement en fonction de sa largeur et de sa hauteur internes fixes, et positionnée uniquement en fonction de son centre, par exemple, ma transformation d'échelle fonctionnera comme prévu. Dans ce code, je supprime les contraintes existantes sur une sous-vue (otherView) et les remplace par ces quatre contraintes, en lui donnant une largeur et une hauteur fixes et en l'épinglant uniquement par son centre. Après cela, ma transformation de balance fonctionne:

NSMutableArray* cons = [NSMutableArray array];
for (NSLayoutConstraint* con in self.view.constraints)
    if (con.firstItem == self.otherView || con.secondItem == self.otherView)
        [cons addObject:con];

[self.view removeConstraints:cons];
[self.otherView removeConstraints:self.otherView.constraints];
[self.view addConstraint:
 [NSLayoutConstraint constraintWithItem:self.otherView attribute:NSLayoutAttributeCenterX relatedBy:0 toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1 constant:self.otherView.center.x]];
[self.view addConstraint:
 [NSLayoutConstraint constraintWithItem:self.otherView attribute:NSLayoutAttributeCenterY relatedBy:0 toItem:self.view attribute:NSLayoutAttributeTop multiplier:1 constant:self.otherView.center.y]];
[self.otherView addConstraint:
 [NSLayoutConstraint constraintWithItem:self.otherView attribute:NSLayoutAttributeWidth relatedBy:0 toItem:nil attribute:0 multiplier:1 constant:self.otherView.bounds.size.width]];
[self.otherView addConstraint:
 [NSLayoutConstraint constraintWithItem:self.otherView attribute:NSLayoutAttributeHeight relatedBy:0 toItem:nil attribute:0 multiplier:1 constant:self.otherView.bounds.size.height]];

Le résultat est que si vous n'avez aucune contrainte qui affecte le cadre d'une vue, l'autolayout ne touchera pas le cadre de la vue, ce qui correspond exactement à ce que vous recherchez lorsqu'une transformation est impliquée.

Solution 3: Utiliser une sous-vue

Le problème avec les deux solutions ci-dessus est que nous perdons les avantages des contraintes pour positionner notre vision. Alors, voici une solution qui résout ce problème. Commencez avec une vue invisible dont le travail consiste uniquement à agir en tant qu'hôte et utilisez des contraintes pour la positionner. À l'intérieur, placez la vue réelle en tant que sous-vue. Utilisez des contraintes pour positionner la sous-vue dans la vue Hôte, mais limitez-les à des contraintes qui ne résistent pas lorsque nous appliquons une transformation.

Voici une illustration:

enter image description here

La vue blanche est la vue hôte; vous êtes censé prétendre qu'il est transparent et donc invisible. La vue rouge est sa sous-vue, positionnée en épinglant son centre au centre de la vue hôte. Maintenant, nous pouvons redimensionner et faire pivoter la vue rouge autour de son centre sans aucun problème, et l’illustration montre bien que nous l’avons fait:

self.otherView.transform = CGAffineTransformScale(self.otherView.transform, 0.5, 0.5);
self.otherView.transform = CGAffineTransformRotate(self.otherView.transform, M_PI/8.0);

Et pendant ce temps, les contraintes sur la vue de l'hôte le maintiennent au bon endroit lorsque nous faisons pivoter le périphérique.

Solution 4: utilisez plutôt les transformations de couche

Au lieu de transformer les vues, utilisez des transformations de calque, qui ne déclenchent pas la présentation et ne causent donc pas de conflit immédiat avec les contraintes.

Par exemple, cette simple animation de vue "throb" peut très bien se casser sous autolayout:

[UIView animateWithDuration:0.3 delay:0
                    options:UIViewAnimationOptionAutoreverse
                 animations:^{
    v.transform = CGAffineTransformMakeScale(1.1, 1.1);
} completion:^(BOOL finished) {
    v.transform = CGAffineTransformIdentity;
}];

Même si au final, la taille de la vue n’a pas changé, le simple fait de définir sa transform provoque la présentation et les contraintes peuvent faire basculer la vue. (Est-ce que cela ressemble à un bug ou quoi?) Mais si nous faisons la même chose avec Core Animation (en utilisant une CABasicAnimation et en appliquant l'animation au calque de la vue), la mise en page ne se produit pas et tout fonctionne correctement:

CABasicAnimation* ba = [CABasicAnimation animationWithKeyPath:@"transform"];
ba.autoreverses = YES;
ba.duration = 0.3;
ba.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.1, 1.1, 1)];
[v.layer addAnimation:ba forKey:nil];
356
matt

J'avais une Isuue similaire et venais d'entendre De retour de l'équipe Autolayout chez Apple. Ils suggèrent d'utiliser l'approche vue conteneur matt suggère, mais ils créent une sous-classe de UIView pour écraser layoutSubviews et appliquer un code de mise en page personnalisé à cet endroit. Il fonctionne comme un charme.

Le fichier d'en-tête ressemble à cela afin que vous puissiez lier la sous-vue de votre choix directement à partir d'Interface Builder.

#import <UIKit/UIKit.h>

@interface BugFixContainerView : UIView
@property(nonatomic,strong) IBOutlet UIImageView *knobImageView;
@end

et le fichier m applique le code spécial comme celui-ci:

#import "BugFixContainerView.h"

@implementation BugFixContainerView
- (void)layoutSubviews
{
    static CGPoint fixCenter = {0};
    [super layoutSubviews];
    if (CGPointEqualToPoint(fixCenter, CGPointZero)) {
        fixCenter = [self.knobImageView center];
    } else {
        self.knobImageView.center = fixCenter;
    }
}
@end

Comme vous pouvez le constater, il saisit le point central de la vue lors de son premier appel et réutilise cette position lors d'appels ultérieurs afin de placer la vue en conséquence. Ceci écrase le code Autolayout en ce sens qu'il a lieu après [super layoutSubviews]; qui contient le code autolayout.

De cette manière, il n'est plus nécessaire d'éviter Autolayout, mais vous pouvez créer votre propre autolayout lorsque les comportements par défaut ne sont plus appropriés. Bien sûr, vous pouvez appliquer des choses bien plus compliquées que ce qui est dans cet exemple, mais c'était tout ce dont j'avais besoin puisque mon application ne peut utiliser que le mode Portrait.

40
sensslen

Je trouve un moyen simple. Et cela fonctionne sur iOS 8 et iOS 9.

Par exemple, ajustez anchorPoint lorsque vous utilisez une disposition basée sur des cadres:

let oldFrame = layerView.frame
layerView.layer.anchorPoint = newAnchorPoint
layerView.frame = oldFrame

Lorsque vous ajustez l'ancrage de la vue avec la disposition automatique, vous procédez de la même manière, mais de manière contraignante. Lorsque anchorPoint change de (0.5, 0.5) à (1, 0.5), le layerView se déplace vers la gauche avec une distance égale à la moitié de la largeur de la vue. Vous devez donc compenser cela.

Je ne comprends pas la contrainte dans la question.Alors, supposons que vous ajoutiez une contrainte centerX relative à superView centerX avec une constante: layerView.centerX = superView.centerX + constant

layerView.layer.anchorPoint = CGPoint(1, 0.5)
let centerXConstraint = .....
centerXConstraint.constant = centerXConstraint.constant + layerView.bounds.size.width/2
7
seedante

Si vous utilisez la disposition automatique, je ne vois pas comment définir manuellement la position servira à long terme, car la disposition automatique finira par obstruer la valeur de position que vous avez définie lors du calcul de sa propre disposition.

Au lieu de cela, il est nécessaire de modifier les contraintes de présentation elles-mêmes pour compenser les changements produits en définissant le anchorPoint. La fonction suivante le fait pour les vues non transformées.

/**
  Set the anchorPoint of view without changing is perceived position.

 @param view view whose anchorPoint we will mutate
 @param anchorPoint new anchorPoint of the view in unit coords (e.g., {0.5,1.0})
 @param xConstraint an NSLayoutConstraint whose constant property adjust's view x.center
 @param yConstraint an NSLayoutConstraint whose constant property adjust's view y.center

  As multiple constraints can contribute to determining a view's center, the user of this
 function must specify which constraint they want modified in order to compensate for the
 modification in anchorPoint
 */
void SetViewAnchorPointMotionlesslyUpdatingConstraints(UIView * view,CGPoint anchorPoint,
                                                       NSLayoutConstraint * xConstraint,
                                                       NSLayoutConstraint * yConstraint)
{
  // assert: old and new anchorPoint are in view's unit coords
  CGPoint const oldAnchorPoint = view.layer.anchorPoint;
  CGPoint const newAnchorPoint = anchorPoint;

  // Calculate anchorPoints in view's absolute coords
  CGPoint const oldPoint = CGPointMake(view.bounds.size.width * oldAnchorPoint.x,
                                 view.bounds.size.height * oldAnchorPoint.y);
  CGPoint const newPoint = CGPointMake(view.bounds.size.width * newAnchorPoint.x,
                                 view.bounds.size.height * newAnchorPoint.y);

  // Calculate the delta between the anchorPoints
  CGPoint const delta = CGPointMake(newPoint.x-oldPoint.x, newPoint.y-oldPoint.y);

  // get the x & y constraints constants which were contributing to the current
  // view's position, and whose constant properties we will Tweak to adjust its position
  CGFloat const oldXConstraintConstant = xConstraint.constant;
  CGFloat const oldYConstraintConstant = yConstraint.constant;

  // calculate new values for the x & y constraints, from the delta in anchorPoint
  // when autolayout recalculates the layout from the modified constraints,
  // it will set a new view.center that compensates for the affect of the anchorPoint
  CGFloat const newXConstraintConstant = oldXConstraintConstant + delta.x;
  CGFloat const newYConstraintConstant = oldYConstraintConstant + delta.y;

  view.layer.anchorPoint = newAnchorPoint;
  xConstraint.constant = newXConstraintConstant;
  yConstraint.constant = newYConstraintConstant;
  [view setNeedsLayout];
}

J'admets que ce n'est probablement pas tout ce que vous espériez, car habituellement, la seule raison pour laquelle vous souhaitez modifier le point d'ancrage est de définir une transformation. Cela nécessiterait une fonction plus complexe qui met à jour les contraintes de présentation pour refléter tout les modifications de trame pouvant être causées par la propriété de transformation elle-même. C'est délicat car les transformations peuvent faire beaucoup pour le cadre. Une transformation de mise à l'échelle ou de rotation rendrait le cadre plus grand, nous aurions donc besoin de mettre à jour les contraintes de largeur ou de hauteur, etc.

Si vous utilisez uniquement la transformation pour une animation temporaire, ce qui est présenté ci-dessus peut suffire, car je ne crois pas que la disposition automatique empêchera l'animation en vol de présenter des images représentant des violations purement transitoires des contraintes.

3
algal

tl: dr: Vous pouvez créer une sortie pour l'une des contraintes afin qu'elle puisse être supprimée et rajoutée.


J'ai créé un nouveau projet et ajouté une vue avec une taille fixe au centre. Les contraintes sont montrées dans l'image ci-dessous.

The constraints for the smallest example I could think of.

Ensuite, j'ai ajouté un point de vente pour la vue en rotation et pour la contrainte d'alignement centre x.

@property (weak, nonatomic) IBOutlet UIView *rotatingView;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *xAlignmentContstraint;

Plus tard dans viewDidAppear je calcule le nouveau point d'ancrage

UIView *view = self.rotatingView;

CGPoint rotationPoint = // The point I'm rotating around... (only X differs)
CGPoint anchorPoint = CGPointMake((rotationPoint.x-CGRectGetMinX(view.frame))/CGRectGetWidth(view.frame),
                                  (rotationPoint.y-CGRectGetMinY(view.frame))/CGRectGetHeight(view.bounds));

CGFloat xCenterDifference = rotationPoint.x-CGRectGetMidX(view.frame);

view.layer.anchorPoint = anchorPoint;

Ensuite, je supprime la contrainte pour laquelle je dispose d’un exutoire, en crée un nouveau qui est décalé et le rajoute à nouveau. Après cela, je dis à la vue avec la contrainte modifiée qu'elle doit mettre à jour les contraintes.

[self.view removeConstraint:self.xAlignmentContstraint];
self.xAlignmentContstraint = [NSLayoutConstraint constraintWithItem:self.rotatingView
                                                          attribute:NSLayoutAttributeCenterX
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:self.view
                                                          attribute:NSLayoutAttributeCenterX
                                                         multiplier:1.0
                                                           constant:xDiff];
[self.view addConstraint:self.xAlignmentContstraint];
[self.view needsUpdateConstraints];

Enfin, je viens d'ajouter l'animation de rotation à la vue en rotation.

CABasicAnimation *rotate = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotate.toValue = @(-M_PI_2);
rotate.autoreverses = YES;
rotate.repeatCount = INFINITY;
rotate.duration = 1.0;
rotate.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 

[view.layer addAnimation:rotate forKey:@"myRotationAnimation"];

La couche en rotation donne l’impression qu’elle reste centrée (ce qui devrait être le cas) même lors de la rotation de l’appareil ou lors de la mise à jour des contraintes. La nouvelle contrainte et le point d'ancrage modifié s'annulent visuellement.

3
David Rönnqvist

Inspiré par la réponse de mon matt, j'ai décidé d'essayer une approche différente. Une vue de conteneur, avec des contraintes appliquées de manière appropriée, peut être utilisée. La vue avec le point d'ancrage modifié peut ensuite être placée dans la vue du conteneur, à l'aide de masques à redimensionnement automatique et d'un paramètre de cadre explicite, comme à l'ancienne.

Cela fonctionne un régal, pour ma situation de toute façon. Les vues sont configurées ici dans viewDidLoad:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    UIView *redView = [UIView new];
    redView.translatesAutoresizingMaskIntoConstraints = NO;
    redView.backgroundColor = [UIColor redColor];
    [self.view addSubview:redView];

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-[redView]-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(redView)]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[redView]-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(redView)]];
    self.redView = redView;

    UIView *greenView = [UIView new];
    greenView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    greenView.layer.anchorPoint = CGPointMake(1.0, 0.5);
    greenView.frame = redView.bounds;
    greenView.backgroundColor = [UIColor greenColor];
    [redView addSubview:greenView];
    self.greenView = greenView;

    CATransform3D perspective = CATransform3DIdentity;
    perspective.m34 = 0.005;
    self.redView.layer.sublayerTransform = perspective;
}

Peu importe que les images de la vue rouge soient nulles à ce stade, à cause du masque de redimensionnement automatique de la vue verte.

J'ai ajouté une transformation de rotation sur une méthode d'action et voici le résultat:

enter image description here

Il a semblé se perdre lors de la rotation du périphérique, alors j'ai ajouté ceci à la méthode viewDidLayoutSubviews:

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    CATransform3D transform = self.greenView.layer.transform;
    self.greenView.layer.transform = CATransform3DIdentity;
    self.greenView.frame = self.redView.bounds;
    self.greenView.layer.transform = transform;
    [CATransaction commit];

}
1
jrturton

Ma solution actuelle consiste à ajuster manuellement la position du calque dans viewDidLayoutSubviews. Ce code pourrait également être utilisé dans layoutSubviews pour une sous-classe de vue, mais dans mon cas, ma vue est une vue de niveau supérieur dans un contrôleur de vue, ce qui signifie que je n'ai pas à créer de sous-classe UIView.

Cela semble être trop d'efforts, alors les autres réponses sont les bienvenues.

-(void)viewDidLayoutSubviews
{
    for (UIView *view in self.view.subviews)
    {
        CGPoint anchorPoint = view.layer.anchorPoint;
        // We're only interested in views with a non-standard anchor point
        if (!CGPointEqualToPoint(CGPointMake(0.5, 0.5),anchorPoint))
        {
            CGFloat xDifference = anchorPoint.x - 0.5;
            CGFloat yDifference = anchorPoint.y - 0.5;
            CGPoint currentPosition = view.layer.position;

            // Use transforms if we can, otherwise manually calculate the frame change
            // Assuming a transform is in use since we are changing the anchor point. 
            if (CATransform3DIsAffine(view.layer.transform))
            {
                CGAffineTransform current = CATransform3DGetAffineTransform(view.layer.transform);
                CGAffineTransform invert = CGAffineTransformInvert(current);
                currentPosition = CGPointApplyAffineTransform(currentPosition, invert);
                currentPosition.x += (view.bounds.size.width * xDifference);
                currentPosition.y += (view.bounds.size.height * yDifference);
                currentPosition = CGPointApplyAffineTransform(currentPosition, current);
            }
            else
            {
                CGFloat transformXRatio = view.bounds.size.width / view.frame.size.width;

                if (xDifference < 0)
                    transformXRatio = 1.0/transformXRatio;

                CGFloat transformYRatio = view.bounds.size.height / view.frame.size.height;
                if (yDifference < 0)
                    transformYRatio = 1.0/transformYRatio;

                currentPosition.x += (view.bounds.size.width * xDifference) * transformXRatio;
                currentPosition.y += (view.bounds.size.height * yDifference) * transformYRatio;
            }
            view.layer.position = currentPosition;
        }

    }
}
1
jrturton

Je pense que vous niez le but de l'autolayout avec cette méthode. Vous avez mentionné que la largeur et le bord exact dépendent de la vue d'ensemble, alors pourquoi ne pas simplement ajouter des contraintes dans cette ligne de pensée?

Perdez le paradigme anchorPoint/transform et essayez:

[self.view addConstraint:
[NSLayoutConstraint constraintWithItem:layerView
                             attribute:NSLayoutAttributeRight
                             relatedBy:NSLayoutRelationEqual 
                                toItem:self.view 
                             attribute:NSLayoutAttributeWidth 
                            multiplier:1.0f
                              constant:-somePadding]];
[self.view addConstraint:
[NSLayoutConstraint constraintWithItem:layerView
                             attribute:NSLayoutAttributeWidth
                             relatedBy:NSLayoutRelationEqual 
                                toItem:someViewWeDependTheWidthOn
                             attribute:NSLayoutAttributeWidth 
                            multiplier:0.5f // because you want it to be half of someViewWeDependTheWidthOn
                              constant:-20.0f]]; // your 20pt offset from the left

La contrainte NSLayoutAttributeRight signifie exactement comme anchorPoint = CGPointMake(1.0, 0.5), et la contrainte NSLayoutAttributeWidth est à peu près équivalente à celle de votre code précédent NSLayoutAttributeLeft.

0
John Estropia

C'est un sujet important et je n'ai pas lu tous les commentaires, mais je faisais face au même problème.

J'ai eu une vue de XIB avec autolayout. Et je voulais mettre à jour sa propriété de transformation. Intégrer la vue dans une vue conteneur ne résout pas mon problème, car l'autolayout agissait bizarrement sur la vue conteneur. C'est pourquoi j'ai simplement ajouté une deuxième vue de conteneur pour contenir la vue de conteneur qui contient ma vue et qui lui appliquait des transformations.

0
plamkata__

Cette question et ses réponses m'ont incité à résoudre mes propres problèmes avec Autolayout et la mise à l'échelle, mais avec des vues de défilement. J'ai créé un exemple de ma solution sur github:

https://github.com/hansdesmedt/AutoLayout-scrollview-scale

Ceci est un exemple de UIScrollView avec une pagination personnalisée entièrement réalisée avec AutoLayout. Elle est évolutive (CATransform3DMakeScale) lorsque vous appuyez longuement dessus et appuyez sur pour zoomer. Compatible iOS 6 et 7.

0
Hans

tl; dr Disons que vous avez changé le point d'ancrage en (0, 0). Le point d'ancrage est maintenant en haut à gauche. Chaque fois que vous voyez le mot centre dans la mise en page automatique, vous devriez penser en haut à gauche.

Lorsque vous ajustez anchorPoint, vous modifiez simplement la sémantique de la mise en forme automatique. La mise en page automatique n'interférera pas avec votre point d'ancrage, ni inversement. Si vous ne comprenez pas cela, vous allez passer un mauvais moment .


Exemple:

Figure A. Aucune modification du point d'ancrage

#Before changing anchor point to top-left
view.size == superview.size
view.center == superview.center

Figure B. Point d'ancrage changé en haut à gauche

view.layer.anchorPoint = CGPointMake(0, 0)
view.size == superview.size
view.center == superview.topLeft                <----- L0-0K, center is now top-left

Les figures A et B ont exactement le même aspect. Rien n'a changé. Juste la définition de quoi centre fait référence à changé.

0
seo