SkiaSharp is a cross-platform 2D graphics API for .NET platforms based on Google's Skia Graphics Library. It provides a comprehensive 2D API that can be used across mobile, server and desktop models to render images.
MIT License
4.5k
stars
538
forks
source link
[QUESTION] SVG not showing up after upgrade to Android 11 / API 30 #1845
We have been using SkiaSharp to render SVG icons as part of our tabbed page icons for quite some time. I recently changed the targeted sdk to 30 from 29, and the icons do not render any longer. I have tried to update to the latest versions of SkiaSharp, but that didn't help.
here is the code we use to load/draw the svg
using System;
using System.IO;
using System.Reflection;
using System.Collections.Generic;
using SkiaSharp;
using SkiaSharp.Views.Forms;
using Xamarin.Forms;
namespace TemptaleApp.Extensions
{
public class TabSvgIcon : SKCanvasView
{
SkiaSharp.Extended.Svg.SKSvg svg;
static Assembly mainPclAssembly;
public static Assembly MainPclAssembly
{
get
{
if (mainPclAssembly == null)
{
if (Application.Current == null)
throw new InvalidOperationException();
mainPclAssembly = Application.Current.GetType().GetTypeInfo().Assembly;
}
return mainPclAssembly;
}
set
{
mainPclAssembly = value;
}
}
/// <summary>
/// Cache for SVG icons. Each SVG is kept in memory only once even if it's used multple places in application.
/// </summary>
static readonly IDictionary<string, SkiaSharp.Extended.Svg.SKSvg> SvgCache = new Dictionary<string, SkiaSharp.Extended.Svg.SKSvg>();
/// <summary>
/// Global prefix for resource ids. Enabled writing cleaner XAML.
/// </summary>
public static string ResourceIdsPrefix { get; set; } = string.Empty;
#region Bindable properties
public static readonly BindableProperty ResourceIdProperty = BindableProperty.Create(nameof(ResourceId), typeof(string), typeof(SvgIcon), default(string));
public string ResourceId
{
get { return (string)GetValue(ResourceIdProperty); }
set { SetValue(ResourceIdProperty, value); }
}
public static readonly BindableProperty SelectedResourceIdProperty = BindableProperty.Create(nameof(SelectedResourceId), typeof(string), typeof(SvgIcon), default(string));
public string SelectedResourceId
{
get { return (string)GetValue(SelectedResourceIdProperty); }
set {
SetValue(SelectedResourceIdProperty, value);
}
}
public static readonly BindableProperty SelectedTabValueProperty = BindableProperty.Create(nameof(SelectedTabValue), typeof(String), typeof(SvgIcon), default(string));
public string SelectedTabValue
{
get { return (string)GetValue(SelectedTabValueProperty); }
set {
SetValue(SelectedTabValueProperty, value);
}
}
public string TabValue
{
get;
set;
}
public static readonly BindableProperty ColorProperty = BindableProperty.Create(nameof(Color), typeof(Color), typeof(SvgIcon), Color.Black);
public Color Color
{
get { return (Color)GetValue(ColorProperty); }
set { SetValue(ColorProperty, value); }
}
#endregion
void LoadSvgImage()
{
var loadResourceId = (TabValue.Equals(SelectedTabValue) ? SelectedResourceId : ResourceId);
if (svg != null && loadResourceId == null)
return;
if (!SvgCache.TryGetValue(loadResourceId, out svg))
{
string fullKey = $"{ResourceIdsPrefix}{loadResourceId}";
using (Stream stream = MainPclAssembly.GetManifestResourceStream(fullKey))
{
if (stream == null)
throw new FileNotFoundException($"SvgIcon : could not load SVG file {fullKey} in assembly {MainPclAssembly}. Make sure the ID is correct, the file is there and it is set to Embedded Resource build action.");
svg = new SkiaSharp.Extended.Svg.SKSvg();
svg.Load(stream);
SvgCache.Add(loadResourceId, svg);
}
}
}
protected override void OnPaintSurface(SKPaintSurfaceEventArgs e)
{
base.OnPaintSurface(e);
e.Surface.Canvas.Clear();
LoadSvgImage();
var matrix = CalculateScale(e.Info);
using (var paint = new SKPaint())
{
// Unlike CreateLighting(), blend mode support alpha channel of the color
paint.ColorFilter = SKColorFilter.CreateBlendMode(Color.ToSKColor(), SKBlendMode.SrcIn);
e.Surface.Canvas.DrawPicture(svg.Picture, ref matrix, paint);
}
}
SKMatrix CalculateScale(SKImageInfo info)
{
float canvasMin = Math.Min(info.Width, info.Height);
float svgMax = Math.Max(svg.Picture.CullRect.Width, svg.Picture.CullRect.Height);
float scale = canvasMin / svgMax;
return SKMatrix.MakeScale(scale, scale);
}
protected override void OnPropertyChanged(string propertyName = null)
{
base.OnPropertyChanged(propertyName);
if (propertyName == ResourceIdProperty.PropertyName)
svg = null;
if (propertyName == ResourceIdProperty.PropertyName
|| propertyName == ColorProperty.PropertyName)
InvalidateSurface();
}
}
}
Any thoughts or guidance would be greatly appreciated
Use Svg.Skia instead. The internal svg stuff here hasn't been updated for a very long time and the recommendation for several years has been to move to Svg.Skia for anything serious.
Good day,
We have been using SkiaSharp to render SVG icons as part of our tabbed page icons for quite some time. I recently changed the targeted sdk to 30 from 29, and the icons do not render any longer. I have tried to update to the latest versions of SkiaSharp, but that didn't help.
here is the code we use to load/draw the svg
Any thoughts or guidance would be greatly appreciated