web-dev-qa-db-fra.com

Ajouter une ombre intérieure en haut de UIView

Je levai les yeux mais je ne trouvais pas comment ajouter une ombre intérieure à UIView, uniquement en haut (de haut en bas) pour Swift. Quel est le meilleur moyen d'ajouter un cercle intérieur dans Swift? 

Edit: J'ai trouvé quelques questions et réponses sur SO, mais elles sont soit dans obj-c, soit si compliquées. Je cherchais simplement une méthode plus rapide, s’il y en avait

Ce que je veux réaliser:

 enter image description here

16
senty

Voici une version pure Swift que j'ai concoctée:

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

Pour l'utiliser,

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

Notez qu’il s’agit par défaut d’un dégradé de noir à blanc d’une profondeur de 20 points.

Le code complet, avec un exemple UIViewController qui permet de basculer les ombres aux quatre coins d'une vue, est disponible à l'adresse https://github.com/jrtibbetts/Tenebrae . J'ai également documenté la EdgeShadowLayer de manière assez approfondie.

20
NRitH

J'ai utilisé implémenter ombre intérieure dans UIView en utilisant Objective-C. J'essaie de traduire le code en Swift. S'il vous plaît pardonnez-moi pour ma pauvre syntaxe Swift

vous pouvez appeler la fonction ci-dessous dans 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)
    }
}
14
J.Hunter

J'ai réécrit la solution @NRitH sur Swift 3, aussi légèrement reformulée

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)
    }
}
2
Bohdan Savych

J'ai mis à jour la réponse de @ NRitH et en ai fait une extension également modifiée afin que vous puissiez manipuler plusieurs bords en une

usage

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

2
anoop4real

voici comment j'ai ajouté une ombre intérieure dans une vue. 

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
}
0
Dinu Nicolae