2013-05-28 6 views
9

Я хочу исчезать между двумя изображениями UIButton с целью настройки избранных в UITableView.исчезают между двумя изображениями UIButton

В настоящее время переход осуществляется без эффекта - это просто изменяет изображения непосредственно на клик/контакт:

trans_img = [UIImage imageNamed:@"fav_on.png"]; 

NSArray *subviews = [owningCell subviews]; 
UIButton *favbutton = [subviews objectAtIndex:2]; 

favbutton.imageView.animationImages = 
[NSArray arrayWithObjects:trans_img, 
nil]; 

[favbutton.imageView startAnimating]; 

Все, что я нашел был переход между UIViews :(

Было бы неплохо, если бы image fav_off получает плавное изменение в fav_on и наоборот, как fadein/fadeout.

ответ

2

Вы можете попробовать перевести значения alpha так, чтобы получить эффект, который вы хотите:

trans_img = [UIImage imageNamed:@"fav_on.png"]; 

NSArray *subviews = [owningCell subviews]; 
UIButton *favbutton = [subviews objectAtIndex:2]; 
[UIView animateWithDuration:0.5 animations:^{ 
    favbutton.alpha = 0.0f; 
} completion:^(BOOL finished) { 
    favbutton.imageView.animationImages = [NSArray arrayWithObjects:trans_img,nil]; 
    [favbutton.imageView startAnimating]; 
    [UIView animateWithDuration:0.5 animations:^{ 
     favbutton.alpha = 1.0f; 
    }]; 
}]; 
+0

это просто удивительно :) – user1069822

+0

Это работает, но я не понимаю, почему. Не могли бы вы объяснить вторую часть с анимацией? –

31

Кажется, что вы ищите именно это. Он анимирует изображения на UIButton без добавления новых изображений, создания массива или изменения альфа-значений!

CABasicAnimation *crossFade = [CABasicAnimation animationWithKeyPath:@"contents"]; 
crossFade.duration = 0.7; 
crossFade.fromValue = (id)oldImage.CGImage; 
crossFade.toValue = (id)newImage.CGImage; 
crossFade.removedOnCompletion = NO; 
crossFade.fillMode = kCAFillModeForwards; 
[button.imageView.layer addAnimation:crossFade forKey:@"animateContents"]; 

//Make sure to add Image normally after so when the animation 
//is done it is set to the new Image 
[button setImage:newImage forState:UIControlStateNormal]; 
+1

Спасибо за мини-урок по использованию Core Animation! – phatmann

+2

Из любопытства, почему вы решили установить 'removedOnCompletion' в' NO'? – ravron

+3

@RileyAvron Что это значит - убедитесь, что анимация не вернется в конце. По правде говоря, я не уверен, что это на 100% необходимо для этого, потому что мы все равно устанавливаем newImage как образ кнопки ... но я обычно всегда добавляю его там, чтобы быть в безопасности – jkanter

6

Здесь в стрижа:

import UIKit 

    extension UIButton { 

     func changeImageAnimated(image: UIImage?) { 
      guard let imageView = self.imageView, currentImage = imageView.image, newImage = image else { 
       return 
      } 
      let crossFade: CABasicAnimation = CABasicAnimation(keyPath: "contents") 
      crossFade.duration = 0.3 
      crossFade.fromValue = currentImage.CGImage 
      crossFade.toValue = newImage.CGImage 
      crossFade.removedOnCompletion = false 
      crossFade.fillMode = kCAFillModeForwards 
      imageView.layer.addAnimation(crossFade, forKey: "animateContents") 
     } 
    } 


    self.playAndPauseVideo.changeImageAnimated(UIImage(named: "pauseVideo")) 
+1

отлично! благодаря! одно замечание: я добавил последнюю строку в func self.setImage (newImage, для: .normal). Это необходимо для второго нажатия на кнопку –

3

Это небольшое улучшение @ ответ Ponja, что в целом работает хорошо. К сожалению, newImage не «прилипает», поэтому, если вы хотите переключиться между двумя изображениями, первое затухание будет работать гладко, но возврат к исходному изображению «привяжется» назад без угасания. Фиксированный его с помощью CATransaction:

