将内部阴影添加到UIView的顶部

时间:2016-06-07 01:00:54

标签: ios swift uiview shadow

我抬起头但是我无法找到如何为UIView添加内部阴影,只为Swift添加顶部(从上到下)。在Swift中添加内圈的最佳方法是什么?

编辑:我发现了一些问题&然而,他们要么是obj-c,要么看起来如此复杂。如果有任何

,我只是想找一个更加Swifty的方式

我想要实现的目标:

enter image description here

7 个答案:

答案 0 :(得分:21)

这是我提出的一个纯粹的Swift版本:

public class EdgeShadowLayer: CAGradientLayer {

    public enum Edge {
        case Top
        case Left
        case Bottom
        case Right
    }

    public init(forView view: UIView,
                edge: Edge = Edge.Top,
                shadowRadius radius: CGFloat = 20.0,
                toColor: UIColor = UIColor.white,
                fromColor: UIColor = UIColor.black) {
        super.init()
        self.colors = [fromColor.cgColor, toColor.cgColor]
        self.shadowRadius = radius

        let viewFrame = view.frame

        switch edge {
            case .Top:
                startPoint = CGPoint(x: 0.5, y: 0.0)
                endPoint = CGPoint(x: 0.5, y: 1.0)
                self.frame = CGRect(x: 0.0, y: 0.0, width: viewFrame.width, height: shadowRadius)
            case .Bottom:
                startPoint = CGPoint(x: 0.5, y: 1.0)
                endPoint = CGPoint(x: 0.5, y: 0.0)
                self.frame = CGRect(x: 0.0, y: viewFrame.height - shadowRadius, width: viewFrame.width, height: shadowRadius)
            case .Left:
                startPoint = CGPoint(x: 0.0, y: 0.5)
                endPoint = CGPoint(x: 1.0, y: 0.5)
                self.frame = CGRect(x: 0.0, y: 0.0, width: shadowRadius, height: viewFrame.height)
            case .Right:
                startPoint = CGPoint(x: 1.0, y: 0.5)
                endPoint = CGPoint(x: 0.0, y: 0.5)
                self.frame = CGRect(x: viewFrame.width - shadowRadius, y: 0.0, width: shadowRadius, height: viewFrame.height)
        }
    }

    required public init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }   
}

要使用它,

let topShadow = EdgeShadowLayer(forView: targetView, edge: .Top)
targetView.layer.addSublayer(topShadow)

请注意,它默认为黑色至白色渐变,深度为20点。

可以在https://github.com/jrtibbetts/Tenebrae找到包含示例UIViewController的完整代码,该示例可让您在视图的所有四个角上切换阴影。我还非常详细地记录了EdgeShadowLayer

答案 1 :(得分:14)

我使用Objective-C将实现内部阴影用于UIView。我尝试将代码翻译成swift。请原谅我糟糕的快速语法

您可以在UIView.didMoveToSuperview

中调用以下功能
func drawShadow() {
    if nil == self.shadowLayer {
        let size = self.frame.size
        self.clipsToBounds = true
        let layer: CALayer = CALayer()
        layer.backgroundColor = UIColor.lightGrayColor().CGColor
        layer.position = CGPointMake(size.width / 2, -size.height / 2 + 0.5)
        layer.bounds = CGRectMake(0, 0, size.width, size.height)
        layer.shadowColor = UIColor.darkGrayColor().CGColor
        layer.shadowOffset = CGSizeMake(0.5, 0.5)
        layer.shadowOpacity = 0.8
        layer.shadowRadius = 5.0
        self.shadowLayer = layer

        self.layer.addSublayer(layer)
    }
}

答案 2 :(得分:2)

我在Swift 3上重写了@NRitH解决方案,也稍微重构了它:

final class SideShadowLayer: CAGradientLayer {
    enum Side {
        case top,
        bottom,
        left,
        right
    }

