如何在 UIView 中制作透明孔

Posted

技术标签:

【中文标题】如何在 UIView 中制作透明孔【英文标题】:How to make transparent holes in a UIView 【发布时间】:2018-03-29 00:07:02 【问题描述】:

在 UIView 的边缘周围创建圆形圆圈的最佳方法是什么,而且圆圈必须是透明的,我用草图创建这个

【问题讨论】:

你检查了吗? ***.com/questions/28448698/… How do I create a UIView with a transparent circle inside (in swift)?的可能重复 Invert CALayer mask that is based on a stroke (no fill)的可能重复 【参考方案1】:

我已经通过使用 UIBezierPath 和 CAShapeLayer 实现了这个功能

我正在从情节提要中获取观点。

@IBOutlet weak var myView: UIView!

创建 UIBezierPath() 的对象

var path = UIBezierPath()

创建一个以圆的中心点为参数的方法,我们创建另一个 UIBezierPath() 作为 circlePath 即圆,我们将圆附加到之前的 UIBezierPath() path. 知道拿一个 CAShapeLayer 并切割 circlePath

func overLay(points: CGPoint) 
    let sizes = CGSize(width: 30, height: 30)
    let circlePath = UIBezierPath(ovalIn: CGRect(origin: points, size: sizes))
    path.append(circlePath)

    let maskLayer = CAShapeLayer() //create the mask layer
    maskLayer.path = path.cgPath // Give the mask layer the path you just draw
    maskLayer.fillRule = kCAFillRuleEvenOdd // Cut out the intersection part
    myView.layer.mask = maskLayer

创建 updateUI() 并使用所有点调用 overLay 方法。

func updateUI() 
    path = UIBezierPath(rect: myView.bounds)
    let viewFrames = myView.bounds
    overLay(points: CGPoint(x: viewFrames.origin.x - 15, y: viewFrames.origin.y - 15))
    overLay(points: CGPoint(x: viewFrames.origin.x + viewFrames.width - 15, y: viewFrames.origin.y - 15))
    overLay(points: CGPoint(x: viewFrames.origin.x - 15, y: viewFrames.origin.y + viewFrames.height - 15))
    overLay(points: CGPoint(x: viewFrames.origin.x + viewFrames.width - 15, y: viewFrames.origin.y + viewFrames.height - 15))
    overLay(points: CGPoint(x: viewFrames.origin.x - 15 , y: viewFrames.origin.y + viewFrames.height/2))
    overLay(points:  CGPoint(x: viewFrames.origin.x + viewFrames.width - 15, y: viewFrames.origin.y + viewFrames.height/2))

从 viewDidLayoutSubviews() 方法调用 updateUI。

override func viewDidLayoutSubviews() 
    updateUI()

它将在视图上创建具有透明度的叠加层。

完整代码 sn -p

导入 UIKit

类视图控制器:UIViewController

@IBOutlet weak var myView: UIView!

var path = UIBezierPath()
override func viewDidLoad() 
    super.viewDidLoad()

    // Do any additional setup after loading the view, typically from a nib.


override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.


func overLay(points: CGPoint) 
    let sizes = CGSize(width: 30, height: 30)
    let circlePath = UIBezierPath(ovalIn: CGRect(origin: points, size: sizes))
    path.append(circlePath)

    let maskLayer = CAShapeLayer() //create the mask layer
    maskLayer.path = path.cgPath // Give the mask layer the path you just draw
    maskLayer.fillRule = kCAFillRuleEvenOdd // Cut out the intersection part
    myView.layer.mask = maskLayer


override func viewDidLayoutSubviews() 
    updateUI()


