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.clipsToBounds
ON 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 clipsToBounds
ON the shadows are clipped also.
这似乎让我很难在图层中添加阴影,因为当我打开时clipsToBounds
,阴影也被剪裁了。
I have been trying to manipulate view.frame
and view.bounds
in 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 clipsToBounds
OFF as shown)
这是我用来添加阴影的代码(这只适用于clipsToBounds
OFF,如图所示)
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 clipsToBounds
is OFF.
这是应用于最浅灰色层的阴影的屏幕截图。希望这可以让我了解如果clipsToBounds
关闭,我的内容将如何重叠。
How can I add a shadow to my UIView
and 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 UIBezierPath
used as shadowPath
is 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 clipToBounds
property 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
我不知道为什么如果共享实例它会变得更快,我猜它会缓存阴影的渲染并且可以将它重用于视图中的其他实例。我想知道这是否更快