    init(frame: CGRect, side: Side, shadowWidth: CGFloat,
         fromColor: UIColor = .black,
         toColor: UIColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0),
         opacity: Float = 0.5) {
        super.init()

        colors = [fromColor.cgColor, toColor.cgColor]
        self.opacity = opacity

        switch side {
        case .bottom:
            startPoint = CGPoint(x: 0.5, y: 1.0)
            endPoint = CGPoint(x: 0.5, y: 0.0)
            self.frame = CGRect(x: 0, y: frame.height - shadowWidth, width: frame.width, height: shadowWidth)

        case .top:
            startPoint = CGPoint(x: 0.5, y: 0.0)
            endPoint = CGPoint(x: 0.5, y: 1.0)
            self.frame = CGRect(x: 0, y: 0, width: frame.width, height: shadowWidth)

        case .left:
            startPoint = CGPoint(x: 0.0, y: 0.5)
            endPoint = CGPoint(x: 1.0, y: 0.5)
            self.frame = CGRect(x: 0, y: 0, width: shadowWidth, height: frame.height)

        case .right:
            startPoint = CGPoint(x: 1.0, y: 0.5)
            endPoint = CGPoint(x: 0.0, y: 0.5)
            self.frame = CGRect(x: frame.width - shadowWidth, y: 0, width: shadowWidth, height: frame.height)
        }
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

答案 3 :(得分:2)

我更新了@NRitH的答案,并对其进行了扩展,并对其进行了修改,以便您可以一次操作多个边缘

使用

myview.addShadow(to: [.top,.bottom], radius: 15.0)

extension UIView{

    func addShadow(to edges:[UIRectEdge], radius:CGFloat){

        let toColor = UIColor(colorLiteralRed: 235.0/255.0, green: 235.0/255.0, blue: 235.0/255.0, alpha: 1.0)
        let fromColor = UIColor(colorLiteralRed: 188.0/255.0, green: 188.0/255.0, blue: 188.0/255.0, alpha: 1.0)
        // Set up its frame.
        let viewFrame = self.frame
        for edge in edges{
            let gradientlayer          = CAGradientLayer()
            gradientlayer.colors       = [fromColor.cgColor,toColor.cgColor]
            gradientlayer.shadowRadius = radius

            switch edge {
            case UIRectEdge.top:
                gradientlayer.startPoint = CGPoint(x: 0.5, y: 0.0)
                gradientlayer.endPoint = CGPoint(x: 0.5, y: 1.0)
                gradientlayer.frame = CGRect(x: 0.0, y: 0.0, width: viewFrame.width, height: gradientlayer.shadowRadius)
            case UIRectEdge.bottom:
                gradientlayer.startPoint = CGPoint(x: 0.5, y: 1.0)
                gradientlayer.endPoint = CGPoint(x: 0.5, y: 0.0)
                gradientlayer.frame = CGRect(x: 0.0, y: viewFrame.height - gradientlayer.shadowRadius, width: viewFrame.width, height: gradientlayer.shadowRadius)
            case UIRectEdge.left:
                gradientlayer.startPoint = CGPoint(x: 0.0, y: 0.5)
                gradientlayer.endPoint = CGPoint(x: 1.0, y: 0.5)
                gradientlayer.frame = CGRect(x: 0.0, y: 0.0, width: gradientlayer.shadowRadius, height: viewFrame.height)
            case UIRectEdge.right:
                gradientlayer.startPoint = CGPoint(x: 1.0, y: 0.5)
                gradientlayer.endPoint = CGPoint(x: 0.0, y: 0.5)
                gradientlayer.frame = CGRect(x: viewFrame.width - gradientlayer.shadowRadius, y: 0.0, width: gradientlayer.shadowRadius, height: viewFrame.height)
            default:
                break
            }
            self.layer.addSublayer(gradientlayer)
        }

    }

    func removeAllSublayers(){
        if let sublayers = self.layer.sublayers, !sublayers.isEmpty{
            for sublayer in sublayers{
                sublayer.removeFromSuperlayer()
            }
        }
    }

}

Shadow

答案 4 :(得分:1)

我使用@作为清晰的toColor调整了@ anoop4real所做的修改,并使界面与CALayer中的阴影设置(包括默认设置)更加一致,除了不透明性(将不透明性设置为0.0)默认。我使用默认值0.6,因为它看起来是最自然的。

extension UIView {
    func addShadow(to edges: [UIRectEdge], radius: CGFloat = 3.0, opacity: Float = 0.6, color: CGColor = UIColor.black.cgColor) {

        let fromColor = color
        let toColor = UIColor.clear.cgColor
        let viewFrame = self.frame
        for edge in edges {
            let gradientLayer = CAGradientLayer()
            gradientLayer.colors = [fromColor, toColor]
            gradientLayer.opacity = opacity

            switch edge {
            case .top:
                gradientLayer.startPoint = CGPoint(x: 0.5, y: 0.0)
                gradientLayer.endPoint = CGPoint(x: 0.5, y: 1.0)
                gradientLayer.frame = CGRect(x: 0.0, y: 0.0, width: viewFrame.width, height: radius)
            case .bottom:
                gradientLayer.startPoint = CGPoint(x: 0.5, y: 1.0)
                gradientLayer.endPoint = CGPoint(x: 0.5, y: 0.0)
                gradientLayer.frame = CGRect(x: 0.0, y: viewFrame.height - radius, width: viewFrame.width, height: radius)
            case .left:
                gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
                gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
                gradientLayer.frame = CGRect(x: 0.0, y: 0.0, width: radius, height: viewFrame.height)
            case .right:
                gradientLayer.startPoint = CGPoint(x: 1.0, y: 0.5)
                gradientLayer.endPoint = CGPoint(x: 0.0, y: 0.5)
                gradientLayer.frame = CGRect(x: viewFrame.width - radius, y: 0.0, width: radius, height: viewFrame.height)
            default:
                break
            }
            self.layer.addSublayer(gradientLayer)
        }
    }

    func removeAllShadows() {
        if let sublayers = self.layer.sublayers, !sublayers.isEmpty {
            for sublayer in sublayers {
                sublayer.removeFromSuperlayer()
            }
        }
    }
}

顶视图是默认设置,底视图使用半径5.0来更清晰地显示。

view1.addShadow([.top, .bottom, .left, .right])
view2.addShadow([.top, .bottom, .left, .right], radius: 5.0)
view2.backgroundColor = .orange

views with inner shadow

答案 5 :(得分:0)

这就是我在视图中添加内部阴影的方式。

func addInerShadowLayer()
{
    clipsToBounds = true
    let shapeLayer = CAShapeLayer()
    let path = UIBezierPath(roundedRect: CGRect(x: -10, y: -self.frame.height/2, width: self.frame.width + 20, height: self.frame.height*2), cornerRadius: 0)
    let buttonPath = UIBezierPath(roundedRect: CGRect(x: -1, y: -1, width: self.frame.width+2, height: self.frame.height+2), cornerRadius: self.frame.height/2)
    path.append(buttonPath.reversing())
    shapeLayer.path = path.cgPath
    self.layer.addSublayer(shapeLayer)
    shapeLayer.shadowOpacity = 0.1
    shapeLayer.shadowColor = UIColor.red.cgColor
    shapeLayer.shadowOffset = CGSize(width: 0, height: 4)
    shapeLayer.shadowRadius = 3
}

答案 6 :(得分:0)

如果您不介意使用 clipsToBounds = true,您可以在视图边缘附近创建一个新的 CALayer 偏移量,并将阴影添加到该视图中。这就是 J.Hunter 的回答。

J.Hunter 的代码添加了顶部阴影,这里我将其更新为 Swift 5 并添加到底部。

斯威夫特 5:

override func draw(_ rect: CGRect) {
  // Create Inner Shadow. Not sure about efficiency of this.
  // You may want to create a shadowLayer property
  //  and only run this code if it hasn't been created yet.
  let size = rect.size
  clipsToBounds = true // Don't want to see your fake view layer
  let innerShadowLayer: CALayer = CALayer()
  
  // Need to set a backgroundColor or it doesn't work
  innerShadowLayer.backgroundColor = UIColor.black.cgColor
  
  // Position your shadow layer (anchor point is in the center)
  //  on the edge of where your shadow needs to be.
  // In my case this moves the shadow layer to the
  //  bottom edge of my view
  innerShadowLayer.position = CGPoint(x: size.width / 2, y: size.height + (size.height / 2))
  
  // This could be smaller I think, just copying J.Hunter's code...
  innerShadowLayer.bounds = CGRect(x: 0, y: 0, width: size.width, height: size.height)
  
  // Normal shadow layer properties you'd use for an outer shadow
  innerShadowLayer.shadowColor = UIColor.black.cgColor
  innerShadowLayer.shadowOffset = CGSize(width: 0, height: 0)
  innerShadowLayer.shadowOpacity = 0.3
  innerShadowLayer.shadowRadius = 3
  
  layer.addSublayer(innerShadowLayer)
}
相关问题