这是公司上上上一个项目的自定义相机界面,原来是swift2.0写的,今天改为swift3.0,记录一下.

效果图如下:

                                                                                                                              

使用AVFoundation制作.

属性:

     var device:AVCaptureDevice!   //获取设备:如摄像头
var input:AVCaptureDeviceInput! //输入流
var photoOutput:AVCaptureStillImageOutput! //输出流
var output:AVCaptureMetadataOutput! //当启动摄像头开始捕获输入
var session:AVCaptureSession!//会话,协调着intput到output的数据传输,input和output的桥梁
var previewLayer:AVCaptureVideoPreviewLayer! //图像预览层,实时显示捕获的图像 var photoButton: UIButton? //拍照按钮
var imageView: UIImageView? //拍照后的成像
var image: UIImage? //拍照后的成像
var isJurisdiction: Bool? //是否获取了拍照标示
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 =
alertView.show()
return false
}
else {
return true
}
return true
}

自定义相机:

  //MARK: 初始化自定义相机
func customCamera(){
guard let devices = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo) as? [AVCaptureDevice] else { return } //初始化摄像头设备
guard let device = devices.filter({ return $.position == .back }).first else{ return}
self.device = device
//输入流初始化
self.input = try? AVCaptureDeviceInput(device: device)
//照片输出流初始化
self.photoOutput = AVCaptureStillImageOutput.init()
//输出流初始化
self.output = AVCaptureMetadataOutput.init()
//生成会话
self.session = AVCaptureSession.init()
if(self.session.canSetSessionPreset("AVCaptureSessionPreset1280x720")){
self.session.sessionPreset = "AVCaptureSessionPreset1280x720"
}
if(self.session.canAddInput(self.input)){
self.session.addInput(self.input)
}
if(self.session.canAddOutput(self.photoOutput)){
self.session.addOutput(self.photoOutput)
}
//使用self.session,初始化预览层,self.session负责驱动input进行信息的采集,layer负责把图像渲染显示
self.previewLayer = AVCaptureVideoPreviewLayer.init(session: self.session)
self.previewLayer.frame = CGRect.init(x: , y: , width: kScreenWH.width, height: kScreenWH.height)
self.previewLayer.videoGravity = "AVLayerVideoGravityResizeAspectFill"
self.view.layer.addSublayer(self.previewLayer)
//启动
self.session.startRunning()
if ((try? device.lockForConfiguration()) != nil) {
if device.isFlashModeSupported(.auto) {
device.flashMode = .auto
}
//自动白平衡
if device.isWhiteBalanceModeSupported(.autoWhiteBalance) {
device.whiteBalanceMode = .autoWhiteBalance
}
device.unlockForConfiguration()
} //闪光灯
do{ try device.lockForConfiguration() }catch{ }
if device.hasFlash == false { return }
device.flashMode = AVCaptureFlashMode.auto
device.unlockForConfiguration() }

自定义相机界面按钮:拍照,取消,闪光灯,前后拍照切换按钮

 //MARK: 添加自定义按钮等UI
