svgmaui.net-8.0skiasharp

Maui .NET 8 ANDROID Modify the color of a section of an SVG image


I'm working on a .NET 8 MAUI project and I have encountered the following issue. The app has different types of users, and based on the user, it changes its primary color at runtime. This is to make the app visually distinct for each type of user.

The problem arises with SVG images used in the app, which have sections that display the primary color. For example, an image of a person might have their shirt in the primary color. This section should change color based on the user, as I mentioned earlier.

In MAUI, for the Android platform, I understand that images are processed in PNG format. I've managed to keep the images in SVG format by storing them in the Resources -> Raw folder and setting their Build Action to MauiAsset.

The approach I'm trying to use for changing the color is via SkiaSharp, which seemed to be the simplest option I found. However, it is not working as expected.

The code I can provide is:

private async void LoadAndModifySvg()
{
    // Path to the original SVG file
    string originalSvgFileName = "man_and_car.svg";

    // Read SVG content
    string svgContent = await ReadSvgFileAsync(originalSvgFileName);

    // Replace the color #F27B13 with #0000FF
    svgContent = Regex.Replace(svgContent, @"#F27B13", "#0000FF", RegexOptions.IgnoreCase);

    // Load the SVG content into SKSvg
    _svg = new SkiaSharp.Extended.Svg.SKSvg();

    using (var stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(svgContent)))
    {
        _svg.Load(stream);
    }

    // Update the view
    CanvasView.InvalidateSurface();
}

private void CanvasView_PaintSurface(object sender, SKPaintSurfaceEventArgs e)
{
    if (_svg == null)
        return;

    var canvas = e.Surface.Canvas;
    canvas.Clear(SKColors.White);

    // Adjust the size and position of the SVG on the canvas
    var scale = Math.Min(e.Info.Width / _svg.Picture.CullRect.Width,
                         e.Info.Height / _svg.Picture.CullRect.Height);
    canvas.Scale((float)scale);

    // Draw the SVG
    canvas.DrawPicture(_svg.Picture);
}

// Method to read the SVG file as text
private async Task<string> ReadSvgFileAsync(string fileName)
{
    using (var stream = await FileSystem.OpenAppPackageFileAsync(fileName))
    using (var reader = new StreamReader(stream))
    {
        return await reader.ReadToEndAsync();
    }
}

From the XAML side, I have:

    <skia:SKCanvasView x:Name="CanvasView" PaintSurface="CanvasView_PaintSurface" 
                       HeightRequest="450"
                       AbsoluteLayout.LayoutBounds="1.1,1"
                        AbsoluteLayout.LayoutFlags="PositionProportional"
                       ZIndex="0"/>

I would appreciate it if someone could help me. The goal is to modify the color of a specific section of an SVG image in MAUI .NET 8. Thank you.


Solution

  • After further analysis of my code I managed to find the error. It was on the xaml side, since it used an absolutlayout. It did not allow the SKCanvasView to render correctly.

    It was solved by using the SKCanvasView, outside of an absolutlayout. A grid was designed to allow correct rendering.

     <skia:SKCanvasView x:Name="CanvasView" PaintSurface="CanvasView_PaintSurface" 
                           HeightRequest="450"
                           ZIndex="0"/>
    

    The aforementioned code together with the code used from c# works perfectly.