2014-02-21 3 views
23

я устанавливаю границы ширину и цвет к UIView подкласса таким образом:Animate CALayer изменение границы

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

Мой вопрос: Как я могу оживить это? Благодарю.

+0

Что вы хотите анимировать ? Пограничный облик? Или вращение? –

+0

@ValentinShamardin окантовка вид. Тот же эффект, что и анимация смены кадров. –

ответ

51

И , и 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"]; 

Если посмотреть на the documentation for CABasicAnimation в разделе «Установка значения интерполяции», вы увидите, что это не нужно указывать как toValue и fromValue, как я сделал, так что код может быть немного короче. Тем не менее, для ясности и удобочитаемости (особенно, когда вы начинаете с Core Animation), более явные могут помочь вам (и вашему коллеге) понять код.

+0

«поскольку вы делаете это в подклассе вида вне блока анимации UIView, неявные анимации (те, которые происходят автоматически при изменении значения) отключены». Является ли это документированным где угодно? Я обнаружил, что много отключил действия на уровне слоев, не знал об этом. – jrturton

+0

@jrturton Вид является делегатом слоя и возвращает 'NSNull' для' actionForLayer: forKey: ', когда вы находитесь вне блока анимации. Весь процесс несколько задокументирован в обсуждении «actionForKey:» на CALayer. Я посмотрю, смогу ли я найти лучшую ссылку для делегирования. –

+0

@jrturton В документах для свойства 'layer' на UIView вы можете прочитать, что представление является делегатом и что вы не должны изменять делегат. –

0

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

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

Если вы собираетесь использовать removeOnCompletion = NO в ответе, то вы обязаны OP, чтобы объяснить последствия. –

+1

Кроме того, * почему * вы используете анимацию ключевого кадра с двумя значениями. Это совсем не очевидно, когда вы читаете код и не нужны сложные. –

14

Вот быстрое решение для @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") 
+1

Вы имели в виду self.view.layer.borderColor вместо 'backgroundColor'? –

+1

Вы должны использовать '#keyPath (CALayer.borderColor)' вместо '" borderColor "'. То же самое с шириной ... –

0

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

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

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

}, completion: nil) 
Смежные вопросы