在两个UIButton图像之间淡入淡出

我想在两个UIButton图像之间淡入淡出,以便在UITableView中设置collections夹。

目前,转换完成无效 – 它只是点击/触摸直接更改图像:

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 🙁

如果图像fav_off平滑地转换为fav_on,反之亦然,就像淡入淡出一样。

你可以尝试像这样转换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; }]; }]; 

看来你正在寻找的是这个。 它animationUIButton上的图像,而不添加新的图像,创build一个数组或更改alpha值!

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

在这里迅速:

  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")) 

感谢@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) } } 

这对@ 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() } } 

@ 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() } } 

jkanterSwift中回答:

 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)