如何为图层 shadowOpacity 设置动画?
Posted
技术标签:
【中文标题】如何为图层 shadowOpacity 设置动画?【英文标题】:How to animate layer shadowOpacity? 【发布时间】:2011-05-29 00:05:10 【问题描述】:我有一个视图,我已将 layerOpacity 设置为 1。
theView.layer.shadowOpacity = 1.0;
当视图位于屏幕下方时,这看起来不错。当我将此视图向上移动以与另一个有阴影的视图齐平时,它们看起来不太好。有没有办法可以将我图层上的shadowOpacity
设置为 0?我尝试使用动画块,但似乎这个属性是不可动画的。
编辑:请求无效的代码:
[UIView animateWithDuration:1.0 animations:^
splitView2.layer.shadowOpacity = 0;
completion:NULL];
【问题讨论】:
来自 Apple 的文档:“@property float shadowOpacity
指定接收者阴影的不透明度。Animatable。”你能发布一些不起作用的代码吗?
在 UIView animateWithDuration 中不起作用
@JoeBlow:正确,这就是我写我发布的代码不起作用的原因。您必须直接使用 Core Animation,因为 UIView
没有为它提供隐式动画。
嗨,须藤!为了清楚起见,请注意@Costique 的评论:我正在回复该评论。干杯!感谢您提出这个方便的问题,它在下面得到了很好的答案。
【参考方案1】:
这将正常工作:
#import <QuartzCore/CAAnimation.h>
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"shadowOpacity"];
anim.fromValue = [NSNumber numberWithFloat:1.0];
anim.toValue = [NSNumber numberWithFloat:0.0];
anim.duration = 1.0;
[vv.layer addAnimation:anim forKey:@"shadowOpacity"];
vv.layer.shadowOpacity = 0.0;
对于 Swift 3.0:
let animation = CABasicAnimation(keyPath: "shadowOpacity")
animation.fromValue = layer.shadowOpacity
animation.toValue = 0.0
animation.duration = 1.0
view.layer.add(animation, forKey: animation.keyPath)
view.layer.shadowOpacity = 0.0
【讨论】:
如果没有设置 vv.layer.shadowOpacity = 0.0;在最后一行,动画将完成,但之后它会跳回旧层 如果你想打开而不是关闭阴影,这两部分很重要:anim.removedOnCompletion = NO; anim.fillMode = kCAFillModeForwards;
@moby 感谢您的评论。这是让这个答案发挥作用的关键。
可以用anim.removeOnCompletion
应该去哪里更新代码sn-p吗?
重要提示:在 ios 模拟器中启用“调试 > 慢动画”时,通过此方法实现的动画可能不会以降低的速度运行。这个让我在杂草丛生了很长一段时间。具体来说,我认为我的动画设置不正确,因为我的自定义视图转换运行速度降低,但我的 CABasic 动画全速运行。【参考方案2】:
我把上面的代码放在了 UIView 的一个小扩展中:
extension UIView
func animateLayer<Value>(_ keyPath: WritableKeyPath<CALayer, Value>, to value:Value, duration: CFTimeInterval)
let keyString = NSExpression(forKeyPath: keyPath).keyPath
let animation = CABasicAnimation(keyPath: keyString)
animation.fromValue = self.layer[keyPath: keyPath]
animation.toValue = value
animation.duration = duration
self.layer.add(animation, forKey: animation.keyPath)
var thelayer = layer
thelayer[keyPath: keyPath] = value
用法如下:
animateLayer(\.shadowOffset, to: CGSize(width: 3, height: 3), duration:1)
animateLayer(\.shadowOpacity, to: 0.4, duration: 1)
它没有经过彻底的测试。但为我工作。 (也发帖here)
【讨论】:
【参考方案3】:下面的代码对我有用
1)添加QuartzCore框架 2)导入QuartzCore框架
在需要的地方添加如下代码
UIImageView * glowimageview = [[[UIImageView alloc]init]autorelease];
[glowimageview setFrame:CGRectMake(500,400,200,200)];
[glowimageview setImage:[UIImage imageNamed:@"144.png"]];
[sender addSubview:glowimageview];
glowimageview.layer.shadowColor = [UIColor redColor].CGColor;
glowimageview.layer.shadowRadius = 10.0f;
glowimageview.layer.shadowOpacity = 1.0f;
glowimageview.layer.shadowOffset = CGSizeZero;
CABasicAnimation *shadowAnimation = [CABasicAnimation animationWithKeyPath:@"shadowOpacity"];
shadowAnimation.duration=1.0;
shadowAnimation.repeatCount=HUGE_VALF;
shadowAnimation.autoreverses=YES;
shadowAnimation.fromValue = [NSNumber numberWithFloat:1.0];
shadowAnimation.toValue = [NSNumber numberWithFloat:0.0];
[glowimageview.layer addAnimation:shadowAnimation forKey:@"shadowOpacity"];
它会起作用的。根据您的要求更改代码的格式
【讨论】:
【参考方案4】:这是一个材料设计,类似于上面的一些动画 它也可以通过 Carthage https://github.com/sevenapps/SVNMaterialButton 以框架形式在此处使用
public init(frame: CGRect, color: UIColor)
super.init(frame: frame)
self.backgroundColor = color
self.layer.masksToBounds = false
self.layer.borderWidth = 1.0
self.layer.shadowColor = UIColor.black.cgColor
self.layer.shadowOpacity = 0.8
self.layer.shadowRadius = 8
self.layer.shadowOffset = CGSize(width: 8.0, height: 8.0)
required public init?(coder aDecoder: NSCoder)
fatalError("This class is not set up to be instaciated with coder use init(frame) instead")
public override func layoutSubviews()
super.layoutSubviews()
self.layer.cornerRadius = self.frame.height / 4
public override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
self.animate(to: 0.5, and: CGSize(width: 5.0, height: 5.0), with: 0.5)
super.touchesBegan(touches, with: event)
public override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?)
self.animate(to: 0.8, and: CGSize(width: 8.0, height: 8.0), with: 0.5)
super.touchesBegan(touches, with: event)
private func animate(to opacity: Double, and offset: CGSize, with duration: Double)
CATransaction.begin()
let opacityAnimation = CABasicAnimation(keyPath: "shadowOpacity")
opacityAnimation.toValue = opacity
opacityAnimation.duration = duration
opacityAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
opacityAnimation.fillMode = kCAFillModeBoth
opacityAnimation.isRemovedOnCompletion = false
let offsetAnimation = CABasicAnimation(keyPath: "shadowOffset")
offsetAnimation.toValue = offset
offsetAnimation.duration = duration
offsetAnimation.timingFunction = opacityAnimation.timingFunction
offsetAnimation.fillMode = opacityAnimation.fillMode
offsetAnimation.isRemovedOnCompletion = false
self.layer.add(offsetAnimation, forKey: offsetAnimation.keyPath!)
self.layer.add(opacityAnimation, forKey: opacityAnimation.keyPath!)
CATransaction.commit()
【讨论】:
以上是关于如何为图层 shadowOpacity 设置动画?的主要内容,如果未能解决你的问题,请参考以下文章