iOS 10自定义相机功能
时间:2021-01-29 09:30:31|栏目:iOS代码|点击: 次
本文实例为大家分享了iOS 10自定义相机功能的具体代码,供大家参考,具体内容如下
直接上代码
// // TGCameraVC.swift // TGPhotoPicker // // Created by targetcloud on 2017/7/25. // Copyright © 2017年 targetcloud. All rights reserved. // import UIKit import AVFoundation import Photos @available(iOS 10.0, *) class TGCameraVC: UIViewController { var callbackPicutureData: ((Data?) -> ())? private var device: AVCaptureDevice? private var input: AVCaptureDeviceInput? private var imageOutput: AVCapturePhotoOutput? private var session: AVCaptureSession? private var previewLayer: AVCaptureVideoPreviewLayer? fileprivate var showImageContainerView: UIView? fileprivate var showImageView: UIImageView? fileprivate var picData: Data? private var flashMode: AVCaptureFlashMode = .auto private weak var flashButton: UIButton? override func viewDidLoad() { super.viewDidLoad() setupCamera() setupUI() if #available(iOS 9.0, *) { let isVCBased = Bundle.main.infoDictionary?["UIViewControllerBasedStatusBarAppearance"] as? Bool ?? false if !isVCBased{ UIApplication.shared.setStatusBarHidden(false, with: .none) } }else { UIApplication.shared.statusBarStyle = .lightContent UIApplication.shared.setStatusBarHidden(false, with: .none) } } override var prefersStatusBarHidden: Bool{ return false } override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent } private func setupCamera() { AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo) { success in if !success { let alertVC = UIAlertController(title: TGPhotoPickerConfig.shared.cameraUsage, message: TGPhotoPickerConfig.shared.cameraUsageTip, preferredStyle: .actionSheet) alertVC.addAction(UIAlertAction(title: TGPhotoPickerConfig.shared.confirmTitle, style: .default, handler: nil)) self.present(alertVC, animated: true, completion: nil) } } device = cameraWithPosistion(.back) input = try? AVCaptureDeviceInput(device: device) guard input != nil else { return } imageOutput = AVCapturePhotoOutput() session = AVCaptureSession() session?.beginConfiguration() session?.sessionPreset = TGPhotoPickerConfig.shared.sessionPreset if session!.canAddInput(input) { session!.addInput(input) } if session!.canAddOutput(imageOutput) { session!.addOutput(imageOutput) } previewLayer = AVCaptureVideoPreviewLayer(session: session) previewLayer?.frame = view.bounds previewLayer?.videoGravity = TGPhotoPickerConfig.shared.videoGravity view.layer.addSublayer(previewLayer!) session?.commitConfiguration() session?.startRunning() } private func cameraWithPosistion(_ position: AVCaptureDevicePosition) -> AVCaptureDevice { let type = AVCaptureDeviceType(rawValue: TGPhotoPickerConfig.shared.captureDeviceType.rawValue) return AVCaptureDevice.defaultDevice(withDeviceType: type, mediaType: AVMediaTypeVideo, position: position) } private func setupUI() { let takeButton = UIButton(frame: CGRect(x: 0, y: 0, width: TGPhotoPickerConfig.shared.takeWH, height: TGPhotoPickerConfig.shared.takeWH)) takeButton.center = CGPoint(x: UIScreen.main.bounds.width / 2, y: UIScreen.main.bounds.height - TGPhotoPickerConfig.shared.buttonEdge.bottom) takeButton.setImage(UIImage.size(width: TGPhotoPickerConfig.shared.takeWH, height: TGPhotoPickerConfig.shared.takeWH).border(width: 3).border(color: .white).color(.clear).corner(radius: TGPhotoPickerConfig.shared.takeWH / 2).image + UIImage.size(width: TGPhotoPickerConfig.shared.takeWH - 10, height: TGPhotoPickerConfig.shared.takeWH - 10).color(UIColor(white: 0.95, alpha: 1) ).corner(radius: (TGPhotoPickerConfig.shared.takeWH - 10) / 2).image, for: .normal) takeButton.setImage(UIImage.size(width: TGPhotoPickerConfig.shared.takeWH, height: TGPhotoPickerConfig.shared.takeWH).border(width: 3).border(color: .white).color(.clear).corner(radius: TGPhotoPickerConfig.shared.takeWH / 2).image + UIImage.size(width: TGPhotoPickerConfig.shared.takeWH - 10, height: TGPhotoPickerConfig.shared.takeWH - 10).color(UIColor(white: 0.8, alpha: 1) ).corner(radius: (TGPhotoPickerConfig.shared.takeWH - 10) / 2).image, for: .highlighted) takeButton.addTarget(self, action: #selector(takePhotoAction), for: .touchUpInside) view.addSubview(takeButton) let cameraChangeButton = UIButton(frame: CGRect(x: 0, y: 0, width: TGPhotoPickerConfig.shared.takeWH * 0.6, height: TGPhotoPickerConfig.shared.takeWH * 0.6)) cameraChangeButton.setImage(TGPhotoPickerConfig.getImageNo2x3xSuffix("camera"), for: .normal) cameraChangeButton.center = CGPoint(x: UIScreen.main.bounds.width - TGPhotoPickerConfig.shared.buttonEdge.right, y: takeButton.center.y) cameraChangeButton.addTarget(self, action: #selector(changeCameraPositionAction), for: .touchUpInside) cameraChangeButton.contentMode = .scaleAspectFit view.addSubview(cameraChangeButton) let flashChangeButton = UIButton(frame: CGRect(x: 0, y: 0, width: TGPhotoPickerConfig.shared.takeWH * 0.5, height: TGPhotoPickerConfig.shared.takeWH * 0.5)) flashChangeButton.center = CGPoint(x: cameraChangeButton.center.x, y: TGPhotoPickerConfig.shared.buttonEdge.top) flashChangeButton.setImage(TGPhotoPickerConfig.getImageNo2x3xSuffix("flashauto"), for: .normal) flashChangeButton.addTarget(self, action: #selector(flashChangeAction), for: .touchUpInside) flashChangeButton.contentMode = .scaleAspectFit flashButton = flashChangeButton view.addSubview(flashChangeButton) let backButton = UIButton(frame: CGRect(x: 0, y: 0, width: TGPhotoPickerConfig.shared.takeWH * 0.4, height: TGPhotoPickerConfig.shared.takeWH * 0.4)) backButton.center = CGPoint(x: TGPhotoPickerConfig.shared.buttonEdge.left , y: flashChangeButton.center.y) backButton.setImage(UIImage.size(width: TGPhotoPickerConfig.shared.takeWH * 0.4, height: TGPhotoPickerConfig.shared.takeWH * 0.4) .corner(radius: TGPhotoPickerConfig.shared.takeWH * 0.2) .color(.clear) .border(color: UIColor.white.withAlphaComponent(0.7)) .border(width: TGPhotoPickerConfig.shared.isShowBorder ? TGPhotoPickerConfig.shared.checkboxLineW : 0) .image .with({ context in context.setLineCap(.round) UIColor.white.setStroke() context.setLineWidth(TGPhotoPickerConfig.shared.checkboxLineW) let WH = TGPhotoPickerConfig.shared.takeWH * 0.4 context.move(to: CGPoint(x: WH * 0.6, y: WH * 0.2)) context.addLine(to: CGPoint(x: WH * 0.35, y: WH * 0.5)) context.move(to: CGPoint(x: WH * 0.35, y: WH * 0.5)) context.addLine(to: CGPoint(x: WH * 0.6, y: WH * 0.8)) context.strokePath() }), for: .normal) backButton.contentMode = .scaleAspectFit backButton.addTarget(self, action: #selector(backAction), for: .touchUpInside) view.addSubview(backButton) showImageContainerView = UIView(frame: view.bounds) showImageContainerView?.backgroundColor = TGPhotoPickerConfig.shared.previewBGColor view.addSubview(showImageContainerView!) let height = showImageContainerView!.bounds.height - TGPhotoPickerConfig.shared.takeWH - TGPhotoPickerConfig.shared.buttonEdge.bottom - TGPhotoPickerConfig.shared.previewPadding * 2 showImageView = UIImageView(frame: CGRect(x: TGPhotoPickerConfig.shared.previewPadding, y: TGPhotoPickerConfig.shared.previewPadding * 2, width: showImageContainerView!.bounds.width - 2 * TGPhotoPickerConfig.shared.previewPadding, height: height)) showImageView?.contentMode = .scaleAspectFit showImageContainerView?.addSubview(showImageView!) showImageContainerView?.isHidden = true let giveupButton = createImageOperatorButton(nil, CGPoint(x: TGPhotoPickerConfig.shared.takeWH * 1.5, y: showImageContainerView!.bounds.height - TGPhotoPickerConfig.shared.takeWH * 1.5), TGPhotoPickerConfig.shared.getCheckboxImage(true, true, .circle, TGPhotoPickerConfig.shared.takeWH * 0.7).unselect) giveupButton.addTarget(self, action: #selector(giveupImageAction), for: .touchUpInside) showImageContainerView?.addSubview(giveupButton) let ensureButton = createImageOperatorButton(nil, CGPoint(x: showImageContainerView!.bounds.width - TGPhotoPickerConfig.shared.takeWH * 1.5, y: showImageContainerView!.bounds.height - TGPhotoPickerConfig.shared.takeWH * 1.5), TGPhotoPickerConfig.shared.getCheckboxImage(true, false, .circle, TGPhotoPickerConfig.shared.takeWH * 0.7).select) ensureButton.addTarget(self, action: #selector(useImageAction), for: .touchUpInside) showImageContainerView?.addSubview(ensureButton) } private func createImageOperatorButton(_ title: String?, _ center: CGPoint, _ img: UIImage?) -> UIButton { let btn = UIButton(frame: CGRect(x: 0, y: 0, width: TGPhotoPickerConfig.shared.takeWH * 0.7, height: TGPhotoPickerConfig.shared.takeWH * 0.7)) btn.center = center btn.setTitle(title, for: .normal) btn.setImage(img, for: .normal) btn.contentMode = .scaleAspectFit return btn } @objc private func flashChangeAction() { switch flashMode { case .auto: flashMode = .on flashButton?.setImage(TGPhotoPickerConfig.getImageNo2x3xSuffix("flash"), for: .normal) case .on: flashMode = .off flashButton?.setImage(TGPhotoPickerConfig.getImageNo2x3xSuffix("flashno"), for: .normal) case .off: flashMode = .auto flashButton?.setImage(TGPhotoPickerConfig.getImageNo2x3xSuffix("flashauto"), for: .normal) } } @objc private func backAction() { dismiss(animated: true, completion: nil) } @objc private func takePhotoAction() { let connection = imageOutput?.connection(withMediaType: AVMediaTypeVideo) guard connection != nil else { return } let photoSettings = AVCapturePhotoSettings() photoSettings.flashMode = flashMode imageOutput?.capturePhoto(with: photoSettings, delegate: self) } @objc private func changeCameraPositionAction() { let animation = CATransition() animation.duration = 0.5 animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) animation.type = TGPhotoPickerConfig.shared.transitionType let newDevice: AVCaptureDevice! let newInput: AVCaptureDeviceInput? let position = input?.device.position if position == .front { newDevice = cameraWithPosistion(.back) animation.subtype = kCATransitionFromLeft } else { newDevice = cameraWithPosistion(.front) animation.subtype = kCATransitionFromRight } newInput = try? AVCaptureDeviceInput(device: newDevice) guard newInput != nil else{ return } previewLayer?.add(animation, forKey: nil) session?.beginConfiguration() session?.removeInput(input) if session!.canAddInput(newInput) { session?.addInput(newInput!) input = newInput } else { session?.addInput(input) } session?.commitConfiguration() } @objc private func giveupImageAction() { showImageView?.image = UIImage() showImageContainerView?.isHidden = true } @objc private func useImageAction() { callbackPicutureData?(picData) dismiss(animated: true, completion: nil) } } @available(iOS 10.0, *) extension TGCameraVC: AVCapturePhotoCaptureDelegate { func capture(_ captureOutput: AVCapturePhotoOutput, didFinishProcessingPhotoSampleBuffer photoSampleBuffer: CMSampleBuffer?, previewPhotoSampleBuffer: CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?) { if error != nil { print("error = \(String(describing: error?.localizedDescription))") } else { if let imageData = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: photoSampleBuffer!, previewPhotoSampleBuffer: previewPhotoSampleBuffer){ picData = imageData showImageContainerView?.isHidden = false showImageView?.image = UIImage(data: imageData) if TGPhotoPickerConfig.shared.saveImageToPhotoAlbum{ self.saveImageToPhotoAlbum(UIImage(data: imageData)!) } } } } fileprivate func saveImageToPhotoAlbum(_ savedImage:UIImage){ UIImageWriteToSavedPhotosAlbum(savedImage, self, #selector(imageDidFinishSavingWithErrorContextInfo), nil) } @objc fileprivate func imageDidFinishSavingWithErrorContextInfo(image:UIImage,error:NSError?,contextInfo:UnsafeMutableRawPointer?){ if canUseAlbum(){ let msg = (error != nil) ? TGPhotoPickerConfig.shared.saveImageFailTip : TGPhotoPickerConfig.shared.saveImageSuccessTip let alert = UIAlertView(title: TGPhotoPickerConfig.shared.saveImageTip, message: msg, delegate: self, cancelButtonTitle: TGPhotoPickerConfig.shared.confirmTitle) alert.show() } } fileprivate func canUseAlbum()-> Bool{ if PHPhotoLibrary.authorizationStatus() != PHAuthorizationStatus.authorized { let alertView = UIAlertView(title: TGPhotoPickerConfig.shared.PhotoLibraryUsage, message: TGPhotoPickerConfig.shared.PhotoLibraryUsageTip, delegate: nil, cancelButtonTitle: TGPhotoPickerConfig.shared.confirmTitle, otherButtonTitles: TGPhotoPickerConfig.shared.cancelTitle) alertView.tag = TGPhotoPickerConfig.shared.alertViewTag alertView.show() return false }else{ return true } } }
效果如下
完整使用DEMO见:点击打开链接