Forum Xamarin.Android

Rendering views to bitmaps doesn't include images

I'm trying to render views to bitmaps on Android in a Xamarin Forms project. Everything works great on iOS, but Android only seems to render native elements and not any image sources.

The rendering code is super standard:

viewGroup.DrawingCacheEnabled = true;
var image = Bitmap.CreateBitmap(viewGroup.GetDrawingCache(false));
viewGroup.DrawingCacheEnabled = cacheEnabled;

Some of the images that aren't rendering in the output look like this:

<Image ... Source="Some_Resource" />

Things I've tried
1. Changing the source to a full path
2. Setting the source with embedded images
3. Using the alternative rendering approach of drawing the bitmap on a canvas
4. Ensuring that DrawingCacheEnabled = true on the whole view tree
5. Moving resources into the project that contains this class (separate from the Android project)

The full class:

    public class ViewRenderer : IViewRenderer
    {
        public ViewRenderer()
        {
        }

        public byte[] Render(Xamarin.Forms.View view)
        {
            var viewGroup = ConvertToNative(view);

            var cacheEnabled = viewGroup.DrawingCacheEnabled;
            viewGroup.DrawingCacheEnabled = true;
            var image = Bitmap.CreateBitmap(viewGroup.GetDrawingCache(false));
            viewGroup.DrawingCacheEnabled = cacheEnabled;

            using (var stream = new MemoryStream())
            {
                image.Compress(Bitmap.CompressFormat.Png, 0, stream);
                var imageBytes = stream.ToArray();
                return imageBytes;
            }
        }

        private ViewGroup ConvertToNative(Xamarin.Forms.View view)
        {
            var renderer = Platform.CreateRenderer(view);

            var viewGroup = renderer.ViewGroup;
            renderer.Tracker.UpdateLayout();

            var density = Xamarin.Forms.Forms.Context.Resources.DisplayMetrics.Density;
            var size = new Xamarin.Forms.Rectangle(0, 0, view.Width * density, view.Height * density);

            var layoutParams = new ViewGroup.LayoutParams((int)size.Width, (int)size.Height);
            viewGroup.LayoutParameters = layoutParams;
            viewGroup.Layout(0, 0, (int)size.Width, (int)size.Height);

            return viewGroup;
        }
    }

I'm pretty stumped on this, so if anyone can help me out that would be awesome!

Best Answer

  • AndrewTempleAndrewTemple USMember
    Accepted Answer

    Teammate figured it out - apparently creating the native view wasn't quite right.

            private ViewGroup ConvertToNative(Xamarin.Forms.View view)
            {
                IVisualElementRenderer renderer = (IVisualElementRenderer) view.GetValue(RendererProperty);
                if (renderer == null)
                {
                    renderer = Platform.CreateRenderer(view);
                    view.SetValue(RendererProperty, renderer);
                }
    
                var viewGroup = renderer.ViewGroup;
    
                var density = Xamarin.Forms.Forms.Context.Resources.DisplayMetrics.Density;
                var size = new Xamarin.Forms.Rectangle(0, 0, view.Width * density, view.Height * density);
    
                return viewGroup;
            }
    

    Sometimes there's still a little weirdness (parts of labels not rendering), but for our purposes it works :+1:

Answers

  • AndrewTempleAndrewTemple USMember
    Accepted Answer

    Teammate figured it out - apparently creating the native view wasn't quite right.

            private ViewGroup ConvertToNative(Xamarin.Forms.View view)
            {
                IVisualElementRenderer renderer = (IVisualElementRenderer) view.GetValue(RendererProperty);
                if (renderer == null)
                {
                    renderer = Platform.CreateRenderer(view);
                    view.SetValue(RendererProperty, renderer);
                }
    
                var viewGroup = renderer.ViewGroup;
    
                var density = Xamarin.Forms.Forms.Context.Resources.DisplayMetrics.Density;
                var size = new Xamarin.Forms.Rectangle(0, 0, view.Width * density, view.Height * density);
    
                return viewGroup;
            }
    

    Sometimes there's still a little weirdness (parts of labels not rendering), but for our purposes it works :+1:

  • Hi,
    Can you please share RendererProperty value set in above code. I am also trying to render image as bitmap it's not rendering.

    Thanks in advance..

Sign In or Register to comment.