这是公司上上上一个项目的自定义相机界面,原来是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. 程序员的快速开发框架:Github上 10 大优秀的开源后台控制面板

    程序员的快速开发框架:Github上 10 大优秀的开源后台控制面板 Web 开发中几乎的平台都需要一个后台管理,但是从零开发一套后台控制面板并不容易,幸运的是有很多开源免费的后台控制面板可以给开发者 ...

  2. ELK(ElasticSearch+Logstash+ Kibana)搭建实时日志分析平台

    一.简介 ELK 由三部分组成elasticsearch.logstash.kibana,elasticsearch是一个近似实时的搜索平台,它让你以前所未有的速度处理大数据成为可能. Elastic ...

  3. Dockerfile构建容器---语法高亮

    三个文件扔进相关的目录即可 wget -O /usr/share/vim/vimfiles/doc/dockerfile.txt https://raw.githubusercontent.com/a ...

  4. 剑指offer(14)链表中倒数第K个节点

    题目描述 输入一个链表,输出该链表中倒数第k个节点. 题目分析 用两个指针来跑,两个指针中间相距k-1个节点,第一个指针先跑,跑到了第k个节点时,第二个指针则是第一个节点. 这时候两个一起跑.当第一个 ...

  5. JS设计模式(11)中介者模式

    什么是中介者模式? 中介者模式:对象和对象之间借助第三方中介者进行通信. 定义:用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的 ...

  6. Struts2 使用Jquery+ajax 文件上传

    话不多说 直接上代码 前台js: var formData = new FormData(); formData.append("file1",$("#file1&quo ...

  7. JS求任意字符串中出现最多的字符以及出现的次数

    我爱撸码,撸码使我感到快乐!大家好,我是Counter本节讲讲如何利用JS来查找任意给定的字符串,求字符串中出现次数最多的字符,出现的次数.直接上代码了,该注释的都注释啦.非常轻松加愉快.效果如下: ...

  8. 20175312 2018-2019-2 《Java程序设计》第1周学习总结

    20175312 2018-2019-2 <Java程序设计>第1周学习总结 教材学习内容总结 已依照教材要求完成了第一章的学习,我总结的话,主要的学习量还是在安装相关软件上.其他的,比如 ...

  9. POJ3090 Visible Lattice Points

    /* * POJ3090 Visible Lattice Points * 欧拉函数 */ #include<cstdio> using namespace std; int C,N; / ...

  10. innoDB锁小结

    innodb的锁分两类:lock和latch. 其中latch主要是保证并发线程操作临界资源的正确性,要求时间非常短,所以没有死锁检测机制.latch包括mutex(互斥量)和rwlock(读写锁). ...