func updateUI() 
    path = UIBezierPath(rect: myView.bounds)
    let viewFrames = myView.bounds
    overLay(points: CGPoint(x: viewFrames.origin.x - 15, y: viewFrames.origin.y - 15))
    overLay(points: CGPoint(x: viewFrames.origin.x + viewFrames.width - 15, y: viewFrames.origin.y - 15))
    overLay(points: CGPoint(x: viewFrames.origin.x - 15, y: viewFrames.origin.y + viewFrames.height - 15))
    overLay(points: CGPoint(x: viewFrames.origin.x + viewFrames.width - 15, y: viewFrames.origin.y + viewFrames.height - 15))
    overLay(points: CGPoint(x: viewFrames.origin.x - 15 , y: viewFrames.origin.y + viewFrames.height/2))
    overLay(points:  CGPoint(x: viewFrames.origin.x + viewFrames.width - 15, y: viewFrames.origin.y + viewFrames.height/2))

【讨论】:

【参考方案2】:

我创建了一个枚举,其中包含需要放置圆的所有角。

enum Corners 
    case topLeft
    case topRight
    case bottomLeft
    case bottomRight
    case centerLeft
    case centerRight

我以编程方式将圆形视图添加到视图控制器的视图并设置它的颜色。这里,我给了白色,你可以把它改成你各自的透明背景。

func addCircularViews(toCorners corners: [Corners]) 
    for corner in corners 
        let circleView = UIView(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
        circleView.layer.cornerRadius = circleView.frame.width/2
        circleView.backgroundColor = UIColor.white
        self.view.addSubview(circleView)
        setPosition(forCircularView: corner, circleView)
    

我正在通过更改圆形视图的中心来设置圆形的位置。

func setPosition(forCircularView corner: Corners,_ circleView: UIView) 
    let screenFrame = UIScreen.main.bounds
    switch corner 
    case .topLeft:
        circleView.center = CGPoint(x: screenFrame.origin.x, y: screenFrame.origin.y)
    case .topRight:
        circleView.center = CGPoint(x: screenFrame.origin.x + screenFrame.width, y: screenFrame.origin.y)
    case .bottomLeft:
        circleView.center = CGPoint(x: screenFrame.origin.x , y: screenFrame.origin.y + screenFrame.height)
    case .bottomRight:
        circleView.center = CGPoint(x: screenFrame.origin.x + screenFrame.width , y: screenFrame.origin.y + screenFrame.height)
    case .centerLeft:
        circleView.center = CGPoint(x: screenFrame.origin.x , y: screenFrame.origin.y + screenFrame.height/2)
    case .centerRight:
        circleView.center = CGPoint(x: screenFrame.origin.x + screenFrame.width , y: screenFrame.origin.y + screenFrame.height/2)
    

您可以在需要时调用上述函数

addCircularViews(toCorners: [.topLeft, .topRight, .centerRight, .centerLeft, .bottomLeft, .bottomRight])

由于上面是一个数组,所以可以根据需要设置角点。 希望对你有帮助!!

【讨论】:

【参考方案3】:

我有一个UIView 的子类来完成这些任务。基本上,它使用由UIBezierPath 创建的CAShapeLayer 作为视图的掩码。您可以自定义框架和孔的角半径。这是我的代码:

import UIKit

struct TransparentPart 
    var rect: CGRect
    var cornerRadius: CGFloat



class PartiallyTransparentView: UIView 
    var transparentParts: [TransparentPart] = []

    override func draw(_ rect: CGRect) 
        super.draw(rect)

        backgroundColor?.setFill()
        UIRectFill(rect)

        let clipPath = UIBezierPath(rect: self.bounds)

        for part in transparentParts 
            let holeRect = part.rect
            let radius = part.cornerRadius

            let path = UIBezierPath(roundedRect: holeRect, cornerRadius: radius)

            clipPath.append(path)
        

        let layer = CAShapeLayer()
        layer.path = clipPath.cgPath
        layer.fillRule = kCAFillRuleEvenOdd
        self.layer.mask = layer
        self.layer.masksToBounds = true
    

【讨论】:

以上是关于如何在 UIView 中制作透明孔的主要内容,如果未能解决你的问题,请参考以下文章

在覆盖 UIView 的右下角创建四分之一透明孔

iphone:如何在 UIVIEW 上制作透明蒙版

如何在 UIImage 中“切割”透明孔?

如何在 UIView 周围制作自定义边框?

如何在视图透明的同时接收滑动手势?

如何在覆盖css的底角制作一个孔区域