如何在UIView下绘制阴影?

我试图在cocoa触摸UIView的底部边缘下绘制阴影。 我明白我应该使用CGContextSetShadow()来绘制阴影,但Quartz 2D编程指南有点含糊:

  1. 保存graphics状态。
  2. 调用函数CGContextSetShadow ,传递适当的值。
  3. 执行所有您想要应用阴影的绘图。
  4. 恢复graphics状态

我已经在UIView子类中尝试了以下内容:

 - (void)drawRect:(CGRect)rect { CGContextRef currentContext = UIGraphicsGetCurrentContext(); CGContextSaveGState(currentContext); CGContextSetShadow(currentContext, CGSizeMake(-15, 20), 5); CGContextRestoreGState(currentContext); [super drawRect: rect]; } 

..但这不适用于我,我有点卡住(a)下一步去哪里和(b)如果有什么我需要做我的UIView做这个工作?

在当前代码中,保存当前上下文的GState ,并将其configuration为绘制阴影。并将其恢复为将其configuration为绘制阴影之前的状态。 然后,最后,调用超类的drawRect :的实现。

任何应该受到阴影设置影响的graphics都需要在发生之后发生

 CGContextSetShadow(currentContext, CGSizeMake(-15, 20), 5); 

之前

 CGContextRestoreGState(currentContext); 

所以如果你想要超类的drawRect:被“包装”在一个阴影中,那么如果你重新排列你的代码是这样的呢?

 - (void)drawRect:(CGRect)rect { CGContextRef currentContext = UIGraphicsGetCurrentContext(); CGContextSaveGState(currentContext); CGContextSetShadow(currentContext, CGSizeMake(-15, 20), 5); [super drawRect: rect]; CGContextRestoreGState(currentContext); } 

更简单的方法是在初始化时设置视图的一些图层属性:

 self.layer.masksToBounds = NO; self.layer.shadowOffset = CGSizeMake(-15, 20); self.layer.shadowRadius = 5; self.layer.shadowOpacity = 0.5; 

你需要导入QuartzCore。

 #import <QuartzCore/QuartzCore.h> 
 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; 

这会减慢应用程序的速度。 只要您的视图是可见的矩形,添加以下行可以提高性能:

 self.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.bounds].CGPath; 

同样的解决scheme,但只是提醒你:你可以直接在故事板中定义阴影。

例如:

在这里输入图像说明

你可以试试这个….你可以玩的价值观。 shadowRadius指示模糊量。 shadowOffset决定阴影的位置。

Swift 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

 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 

示例与传播

示例与传播

创造一个基本的影子

  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 

基本的影子例子在Swift 2.0中

OUTPUT

使用Interface Builder的简单而干净的解决scheme

在您的项目中添加一个名为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 } } } 

然后,在“工具”面板的“属性检查器”中的“界面生成器”中,

实用程序面板

你现在可以很容易地设置阴影。

笔记:
– 只有在运行时才会出现阴影。
– 正如Mazen Kasser所说

对于那些没有得到这个工作,以确保剪辑子视图( clipsToBounds )未启用

我使用这个作为我的工具的一部分。 有了这个,我们不仅可以设置阴影,而且可以为任何UIView获得一个圆angular。 你也可以设置你喜欢的颜色阴影。 通常黑色是首选,但有时,当背景是非白色的,你可能需要别的东西。 这是我使用的 –

 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; } 

要使用这个,我们需要调用这个 – [utils roundedLayer:yourview.layer radius:5.0f shadow:YES];

Swift 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 } } 

对于那些在尝试所有答案之后无​​法正常工作的人(就像我自己一样),只要确保“ 剪辑子视图”在“属性”检查器中未启用…

Swift 3

 self.paddingView.layer.masksToBounds = false self.paddingView.layer.shadowOffset = CGSize(width: -15, height: 10) self.paddingView.layer.shadowRadius = 5 self.paddingView.layer.shadowOpacity = 0.5 

您可以使用我为阴影和angular半径创build的效用函数,如下所示:

 - (void)addShadowWithRadius:(CGFloat)shadowRadius withShadowOpacity:(CGFloat)shadowOpacity withShadowOffset:(CGSize)shadowOffset withShadowColor:(UIColor *)shadowColor withCornerRadius:(CGFloat)cornerRadius withBorderColor:(UIColor *)borderColor withBorderWidth:(CGFloat)borderWidth forView:(UIView *)view{ // drop shadow [view.layer setShadowRadius:shadowRadius]; [view.layer setShadowOpacity:shadowOpacity]; [view.layer setShadowOffset:shadowOffset]; [view.layer setShadowColor:shadowColor.CGColor]; // border radius [view.layer setCornerRadius:cornerRadius]; // border [view.layer setBorderColor:borderColor.CGColor]; [view.layer setBorderWidth:borderWidth]; } 

希望它会帮助你!

所有答案都很好,但我想补充一点

如果您在使用表格单元格时遇到问题,则使新单元格出现阴影不匹配的情况,因此在这种情况下,需要将阴影代码放在layoutSubviews方法中,以便在所有情况下都能很好地运行。

 -(void)layoutSubviews{ [super layoutSubviews]; [self.contentView setNeedsLayout]; [self.contentView layoutIfNeeded]; [VPShadow applyShadowView:self]; } 

或者在ViewControllers中为特定的视图放置下面的方法中的影子代码,以便它工作正常

 -(void)viewDidLayoutSubviews{ [super viewDidLayoutSubviews]; [self.viewShadow layoutIfNeeded]; [VPShadow applyShadowView:self.viewShadow]; } 

我已经修改了我的新的开发人员的影子执行更广义的forms例如:

 /*! @brief Add shadow to a view. @param layer CALayer of the view. */ +(void)applyShadowOnView:(CALayer *)layer OffsetX:(CGFloat)x OffsetY:(CGFloat)y blur:(CGFloat)radius opacity:(CGFloat)alpha RoundingCorners:(CGFloat)cornerRadius{ UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRoundedRect:layer.bounds cornerRadius:cornerRadius]; layer.masksToBounds = NO; layer.shadowColor = [UIColor blackColor].CGColor; layer.shadowOffset = CGSizeMake(x,y);// shadow x and y layer.shadowOpacity = alpha; layer.shadowRadius = radius;// blur effect layer.shadowPath = shadowPath.CGPath; }