Search code examples
uiviewxamarin.iosxamarinscreenshotuigraphicscontext

Screenshot of current UIView distorts and stretches the UIView at UIView.DrawViewHierarchy


I'm creating a screenshot of a UIView currently displayed. I faced with an issue when controls are distorted and stretched for a moment (0.2-0.5 sec) during this process. It is reproduced for iPhone 6, 6+ ONLY.

my simple code is here (Xamarin.iOS):

public UIImage CreateScreenshotImage()
{
    UIView rootView = UIApplication.SharedApplication.KeyWindow.RootViewController.View;
    if (rootView != null)
    {
        var bounds = rootView.Bounds;
        UIGraphics.BeginImageContextWithOptions(bounds.Size, false, 0);
        **//here distortion starts, I can clearly see it in the DEBUG mode**
        rootView.DrawViewHierarchy(bounds, true); 
        var screenshotImage = UIGraphics.GetImageFromCurrentImageContext();
        UIGraphics.EndImageContext();
        return screenshotImage;
     }
     return null;
}

I don't believe it is related to Xamarin so it should be the same issue for native iOS app as well.

What could be the reason?


Solution

  • Try with this:

    public static class UIViewScreenshot
    {
        public static UIImage Screenshot(this UIView view, bool optimized = true)
        {
            if (optimized)
            {
                // take screenshot of the view
                if (view.GetType ().Name == "MKMapView") {
                    if (float.Parse(UIDevice.CurrentDevice.SystemVersion) >= 6.0) {
    
                        // in iOS6, there is no problem using a non-retina screenshot in a retina display screen
                        UIGraphics.BeginImageContextWithOptions (view.Frame.Size, false, 1.0f);
    
                    } else {
    
                        // if the view is a mapview in iOS5.0 and below, screenshot has to take the screen scale into consideration
                        // else, the screen shot in retina display devices will be of a less detail map (note, it is not the size of the screenshot, but it is the level of detail of the screenshot
                        UIGraphics.BeginImageContextWithOptions (view.Frame.Size, false, 1.0f);
                    }
                } else {
                    // for performance consideration, everything else other than mapview will use a lower quality screenshot
                    UIGraphics.BeginImageContext (view.Frame.Size); 
                }
    
            } else
            {
                UIGraphics.BeginImageContextWithOptions (view.Frame.Size, false, 0.0f);
            }
    
    
            var context = UIGraphics.GetCurrentContext ();
    
            if (context == null)
            {
                Console.WriteLine("UIGraphicsGetCurrentContext() is nil. You may have a UIView with CGRectZero");
                return null;
            }
            else
            {
                view.Layer.RenderInContext (context);
    
                var screenshot = UIGraphics.GetImageFromCurrentImageContext ();
                UIGraphics.EndImageContext();
    
                return screenshot;
            }
        }
    }