iOS CAlayer Orientation AVCaptureVideoPreviewLayer doesn't rotate

后端 未结 8 730
既然无缘
既然无缘 2020-12-24 09:50

\"enter Summary: I can\'t force the CALayer to respond correctly to orientati

相关标签:
8条回答
  • 2020-12-24 10:25
    // layout iOS 8+ animated 
    - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
    {
        [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context)
        {
             NSString *timingFunc = nil;
             switch ( [context completionCurve] )
             {
                 case UIViewAnimationCurveEaseIn:    timingFunc = kCAMediaTimingFunctionEaseIn;          break;
                 case UIViewAnimationCurveEaseInOut: timingFunc = kCAMediaTimingFunctionEaseInEaseOut;   break;
                 case UIViewAnimationCurveEaseOut:   timingFunc = kCAMediaTimingFunctionEaseOut;         break;
                 case UIViewAnimationCurveLinear:    timingFunc = kCAMediaTimingFunctionLinear;          break;
             }
    
             [CATransaction begin];
             [CATransaction setAnimationDuration:[context transitionDuration]];
             [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:timingFunc]];
             [self updatePreviewLayer];
             [CATransaction commit];
    
             UIInterfaceOrientation toOrientation = [[UIApplication sharedApplication] statusBarOrientation];
             // layout ui if needed
    
        } completion:^(id<UIViewControllerTransitionCoordinatorContext> context)
        {
    
        }];
    
        [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
    }
    
    - (void)updatePreviewLayer
    {
        CGAffineTransform transform = CGAffineTransformIdentity;
        switch ( UIDevice.currentDevice.orientation )
        {
            case UIDeviceOrientationLandscapeLeft:
                transform = CGAffineTransformRotate(transform, -M_PI_2);
            break;
            case UIDeviceOrientationLandscapeRight:
                transform = CGAffineTransformRotate(transform, M_PI_2);
            break;
            case UIDeviceOrientationPortraitUpsideDown:
                transform = CGAffineTransformRotate(transform, M_PI);
            break;
            default:
            break;
        }
        preview.affineTransform = transform;
        preview.frame = self.view.bounds;
    }
    
    0 讨论(0)
  • 2020-12-24 10:30

    This the method I use in the view controller to maintain the orientation of the capture layer so that it is always right-side-up:

    - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
        if (_previewLayer.connection.supportsVideoOrientation)
        {
        switch (toInterfaceOrientation)
            {
            case UIInterfaceOrientationPortrait:
                {
                _previewLayer.connection.videoOrientation = AVCaptureVideoOrientationPortrait;
                break;
                }
            case UIInterfaceOrientationPortraitUpsideDown:
                {
                _previewLayer.connection.videoOrientation = AVCaptureVideoOrientationPortraitUpsideDown;
                break;
                }
            case UIInterfaceOrientationLandscapeLeft:
                {
                _previewLayer.connection.videoOrientation = AVCaptureVideoOrientationLandscapeLeft;
                break;
                }
            case UIInterfaceOrientationLandscapeRight:
                {
                _previewLayer.connection.videoOrientation = AVCaptureVideoOrientationLandscapeRight;
                break;
                }
            }
        }
    

    A little wordy, but safe even if either enumeration ever changes in the future.

    0 讨论(0)
  • 2020-12-24 10:30

    @Janusz Chudzynski here is the detailed explanation what rotateLayer method does

    This method is created after examine how different orientation affect the previewLayer so creater has checked when orientation is in LandscapeLeft then it should be 270 degrees rotated to make it in correct position for that he has used

    stuckview.affineTransform = CGAffineTransformMakeRotation(M_PI+ M_PI_2);
    
         M_PI        3.14159265358979323846264338327950288   // pi     = 180 degree  
                                        +      
         M_PI_2      1.57079632679489661923132169163975144   // pi/2   = 90  degree
    
                                                             // Total  = 270 degree
    

    so creater has noticed that if I will rotate previewLayer to 270 degrees when its in LandscapeLeft then it will be in correct position just like that he has rotate previewLayer for every rotation possible

    0 讨论(0)
  • 2020-12-24 10:38

    What about this?

    - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
    {
        _videoPreviewLayer.connection.videoOrientation = toInterfaceOrientation;
    }
    
    0 讨论(0)
  • 2020-12-24 10:38

    I'm with @Siegfault, although I also found that when my view loads in landscape orientation on the iPad initially, the orientation is still in correct. To fix, I call that same delegate method in viewDidAppear: with the current interfaceOrientation:

    - (void)viewDidAppear:(BOOL)animated {
        [super viewDidAppear:animated];
        [self willRotateToInterfaceOrientation:self.interfaceOrientation duration:0.0];
    }
    
    0 讨论(0)
  • 2020-12-24 10:39

    The answer using willRotateToUserInterfaceOrientation works fine, except that that method has been deprecated. So if you're able to use iOS 9, then here's the way to do it, in Swift:

    override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
            let newOrientation = UIDevice.currentDevice().orientation
            switch newOrientation {
            case .LandscapeLeft:
                self.capturePreviewLayer?.connection.videoOrientation = .LandscapeLeft
            case .LandscapeRight:
                self.capturePreviewLayer?.connection.videoOrientation = .LandscapeRight
            case .Portrait, .Unknown, .FaceUp, .FaceDown:
                self.capturePreviewLayer?.connection.videoOrientation = .Portrait
            case .PortraitUpsideDown:
                self.capturePreviewLayer?.connection.videoOrientation = .PortraitUpsideDown
            }
            super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
        }
    
    0 讨论(0)
提交回复
热议问题