這是公司上上上一個項目的自定義相機界面,原來是swift2.0寫的,今天改為swift3.0,記錄一下.
效果圖如下:
使用AVFoundation制作.
屬性:
1 var device:AVCaptureDevice! //獲取設備:如攝像頭 2 var input:AVCaptureDeviceInput! //輸入流 3 var photoOutput:AVCaptureStillImageOutput! //輸出流 4 var output:AVCaptureMetadataOutput! //當啟動攝像頭開始捕獲輸入 5 var session:AVCaptureSession!//會話,協調着intput到output的數據傳輸,input和output的橋梁 6 var previewLayer:AVCaptureVideoPreviewLayer! //圖像預覽層,實時顯示捕獲的圖像 7 8 var photoButton: UIButton? //拍照按鈕 9 var imageView: UIImageView? //拍照后的成像 10 var image: UIImage? //拍照后的成像 11 var isJurisdiction: Bool? //是否獲取了拍照標示 12 var flashBtn:UIButton? //閃光燈按鈕
在viewDidLoad里面判斷下權限,沒給權限給個提示
isJurisdiction = canUserCamear() if isJurisdiction! { customCamera() //自定義相機 customUI() //自定義相機按鈕 } else { return }
// MARK: - 檢查相機權限 func canUserCamear() -> Bool { let authStatus: AVAuthorizationStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo) if authStatus == .denied { let alertView = UIAlertView(title: "請打開相機權限", message: "設置-隱私-相機", delegate: self, cancelButtonTitle: "確定", otherButtonTitles: "取消") alertView.tag = 100 alertView.show() return false } else { return true } return true }
自定義相機:

1 //MARK: 初始化自定義相機 2 func customCamera(){ 3 guard let devices = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo) as? [AVCaptureDevice] else { return } //初始化攝像頭設備 4 guard let device = devices.filter({ return $0.position == .back }).first else{ return} 5 self.device = device 6 //輸入流初始化 7 self.input = try? AVCaptureDeviceInput(device: device) 8 //照片輸出流初始化 9 self.photoOutput = AVCaptureStillImageOutput.init() 10 //輸出流初始化 11 self.output = AVCaptureMetadataOutput.init() 12 //生成會話 13 self.session = AVCaptureSession.init() 14 if(self.session.canSetSessionPreset("AVCaptureSessionPreset1280x720")){ 15 self.session.sessionPreset = "AVCaptureSessionPreset1280x720" 16 } 17 if(self.session.canAddInput(self.input)){ 18 self.session.addInput(self.input) 19 } 20 if(self.session.canAddOutput(self.photoOutput)){ 21 self.session.addOutput(self.photoOutput) 22 } 23 //使用self.session,初始化預覽層,self.session負責驅動input進行信息的采集,layer負責把圖像渲染顯示 24 self.previewLayer = AVCaptureVideoPreviewLayer.init(session: self.session) 25 self.previewLayer.frame = CGRect.init(x: 0, y: 0, width: kScreenWH.width, height: kScreenWH.height) 26 self.previewLayer.videoGravity = "AVLayerVideoGravityResizeAspectFill" 27 self.view.layer.addSublayer(self.previewLayer) 28 //啟動 29 self.session.startRunning() 30 if ((try? device.lockForConfiguration()) != nil) { 31 if device.isFlashModeSupported(.auto) { 32 device.flashMode = .auto 33 } 34 //自動白平衡 35 if device.isWhiteBalanceModeSupported(.autoWhiteBalance) { 36 device.whiteBalanceMode = .autoWhiteBalance 37 } 38 device.unlockForConfiguration() 39 } 40 41 //閃光燈 42 do{ try device.lockForConfiguration() }catch{ } 43 if device.hasFlash == false { return } 44 device.flashMode = AVCaptureFlashMode.auto 45 device.unlockForConfiguration() 46 47 }
自定義相機界面按鈕:拍照,取消,閃光燈,前后拍照切換按鈕

1 //MARK: 添加自定義按鈕等UI 2 func customUI(){ 3 //前后攝像頭切換 4 let changeBtn = UIButton.init() 5 changeBtn.frame = CGRect.init(x: kScreenWH.width - 50, y: 20, width: 40, height: 40) 6 changeBtn.setImage(#imageLiteral(resourceName: "change"), for: .normal) 7 changeBtn.addTarget(self, action: #selector(self.changeCamera), for: .touchUpInside) 8 view.addSubview(changeBtn) 9 10 //拍照按鈕 11 photoButton = UIButton(type: .custom) 12 photoButton?.frame = CGRect(x: kScreenWH.width * 1 / 2.0 - 30, y: kScreenWH.height - 100, width: 60, height: 60) 13 photoButton?.setImage(UIImage(named: "photograph"), for: .normal) 14 photoButton?.setImage(UIImage(named: "photograph_Select"), for: .normal) 15 photoButton?.addTarget(self, action: #selector(self.shutterCamera), for: .touchUpInside) 16 view.addSubview(photoButton!) 17 18 //閃光燈按鈕 19 flashBtn = UIButton.init() 20 flashBtn?.frame = CGRect.init(x: 10, y: 20, width: 40, height: 40) 21 flashBtn?.addTarget(self, action: #selector(self.flashAction), for: .touchUpInside) 22 flashBtn?.setImage(#imageLiteral(resourceName: "flash-A"), for: .normal) 23 view.addSubview(flashBtn!) 24 25 //取消 26 let cancelBtn = UIButton.init() 27 cancelBtn.frame = CGRect.init(x: 10, y: kScreenWH.height - 100, width: 60, height: 60) 28 cancelBtn.setTitle("取消", for: .normal) 29 cancelBtn.addTarget(self, action: #selector(self.cancelActin), for: .touchUpInside) 30 view.addSubview(cancelBtn) 31 } 32 //MARK:前后攝像頭更改事件 33 func changeCamera(){ 34 //獲取之前的鏡頭 35 guard var position = input?.device.position else { return } 36 //獲取當前應該顯示的鏡頭 37 position = position == .front ? .back : .front 38 //創建新的device 39 guard let devices = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo) as? [AVCaptureDevice] else { return } 40 // 1.2.取出獲取前置攝像頭 41 let d = devices.filter({ return $0.position == position }).first 42 device = d 43 //input 44 guard let videoInput = try? AVCaptureDeviceInput(device: d) else { return } 45 46 //切換 47 session.beginConfiguration() 48 session.removeInput(self.input!) 49 session.addInput(videoInput) 50 session.commitConfiguration() 51 self.input = videoInput 52 53 }
拍照按鈕點擊事件:

1 //MARK:拍照按鈕點擊事件 2 func shutterCamera(){ 3 let videoConnection: AVCaptureConnection? = photoOutput.connection(withMediaType: AVMediaTypeVideo) 4 if videoConnection == nil { 5 print("take photo failed!") 6 return 7 } 8 photoOutput.captureStillImageAsynchronously(from: videoConnection ?? AVCaptureConnection(), completionHandler: {(_ imageDataSampleBuffer: CMSampleBuffer?, _ error: Error?) -> Void in 9 if imageDataSampleBuffer == nil { 10 return 11 } 12 let imageData: Data? = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer) //照片數據流 13 self.image = UIImage(data: imageData!) 14 self.session.stopRunning() 15 self.imageView = UIImageView(frame: self.previewLayer.frame) 16 self.view.insertSubview(self.imageView!, belowSubview: self.photoButton!) 17 self.imageView?.layer.masksToBounds = true 18 self.imageView?.image = self.image 19 print("image size = \(NSStringFromCGSize((self.image?.size)!))") 20 }) 21 }
閃光燈切換事件:

1 //MARK: 閃光燈開關 2 func flashAction(){ 3 try? device.lockForConfiguration() 4 switch device.flashMode.rawValue { 5 case 0: 6 device!.flashMode = AVCaptureFlashMode.on 7 flashBtn?.setImage(#imageLiteral(resourceName: "flash-on"), for: .normal) 8 break 9 case 1: 10 device!.flashMode = AVCaptureFlashMode.auto 11 flashBtn?.setImage(#imageLiteral(resourceName: "flash-A"), for: .normal) 12 break 13 default: 14 device!.flashMode = AVCaptureFlashMode.off 15 flashBtn?.setImage(#imageLiteral(resourceName: "flash-off"), for: .normal) 16 } 17 device.unlockForConfiguration() 18 19 }
取消按鈕點擊事件:
//MARK:取消按鈕 func cancelActin(){ self.imageView?.removeFromSuperview() self.session.startRunning() }
github源碼地址:https://github.com/pheromone/swift_custom_camera