我试图在Cocoa Touch的UIView的底部边缘下画一个阴影。我知道我应该使用CGContextSetShadow()来绘制阴影,但Quartz 2D编程指南有点模糊:

保存图形状态。 调用CGContextSetShadow函数,传递适当的值。 执行要应用阴影的所有绘图。 恢复图形状态

我已经尝试了以下在一个UIView子类:

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

..但是这对我来说不工作,我有点卡住了(a)下一步要去哪里(b)如果我需要对我的UIView做什么来让这个工作?


当前回答

斯威夫特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
    }
}

其他回答

如果你想使用StoryBoard并且不想一直输入运行时属性,你可以很容易地为视图创建一个扩展,并使它们在StoryBoard中可用。

步骤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
    }
}
}

步骤2。您现在可以在故事板中使用这些属性

对于那些没能让这个工作的人(就像我自己一样!),在尝试了所有的答案后,只要确保剪辑子视图没有在属性检查器中启用…

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

任何应该受到阴影设置影响的绘图都需要在之后进行

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

简单和干净的解决方案使用接口生成器

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

然后,这将在接口生成器中为实用工具面板>属性检查器中的每个视图可用:

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

注: 影子不会在IB中出现,只在运行时出现。 -正如Mazen Kasser所说

对于那些未能实现这一目标的人……确保剪辑子视图(clipsToBounds)未启用

斯威夫特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