如何创建仅四角带边框的方形UIView?二维码扫描UI背景处理
实现二维码扫描框:四角边框+深色遮罩效果
一、仅四角带边框的扫描框实现
你可以通过自定义UIView并重写draw(_ rect:)方法来绘制四角边框,精准控制每个角的样式:
class ScanBorderView: UIView { // 可自定义的边框属性 var borderColor: UIColor = .white { didSet { setNeedsDisplay() } } var borderWidth: CGFloat = 2 { didSet { setNeedsDisplay() } } var cornerLength: CGFloat = 20 { didSet { setNeedsDisplay() } } override func draw(_ rect: CGRect) { super.draw(rect) guard let context = UIGraphicsGetCurrentContext() else { return } context.setStrokeColor(borderColor.cgColor) context.setLineWidth(borderWidth) context.setLineCap(.square) // 左上角:顶部横线 + 左侧竖线 context.move(to: CGPoint(x: rect.minX, y: rect.minY + cornerLength)) context.addLine(to: CGPoint(x: rect.minX, y: rect.minY)) context.addLine(to: CGPoint(x: rect.minX + cornerLength, y: rect.minY)) // 右上角:顶部横线 + 右侧竖线 context.move(to: CGPoint(x: rect.maxX - cornerLength, y: rect.minY)) context.addLine(to: CGPoint(x: rect.maxX, y: rect.minY)) context.addLine(to: CGPoint(x: rect.maxX, y: rect.minY + cornerLength)) // 左下角:底部横线 + 左侧竖线 context.move(to: CGPoint(x: rect.minX, y: rect.maxY - cornerLength)) context.addLine(to: CGPoint(x: rect.minX, y: rect.maxY)) context.addLine(to: CGPoint(x: rect.minX + cornerLength, y: rect.maxY)) // 右下角:底部横线 + 右侧竖线 context.move(to: CGPoint(x: rect.maxX - cornerLength, y: rect.maxY)) context.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY)) context.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY - cornerLength)) context.strokePath() } }
使用时直接实例化并设置位置尺寸:
let scanBorder = ScanBorderView(frame: CGRect(x: 0, y: 0, width: 250, height: 250)) scanBorder.center = view.center view.addSubview(scanBorder)
二、周围深色背景+方形透明的遮罩实现
通过CAShapeLayer创建遮罩层,核心是绘制全屏路径并减去中间扫描框路径,实现中间透明、周围深色的效果:
class ScanMaskView: UIView { // 扫描框尺寸,可调整 var scanFrame: CGRect = CGRect(x: 0, y: 0, width: 250, height: 250) { didSet { updateMask() } } // 遮罩背景色,支持透明度 var maskColor: UIColor = UIColor.black.withAlphaComponent(0.6) { didSet { backgroundColor = maskColor } } override init(frame: CGRect) { super.init(frame: frame) setupView() } required init?(coder: NSCoder) { super.init(coder: coder) setupView() } private func setupView() { backgroundColor = maskColor updateMask() } private func updateMask() { let maskLayer = CAShapeLayer() let fullPath = UIBezierPath(rect: bounds) let scanPath = UIBezierPath(rect: scanFrame) // 从全屏路径中减去扫描框路径 fullPath.append(scanPath) fullPath.usesEvenOddFillRule = true maskLayer.path = fullPath.cgPath maskLayer.fillRule = .evenOdd layer.mask = maskLayer } override func layoutSubviews() { super.layoutSubviews() // 确保屏幕旋转或尺寸变化时,扫描框保持居中 scanFrame = scanFrame.offsetBy(dx: center.x - scanFrame.midX, dy: center.y - scanFrame.midY) updateMask() } }
组合使用遮罩和边框视图:
let maskView = ScanMaskView(frame: view.bounds) // 设置扫描框居中 maskView.scanFrame.origin = CGPoint(x: view.center.x - 125, y: view.center.y - 125) view.addSubview(maskView) // 添加四角边框到遮罩层上 let scanBorder = ScanBorderView(frame: maskView.scanFrame) maskView.addSubview(scanBorder)
内容的提问来源于stack exchange,提问作者phast
相关产品推荐
相关产品推荐

