import UIKit
import AVFoundation
protocol ScanViewDelegate: NSObjectProtocol{
func captureOutputSuccess(pileCode:String);
}
class ScanView: UIView,AVCaptureMetadataOutputObjectsDelegate {
/// 创建设备
var captureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
/// 捕获视频
var captureSession : AVCaptureSession?
/// 捕获视频的预览层
var videoPreviewLayer : AVCaptureVideoPreviewLayer?
/// 提示文字
var titleLabel = UILabel()
/// 图片
var quJingImage:UIImageView!
var saoMaTiaoImage : UIImageView?
/// 开灯
var openLampButton:UIButton!
// 代理
weak var delegate : ScanViewDelegate!
/// 元数据输出
let captureMetadataOutput = AVCaptureMetadataOutput()
override init(frame: CGRect) {
super.init(frame: frame)
createQrView()
createScanPanelView()
}
/// 创建扫描设备
func createQrView(){
let authStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo)
if authStatus == AVAuthorizationStatus.restricted || authStatus == AVAuthorizationStatus.denied {
DZAlertView.sharedInstance.show(DZAlertViewType.blackViewAndClickDisappear, contentType: DZAlertContentViewType.warning, message: ["请在iPhone的“设置”-“隐私”-“相机”功能中,找到“\(Bundle.main.appDisplayName)”打开相机访问权限"])
return
}
//给设备添加input输入
var input : AnyObject!
do{
input = try AVCaptureDeviceInput(device: captureDevice)
}catch{
}
if input == nil {
return
}
captureSession = AVCaptureSession()
captureSession?.addInput(input as! AVCaptureInput)
captureSession?.addOutput(captureMetadataOutput)
captureMetadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
captureMetadataOutput.metadataObjectTypes = [AVMetadataObjectTypeQRCode]
/// 显示的layer
videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
let isphone = UIDevice.current.userInterfaceIdiom == UIUserInterfaceIdiom.phone ? true : false
if isphone {
videoPreviewLayer?.connection.videoOrientation = AVCaptureVideoOrientation.portrait
}else{
videoPreviewLayer?.connection.videoOrientation = AVCaptureVideoOrientation.landscapeRight
}
videoPreviewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
videoPreviewLayer?.frame = self.layer.bounds
self.layer.addSublayer(videoPreviewLayer!)
captureSession?.startRunning()
}
/// 创建扫描面板
func createScanPanelView(){
//提示文字
self.addSubview(titleLabel)
titleLabel.snp.makeConstraints { (make) -> Void in
make.top.equalTo(UIConfigure.Width / 750 * 45)
make.left.equalTo(40)
make.right.equalTo(-40)
}
titleLabel.numberOfLines = 0
titleLabel.textAlignment = NSTextAlignment.center
titleLabel.text = "将二维码放入框中即可自动扫描"
titleLabel.textColor = UIColor.white
titleLabel.font = UIConfigure.Font14
// 取景框图片
quJingImage = UIImageView(image: BaseImage(named: "QSD_Scan_ScanQr")?.image)
self.addSubview(quJingImage)
quJingImage.snp.makeConstraints { (make) -> Void in
make.top.equalTo(titleLabel.snp.bottom).offset(UIConfigure.Width / 750 * 30 * UIConfigure.SizeScale)
make.centerX.equalTo(self.snp.centerX)
make.width.equalTo(220 * UIConfigure.SizeScale)
make.height.equalTo(220 * UIConfigure.SizeScale)
}
self.layoutIfNeeded()
print(CGRect(x: quJingImage.frame.origin.x / UIConfigure.Width, y: quJingImage.frame.origin.y / (UIConfigure.Height - 64), width: quJingImage.frame.size.width / UIConfigure.Width, height: quJingImage.frame.size.height / (UIConfigure.Height - 64)))
// captureMetadataOutput.rectOfInterest = CGRect(x: quJingImage.frame.origin.x / UIConfigure.Height, y: quJingImage.frame.origin.y / UIConfigure.Width, width: quJingImage.frame.size.width / UIConfigure.Width, height: quJingImage.frame.size.height / UIConfigure.Width)
// 上下左右四个遮盖黑边
let topView = UIView()
self.addSubview(topView)
topView.snp.makeConstraints { (make) -> Void in
make.top.equalTo(0)
make.left.equalTo(0)
make.right.equalTo(0)
make.bottom.equalTo(quJingImage.snp.top)
}
topView.backgroundColor = UIColor.black
topView.alpha = 0.3
let leftView = UIView()
self.addSubview(leftView)
leftView.snp.makeConstraints { (make) -> Void in
make.top.equalTo(topView.snp.bottom)
make.left.equalTo(0)
make.right.equalTo(quJingImage.snp.left)
make.bottom.equalTo(0)
}
leftView.backgroundColor = UIColor.black
leftView.alpha = 0.3
let rightView = UIView()
self.addSubview(rightView)
rightView.snp.makeConstraints { (make) -> Void in
make.top.equalTo(topView.snp.bottom)
make.left.equalTo(quJingImage.snp.right)
make.right.equalTo(0)
make.bottom.equalTo(0)
}
rightView.backgroundColor = UIColor.black
rightView.alpha = 0.3
let bottomView = UIView()
self.addSubview(bottomView)
bottomView.snp.makeConstraints { (make) -> Void in
make.top.equalTo(quJingImage.snp.bottom)
make.left.equalTo(leftView.snp.right)
make.right.equalTo(rightView.snp.left)
make.bottom.equalTo(0)
}
bottomView.backgroundColor = UIColor.black
bottomView.alpha = 0.3
self.bringSubview(toFront: titleLabel)
//扫描条不断动的那个
saoMaTiaoImage = UIImageView(image: BaseImage(named: "QSD_Scan_ScanQrLIne")?.image)
self.addSubview(saoMaTiaoImage!)
saoMaTiaoImage!.snp.makeConstraints { (make) -> Void in
make.top.equalTo(quJingImage.snp.top)
make.centerX.equalTo(quJingImage.snp.centerX)
make.width.equalTo(200 * UIConfigure.SizeScale)
make.height.equalTo(1)
}
saoMaTiaoImage?.isHidden = false
changeStyle()
//闪光灯按钮
openLampButton = UIButton()
self.addSubview(openLampButton)
openLampButton.snp.makeConstraints { (make) -> Void in
make.top.equalTo(quJingImage.snp.bottom).offset(UIConfigure.Width / 750 * 15 * UIConfigure.SizeScale)
make.left.equalTo(quJingImage.snp.left)
make.right.equalTo(quJingImage.snp.right)
make.height.equalTo(UIConfigure.SimallButtonHeight)
}
openLampButton.setTitle("开灯", for: UIControlState.normal)
openLampButton.setTitle("关灯", for: UIControlState.selected)
openLampButton.addTarget(self, action: #selector(ScanView.openShanGuang(sender:)), for: UIControlEvents.touchUpInside)
openLampButton.setTitleColor(UIConfigure.ThemeColor, for: UIControlState.normal)
openLampButton.titleLabel?.textColor = UIConfigure.ThemeColor
openLampButton.backgroundColor = UIColor.white
openLampButton.layer.cornerRadius = UIConfigure.CornerRadius
openLampButton.layer.masksToBounds = true
openLampButton.layer.borderColor = UIConfigure.ThemeColor.cgColor
openLampButton.layer.borderWidth = 0.5
}
func changeStyle(){
guard self.saoMaTiaoImage != nil else {
return
}
self.saoMaTiaoImage?.isHidden = false
UIView.animate(withDuration: 3.5, animations: { [weak self] () -> Void in
if(self != nil){
self!.saoMaTiaoImage?.transform = CGAffineTransform(translationX: 0, y: 220 * UIConfigure.SizeScale)
}
}) { [weak self](end) -> Void in
if(self != nil){
UIView.animate(withDuration: 3.5, animations: { [weak self] in
if(self != nil){
self!.saoMaTiaoImage?.transform = CGAffineTransform.identity
}
}, completion: { [weak self](end) in
if self != nil {
self!.changeStyle()
}
})
}
}
}
/// 开闪光
func openShanGuang(sender:UIButton){
sender.isSelected = !sender.isSelected
if captureDevice != nil && captureDevice!.hasFlash && captureDevice!.hasTorch {
do {
try captureDevice?.lockForConfiguration()
if sender.isSelected {
captureDevice!.flashMode = AVCaptureFlashMode.on
captureDevice!.torchMode = AVCaptureTorchMode.on
}else{
captureDevice!.flashMode = AVCaptureFlashMode.off
captureDevice!.torchMode = AVCaptureTorchMode.off
}
captureDevice?.unlockForConfiguration()
}catch{
}
}else{
DZAlertView.sharedInstance.show(DZAlertViewType.blackViewAndClickDisappear, contentType: DZAlertContentViewType.warning, message: ["不能打开设备的闪光灯"])
}
}
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
if metadataObjects == nil || metadataObjects.count == 0 {
return
}
playSoundEffect(name: "Qcodesound.caf")
let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
if metadataObj.type == AVMetadataObjectTypeQRCode {
if metadataObj.stringValue != nil {
captureSession?.stopRunning()
print("刚刚扫描出来!!!\(metadataObj.stringValue)")
delegate.captureOutputSuccess(pileCode: metadataObj.stringValue!)
}
}
}
/// 扫描成功后播放声音
///
/// - Parameter name: 地址
func playSoundEffect(name : String){
let audioFile = Bundle.main.path(forResource: name, ofType: nil)
let fileUrl = URL(fileURLWithPath: audioFile!)
var soundID : SystemSoundID = 0
AudioServicesCreateSystemSoundID(fileUrl as CFURL, &soundID)
AudioServicesAddSystemSoundCompletion(soundID, nil, nil, { (SounID, clientData) in
print("播放完成")
}, nil)
AudioServicesPlaySystemSound(soundID)
}
deinit {
print("扫描销毁")
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}