Swift - 如何创建其中裁剪形状的视图
Swift - How to create a view with a shape cropped in it
我正在尝试使用 swift 1.2 和 xcode 6 获得图中显示的结果。
基本上我想创建一个带有形状切割的视图,以便能够看到下面的视图来为我的应用程序制作教程。
我知道如何创建圆形,但我不知道如何在视图中将其剪掉。
我需要一个完整的示例来说明如何操作。
提前致谢
执行此操作的最简单方法是创建一个 png 图像,其外部为部分透明的白色,中间为透明圆圈。然后将 2 个图像视图堆叠在一起,遮罩图像在顶部,并将其“不透明”标志设置为 false。
您也可以通过创建一个 CAShapeLayer 并将其设置为使用半透明的白色来实现此目的,然后安装一个形状,该形状是从其形状中切出孔的正方形。您将该形状层安装在图像视图层的顶部。
最通用的方法是创建 UIImageView 的自定义子类,并让子类的 init 方法创建和安装形状层。我昨天刚刚创建了一个要点,说明了创建 UIImageView 的自定义子类。这是 link:ImageViewWithGradient gist
该要点创建了一个渐变图层。让它适应创建一个形状层将是一件简单的事情,如果你修改了 layoutSubviews 方法,你可以让它在图像视图调整大小时适应视图和路径。
编辑:
好的,我采取了额外的步骤来创建一个创建裁剪图像视图的游乐场。您可以在 ImageViewWithMask on github
找到它
我的游乐场生成的图像如下所示:
以下是如何为 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
这是我在操场上做的:
虽然有答案,但我想分享我的方法:
// 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.
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)
}
}
//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
我正在尝试使用 swift 1.2 和 xcode 6 获得图中显示的结果。
基本上我想创建一个带有形状切割的视图,以便能够看到下面的视图来为我的应用程序制作教程。 我知道如何创建圆形,但我不知道如何在视图中将其剪掉。 我需要一个完整的示例来说明如何操作。 提前致谢
执行此操作的最简单方法是创建一个 png 图像,其外部为部分透明的白色,中间为透明圆圈。然后将 2 个图像视图堆叠在一起,遮罩图像在顶部,并将其“不透明”标志设置为 false。
您也可以通过创建一个 CAShapeLayer 并将其设置为使用半透明的白色来实现此目的,然后安装一个形状,该形状是从其形状中切出孔的正方形。您将该形状层安装在图像视图层的顶部。
最通用的方法是创建 UIImageView 的自定义子类,并让子类的 init 方法创建和安装形状层。我昨天刚刚创建了一个要点,说明了创建 UIImageView 的自定义子类。这是 link:ImageViewWithGradient gist
该要点创建了一个渐变图层。让它适应创建一个形状层将是一件简单的事情,如果你修改了 layoutSubviews 方法,你可以让它在图像视图调整大小时适应视图和路径。
编辑:
好的,我采取了额外的步骤来创建一个创建裁剪图像视图的游乐场。您可以在 ImageViewWithMask on github
找到它我的游乐场生成的图像如下所示:
以下是如何为 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
这是我在操场上做的:
虽然有答案,但我想分享我的方法:
// 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.
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)
}
}
//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