import UIKit 

extension UIButton { 
    func changeImageAnimated(image: UIImage?) { 
     guard let imageView = self.imageView, currentImage = imageView.image, newImage = image else { 
      return 
     } 
     CATransaction.begin() 
     CATransaction.setCompletionBlock { 
      self.setImage(newImage, forState: UIControlState.Normal) 
     } 
     let crossFade: CABasicAnimation = CABasicAnimation(keyPath: "contents") 
     crossFade.duration = 0.3 
     crossFade.fromValue = currentImage.CGImage 
     crossFade.toValue = newImage.CGImage 
     crossFade.removedOnCompletion = false 
     crossFade.fillMode = kCAFillModeForwards 
     imageView.layer.addAnimation(crossFade, forKey: "animateContents") 
     CATransaction.commit() 
    } 
} 
+0

Это работает очень хорошо, но у меня есть tintColor, и это превращает его в черный. Вы знаете, как я могу поддерживать текущий tintColor? – Morgan

+0

Я закончил тем, что добавил еще один CABasicAnimation отдельно для цвета, который, похоже, выполняет эту работу. – Morgan

1

@ ответ SuperDuperTango с tintColor добавил:

extension UIButton { 
    func changeImageAnimated(image: UIImage?) { 
     guard let imageView = self.imageView, currentImage = imageView.image, newImage = image else { 
      return 
     } 
     CATransaction.begin() 
     CATransaction.setCompletionBlock { 
      self.setImage(newImage, forState: UIControlState.Normal) 
     } 
     let crossFade: CABasicAnimation = CABasicAnimation(keyPath: "contents") 
     crossFade.duration = 0.3 
     crossFade.fromValue = currentImage.CGImage 
     crossFade.toValue = newImage.CGImage 
     crossFade.removedOnCompletion = false 
     crossFade.fillMode = kCAFillModeForwards 
     imageView.layer.addAnimation(crossFade, forKey: "animateContents") 
     CATransaction.commit() 

     let crossFadeColor: CABasicAnimation = CABasicAnimation(keyPath: "contents") 
     crossFadeColor.duration = 0.3 
     crossFadeColor.fromValue = UIColor.blackColor() 
     crossFadeColor.toValue = UIColor(red: 232.0/255.0, green: 85.0/255.0, blue: 71.0/255.0, alpha: 1.0) 
     crossFadeColor.removedOnCompletion = false 
     crossFadeColor.fillMode = kCAFillModeForwards 
     imageView.layer.addAnimation(crossFadeColor, forKey: "animateContents") 
     CATransaction.commit() 
    } 
} 
4

Спасибо @jkanter за большой ответ. Я сделал мое расширение Swift 3.0, которое, как я думал, также может быть полезно для всех, кто наткнулся на этот пост.

extension UIButton { 

    func setImage(_ image: UIImage?, for state: UIControlState, animated: Bool) { 
     guard animated, let oldImage = imageView?.image, let newImage = image else { 
      // Revert to default functionality 
      setImage(image, for: state) 
      return 
     } 

     let crossFade = CABasicAnimation(keyPath:"contents") 
     crossFade.duration = 0.35 
     crossFade.fromValue = oldImage.cgImage 
     crossFade.toValue = newImage.cgImage 
     crossFade.isRemovedOnCompletion = false 
     imageView?.layer.add(crossFade, forKey: "animateContents") 

     setImage(image, for: state) 
    } 
} 
-1

jkanter ответ в Swift:

let crossFade = CABasicAnimation.init(keyPath: "contents") 
crossFade.duration = 0.7 
crossFade.fromValue = oldImage.cgImage 
crossFade.toValue = newImage.cgImage 
crossFade.isRemovedOnCompletion = false 
crossFade.fillMode = kCAFillModeForwards 
button.imageView?.layer.add(crossFade, forKey: "animateContents") 

//Make sure to add Image normally after so when the animation 
//is done it is set to the new Image 
button.setImage(newImage, for: .normal) 
+0

Почему downvote? Я в порядке, но, пожалуйста, не стесняйтесь упоминать причину. – Hemang

Смежные вопросы