ios 如何在 UIView 下绘制阴影?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/805872/
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
How do I draw a shadow under a UIView?
提问by Fraser Speirs
I'm trying to draw a shadow under the bottom edge of a UIView
in Cocoa Touch. I understand that I should use CGContextSetShadow()
to draw the shadow, but the Quartz 2D programming guide is a little vague:
我正在尝试UIView
在 Cocoa Touch的底部边缘绘制阴影。我明白我应该CGContextSetShadow()
用来绘制阴影,但是Quartz 2D编程指南有点模糊:
- Save the graphics state.
- Call the function
CGContextSetShadow
, passing the appropriate values. - Perform all the drawing to which you want to apply shadows.
- Restore the graphics state
- 保存图形状态。
- 调用函数
CGContextSetShadow
,传递适当的值。 - 执行所有要应用阴影的绘图。
- 恢复图形状态
I've tried the following in a UIView
subclass:
我在UIView
子类中尝试了以下内容:
- (void)drawRect:(CGRect)rect {
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSaveGState(currentContext);
CGContextSetShadow(currentContext, CGSizeMake(-15, 20), 5);
CGContextRestoreGState(currentContext);
[super drawRect: rect];
}
..but this doesn't work for me and I'm a bit stuck about (a) where to go next and (b) if there's anything I need to do to my UIView
to make this work?
..但这对我不起作用,而且我对 (a) 下一步要去哪里以及 (b) 是否需要对我做些什么UIView
来使这项工作有所困扰?
采纳答案by Christian Brunschen
In your current code, you save the GState
of the current context, configure it to draw a shadow .. and the restore it to what it was before you configured it to draw a shadow. Then, finally, you invoke the superclass's implementation of drawRect
: .
在您当前的代码中,您保存GState
当前上下文的 ,将其配置为绘制阴影 .. 并将其恢复到配置为绘制阴影之前的状态。然后,最后,您调用超类的 : 实现drawRect
。
Any drawing that should be affected by the shadow setting needs to happen after
任何应该受阴影设置影响的绘图都需要在
CGContextSetShadow(currentContext, CGSizeMake(-15, 20), 5);
but before
但之前
CGContextRestoreGState(currentContext);
So if you want the superclass's drawRect:
to be 'wrapped' in a shadow, then how about if you rearrange your code like this?
因此,如果您希望超类drawRect:
被“包裹”在阴影中,那么如果您像这样重新排列代码呢?
- (void)drawRect:(CGRect)rect {
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSaveGState(currentContext);
CGContextSetShadow(currentContext, CGSizeMake(-15, 20), 5);
[super drawRect: rect];
CGContextRestoreGState(currentContext);
}
回答by ollie
A by far easier approach is to set some layer attributes of the view on initialization:
一个更简单的方法是在初始化时设置视图的一些层属性:
self.layer.masksToBounds = NO;
self.layer.shadowOffset = CGSizeMake(-15, 20);
self.layer.shadowRadius = 5;
self.layer.shadowOpacity = 0.5;
You need to import QuartzCore.
您需要导入 QuartzCore。
#import <QuartzCore/QuartzCore.h>
回答by ZYiOS
self.layer.masksToBounds = NO;
self.layer.cornerRadius = 8; // if you like rounded corners
self.layer.shadowOffset = CGSizeMake(-15, 20);
self.layer.shadowRadius = 5;
self.layer.shadowOpacity = 0.5;
This will slow down the application. Adding the following line can improve performance as long as your view is visibly rectangular:
这会减慢应用程序的速度。只要您的视图是可见的矩形,添加以下行可以提高性能:
self.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.bounds].CGPath;
回答by Antzi
Same solution, but just to remind you: You can define the shadow directly in the storyboard.
相同的解决方案,但只是提醒您:您可以直接在故事板中定义阴影。
Ex:
前任:
回答by O-mkar
You can try this .... you can play with the values.
The shadowRadius
dictates the amount of blur. shadowOffset
dictates where the shadow goes.
你可以试试这个....你可以玩这些值。该shadowRadius
使然模糊量。shadowOffset
决定了阴影的去向。
Swift 2.0
斯威夫特 2.0
let radius: CGFloat = demoView.frame.width / 2.0 //change it to .height if you need spread for height
let shadowPath = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 2.1 * radius, height: demoView.frame.height))
//Change 2.1 to amount of spread you need and for height replace the code for height
demoView.layer.cornerRadius = 2
demoView.layer.shadowColor = UIColor.blackColor().CGColor
demoView.layer.shadowOffset = CGSize(width: 0.5, height: 0.4) //Here you control x and y
demoView.layer.shadowOpacity = 0.5
demoView.layer.shadowRadius = 5.0 //Here your control your blur
demoView.layer.masksToBounds = false
demoView.layer.shadowPath = shadowPath.CGPath
Swift 3.0
斯威夫特 3.0
let radius: CGFloat = demoView.frame.width / 2.0 //change it to .height if you need spread for height
let shadowPath = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 2.1 * radius, height: demoView.frame.height))
//Change 2.1 to amount of spread you need and for height replace the code for height
demoView.layer.cornerRadius = 2
demoView.layer.shadowColor = UIColor.black.cgColor
demoView.layer.shadowOffset = CGSize(width: 0.5, height: 0.4) //Here you control x and y
demoView.layer.shadowOpacity = 0.5
demoView.layer.shadowRadius = 5.0 //Here your control your blur
demoView.layer.masksToBounds = false
demoView.layer.shadowPath = shadowPath.cgPath
Example with spread
传播示例
To create a basic shadow
创建基本阴影
demoView.layer.cornerRadius = 2
demoView.layer.shadowColor = UIColor.blackColor().CGColor
demoView.layer.shadowOffset = CGSizeMake(0.5, 4.0); //Here your control your spread
demoView.layer.shadowOpacity = 0.5
demoView.layer.shadowRadius = 5.0 //Here your control your blur
Basic Shadow example in Swift 2.0
Swift 2.0 中的基本阴影示例
回答by Axel Guilmin
Simple and clean solution using Interface Builder
使用 Interface Builder 的简单干净的解决方案
Add a file named UIView.swift in your project (or just paste this in any file) :
在您的项目中添加一个名为 UIView.swift 的文件(或将其粘贴到任何文件中):
import UIKit
@IBDesignable extension UIView {
/* The color of the shadow. Defaults to opaque black. Colors created
* from patterns are currently NOT supported. Animatable. */
@IBInspectable var shadowColor: UIColor? {
set {
layer.shadowColor = newValue!.CGColor
}
get {
if let color = layer.shadowColor {
return UIColor(CGColor:color)
}
else {
return nil
}
}
}
/* The opacity of the shadow. Defaults to 0. Specifying a value outside the
* [0,1] range will give undefined results. Animatable. */
@IBInspectable var shadowOpacity: Float {
set {
layer.shadowOpacity = newValue
}
get {
return layer.shadowOpacity
}
}
/* The shadow offset. Defaults to (0, -3). Animatable. */
@IBInspectable var shadowOffset: CGPoint {
set {
layer.shadowOffset = CGSize(width: newValue.x, height: newValue.y)
}
get {
return CGPoint(x: layer.shadowOffset.width, y:layer.shadowOffset.height)
}
}
/* The blur radius used to create the shadow. Defaults to 3. Animatable. */
@IBInspectable var shadowRadius: CGFloat {
set {
layer.shadowRadius = newValue
}
get {
return layer.shadowRadius
}
}
}
Then this will be available in Interface Builder for every view in the Utilities Panel > Attributes Inspector :
然后这将在 Interface Builder 中为 Utilities Panel > Attributes Inspector 中的每个视图提供:
You can easily set the shadow now.
您现在可以轻松设置阴影。
Notes:
- The shadow won't appear in IB, only at runtime.
- As Mazen Kasser said
注意:
- 阴影不会出现在 IB 中,仅在运行时出现。
- 正如 Mazen Kasser 所说
To those who failed in getting this to work [...] make sure Clip Subviews (
clipsToBounds
) is not enabled
对于那些未能使其工作的人 [...] 确保
clipsToBounds
未启用Clip Subviews ( )
回答by Srikar Appalaraju
I use this as part of my utils. With this we can not only set shadow but also can get a rounded corner for any UIView
. Also you could set what color shadow you prefer. Normally black is preferred but sometimes, when the background is non-white you might want something else. Here's what I use -
我将它用作我的实用程序的一部分。有了这个,我们不仅可以设置阴影,还可以为任何UIView
. 您也可以设置您喜欢的颜色阴影。通常首选黑色,但有时,当背景为非白色时,您可能需要其他颜色。这是我使用的 -
in utils.m
+ (void)roundedLayer:(CALayer *)viewLayer
radius:(float)r
shadow:(BOOL)s
{
[viewLayer setMasksToBounds:YES];
[viewLayer setCornerRadius:r];
[viewLayer setBorderColor:[RGB(180, 180, 180) CGColor]];
[viewLayer setBorderWidth:1.0f];
if(s)
{
[viewLayer setShadowColor:[RGB(0, 0, 0) CGColor]];
[viewLayer setShadowOffset:CGSizeMake(0, 0)];
[viewLayer setShadowOpacity:1];
[viewLayer setShadowRadius:2.0];
}
return;
}
To use this we need to call this - [utils roundedLayer:yourview.layer radius:5.0f shadow:YES];
要使用它,我们需要调用它 - [utils roundedLayer:yourview.layer radius:5.0f shadow:YES];
回答by neoneye
Swift 3
斯威夫特 3
extension UIView {
func installShadow() {
layer.cornerRadius = 2
layer.masksToBounds = false
layer.shadowColor = UIColor.black.cgColor
layer.shadowOffset = CGSize(width: 0, height: 1)
layer.shadowOpacity = 0.45
layer.shadowPath = UIBezierPath(rect: bounds).cgPath
layer.shadowRadius = 1.0
}
}
回答by king_T
If you would like to use StoryBoard and wouldnt like to keep typing in runtime attributes, you can easily create an extension to views and make them usable in storyboard.
如果您想使用 StoryBoard 并且不想继续输入运行时属性,您可以轻松创建视图的扩展并使它们在故事板中可用。
Step 1. create extension
步骤 1. 创建扩展
extension UIView {
@IBInspectable var shadowRadius: CGFloat {
get {
return layer.shadowRadius
}
set {
layer.shadowRadius = newValue
}
}
@IBInspectable var shadowOpacity: Float {
get {
return layer.shadowOpacity
}
set {
layer.shadowOpacity = newValue
}
}
@IBInspectable var shadowOffset: CGSize {
get {
return layer.shadowOffset
}
set {
layer.shadowOffset = newValue
}
}
@IBInspectable var maskToBound: Bool {
get {
return layer.masksToBounds
}
set {
layer.masksToBounds = newValue
}
}
}
回答by Mazen Kasser
To those who failed in getting this to work (As myself!) after trying all the answers here, just make sure Clip Subviewsis not enabled at the Attributes inspector...
对于在尝试了所有答案后未能使其正常工作的人(作为我自己!),只需确保在属性检查器中未启用剪辑子视图...