Swift - How to create a view with a shape cropped in it

后端 未结 5 2088
盖世英雄少女心
盖世英雄少女心 2021-01-04 10:00

I\'m trying to achieve the result shown in the image using swift 1.2 and xcode 6.

Basically I want to create a view with a shape cut in it to be able to see the the

相关标签:
5条回答
  • 2021-01-04 10:18

    Here is sample code for how you can make a circle Mask for a UIView:

    let sampleView = UIView(frame: UIScreen.mainScreen().bounds)
    let maskLayer = CALayer()
    maskLayer.frame = sampleView.bounds
    let circleLayer = CAShapeLayer()
    //assume the circle's radius is 100
    circleLayer.frame = CGRectMake(sampleView.center.x - 100, sampleView.center.y - 100, 200, 200)
    let circlePath = UIBezierPath(ovalInRect: CGRectMake(0, 0, 200, 200))
    circleLayer.path = circlePath.CGPath
    circleLayer.fillColor = UIColor.blackColor().CGColor
    maskLayer.addSublayer(circleLayer)
    
    sampleView.layer.mask = maskLayer
    

    Here is what I made in the playground:

    enter image description here

    0 讨论(0)
  • 2021-01-04 10:23

    The easiest way to do this would be to create a png image with partly transparent white around the outside and a clear circle in the middle. Then stack 2 image views on top of each other, with the masking image on top, and set its "opaque" flag to false.

    You could also do this by creating a CAShapeLayer and set it up to use a translucent white color, then install a shape that is the square with the hole cut out of it shape. You'd install that shape layer on top of your image view's layer.

    The most general-purpose way to do that would be to create a custom subclass of UIImageView and have the init method of your subclass create and install the shape layer. I just created a gist yesterday that illustrated creating a custom subclass of UIImageView. Here is the link: ImageViewWithGradient gist

    That gist creates a gradient layer. It would be a simple matter to adapt it to create a shape layer instead, and if you modified the layoutSubviews method you could make it adapt the view and path if the image view gets resized.

    EDIT:

    Ok, I took the extra step of creating a playground that creates a cropping image view. You can find that at ImageViewWithMask on github

    The resulting image for my playground looks like this:

    Image with circular mask

    0 讨论(0)
  • 2021-01-04 10:27
    class MakeTransparentHoleOnOverlayView: UIView {
    
        @IBOutlet weak var transparentHoleView: UIView!
    
        // MARK: - Drawing
    
        override func draw(_ rect: CGRect) {
            super.draw(rect)
    
            if self.transparentHoleView != nil {
                // Ensures to use the current background color to set the filling color
                self.backgroundColor?.setFill()
                UIRectFill(rect)
    
                let layer = CAShapeLayer()
                let path = CGMutablePath()
    
                // Make hole in view's overlay
                // NOTE: Here, instead of using the transparentHoleView UIView we could use a specific CFRect location instead...
                path.addRect(transparentHoleView.frame)
                path.addRect(bounds)
    
                layer.path = path
                layer.fillRule = kCAFillRuleEvenOdd
                self.layer.mask = layer
            }
        }
    
        override func layoutSubviews () {
            super.layoutSubviews()
        }
    
        // MARK: - Initialization
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
    
        override init(frame: CGRect) {
            super.init(frame: frame)
        }
    }
    
    0 讨论(0)
  • 2021-01-04 10:29

    Even though there is an answer, i'd like to share my way:

    // Let's say that you have an outlet to the image view called imageView
    // Create the white view 
    let whiteView = UIView(frame: imageView.bounds) 
    let maskLayer = CAShapeLayer() //create the mask layer
    
    // Set the radius to 1/3 of the screen width
    let radius : CGFloat = imageView.bounds.width/3 
    
    // Create a path with the rectangle in it.
    let path = UIBezierPath(rect: imageView.bounds)
    // Put a circle path in the middle
    path.addArcWithCenter(imageView.center, radius: radius, startAngle: 0.0, endAngle: CGFloat(2*M_PI), clockwise: true)
    
    // Give the mask layer the path you just draw
    maskLayer.path = path.CGPath
    // Fill rule set to exclude intersected paths
    maskLayer.fillRule = kCAFillRuleEvenOdd
    
    // By now the mask is a rectangle with a circle cut out of it. Set the mask to the view and clip.
    whiteView.layer.mask = maskLayer
    whiteView.clipsToBounds = true
    
    whiteView.alpha = 0.8
    whiteView.backgroundColor = UIColor.whiteColor()
    
    //If you are in a VC add to the VC's view (over the image)
    view.addSubview(whiteView)    
    // Annnnnd you're done.
    
    0 讨论(0)
  • 2021-01-04 10:30
        //assume you create a UIImageView and content image before execute this code
      let sampleMask = UIView()
        sampleMask.frame = self.view.frame
        sampleMask.backgroundColor =  UIColor.black.withAlphaComponent(0.6)
        //assume you work in UIViewcontroller
        self.view.addSubview(sampleMask)
        let maskLayer = CALayer()
        maskLayer.frame = sampleMask.bounds
        let circleLayer = CAShapeLayer()
        //assume the circle's radius is 150
        circleLayer.frame = CGRect(x:0 , y:0,width: sampleMask.frame.size.width,height: sampleMask.frame.size.height)
        let finalPath = UIBezierPath(roundedRect: CGRect(x:0 , y:0,width: sampleMask.frame.size.width,height: sampleMask.frame.size.height), cornerRadius: 0)
        let circlePath = UIBezierPath(ovalIn: CGRect(x:sampleMask.center.x - 150, y:sampleMask.center.y - 150, width: 300, height: 300))
        finalPath.append(circlePath.reversing())
        circleLayer.path = finalPath.cgPath
        circleLayer.borderColor = UIColor.white.withAlphaComponent(1).cgColor
         circleLayer.borderWidth = 1
        maskLayer.addSublayer(circleLayer)
    
        sampleMask.layer.mask = maskLayer
    

    0 讨论(0)
提交回复
热议问题