美文网首页iOS
iOS自定义相机

iOS自定义相机

作者: 叫我龙哥 | 来源:发表于2017-03-21 22:45 被阅读422次

    iOS自定义相机的实现

    本文主要介绍iOS系统上的自定义相机的实现,其实并不难主要包含了,拍摄设备,输入端,输出端,以及抓取图像,保存图像的操作。

    简单介绍组要控件

    • 上方功能区
      • 取消按钮
      • 闪光灯按钮
      • 相机切换按钮
    • 下方功能区
      • 拍照按钮
      • 重新拍照按钮
      • 选择照片按钮
    • 图像展示视图

    主要代码展示

    头文件内容展示

    • 定了一个block,用于传输照片信息
    #import <UIKit/UIKit.h>
    typedef void(^ImageBlock)(NSDictionary *imageDictionary);
    @interface CameraViewController : UIViewController
    @property (nonatomic, copy) ImageBlock imageblock;
    -(void)setImageblock:(void(^)(NSDictionary *imageDictionary))imageblock;
    @end
    

    视图控件代码,逻辑代码展示

    • 当前视图需要的主要空控件,为了方便操作全部定义为属性
    @interface CameraViewController ()<AVCaptureMetadataOutputObjectsDelegate,UIAlertViewDelegate,CAAnimationDelegate>
    //捕获设备,通常是前置摄像头,后置摄像头,麦克风(音频输入)
    @property(nonatomic)AVCaptureDevice *device;
    //AVCaptureDeviceInput 代表输入设备,他使用AVCaptureDevice 来初始化
    @property(nonatomic)AVCaptureDeviceInput *input;
    //当启动摄像头开始捕获输入
    @property(nonatomic)AVCaptureMetadataOutput *output;
    //输出
    @property (nonatomic)AVCaptureStillImageOutput *ImageOutPut;
    //session:由他把输入输出结合在一起,并开始启动捕获设备(摄像头)
    @property(nonatomic)AVCaptureSession *session;
    //图像预览层,实时显示捕获的图像
    @property(nonatomic)AVCaptureVideoPreviewLayer *previewLayer;
    //设备
    @property (nonatomic, strong)AVCaptureDevice *deveice;
    //拍照
    @property (nonatomic, strong) UIButton *PhotoButton;
    //闪光灯
    @property (nonatomic, strong) UIButton *flashButton;
    //取消
    @property (nonatomic, strong) UIButton *cancleButton;
    //切换摄像头
    @property (nonatomic, strong) UIButton *changeButton;
    //确定选择当前照片
    @property (nonatomic, strong) UIButton *selectButton;
    //重新拍照
    @property (nonatomic, strong) UIButton *reCamButton;
    //照片加载视图
    @property (nonatomic, strong) UIImageView *imageView;
    //对焦区域
    @property (nonatomic, strong) UIImageView *focusView;
    //上方功能区
    @property (nonatomic, strong) UIView *topView;
    //下方功能区
    @property (nonatomic, strong) UIView *bottomView;
    //闪光灯状态
    @property (nonatomic, assign) BOOL isflashOn;
    //拍到的照片
    @property (nonatomic, strong) UIImage *image;
    //照片的信息
    @property (nonatomic, strong) NSDictionary *imageDict;
    //是否可以拍照
    @property (nonatomic, assign) BOOL canCa;
    //闪光灯模式
    @property (nonatomic, assign) AVCaptureFlashMode flahMode;
    //前后摄像头
    @property (nonatomic, assign) AVCaptureDevicePosition cameraPosition;
    //模糊视图
    @property (nonatomic, strong) UIVisualEffectView *effectView;
    @end
    
    • 使用懒加载,减少主要函数中的代码,看起来更为清爽。
    @implementation CameraViewController
    #pragma mark - 更改摄像头
    
    -(UIVisualEffectView *)effectView{
        if (_effectView == nil) {
            UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
            _effectView = [[UIVisualEffectView alloc] initWithEffect:effect];
            _effectView.frame = CGRectMake(0, 0, ScreenWidth(), ScreenHieght());
            _effectView.alpha = 1;
        }
        return _effectView;
    }
     #pragma mark - 更改闪光灯状态
    -(void)setIsflashOn:(BOOL)isflashOn{
        _isflashOn = isflashOn;
        [[NSUserDefaults standardUserDefaults] setObject:@(_isflashOn) forKey:@"flashMode"];
        if (_isflashOn) {
            [self.flashButton setBackgroundImage:[UIImage imageNamed:@"flash_on"] forState:UIControlStateNormal];
        }else{
            [self.flashButton setBackgroundImage:[UIImage imageNamed:@"flash_off"] forState:UIControlStateNormal];
        }
    }
    #pragma mark - 上方功能区
    -(UIView *)topView{
        if (!_topView ) {
            _topView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, ScreenWidth(), 50)];
            _topView.backgroundColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.2];
            [_topView addSubview:self.cancleButton];
            [_topView addSubview:self.flashButton];
            [_topView addSubview:self.changeButton];
        }
        return _topView;
    }
    #pragma mark - 取消
    -(UIButton *)cancleButton{
        if (_cancleButton == nil) {
            _cancleButton = [UIButton buttonWithType:UIButtonTypeCustom];
            _cancleButton.frame = CGRectMake(20, 10, 60, 30);
            [_cancleButton setTitle:@"取消" forState:UIControlStateNormal];
            [_cancleButton addTarget:self action:@selector(cancle) forControlEvents:UIControlEventTouchUpInside];
        }
        return  _cancleButton ;
    }
    #pragma mark - 闪光灯
    -(UIButton *)flashButton{
        if (_flashButton == nil) {
            _flashButton = [UIButton buttonWithType:UIButtonTypeCustom];
            _flashButton.frame = CGRectMake((ScreenWidth()-30)/2.0, 10, 30, 30);
            [_flashButton addTarget:self action:@selector(FlashOn) forControlEvents:UIControlEventTouchUpInside];
        }
        return  _flashButton;
    }
    #pragma mark - 切换摄像头
    -(UIButton *)changeButton{
        if (_changeButton == nil) {
            _changeButton = [UIButton buttonWithType:UIButtonTypeCustom];
            _changeButton.frame = CGRectMake(ScreenWidth()-40, 10, 30, 30);
            [_changeButton setBackgroundImage:[UIImage imageNamed:@"cam"] forState:UIControlStateNormal];
            [_changeButton addTarget:self action:@selector(changeCamera) forControlEvents:UIControlEventTouchUpInside];
        }
        return  _changeButton;
    }
    
    #pragma mark - 下方功能区
    
    -(UIView *)bottomView{
        if (!_bottomView) {
            _bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, ScreenHieght()-80, ScreenWidth(), 80)];
            _bottomView.backgroundColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.4];
            [_bottomView addSubview:self.reCamButton];
            [_bottomView addSubview:self.PhotoButton];
            [_bottomView addSubview:self.selectButton];
        }
        return _bottomView;
    }
    -(UIButton *)reCamButton{
        if (_reCamButton == nil) {
            _reCamButton = [UIButton buttonWithType:UIButtonTypeCustom];
            _reCamButton.frame = CGRectMake(40, 25, 80, 30);
            [_reCamButton addTarget:self action:@selector(reCam) forControlEvents:UIControlEventTouchUpInside];
            [_reCamButton setTitle:@"重新拍照" forState:UIControlStateNormal];
            [_reCamButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
            _reCamButton.alpha = 0;
        }
        return _reCamButton;
    }
    -(UIButton *)PhotoButton{
        if (_PhotoButton == nil) {
            _PhotoButton = [UIButton buttonWithType:UIButtonTypeCustom];
            _PhotoButton.frame = CGRectMake(ScreenWidth()/2.0-30, 10, 60, 60);
            [_PhotoButton setImage:[UIImage imageNamed:@"photograph"] forState: UIControlStateNormal];
            [_PhotoButton setImage:[UIImage imageNamed:@"photograph_Select"] forState:UIControlStateNormal];
            [_PhotoButton addTarget:self action:@selector(shutterCamera) forControlEvents:UIControlEventTouchUpInside];
        }
        return _PhotoButton;
    }
    -(UIButton *)selectButton{
        if (_selectButton == nil) {
            _selectButton = [UIButton buttonWithType:UIButtonTypeCustom];
            _selectButton.frame = CGRectMake(ScreenWidth()-120, 25, 80, 30);
            [_selectButton addTarget:self action:@selector(selectImage) forControlEvents:UIControlEventTouchUpInside];
            [_selectButton setTitle:@"选择照片" forState:UIControlStateNormal];
            [_selectButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
            _selectButton.alpha = 0;
        }
        return _selectButton;
    }
    #pragma mark - 加载照片的视图
    -(UIImageView *)imageView{
        if (_imageView == nil) {
            _imageView = [[UIImageView alloc]initWithFrame:self.previewLayer.frame];
            _imageView.layer.masksToBounds = YES;
            _imageView.image = _image;
        }
        return _imageView;
    }
    #pragma mark - 对焦区域
    -(UIImageView *)focusView{
        if (_focusView == nil) {
            _focusView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 80, 80)];
            _focusView.backgroundColor = [UIColor clearColor];
            _focusView.image = [UIImage imageNamed:@"foucs80pt"];
        }
        return _focusView;
    }
    #pragma mark - 使用self.session,初始化预览层,self.session负责驱动input进行信息的采集,layer负责把图像渲染显示
    -(AVCaptureVideoPreviewLayer *)previewLayer{
        if (_previewLayer == nil) {
            _previewLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:self.session];
            _previewLayer.frame = CGRectMake(0, 0, ScreenWidth(), ScreenHieght());
            _previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
        }
        return  _previewLayer;
    }
    -(AVCaptureStillImageOutput *)ImageOutPut{
        if (_ImageOutPut == nil) {
            _ImageOutPut = [[AVCaptureStillImageOutput alloc] init];
        }
        return _ImageOutPut;
    }
    #pragma mark - 初始化输入
    -(AVCaptureDeviceInput *)input{
        if (_input == nil) {
            
            _input = [[AVCaptureDeviceInput alloc]initWithDevice:self.device error:nil];
        }
        return _input;
    }
    #pragma mark - 初始化输出
    -(AVCaptureMetadataOutput *)output{
        if (_output == nil) {
            
            _output = [[AVCaptureMetadataOutput alloc]init];
        }
        return  _output;
    }
    #pragma mark - 使用AVMediaTypeVideo 指明self.device代表视频,默认使用后置摄像头进行初始化
    -(AVCaptureDevice *)device{
        if (_device == nil) {
            
            _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        }
        return _device;
    }
    

    主要逻辑代码

    #pragma mark - 当前视图控制器的初始化
    - (instancetype)init
    {
        self = [super init];
        if (self) {
            _canCa = [self canUserCamear];
        }
        return self;
    }
    
    -(void)setImageblock:(void (^)(NSDictionary *))imageblock{
        _imageblock = imageblock;
    }
    #pragma mark - 检查相机权限
    - (BOOL)canUserCamear{
        AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
        if (authStatus == AVAuthorizationStatusDenied) {
            UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"请打开相机权限" message:@"设置-隐私-相机" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:@"取消", nil];
            alertView.tag = 100;
            [alertView show];
            return NO;
        }
        else{
            return YES;
        }
        return YES;
    }
    #pragma mark - 视图加载
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.view.backgroundColor = [UIColor clearColor];
        if (_canCa) {
            [self customCamera];
            [self customUI];
            [self FlashOn];
        }else{
            return;
        }
        // Do any additional setup after loading the view, typically from a nib.
    }
    #pragma mark - 自定义视图
    - (void)customUI{
        [self.view addSubview:self.topView];
        [self.view addSubview:self.bottomView];
        [self.view addSubview:self.focusView];
        UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(focusGesture:)];
        [self.view addGestureRecognizer:tapGesture];
        
    }
    #pragma mark - 自定义相机
    - (void)customCamera{
        //生成会话,用来结合输入输出
        self.session = [[AVCaptureSession alloc]init];
        if ([self.session canSetSessionPreset:AVCaptureSessionPresetPhoto]) {
            self.session.sessionPreset = AVCaptureSessionPresetPhoto;
        }
        if ([self.session canAddInput:self.input]) {
            [self.session addInput:self.input];
        }
        
        if ([self.session canAddOutput:self.ImageOutPut]) {
            [self.session addOutput:self.ImageOutPut];
        }
        
        [self.view.layer addSublayer:self.previewLayer];
        
        //开始启动
        [self.session startRunning];
        if ([self.device lockForConfiguration:nil]) {
            if ([self.device isFlashModeSupported:AVCaptureFlashModeAuto]) {
                [self.device setFlashMode:AVCaptureFlashModeAuto];
            }
            //自动白平衡
            if ([self.device isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeAutoWhiteBalance]) {
                [self.device setWhiteBalanceMode:AVCaptureWhiteBalanceModeAutoWhiteBalance];
            }
            
            [self.device unlockForConfiguration];
        }
        [self focusAtPoint:self.view.center];
    }
    

    *闪光灯

    #pragma 闪光灯
    - (void)FlashOn{
        if ([self.device lockForConfiguration:nil]) {
            if (self.isflashOn) {
                if ([self.device isFlashModeSupported:AVCaptureFlashModeOff]) {
                    [self.device setFlashMode:AVCaptureFlashModeOff];
                    self.isflashOn = NO;
                    //[self.flashButton setTitle:@"关" forState:UIControlStateNormal];
                }
            }else{
                if ([self.device isFlashModeSupported:AVCaptureFlashModeAuto]) {
                    [self.device setFlashMode:AVCaptureFlashModeAuto];
                    self.isflashOn = YES;
                    //[self.flashButton setTitle:@"开" forState:UIControlStateNormal];
                }
            }
            
            [self.device unlockForConfiguration];
        }
    }
    
    • 双摄像头切换,切换时使用高斯模糊对试图进行处理
    #pragma mark - 相机切换
    - (void)changeCamera{
        NSUInteger cameraCount = [[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] count];
        if (cameraCount > 1) {
            self.changeButton.userInteractionEnabled = NO;
            [self cutoff];
            NSError *error;
            
            CATransition *animation = [CATransition animation];
            animation.duration = 1;
            animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
            animation.type = @"oglFlip";
            animation.delegate = self;
            AVCaptureDevice *newCamera = nil;
            AVCaptureDeviceInput *newInput = nil;
            AVCaptureDevicePosition position = [[self.input device] position];
            if (position == AVCaptureDevicePositionFront){
                newCamera = [self cameraWithPosition:AVCaptureDevicePositionBack];
                animation.subtype = kCATransitionFromLeft;
                self.cameraPosition = AVCaptureDevicePositionBack;
            }else {
                newCamera = [self cameraWithPosition:AVCaptureDevicePositionFront];
                animation.subtype = kCATransitionFromRight;
                self.cameraPosition = AVCaptureDevicePositionFront;
            }
            
            newInput = [AVCaptureDeviceInput deviceInputWithDevice:newCamera error:nil];
            [self.previewLayer addAnimation:animation forKey:nil];
            /*
             高斯模糊
             */
            
            [self.imageView addSubview:self.effectView];
            [self.view insertSubview:self.imageView belowSubview:self.topView];
            //
            if (newInput != nil) {
                [self.session beginConfiguration];
                [self.session removeInput:self.input];
                if ([self.session canAddInput:newInput]) {
                    [self.session addInput:newInput];
                    self.input = newInput;
    
                } else {
                    [self.session addInput:self.input];
                }
                [self.session commitConfiguration];
                
            } else if (error) {
                NSLog(@"toggle carema failed, error = %@", error);
            }
            //[self.session startRunning];
        }
    }
    - (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition)position{
        NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
        for ( AVCaptureDevice *device in devices )
            if ( device.position == position ) return device;
        return nil;
    }
    -(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
        self.changeButton.userInteractionEnabled = YES;
        [self.effectView removeFromSuperview];
        [self.imageView removeFromSuperview];
        if (self.cameraPosition == AVCaptureDevicePositionFront) {
            self.flashButton.alpha = 0;
        }else if (self.cameraPosition == AVCaptureDevicePositionBack){
            self.flashButton.alpha = 1;
        }
        [self.session startRunning];
    }
    
    • 摄像头对焦
    #pragma mark - 聚焦
    - (void)focusGesture:(UITapGestureRecognizer*)gesture{
        CGPoint point = [gesture locationInView:gesture.view];
        [self focusAtPoint:point];
    }
    - (void)focusAtPoint:(CGPoint)point{
        CGSize size = self.view.bounds.size;
        CGPoint focusPoint = CGPointMake( point.y /size.height ,1-point.x/size.width );
        NSError *error;
        if ([self.device lockForConfiguration:&error]) {
            
            if ([self.device isFocusModeSupported:AVCaptureFocusModeAutoFocus]) {
                [self.device setFocusPointOfInterest:focusPoint];
                [self.device setFocusMode:AVCaptureFocusModeAutoFocus];
            }
            
            if ([self.device isExposureModeSupported:AVCaptureExposureModeAutoExpose ]) {
                [self.device setExposurePointOfInterest:focusPoint];
                [self.device setExposureMode:AVCaptureExposureModeAutoExpose];
            }
            
            [self.device unlockForConfiguration];
            self.focusView.center = point;
            
            //[self startFocusAnimation];
            self.focusView.alpha = 1;
            [UIView animateWithDuration:0.2 animations:^{
                self.focusView.transform = CGAffineTransformMakeScale(1.25f, 1.25f);
            } completion:^(BOOL finished) {
                [UIView animateWithDuration:0.3 animations:^{
                    self.focusView.transform = CGAffineTransformMakeScale(1.0f, 1.0f);
                } completion:^(BOOL finished) {
                    [self hiddenFocusAnimation];
                }];
            }];
        }
        
    }
    

    主要功能按钮 拍照按钮

    #pragma mark - 拍照
    - (void)shutterCamera
    {
        
        AVCaptureConnection * videoConnection = [self.ImageOutPut connectionWithMediaType:AVMediaTypeVideo];
        if (!videoConnection) {
            NSLog(@"take photo failed!");
            return;
        }
        
        [self.ImageOutPut captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
            if (imageDataSampleBuffer == NULL) {
                return;
            }
            NSData * imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
            self.image = [UIImage imageWithData:imageData];
            self.imageDict = @{@"image":self.image,@"info":@{@"PHImageFileUTIKey":@".jpeg"}};
            [self.session stopRunning];
            //[self.view insertSubview:self.imageView belowSubview:self.PhotoButton];
            [self.view insertSubview:self.imageView aboveSubview:self.topView];
            NSLog(@"image size = %@",NSStringFromCGSize(self.image.size));
            self.topView.alpha = 0;
            self.PhotoButton.alpha = 0;
            self.reCamButton.alpha = 1;
            self.selectButton.alpha = 1;
        }];
    }
    
    • 保存至相册
    #pragma - 保存至相册
    - (void)saveImageToPhotoAlbum:(UIImage*)savedImage
    {
        
        UIImageWriteToSavedPhotosAlbum(savedImage, self, @selector(image:didFinishSavingWithError:contextInfo:), NULL);
        
    }
    // 指定回调方法
    
    - (void)image: (UIImage *) image didFinishSavingWithError: (NSError *) error contextInfo: (void *) contextInfo{
        if(error != NULL){
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"保存图片结果提示"
                                                            message:@"保存图片失败"
                                                           delegate:self
                                                  cancelButtonTitle:@"确定"
                                                  otherButtonTitles:nil];
            [alert show];
        }
    }
    
    • 回上层视图
    #pragma mark - 取消 返回上级
    -(void)cancle{
        [self.imageView removeFromSuperview];
        [self.session stopRunning];
        [self.navigationController popViewControllerAnimated:YES];
    }
    
    - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
        if (buttonIndex == 0 && alertView.tag == 100) {
            
            NSURL * url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
            
            if([[UIApplication sharedApplication] canOpenURL:url]) {
                
                [[UIApplication sharedApplication] openURL:url];
                
            }
        }
    }
    
    • 重新拍照
    #pragma mark - 重新拍照
    - (void)reCam{
        self.imageView.image = nil;
        [self.imageView removeFromSuperview];
        [self.session startRunning];
        self.topView.alpha = 1;
        self.PhotoButton.alpha = 1;
        self.reCamButton.alpha = 0;
        self.selectButton.alpha = 0;
    }
    
    • 选择照片
    #pragma mark - 选择照片 返回上级
    - (void)selectImage{
        [self saveImageToPhotoAlbum:self.image];
        self.imageblock(self.image);
        [self.navigationController popViewControllerAnimated:YES];
    }
    -(void)viewDidDisappear:(BOOL)animated{
        
    }
    
    - (void)focusDidFinsh{
        self.focusView.hidden = YES;
        self.focusView.transform = CGAffineTransformMakeScale(1.0f, 1.0f);
        //self.focusView.transform=CGAffineTransformMakeScale(0.7f, 0.7f);
    }
    

    对焦框动画

    - (void)startFocusAnimation{
        self.focusView.hidden = NO;
        self.focusView.transform = CGAffineTransformMakeScale(1.25f, 1.25f);//将要显示的view按照正常比例显示出来
        [UIView beginAnimations:nil context:UIGraphicsGetCurrentContext()];
        //[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];  //InOut 表示进入和出去时都启动动画
        //[UIView setAnimationWillStartSelector:@selector(hiddenFoucsView)];
        [UIView setAnimationDidStopSelector:@selector(hiddenFocusAnimation)];
        [UIView setAnimationDuration:0.5f];//动画时间
        self.focusView.transform = CGAffineTransformIdentity;//先让要显示的view最小直至消失
        [UIView commitAnimations]; //启动动画
        //相反如果想要从小到大的显示效果,则将比例调换
        
    }
    - (void)hiddenFocusAnimation{
        [UIView beginAnimations:nil context:UIGraphicsGetCurrentContext()];
        //NSDate *DATE = [NSDate date];
        //[UIView setAnimationStartDate:[NSDate date]];
        [UIView setAnimationDelay:3];
        self.focusView.alpha = 0;
        [UIView setAnimationDuration:0.5f];//动画时间
        [UIView commitAnimations];
        
    }
    - (void)hiddenFoucsView{
        self.focusView.alpha = !self.focusView.alpha;
    }
    
    
    这里写图片描述
    这里写图片描述

    写在最后

    • 第一次自定义一个相机,代码写的可能不太好理解。
    • 这个项目在码云的git库上有,地址为https://git.oschina.net/LiynXu/PhotoDemo.git
    • 如果有任何意见或者建议,或者发现bug(应该是有的),请移步至git库下给予指导,3Q。

    相关文章

      网友评论

      • 洁简:自定义相机声音怎么根据音量改变呢?
        洁简:@叫我龙哥 你这个有声音的.还有你这个前置摄像头拍出来的不是镜像模式怎么改的?
        叫我龙哥:@洁简 我来试试添加个声音
        叫我龙哥:我这个么有声音:smiley:
      • Eddy_0:Demo地址多了一个句号,希望作者改一下,谢谢! 看文章的同学也可以复制地址,去掉句号就行!
        叫我龙哥:@Eddy_0 恩恩,好的 好的,马上修改,刚刚看到
        Eddy_0:Demo还有个问题,项目里的PrefixHeader.pch文件路径是固定的,下载之后就找不到文件了,把Prefix Header路径写成 $(SRCROOT)/PhotoDemo/PrefixHeader.pch 就OK了
      • 冰三尺:请问使用preview 的大小设置成正方形,预览时是方形,当我拍照时,拍出来的照片是全屏的,如何才能获取照片是方形的呢?
        叫我龙哥:@里脊糖醋 你可是设置一下你的图片获取尺寸

      本文标题:iOS自定义相机

      本文链接:https://www.haomeiwen.com/subject/akrnnttx.html