swift3.0自定义相机界面
这是公司上上上一个项目的自定义相机界面,原来是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自定义相机界面的更多相关文章
- swift3.0 自定义键盘
...绕了一大圈,又绕回原生来了,今天,学习一下swift3.0语法下的自定义键盘.效果图如下: 其实,很简单,只需要把UITextView(或者UITextField)的inputView属性设置为 ...
- swift3.0 创建经典界面的九宫图
网络上很多例子都是早期的 Object-C的效果,现在用到Swift3.0开发,故把网络上的例子翻译过来,达到基本的效果.可是现在这个还不算很满意,再下次继续进行优化 override func vi ...
- Swift3.0 自定义tableView复用cell 的写法,与CollectionViewCell的不同,数据model
Model数据 class HospitalModel: NSObject { //后边不赋值 会报错 var imgurl :String = "" var introducti ...
- 如何用uniapp+vue开发自定义相机插件——拍照+录像功能
调用手机的相机功能并实现拍照和录像是很多APP与插件都必不可少的一个功能,今天智密科技就来分享一下如何基于uniapp + vue实现自定义相机界面,并且实现: 1: 自定义拍照 2: 自定义录像 3 ...
- Swift2.3 --> Swift3.0 的变化
Swift3.0语法变化 首先和大家分享一下学习新语法的技巧: 用Xcode8打开自己的Swift2.3的项目,选择Edit->Convert->To Current Swift Synt ...
- Android相机使用(系统相机、自定义相机、大图片处理)
本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显示出来,该例子也会涉及到Android加载大图片时候的处理(避免OOM),还有简要提一下有些人Surf ...
- Android自定义相机拍照、图片裁剪的实现
最近项目里面又要加一个拍照搜题的功能,也就是用户对着不会做的题目拍一张照片,将照片的文字使用ocr识别出来,再调用题库搜索接口搜索出来展示给用户,类似于小猿搜题.学霸君等app. 其实Android提 ...
- Swift3.0语法变化
写在前面 首先和大家分享一下学习新语法的技巧:用Xcode8打开自己的Swift2.3的项目,选择Edit->Convert->To Current Swift Syntax- 让Xcod ...
- Android调用系统相机以及自定义相机
0.综述 自定义相机,此处展示简单的相机功能,官方文档中还有相应关于视频拍摄的内容,此处不提 1.添加权限 <!--相机权限,数据存储--> <uses-permission and ...
随机推荐
- Docker Compose 配置文件常用指令
Docker Compose 配置文件常用指令 YAML文件格式及编写注意事项 YAML是一种标记语言很直观的数据序列化格式,可读性高.类似于XML数据描述语言,语法比XML简单的很多. YAML数据 ...
- 剑指offer(45)扑克牌顺子
题目描述 LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决 ...
- 剑指offer(46)孩子们的游戏
题目描述 每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此.HF作为牛客的资深元老,自然也准备了一些小游戏.其中,有个游戏是这样的:首先,让小朋友们围成一个大圈.然后,他随机指 ...
- Bootstrap3基础 table-bordered/hover 表格加外边框和鼠标悬停对应行的背景色加深
内容 参数 OS Windows 10 x64 browser Firefox 65.0.2 framework Bootstrap 3.3.7 editor ...
- Linux下Shell的for循环语句
第一类:数字性循环-----------------------------for1-1.sh #!/bin/bash ;i<=;i++)); do + ); done ------------ ...
- Bulbs【暴力?】
问题 B: Bulbs 时间限制: 1 Sec 内存限制: 128 MB 提交: 216 解决: 118 [提交] [状态] [命题人:admin] 题目描述 Greg has an m × n ...
- 【问题解决:SFL4J】启动时SLF4J报错
问题描述 启动时报错 SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Default ...
- 前端UI框架选择区别对比推荐
UI选择务必慎重,货比三家. 弱水三千只取一瓢:弱水三千只取一瓢,源起佛经中的一则故事,警醒人们在一生中可能会遇到很多美好的东西,但只要用心好好把握住其中的一样就足够了 老牌构建于jQuery框架之上 ...
- python内置类型:列表,包括 list 和 tuple
列表list 是一种有序的集合 ,假定list的名字为class list的元素个数:len( class) 访问元素: a. 索引从0开始 b. 也可以使用[-1],[-2],[-3] 从后面 ...
- 『cs231n』卷积神经网络的可视化与进一步理解
cs231n的第18课理解起来很吃力,听后又查了一些资料才算是勉强弄懂,所以这里贴一篇博文(根据自己理解有所修改)和原论文的翻译加深加深理解,其中原论文翻译比博文更容易理解,但是太长,而博文是业者而非 ...