Evitando que AVCaptureVideoPreviewLayer gire, pero permita que la capa de la interfaz de usuario gire con orientación

Tengo dos controlleres de vista. Uno es el VC raíz y contiene la interfaz UI, como el button de grabación. En este controller de vista, también muestro la vista de otro VC en el índice 0. Esta vista contiene un AVCaptureVideoPreviewLayer.

Me gustaría que mi camera de video imite la aplicación de la videocamera Apple, donde la disposition de la interfaz se ajusta con la rotation, pero la capa de vista previa del video no lo hace. Puede ver cómo desaparece el timer de grabación (UILabel) en la aplicación de video de stock y vuelve a aparecer en la parte superior según la orientación.

¿Alguna idea de cómo hacer esto? Encontré una sugerencia que recomienda agregar la vista previa a la window del delegado de la aplicación, ya que no se ajustará a la rotation del controller de navigation, pero no funcionó para mí.

¡Gracias!

Asegúrese de establecer shouldAutorotate para devolver false:

-(BOOL)shouldAutorotate{ return NO; } 

regístrese para notifications que cambiaron la orientación:

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil]; 

implementar el cambio de notificación

 -(void)orientationChanged:(NSNotification *)notif { UIDeviceOrientation deviceOrientation = [[UIDevice currentDevice] orientation]; // Calculate rotation angle CGFloat angle; switch (deviceOrientation) { case UIDeviceOrientationPortraitUpsideDown: angle = M_PI; break; case UIDeviceOrientationLandscapeLeft: angle = M_PI_2; break; case UIDeviceOrientationLandscapeRight: angle = - M_PI_2; break; default: angle = 0; break; } } 

y rotar la interfaz de usuario

  [UIView animateWithDuration:.3 animations:^{ self.closeButton.transform = CGAffineTransformMakeRotation(angle); self.gridButton.transform = CGAffineTransformMakeRotation(angle); self.flashButton.transform = CGAffineTransformMakeRotation(angle); } completion:^(BOOL finished) { }]; 

Así es como implemento la pantalla que está bloqueada pero girando la interfaz de usuario, si esto funciona, vincula la publicación de las stacks y puedo copyrla allí y puedes marcarla: P

Tengo una situación muy similar. Acabo de tener un controller de vista y quiero tener un AVCaptureVideoPreviewLayer que no gire en él. Encontré la solución aceptada por @ SeanLintern88 no funcionó para mí; la barra de estado nunca se movió y el WKWebView que tenía en la pantalla no estaba cambiando de tamaño correctamente.

Uno de los problemas más importantes que encontré fue que estaba poniendo mi AVCaptureVideoPreviewLayer en la vista del controller de vista. Es mucho mejor crear una nueva UIView solo para mantener la capa.

Después de eso, encontré una nota técnica de Apple QA1890: Evitar una vista desde la rotation . Esto me permitió producir el siguiente código rápido:

 override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator) coordinator.animateAlongsideTransition( { (UIViewControllerTransitionCoordinatorContext) in let deltaTransform = coordinator.targetTransform() let deltaAngle = atan2f(Float(deltaTransform.b), Float(deltaTransform.a)) var currentRotation : Float = (self.previewView!.layer.valueForKeyPath("transform.rotation.z")?.floatValue)! // Adding a small value to the rotation angle forces the animation to occur in a the desinetworking direction, preventing an issue where the view would appear to rotate 2PI radians during a rotation from LandscapeRight -> LandscapeLeft. currentRotation += -1 * deltaAngle + 0.0001; self.previewView!.layer.setValue(currentRotation, forKeyPath: "transform.rotation.z") self.previewView!.layer.frame = self.view.bounds }, completion: { (UIViewControllerTransitionCoordinatorContext) in // Integralize the transform to undo the extra 0.0001 added to the rotation angle. var currentTransform : CGAffineTransform = self.previewView!.transform currentTransform.a = round(currentTransform.a) currentTransform.b = round(currentTransform.b) currentTransform.c = round(currentTransform.c) currentTransform.d = round(currentTransform.d) self.previewView!.transform = currentTransform }) } 

La nota técnica original no tenía la línea self.previewView!.layer.frame = self.view.bounds pero encontré que era muy necesario porque aunque el punto de anclaje no se mueve, el marco tiene. Sin esa línea, la vista previa será compensada.

Además, dado que estoy haciendo todo el trabajo manteniendo la vista en la position correcta, tuve que eliminar todas las restricciones de posicionamiento en ella. Cuando los tenía, harían que la vista previa se compensara en la dirección opuesta.

En la vista que muestra la salida de la camera, agrega:

 AVCaptureVideoPreviewLayer *layer = (AVCaptureVideoPreviewLayer *)self.layer; if ([layer.connection isVideoOrientationSupported]) { [layer.connection setVideoOrientation:AVCaptureVideoOrientationPortrait]; } 

AVCaptureVideoOrientationPortrait es solo una opción. Puede elegir entre los siguientes:

 typedef NS_ENUM(NSInteger, AVCaptureVideoOrientation) { AVCaptureVideoOrientationPortrait = 1, AVCaptureVideoOrientationPortraitUpsideDown = 2, AVCaptureVideoOrientationLandscapeRight = 3, AVCaptureVideoOrientationLandscapeLeft = 4, } 

Esto debe hacerse después de configurar la session.