ios 向我的 UIView 添加阴影的最佳方法是什么
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9761189/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What's the best way to add a drop shadow to my UIView
提问by Wez
I am trying to add a drop shadow to views that are layered on top of one another, the views collapse allowing content in other views to be seen, in this vein i want to keep view.clipsToBoundsON so that when the views collapse their content is clipped.
我正在尝试为相互叠加的视图添加阴影,视图折叠允许看到其他视图中的内容,在这种情况下,我想保持view.clipsToBounds打开状态,以便在视图折叠时它们的内容被剪裁。
This seems to have made it difficult for me to add a drop shadow to the layers as when i turn clipsToBoundsON the shadows are clipped also.
这似乎让我很难在图层中添加阴影,因为当我打开时clipsToBounds,阴影也被剪裁了。
I have been trying to manipulate view.frameand view.boundsin order to add a drop shadow to the frame but allow the bounds to be large enough to encompass it, however I have had no luck with this.
我一直在试图操纵view.frame和view.bounds以阴影添加到框架,但允许的范围要大到足以涵盖它,但是我有这个没有运气。
Here is the code I am using to add a Shadow (this only works with clipsToBoundsOFF as shown)
这是我用来添加阴影的代码(这只适用于clipsToBoundsOFF,如图所示)
view.clipsToBounds = NO;
view.layer.shadowColor = [[UIColor blackColor] CGColor];
view.layer.shadowOffset = CGSizeMake(0,5);
view.layer.shadowOpacity = 0.5;
Here is a screenshot of the shadow being applied to the top lightest grey layer. Hopefully this gives an idea of how my content will overlap if clipsToBoundsis OFF.
这是应用于最浅灰色层的阴影的屏幕截图。希望这可以让我了解如果clipsToBounds关闭,我的内容将如何重叠。


