[英]How to animate the shadow border of an UIView at the same time its content grows
I am working on a project which has all views embedded in a view container like this:我正在开发一个将所有视图嵌入到视图容器中的项目,如下所示:
Today, I have to make one of these containers grow vertically in a animatable way when a stack view is showing its arranged subviews.今天,当堆栈视图显示其排列的子视图时,我必须使其中一个容器以动画方式垂直增长。 So, the first problem was that the shadow border of this container is not being animated and I realized that the shadow path should be animated in another way and not just in a UIView.animate block.
所以,第一个问题是这个容器的阴影边框没有动画,我意识到阴影路径应该以另一种方式动画,而不仅仅是在 UIView.animate 块中。
I have isolated the problem in a small project:我在一个小项目中隔离了这个问题:
As you can see, I am trying to deploy/undeploy the container view depending on the inner stackview arranged subviews.如您所见,我正在尝试根据内部堆栈视图排列的子视图来部署/取消部署容器视图。 The problem is the shadow path, which I am already trying to understand how it works.
问题是阴影路径,我已经在尝试了解它是如何工作的。
Can you help me to understand how to manage a UIView shadow layer when you need to update the height of an UIView in an animation block?当您需要更新 animation 块中 UIView 的高度时,您能帮我了解如何管理 UIView 阴影层吗?
Container Shadow view code:容器阴影视图代码:
import UIKit
@IBDesignable final class ShadowView: UIView {
@IBInspectable var cornerRadius: CGFloat = 0.0 {
didSet {
setNeedsLayout()
}
}
@IBInspectable var shadowColor: UIColor = UIColor.darkGray {
didSet {
setNeedsLayout()
}
}
@IBInspectable var shadowOffsetWidth: CGFloat = 0.0 {
didSet {
setNeedsLayout()
}
}
@IBInspectable var shadowOffsetHeight: CGFloat = 1.8 {
didSet {
setNeedsLayout()
}
}
@IBInspectable var shadowOpacity: Float = 0.30 {
didSet {
setNeedsLayout()
}
}
@IBInspectable var shadowRadius: CGFloat = 3.0 {
didSet {
setNeedsLayout()
}
}
@IBInspectable var isAnimatable: Bool = false
private var shadowLayer: CAShapeLayer = CAShapeLayer() {
didSet {
setNeedsLayout()
}
}
private var previousPat: CGPath = CGPath(rect: CGRect(x: 0, y: 0, width: 0, height: 0), transform: .none)
override func layoutSubviews() {
super.layoutSubviews()
layer.cornerRadius = cornerRadius
shadowLayer.path = UIBezierPath(roundedRect: bounds,
cornerRadius: cornerRadius).cgPath
shadowLayer.fillColor = backgroundColor?.cgColor
shadowLayer.shadowColor = shadowColor.cgColor
shadowLayer.shadowPath = shadowLayer.path
shadowLayer.shadowOffset = CGSize(width: shadowOffsetWidth,
height: shadowOffsetHeight)
shadowLayer.shadowOpacity = shadowOpacity
shadowLayer.shadowRadius = shadowRadius
if isAnimatable {
let animation = CABasicAnimation(keyPath: "shadowPath")
animation.fromValue = previousPat
animation.toValue = shadowLayer.path
animation.autoreverses = false
animation.duration = 0.8
shadowLayer.add(animation, forKey: "pathAnimation")
}
layer.insertSublayer(shadowLayer, at: 0)
previousPat = shadowLayer.path!
}
}
Main ViewController code:主视图控制器代码:
final class ViewController: UIViewController {
@IBOutlet weak var stack: UIStackView!
@IBOutlet weak var redContainerLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func animateAction(_ sender: Any) {
UIView.animate(withDuration: 0.8) {
self.redContainerLabel.alpha = self.redContainerLabel.alpha == 0 ? 1 : 0
self.stack.arrangedSubviews.forEach {
$0.isHidden.toggle()
}
}
}
}
I was looking for an answer to exactly this problem and encountered this post here, which I believe is what you're looking for:我一直在寻找这个问题的答案,并在这里遇到了这篇文章,我相信这就是你要找的:
Animating CALayer shadow simultaneously as UITableviewCell height animates 在 UITableviewCell 高度动画的同时动画 CALayer 阴影
The solution is a bit verbose (I'm surprised the use-case is so rare as to not prompt apple to fix(?) it) and a few years old at this point, but the most recent I could find.解决方案有点冗长(我很惊讶用例如此罕见以至于没有提示苹果修复(?)它)并且在这一点上已经有几年了,但我能找到最新的。 Ultimately I decided to work around it by fading out my shadows before resizing, but you might find it useful!
最终我决定通过在调整大小之前淡出我的阴影来解决它,但你可能会发现它很有用!
A couple of other, older posts I've found appear to corroborated the level of effort required for this effect (again, Apple's got a weird list of things it decides are your problem), so that first post is probably your best bet.我发现的其他一些较旧的帖子似乎证实了这种效果所需的努力程度(同样,Apple 有一个奇怪的列表,它认为是你的问题),所以第一篇文章可能是你最好的选择。
https://petosoft.wordpress.com/2012/10/24/shadowpath-not-animating-with-standard-uiview-animations-on-ipad/ https://petosoft.wordpress.com/2012/10/24/shadowpath-not-animating-with-standard-uiview-animations-on-ipad/
Smoothly rotate and change size of UIView with shadow 平滑地旋转和改变 UIView 的大小与阴影
UIView: How to animate CALayer frame with shadow? UIView:如何使用阴影为 CALayer 框架设置动画?
If you've managed to find a more straightforward solution, by all means let me know;如果您设法找到更直接的解决方案,请务必告诉我; in the mean-time I hope this helps.
同时,我希望这会有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.