QRコードスキャンぽいUIの作り方
ちょっと難しいポイント
- 真ん中の空いてる正方形
- 角丸じゃないけど、4つのあれ
作る
画面のビューの構成
自分がこういう画面を作ったとき、こういう構成にした⬇︎
今回の内容は、mask viewの作り方を説明する。
ScanQRMaskView(この命名はただの例)
ScanQRMaskViewというxibファイルを作成
その中の真ん中にcaptureViewという正方形のviewを置いた。そしてよしなにサイズを決めて、真ん中に配置するようにconstraintをはる。
captureViewを置く目的は、ただ正方形のサイズと位置を把握しやすくにするためである。
ScanQRMaskView.swift で簡単なスタイルセットアップをやる
captureViewのIBOutletを作って、そして以下のように設定。
private func setupAppearance() { // とりあえず背景色全部.clearにする backgroundColor = .clear captureView.backgroundColor = .clear // captureViewに白いボーダーをつける(デザイン通り) captureView.layer.borderWidth = 0.5 captureView.layer.borderColor = UIColor.white.cgColor }
drawRectで描画
drawRectでdimming背景、透明の正方形、4つのあれを描画。
override func draw(_ rect: CGRect) { super.draw(rect) // dimming背景を描画 let dimmingColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6) dimmingColor.setFill() UIRectFill(bounds) // 透明の正方形を描画 let captureRect = captureView.frame UIColor.clear.setFill() UIRectFill(captureRect) // 角にある4つのあれをUIBezierPathを使って描画 let cornerLength: CGFloat = 20.0 let cornerWidth: CGFloat = 4.0 let fillColor = UIColor.blue let path = UIBezierPath() // 左上 let leftTop = CGPoint(x: captureRect.origin.x, y: captureRect.origin.y) path.move(to: leftTop) path.addLine(to: CGPoint(x: leftTop.x, y: leftTop.y + cornerLength)) path.addLine(to: CGPoint(x: leftTop.x + cornerWidth, y: leftTop.y + cornerLength)) path.addLine(to: CGPoint(x: leftTop.x + cornerWidth, y: leftTop.y + cornerWidth)) path.addLine(to: CGPoint(x: leftTop.x + cornerLength, y: leftTop.y + cornerWidth)) path.addLine(to: CGPoint(x: leftTop.x + cornerLength, y: leftTop.y)) path.close() fillColor.setFill() path.fill() // 右上 let rightTop = CGPoint(x: captureRect.origin.x + captureRect.width, y: captureRect.origin.y) path.move(to: rightTop) path.addLine(to: CGPoint(x: rightTop.x - cornerLength, y: rightTop.y)) path.addLine(to: CGPoint(x: rightTop.x - cornerLength, y: rightTop.y + cornerWidth)) path.addLine(to: CGPoint(x: rightTop.x - cornerWidth, y: rightTop.y + cornerWidth)) path.addLine(to: CGPoint(x: rightTop.x - cornerWidth, y: rightTop.y + cornerLength)) path.addLine(to: CGPoint(x: rightTop.x, y: rightTop.y + cornerLength)) path.close() fillColor.setFill() path.fill() // 右下 let rightBottom = CGPoint(x: captureRect.origin.x + captureRect.width, y: captureRect.origin.y + captureRect.height) path.move(to: rightBottom) path.addLine(to: CGPoint(x: rightBottom.x, y: rightBottom.y - cornerLength)) path.addLine(to: CGPoint(x: rightBottom.x - cornerWidth, y: rightBottom.y - cornerLength)) path.addLine(to: CGPoint(x: rightBottom.x - cornerWidth, y: rightBottom.y - cornerWidth)) path.addLine(to: CGPoint(x: rightBottom.x - cornerLength, y: rightBottom.y - cornerWidth)) path.addLine(to: CGPoint(x: rightBottom.x - cornerLength, y: rightBottom.y)) path.close() fillColor.setFill() path.fill() // 左下 let leftBottom = CGPoint(x: captureRect.origin.x, y: captureRect.origin.y + captureRect.height) path.move(to: leftBottom) path.addLine(to: CGPoint(x: leftBottom.x, y: leftBottom.y - cornerLength)) path.addLine(to: CGPoint(x: leftBottom.x + cornerWidth, y: leftBottom.y - cornerLength)) path.addLine(to: CGPoint(x: leftBottom.x + cornerWidth, y: leftBottom.y - cornerWidth)) path.addLine(to: CGPoint(x: leftBottom.x + cornerLength, y: leftBottom.y - cornerWidth)) path.addLine(to: CGPoint(x: leftBottom.x + cornerLength, y: leftBottom.y)) path.close() fillColor.setFill() path.fill() }
おわりに
captureViewを用意するのほかの理由は:
- AutoLayoutで各画面サイズと回転を簡単に対応できる
- 簡単に、QRCodeスキャンのcontroller側に、スキャンできる領域を伝えることができる
- 正方形のレイアウトのコード書きたくない