[英]fade between two UIButton images
i want to fade between two UIButton images for the purpose of setting favorites in a UITableView. 我想在两个UIButton图像之间淡入淡出,以便在UITableView中设置收藏夹。
Currently the transition is done without effect - it just changes the images directly on click/touch: 目前转换没有效果 - 它只是在点击/触摸时直接更改图像:
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];
Everything I found was a transition between UIViews :( 我发现的一切都是UIViews之间的过渡:(
It would be nice if the image fav_off gets smoothly changed into fav_on and the other way round like a fadein/fadeout. 如果图像fav_off平滑地变成fav_on而另一种方式像fadein / fadeout那样圆形会很好。
It seems like what you're looking for is this. 看起来你正在寻找的就是这个。 It animates the images on a UIButton without adding new images, creating an array or changing alpha values!
它可以动画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];
Here in swift: 在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"))
Thank you to @jkanter for the great answer. 感谢@jkanter的最佳答案。 I made mine into a Swift 3.0 extension that I thought might also be useful for anyone who stumbles upon this post.
我把我变成了一个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)
}
}
You could try to transition the alpha values like this to get the effect that you want: 你可以尝试转换像这样的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;
}];
}];
This is a slight improvement to @Ponja's answer that generally works well. 这是@Ponja的答案略有改进,通常效果很好。 Unfortunately, the newImage doesn't "stick", so if you wanted to toggle between two images, the first fade would work smoothly, but going back to the original image would "snap" back with no fade.
不幸的是,newImage并没有“坚持”,所以如果你想在两个图像之间切换,第一个淡入淡出会顺利工作,但回到原始图像会“快速”回退而不会出现淡入淡出。 Fixed it by using a CATransaction:
通过使用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's answer with tintColor added: @ 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()
}
}
@SuperDuperTango's answer in Swift 4.2: @ 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()
}
}
jkanter answer in Swift : 在Swift中的 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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.