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 ...
随机推荐
- [C++ Primer Plus] 第7章、函数(二)课后习题
一.复习题 6.为什么不对基本数据类型的函数参数使用const? 8.编写一个函数,将字符串中所有c1替换成c2,并返回替换次数. #include<iostream> using nam ...
- 洛谷 P1273 【有线电视网】
题目描述 某收费有线电视网计划转播一场重要的足球比赛.他们的转播网和用户终端构成一棵树状结构,这棵树的根结点位于足球比赛的现场,树叶为各个用户终端,其他中转站为该树的内部节点. 从转播站到转播站以及从 ...
- [原]编译flightGear
参考:flightgear编译博客201705 flightGear是三维飞行仿真软件,这个款软件是开源的,我们尝试用其源码完整编译一遍这个工程,并使用它. 它用到里以下扩展库: 空气动力学库:JSB ...
- DAY10 函数的参数
一.函数参数的分类 1.实参:调用参数,在括号内传入的实际值,值可以为常量.变量.表达式或三者的组合 2.形参:定义函数时,在括号内声明的变量名,用来接受外界传来的值 注意:形参随着函数的调用而产生, ...
- pymysql的使用与参数简要
pymysql.Connect()参数说明 host(str): MySQL服务器地址 port(int): MySQL服务器端口号 user(str): 用户名 passwd(str): 密码 db ...
- springboot应用无故停止运行killed解决方法
最近使用springboot开发了一个ip代理的程序,今天放到阿里云服务器上运行,多次出现应用运行突然停止的问题. 使用free -h 查看内存使用完全正常.重新运行监视CPU使用也正常.没有出现堆内 ...
- 函数, arguments对象, eval,静态成员和实例成员
函数创建: 3种创建函数的方式 * 直接声明函数 function funcName(/*参数列表*/){ //函数体 } * 函数表达式 var funcName = function(){ ...
- 『流畅的Python』第1~4章笔记_数据结构、编码
由于1~4章内容零散且基础,所以统计一下涉及到的内容,记录一下,方便查阅(第一张图右键新页面打开即可看到清晰大图)
- MVC实战之排球计分(六)—— 使用EF框架,创建Controller,生成数据库。
在上篇博客我们写到,此软件的数据库连接我们使用的是EF框架,code first模式下, 通过模型类,在创建controller的时候直接生成数据库,完成数据库的连接,与操作. 在使用EF框架之前,我 ...
- RMAN 的优缺点及RMAN 备份及恢复步骤
一. RMAN 备份的一些优点和OS命令备份方式相比,使用RMAN的优点 1 备份执行期间不需要人工干预,因此减少了误操作的机会:2 可以有效的将备份和恢复结合起来:3 支持除逻辑备份以外的所有 ...