使用 UIImageView 在 UIView 中切割透明孔
Cut transparent hole in UIView using UIImageView
我正在尝试为我的 QR 相机视图创建下面的图像。
我有一张相机覆盖图(屏幕中间的正方形)。
我查看了 Whosebug 上的类似主题,发现了如何从黑色背景(0.75% 透明)中剪切出相机叠加图像,以便它在中间留下空的 space,但是我'我对它的放置有一些实际问题,我无法找出是什么行为如此奇怪。
这是我用来创建背景黑色图像以及在中心切出正方形的代码:
// Create a view filling the screen.
let backgroundView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
// Set a semi-transparent, black background.
backgroundView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.75)
// Create the initial layer from the view bounds.
let maskLayer = CAShapeLayer()
maskLayer.frame = backgroundView.bounds
maskLayer.fillColor = UIColor.black.cgColor
// Create the path.
let path = UIBezierPath(rect: backgroundView.bounds)
maskLayer.fillRule = CAShapeLayerFillRule.evenOdd
// Append the overlay image to the path so that it is subtracted.
path.append(UIBezierPath(rect: camOverlayImageView.frame))
maskLayer.path = path.cgPath
// Set the mask of the view.
backgroundView.layer.mask = maskLayer
// Add the view so it is visible.
self.view.addSubview(backgroundView)
camOverlayImageView
是在情节提要中创建的,我在它上面使用的只是将其垂直和水平居中到超级视图的约束,如下所示:
但是,当我这样做时,这就是我在设备上得到的:
如果有人知道可能导致此问题的原因或如何修复它,将不胜感激,因为我似乎找不到它。
我当然可以像这样手动移动框架并偏移它,但这不是正确的方法:
let overlayFrame = camOverlayImageView.frame
// Append the overlay image to the path so that it is subtracted.
path.append(UIBezierPath(rect: CGRect(
x: overlayFrame.origin.x + 18,
y: overlayFrame.origin.y - 6,
width: overlayFrame.size.width,
height: overlayFrame.size.height))
)
maskLayer.path = path.cgPath
而不是做我以前做的事情:
path.append(UIBezierPath(rect: camOverlayImageView.frame))
maskLayer.path = path.cgPath
很有可能...
您创建遮罩的时间过早 - 在自动布局调整/定位视图之前。
这样试试:
class HoleInViewController: UIViewController {
@IBOutlet var camOverlayImageView: UIView!
let backgroundView: UIView = {
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = UIColor.black.withAlphaComponent(0.75)
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(backgroundView)
NSLayoutConstraint.activate([
backgroundView.topAnchor.constraint(equalTo: view.topAnchor),
backgroundView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
backgroundView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
backgroundView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
])
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Create the initial layer from the view bounds.
let maskLayer = CAShapeLayer()
maskLayer.frame = backgroundView.bounds
maskLayer.fillColor = UIColor.black.cgColor
// Create the path.
let path = UIBezierPath(rect: backgroundView.bounds)
maskLayer.fillRule = CAShapeLayerFillRule.evenOdd
// Append the overlay image to the path so that it is subtracted.
path.append(UIBezierPath(rect: camOverlayImageView.frame))
maskLayer.path = path.cgPath
// Set the mask of the view.
backgroundView.layer.mask = maskLayer
}
}
我正在尝试为我的 QR 相机视图创建下面的图像。
我有一张相机覆盖图(屏幕中间的正方形)。
我查看了 Whosebug 上的类似主题,发现了如何从黑色背景(0.75% 透明)中剪切出相机叠加图像,以便它在中间留下空的 space,但是我'我对它的放置有一些实际问题,我无法找出是什么行为如此奇怪。
这是我用来创建背景黑色图像以及在中心切出正方形的代码:
// Create a view filling the screen.
let backgroundView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
// Set a semi-transparent, black background.
backgroundView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.75)
// Create the initial layer from the view bounds.
let maskLayer = CAShapeLayer()
maskLayer.frame = backgroundView.bounds
maskLayer.fillColor = UIColor.black.cgColor
// Create the path.
let path = UIBezierPath(rect: backgroundView.bounds)
maskLayer.fillRule = CAShapeLayerFillRule.evenOdd
// Append the overlay image to the path so that it is subtracted.
path.append(UIBezierPath(rect: camOverlayImageView.frame))
maskLayer.path = path.cgPath
// Set the mask of the view.
backgroundView.layer.mask = maskLayer
// Add the view so it is visible.
self.view.addSubview(backgroundView)
camOverlayImageView
是在情节提要中创建的,我在它上面使用的只是将其垂直和水平居中到超级视图的约束,如下所示:
但是,当我这样做时,这就是我在设备上得到的:
如果有人知道可能导致此问题的原因或如何修复它,将不胜感激,因为我似乎找不到它。
我当然可以像这样手动移动框架并偏移它,但这不是正确的方法:
let overlayFrame = camOverlayImageView.frame
// Append the overlay image to the path so that it is subtracted.
path.append(UIBezierPath(rect: CGRect(
x: overlayFrame.origin.x + 18,
y: overlayFrame.origin.y - 6,
width: overlayFrame.size.width,
height: overlayFrame.size.height))
)
maskLayer.path = path.cgPath
而不是做我以前做的事情:
path.append(UIBezierPath(rect: camOverlayImageView.frame))
maskLayer.path = path.cgPath
很有可能...
您创建遮罩的时间过早 - 在自动布局调整/定位视图之前。
这样试试:
class HoleInViewController: UIViewController {
@IBOutlet var camOverlayImageView: UIView!
let backgroundView: UIView = {
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = UIColor.black.withAlphaComponent(0.75)
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(backgroundView)
NSLayoutConstraint.activate([
backgroundView.topAnchor.constraint(equalTo: view.topAnchor),
backgroundView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
backgroundView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
backgroundView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
])
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Create the initial layer from the view bounds.
let maskLayer = CAShapeLayer()
maskLayer.frame = backgroundView.bounds
maskLayer.fillColor = UIColor.black.cgColor
// Create the path.
let path = UIBezierPath(rect: backgroundView.bounds)
maskLayer.fillRule = CAShapeLayerFillRule.evenOdd
// Append the overlay image to the path so that it is subtracted.
path.append(UIBezierPath(rect: camOverlayImageView.frame))
maskLayer.path = path.cgPath
// Set the mask of the view.
backgroundView.layer.mask = maskLayer
}
}