我想在两个UIButton图像之间淡入淡出,以便在UITableView中设置收藏夹。
目前转换没有效果 - 它只是在点击/触摸时直接更改图像:
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而另一种方式像fadein / fadeout那样圆形会很好。
答案 0 :(得分:31)
看起来你正在寻找的就是这个。它可以动画UIButton上的图像,而无需添加新图像,创建数组或更改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];
答案 1 :(得分:6)
这里有swift:
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"))
答案 2 :(得分:5)
感谢@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)
}
}
答案 3 :(得分: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()
}
}
答案 4 :(得分: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;
}];
}];
答案 5 :(得分: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()
}
}
答案 6 :(得分:0)
@SuperDuperTango在Swift 4.2中的答案:
extension UIButton {
func changeImageAnimated(image: UIImage?) {
guard let imageView = self.imageView, let currentImage = imageView.image, let newImage = image else { return }
CATransaction.begin()
CATransaction.setCompletionBlock {
self.setImage(newImage, for: .normal)
}
let crossFade: CABasicAnimation = CABasicAnimation(keyPath: "contents")
crossFade.duration = 0.3
crossFade.fromValue = currentImage.cgImage
crossFade.toValue = newImage.cgImage
crossFade.isRemovedOnCompletion = false
crossFade.fillMode = CAMediaTimingFillMode.forwards
imageView.layer.add(crossFade, forKey: "animateContents")
CATransaction.commit()
}
}
答案 7 :(得分:-1)
jkanter 回答:
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)