web-dev-qa-db-fra.com

Animer le changement de bordure de CALayer

Je fixe une largeur et une couleur border à une sous-classe UIView de cette façon:

- (void) setViewBorder
{
    self.layer.borderColor = [UIColor greenColor].CGColor;
    self.layer.borderWidth = 3.0f;
}

Ma question est: Comment puis-je animer cela? Merci.

31
iOS Dev

borderColor et borderWidth sont des propriétés animables mais comme vous le faites dans une sous-classe de vue en dehors d'un bloc d'animation UIView, les animations implicites (celles qui se produisent automatiquement lorsque vous modifiez une valeur) sont désactivées.

Si vous souhaitez animer ces propriétés, vous pouvez faire une animation explicite avec un CABasicAnimation. Puisque vous animez deux propriétés sur le même calque, vous pouvez les ajouter à la fois à un groupe d'animation et ne configurer la durée, le timing, etc. qu'une seule fois. Notez que les animations explicites sont purement visuelles, la valeur du modèle (la propriété réelle) ne change pas lorsque vous les ajoutez. C'est pourquoi vous configurez à la fois l'animation et définissez la valeur du modèle.

CABasicAnimation *color = [CABasicAnimation animationWithKeyPath:@"borderColor"];
// animate from red to blue border ...
color.fromValue = (id)[UIColor redColor].CGColor;
color.toValue   = (id)[UIColor blueColor].CGColor;
// ... and change the model value
self.layer.borderColor = [UIColor blueColor].CGColor;

CABasicAnimation *width = [CABasicAnimation animationWithKeyPath:@"borderWidth"];
// animate from 2pt to 4pt wide border ...
width.fromValue = @2;
width.toValue   = @4;
// ... and change the model value
self.layer.borderWidth = 4;

CAAnimationGroup *both = [CAAnimationGroup animation];
// animate both as a group with the duration of 0.5 seconds
both.duration   = 0.5;
both.animations = @[color, width];
// optionally add other configuration (that applies to both animations)
both.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

[self.layer addAnimation:both forKey:@"color and width"];

Si vous regardez la documentation de CABasicAnimation dans la section "Définition des valeurs d'interpolation", vous verrez qu'il n'est pas nécessaire de spécifier à la fois la toValue et la fromValue comme je l'ai fait, donc le code pourrait être légèrement modifié plus court. Cependant, pour plus de clarté et de lisibilité (en particulier lorsque vous commencez avec Core Animation), être plus explicite peut vous aider (ainsi que votre collègue) à comprendre le code.

56
David Rönnqvist

Voici une solution Swift pour la réponse @David:

let colorAnimation = CABasicAnimation(keyPath: "borderColor")
colorAnimation.fromValue = UIColor.red.cgColor
colorAnimation.toValue = UIColor.blue.cgColor
view.layer.borderColor = UIColor.blue.cgColor

let widthAnimation = CABasicAnimation(keyPath: "borderWidth")
widthAnimation.fromValue = 2
widthAnimation.toValue = 4
widthAnimation.duration = 4
view.layer.borderWidth = 4

let bothAnimations = CAAnimationGroup()
bothAnimations.duration = 0.5
bothAnimations.animations = [colorAnimation, widthAnimation]
bothAnimations.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)

view.layer.add(bothAnimations, forKey: "color and width")
22
Meseery

Si vous souhaitez simplement estomper la bordure, vous pouvez également le faire:

UIView.transition(with: self, duration: 0.3, options: .transitionCrossDissolve, animations: {

        self.layer.borderColor = UIColor.green.cgColor
        self.layer.borderWidth = 3

}, completion: nil)
9
inf1783

Vous pouvez créer une animation d'images clés, l'ajouter à votre vue.

//Create animation
        CAKeyframeAnimation *colorsAnimation = [CAKeyframeAnimation animationWithKeyPath:@"borderColor"];
        colorsAnimation.values = [NSArray arrayWithObjects: (id)[UIColor greenColor].CGColor,
                                  (id)[UIColor yellowColor].CGColor, nil];
        colorsAnimation.keyTimes = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.25],[NSNumber numberWithFloat:1.0], nil];
        colorsAnimation.calculationMode = kCAAnimationLinear;
        colorsAnimation.removedOnCompletion = NO;
        colorsAnimation.fillMode = kCAFillModeForwards;
        colorsAnimation.duration = 3.0f;

    //Create animation
    CAKeyframeAnimation *sizeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"borderWidth"];
    sizeAnimation.values = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0],
                             [NSNumber numberWithFloat:5.0], nil];
    sizeAnimation.keyTimes = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0],[NSNumber numberWithFloat:3.0], nil];
    sizeAnimation.calculationMode = kCAAnimationLinear;
    sizeAnimation.removedOnCompletion = NO;
    sizeAnimation.fillMode = kCAFillModeForwards;
    sizeAnimation.duration = 3.0f;

    //Add animation
    [yoursubview.layer   addAnimation:colorsAnimation forKey:nil];
    [yoursubview.layer   addAnimation:sizeAnimation forKey:nil];
2
CoolMonster