For some reason when I orient the phone to landscape mode the camera preview is upside down (flipped horizontally). I'm using the sample project that Xamarin ported; AVCamBarcode.
I ended up coming up with a half complete fix by using GeometryFlipped in landscape orientation. However, now the drawn barcodes are not drawn in the correct locations in landscape mode.
- Is this a device/os issue or is the sample incomplete?
What is the recommended method to correct this?
public override void ViewWillTransitionToSize (CGSize toSize, IUIViewControllerTransitionCoordinator coordinator) { base.ViewWillTransitionToSize (toSize, coordinator); var videoPreviewLayerConnection = PreviewView.VideoPreviewLayer.Connection; if (videoPreviewLayerConnection != null) { var deviceOrientation = UIDevice.CurrentDevice.Orientation; if (!deviceOrientation.IsPortrait () && !deviceOrientation.IsLandscape ()) return; var newVideoOrientation = VideoOrientationFor (deviceOrientation); var oldSize = View.Frame.Size; var oldVideoOrientation = videoPreviewLayerConnection.VideoOrientation; videoPreviewLayerConnection.VideoOrientation = newVideoOrientation; //THIS IS THE HALF FIX I CAME UP WITH if (deviceOrientation.IsLandscape()) videoPreviewLayerConnection.VideoPreviewLayer.GeometryFlipped = true; else videoPreviewLayerConnection.VideoPreviewLayer.GeometryFlipped = false; //END FIX // When we transition to the new size, we need to adjust the region // of interest's origin and size so that it stays anchored relative // to the camera. coordinator.AnimateAlongsideTransition (context => { var oldRegion = PreviewView.RegionOfInterest; var newRegion = new CGRect (); if (oldVideoOrientation == LandscapeRight && newVideoOrientation == LandscapeLeft) { newRegion = oldRegion.WithX (oldSize.Width - oldRegion.X - oldRegion.Width); } else if (oldVideoOrientation == LandscapeRight && newVideoOrientation == Portrait) { newRegion.X = toSize.Width - oldRegion.Y - oldRegion.Height; newRegion.Y = oldRegion.X; newRegion.Width = oldRegion.Height; newRegion.Height = oldRegion.Width; } else if (oldVideoOrientation == LandscapeLeft && newVideoOrientation == LandscapeRight) { newRegion = oldRegion.WithX (oldSize.Width - oldRegion.X - oldRegion.Width); } else if (oldVideoOrientation == LandscapeLeft && newVideoOrientation == Portrait) { newRegion.X = oldRegion.Y; newRegion.Y = oldSize.Width - oldRegion.X - oldRegion.Width; newRegion.Width = oldRegion.Height; newRegion.Height = oldRegion.Width; } else if (oldVideoOrientation == Portrait && newVideoOrientation == LandscapeRight) { newRegion.X = oldRegion.Y; newRegion.Y = toSize.Height - oldRegion.X - oldRegion.Width; newRegion.Width = oldRegion.Height; newRegion.Height = oldRegion.Width; } else if (oldVideoOrientation == Portrait && newVideoOrientation == LandscapeLeft) { newRegion.X = oldSize.Height - oldRegion.Y - oldRegion.Height; newRegion.Y = oldRegion.X; newRegion.Width = oldRegion.Height; newRegion.Height = oldRegion.Width; } PreviewView.SetRegionOfInterestWithProposedRegionOfInterest (newRegion); }, context => { sessionQueue.DispatchAsync (() => { metadataOutput.RectOfInterest = PreviewView.VideoPreviewLayer.MapToLayerCoordinates (PreviewView.RegionOfInterest); }); // Remove the old metadata object overlays. RemoveMetadataObjectOverlayLayers (); }); } }
Edit
AVCaptureVideoOrientation VideoOrientationFor (UIDeviceOrientation deviceOrientation)
{
switch (deviceOrientation) {
case UIDeviceOrientation.Portrait:
return Portrait;
case UIDeviceOrientation.PortraitUpsideDown:
return PortraitUpsideDown;
case UIDeviceOrientation.LandscapeLeft:
return LandscapeLeft;
case UIDeviceOrientation.LandscapeRight:
return LandscapeRight;
default:
throw new InvalidProgramException ();
}
}