How can I add a shadow to my UIViewand keep my content clipped?
如何为UIView我的内容添加阴影并保持剪切?
Edit: Just wanted to add that I have also played around with using background images with shadows on, which does work well, however I would still like to know the best coded solution for this.
编辑:只是想补充一点,我也使用过带阴影的背景图像,效果很好,但是我仍然想知道最好的编码解决方案。
回答by pkluz
Try this:
尝试这个:
UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRect:view.bounds];
view.layer.masksToBounds = NO;
view.layer.shadowColor = [UIColor blackColor].CGColor;
view.layer.shadowOffset = CGSizeMake(0.0f, 5.0f);
view.layer.shadowOpacity = 0.5f;
view.layer.shadowPath = shadowPath.CGPath;
First of all: The UIBezierPathused as shadowPathis crucial. If you don't use it, you might not notice a difference at first, but the keen eye will observe a certain lag occurring during events like rotating the device and/or similar. It's an important performance tweak.
首先:UIBezierPath使用的 asshadowPath至关重要。如果您不使用它,一开始您可能不会注意到差异,但敏锐的眼睛会观察到在旋转设备和/或类似事件期间发生的一定滞后。这是一个重要的性能调整。
Regarding your issue specifically: The important line is view.layer.masksToBounds = NO. It disables the clipping of the view's layer's sublayersthat extend further than the view's bounds.
关于您的具体问题:重要的一点是view.layer.masksToBounds = NO。它禁用了超出视图边界的视图层子层的裁剪。
For those wondering what the difference between masksToBounds(on the layer) and the view's own clipToBoundsproperty is: There isn't really any. Toggling one will have an effect on the other. Just a different level of abstraction.
对于那些想知道masksToBounds(在图层上)和视图自己的clipToBounds属性之间有什么区别的人:实际上没有任何区别。切换一个会对另一个产生影响。只是抽象层次不同。
Swift 2.2:
斯威夫特 2.2:
override func layoutSubviews()
{
super.layoutSubviews()
let shadowPath = UIBezierPath(rect: bounds)
layer.masksToBounds = false
layer.shadowColor = UIColor.blackColor().CGColor
layer.shadowOffset = CGSizeMake(0.0, 5.0)
layer.shadowOpacity = 0.5
layer.shadowPath = shadowPath.CGPath
}
Swift 3:
斯威夫特 3:
override func layoutSubviews()
{
super.layoutSubviews()
let shadowPath = UIBezierPath(rect: bounds)
layer.masksToBounds = false
layer.shadowColor = UIColor.black.cgColor
layer.shadowOffset = CGSize(width: 0.0, height: 5.0)
layer.shadowOpacity = 0.5
layer.shadowPath = shadowPath.cgPath
}
回答by Bart van Kuik
Wasabii's answer in Swift 2.3:
Wasabii 在 Swift 2.3 中的回答:
let shadowPath = UIBezierPath(rect: view.bounds)
view.layer.masksToBounds = false
view.layer.shadowColor = UIColor.blackColor().CGColor
view.layer.shadowOffset = CGSize(width: 0, height: 0.5)
view.layer.shadowOpacity = 0.2
view.layer.shadowPath = shadowPath.CGPath
And in Swift 3/4/5:
在 Swift 3/4/5 中:
let shadowPath = UIBezierPath(rect: view.bounds)
view.layer.masksToBounds = false
view.layer.shadowColor = UIColor.black.cgColor
view.layer.shadowOffset = CGSize(width: 0, height: 0.5)
view.layer.shadowOpacity = 0.2
view.layer.shadowPath = shadowPath.cgPath
Put this code in layoutSubviews() if you're using AutoLayout.
如果您使用 AutoLayout,请将此代码放在 layoutSubviews() 中。
In SwiftUI, this is all much easier:
在 SwiftUI 中,这一切都容易得多:
Color.yellow // or whatever your view
.shadow(radius: 3)
.frame(width: 200, height: 100)
回答by sergio
回答by Chris Stillwell
You can create an extension for UIView to access these values in the design editor
您可以为 UIView 创建扩展以在设计编辑器中访问这些值
extension UIView{
@IBInspectable var shadowOffset: CGSize{
get{
return self.layer.shadowOffset
}
set{
self.layer.shadowOffset = newValue
}
}
@IBInspectable var shadowColor: UIColor{
get{
return UIColor(cgColor: self.layer.shadowColor!)
}
set{
self.layer.shadowColor = newValue.cgColor
}
}
@IBInspectable var shadowRadius: CGFloat{
get{
return self.layer.shadowRadius
}
set{
self.layer.shadowRadius = newValue
}
}
@IBInspectable var shadowOpacity: Float{
get{
return self.layer.shadowOpacity
}
set{
self.layer.shadowOpacity = newValue
}
}
}
回答by A.G
On viewWillLayoutSubviews:
在 viewWillLayoutSubviews 上:
override func viewWillLayoutSubviews() {
sampleView.layer.masksToBounds = false
sampleView.layer.shadowColor = UIColor.darkGrayColor().CGColor;
sampleView.layer.shadowOffset = CGSizeMake(2.0, 2.0)
sampleView.layer.shadowOpacity = 1.0
}
Using Extension of UIView:
使用 UIView 的扩展:
extension UIView {
func addDropShadowToView(targetView:UIView? ){
targetView!.layer.masksToBounds = false
targetView!.layer.shadowColor = UIColor.darkGrayColor().CGColor;
targetView!.layer.shadowOffset = CGSizeMake(2.0, 2.0)
targetView!.layer.shadowOpacity = 1.0
}
}
Usage:
用法:
sampleView.addDropShadowToView(sampleView)
回答by Rufus Mall
So yes, you should prefer the shadowPath property for performance, but also: From the header file of CALayer.shadowPath
所以是的,您应该更喜欢 shadowPath 属性以提高性能,而且:来自 CALayer.shadowPath 的头文件
Specifying the path explicitly using this property will usually * improve rendering performance, as will sharing the same path * reference across multiple layers
使用此属性显式指定路径通常会 * 提高渲染性能,因为将共享相同的路径 * 跨多个层引用
A lesser known trick is sharing the same reference across multiple layers. Of course they have to use the same shape, but this is common with table/collection view cells.
一个鲜为人知的技巧是跨多个层共享相同的参考。当然,它们必须使用相同的形状,但这在表格/集合视图单元格中很常见。
I don't know why it gets faster if you share instances, i'm guessing it caches the rendering of the shadow and can reuse it for other instances in the view. I wonder if this is even faster with
我不知道为什么如果共享实例它会变得更快,我猜它会缓存阴影的渲染并且可以将它重用于视图中的其他实例。我想知道这是否更快