func customUI(){
//前后摄像头切换
let changeBtn = UIButton.init()
changeBtn.frame = CGRect.init(x: kScreenWH.width - , y: , width: , height: )
changeBtn.setImage(#imageLiteral(resourceName: "change"), for: .normal)
changeBtn.addTarget(self, action: #selector(self.changeCamera), for: .touchUpInside)
view.addSubview(changeBtn) //拍照按钮
photoButton = UIButton(type: .custom)
photoButton?.frame = CGRect(x: kScreenWH.width * / 2.0 - , y: kScreenWH.height - , width: , height: )
photoButton?.setImage(UIImage(named: "photograph"), for: .normal)
photoButton?.setImage(UIImage(named: "photograph_Select"), for: .normal)
photoButton?.addTarget(self, action: #selector(self.shutterCamera), for: .touchUpInside)
view.addSubview(photoButton!) //闪光灯按钮
flashBtn = UIButton.init()
flashBtn?.frame = CGRect.init(x: , y: , width: , height: )
flashBtn?.addTarget(self, action: #selector(self.flashAction), for: .touchUpInside)
flashBtn?.setImage(#imageLiteral(resourceName: "flash-A"), for: .normal)
view.addSubview(flashBtn!) //取消
let cancelBtn = UIButton.init()
cancelBtn.frame = CGRect.init(x: , y: kScreenWH.height - , width: , height: )
cancelBtn.setTitle("取消", for: .normal)
cancelBtn.addTarget(self, action: #selector(self.cancelActin), for: .touchUpInside)
view.addSubview(cancelBtn)
}
//MARK:前后摄像头更改事件
func changeCamera(){
//获取之前的镜头
guard var position = input?.device.position else { return }
//获取当前应该显示的镜头
position = position == .front ? .back : .front
//创建新的device
guard let devices = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo) as? [AVCaptureDevice] else { return }
// 1.2.取出获取前置摄像头
let d = devices.filter({ return $.position == position }).first
device = d
//input
guard let videoInput = try? AVCaptureDeviceInput(device: d) else { return } //切换
session.beginConfiguration()
session.removeInput(self.input!)
session.addInput(videoInput)
session.commitConfiguration()
self.input = videoInput }

拍照按钮点击事件:

     //MARK:拍照按钮点击事件
func shutterCamera(){
let videoConnection: AVCaptureConnection? = photoOutput.connection(withMediaType: AVMediaTypeVideo)
if videoConnection == nil {
print("take photo failed!")
return
}
photoOutput.captureStillImageAsynchronously(from: videoConnection ?? AVCaptureConnection(), completionHandler: {(_ imageDataSampleBuffer: CMSampleBuffer?, _ error: Error?) -> Void in
if imageDataSampleBuffer == nil {
return
}
let imageData: Data? = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer) //照片数据流
self.image = UIImage(data: imageData!)
self.session.stopRunning()
self.imageView = UIImageView(frame: self.previewLayer.frame)
self.view.insertSubview(self.imageView!, belowSubview: self.photoButton!)
self.imageView?.layer.masksToBounds = true
self.imageView?.image = self.image
print("image size = \(NSStringFromCGSize((self.image?.size)!))")
})
}

闪光灯切换事件:

     //MARK: 闪光灯开关
func flashAction(){
try? device.lockForConfiguration()
switch device.flashMode.rawValue {
case :
device!.flashMode = AVCaptureFlashMode.on
flashBtn?.setImage(#imageLiteral(resourceName: "flash-on"), for: .normal)
break
case :
device!.flashMode = AVCaptureFlashMode.auto
flashBtn?.setImage(#imageLiteral(resourceName: "flash-A"), for: .normal)
break
default:
device!.flashMode = AVCaptureFlashMode.off
flashBtn?.setImage(#imageLiteral(resourceName: "flash-off"), for: .normal)
}
device.unlockForConfiguration() }

取消按钮点击事件:

    //MARK:取消按钮
func cancelActin(){
self.imageView?.removeFromSuperview()
self.session.startRunning()
}

github源码地址:https://github.com/pheromone/swift_custom_camera

swift3.0自定义相机界面的更多相关文章

  1. swift3.0 自定义键盘

    ...绕了一大圈,又绕回原生来了,今天,学习一下swift3.0语法下的自定义键盘.效果图如下: 其实,很简单,只需要把UITextView(或者UITextField)的inputView属性设置为 ...

  2. swift3.0 创建经典界面的九宫图

    网络上很多例子都是早期的 Object-C的效果,现在用到Swift3.0开发,故把网络上的例子翻译过来,达到基本的效果.可是现在这个还不算很满意,再下次继续进行优化 override func vi ...

  3. Swift3.0 自定义tableView复用cell 的写法,与CollectionViewCell的不同,数据model

    Model数据 class HospitalModel: NSObject { //后边不赋值 会报错 var imgurl :String = "" var introducti ...

  4. 如何用uniapp+vue开发自定义相机插件——拍照+录像功能

    调用手机的相机功能并实现拍照和录像是很多APP与插件都必不可少的一个功能,今天智密科技就来分享一下如何基于uniapp + vue实现自定义相机界面,并且实现: 1: 自定义拍照 2: 自定义录像 3 ...

  5. Swift2.3 --> Swift3.0 的变化

    Swift3.0语法变化 首先和大家分享一下学习新语法的技巧: 用Xcode8打开自己的Swift2.3的项目,选择Edit->Convert->To Current Swift Synt ...

  6. Android相机使用(系统相机、自定义相机、大图片处理)

    本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显示出来,该例子也会涉及到Android加载大图片时候的处理(避免OOM),还有简要提一下有些人Surf ...

  7. Android自定义相机拍照、图片裁剪的实现

    最近项目里面又要加一个拍照搜题的功能,也就是用户对着不会做的题目拍一张照片,将照片的文字使用ocr识别出来,再调用题库搜索接口搜索出来展示给用户,类似于小猿搜题.学霸君等app. 其实Android提 ...

  8. Swift3.0语法变化

    写在前面 首先和大家分享一下学习新语法的技巧:用Xcode8打开自己的Swift2.3的项目,选择Edit->Convert->To Current Swift Syntax- 让Xcod ...

  9. Android调用系统相机以及自定义相机

    0.综述 自定义相机,此处展示简单的相机功能,官方文档中还有相应关于视频拍摄的内容,此处不提 1.添加权限 <!--相机权限,数据存储--> <uses-permission and ...

随机推荐

  1. 配置cron定时任务

    题:配置一个 cron 任务用户 natasha 必须配置一个定时执行任务,每天在本地时间 14:23 时执行命令* /bin/echo hiya 答: # 方法1 # su - natasha # ...

  2. P1903 [国家集训队]数颜色 / 维护队列

    思路 带修莫队的板子 带修莫队只需要多维护一个时间的指针即可,记录一下每个询问在第几次修改之后,再回退或者前进几个修改操作 排序的时候如果a.l和b.l在一个块里,就看r,如果a.r和b.r在一个块里 ...

  3. FI 创建资产接口AS01

    FUNCTION ZREIP_CREATE_AS01TSET. *"------------------------------------------------------------- ...

  4. Docker应用

    1.tomcat容器创建 docker run -d --name Jdd_tomcat  -p 8081:8080 tomcat [root@localhost etc]# docker run - ...

  5. tcp协议以及socket介绍

    壹:tcp协议:可靠传输 一: 3次握手,建立链接:4次挥手,断开链接 3次握手,建立链接:图解 ,这样双向通路就建立完成了. 在建立链接时,并没有数据传输,所以中间两部可以合在一起,也就是3次握手, ...

  6. TCP/IP三次握手和四次挥手

    原博链接:https://www.cnblogs.com/Andya/p/7272462.html

  7. 文献导读 | A Pan-Cancer Analysis of Enhancer Expression in Nearly 9000 Patient Samples

    Chen, H., Li, C., Peng, X., Zhou, Z., Weinstein, J.N., Liang, H. and Cancer Genome Atlas Research Ne ...

  8. 深入理解Plasma(三)Plasma MVP

    这一系列文章将围绕以太坊的二层扩容框架 Plasma,介绍其基本运行原理,具体操作细节,安全性讨论以及未来研究方向等.本篇文章主要介绍 Plasma 的一个最小实现 Plasma MVP(Minima ...

  9. C#集合类型大揭秘

    集合是.NET FCL(Framework Class Library)的重要组成部分,我们平常撸C#代码时免不了和集合打交道,FCL提供了丰富易用的集合类型,给我们撸码提供了极大的便利.正是因为这种 ...

  10. fcgi-2.4.1 fastcgi开发包 make编译出错

    fcgio.cpp: In destructor 'virtual fcgi_streambuf::~fcgi_streambuf()':fcgio.cpp:50: error: 'EOF' was ...