Подтвердить что ты не робот

Анимировать изменение границы CALayer

Я устанавливаю ширину и цвет border в подкласс UIView следующим образом:

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

Мой вопрос: Как я могу оживить это? Спасибо.

4b9b3361

Ответ 1

Оба borderColor и borderWidth являются анимированными свойствами, но поскольку вы делаете это в подклассе вида вне блока анимации UIView, неявные анимации (те, которые происходят автоматически при изменении значения) отключены.

Если вы хотите анимировать эти свойства, вы можете сделать явную анимацию с помощью CABasicAnimation. Поскольку вы анималируете два свойства на одном уровне, вы можете добавить их как в группу анимации, так и только один раз настроить продолжительность, время и т.д. Обратите внимание, что явные анимации являются чисто визуальными, значение модели (фактическое свойство) не изменяется при их добавлении. Вот почему вы оба настраиваете анимацию и устанавливаете значение модели.

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"];

Если вы посмотрите документацию для CABasicAnimation в разделе "Настройка значений интерполяции", вы увидите, что нет необходимости указывать как toValue, так и fromValue, например Я сделал, поэтому код можно сделать немного короче. Однако для ясности и удобочитаемости (особенно, когда вы начинаете с Core Animation), более явные могут помочь вам (и вашему коллеге) понять код.

Ответ 2

Здесь быстрое решение для ответа @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")

Ответ 3

Вы можете создать анимацию ключевого кадра, добавив ее в свой вид.

//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];

Ответ 4

Если вы хотите просто исчезнуть на границе, вы также можете сделать это:

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

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

}, completion: nil)