从绑定设置 HeightRequest/WidthRequest 时 FFImageLoading、SVGCachedImage 模糊

FFImageLoading, SVGCachedImage blurry when setting HeightRequest/WidthRequest from a binding

我正在使用 FFImageLoading 在我的 Xamarin.Forms 项目中显示 svg 图标。我的理解是必须明确设置高度和宽度请求才能正确呈现 SVG。每当我尝试将 Height/Width 请求绑定到 ViewModel 上的值时,我都会得到很多像素化(我有这个需要,因为所需的大小取决于数据)。如果我明确设置大小,一切看起来都很好。

每当 Height/Width 请求的绑定发生变化时,SvgCachedImage 不会重新绘制 SVG 吗?

如果不是,有没有办法让我在大小改变时明确强制它们失效并重绘?

模糊问题已通过将水平和垂直选项设置为填充而不是中心来解决:

<Grid>
                                <ffimageloadingsvg:SvgCachedImage  BackgroundColor="Transparent"
                                                              Margin="{Binding HarmonicIconMargin}"
                                                              HorizontalOptions="Fill"
                                                              VerticalOptions="Fill"
                                                              WidthRequest="{Binding HarmonicIconWidth}"
                                                              HeightRequest="{Binding HarmonicIconWidth}"
                                                              Source="{Binding CurrentTestItem, Converter={StaticResource TestItemToHarmonicIconConverter}}" />
                            </Grid>

那时它似乎忽略了 height/width 请求。我本可以尝试更多(也许请求太多 space),但我发现将边距绑定到计算的 属性 有效地使我能够控制 SVG 图像的大小,同时不会导致它变得模糊。

为了解决缩放视图时svg模糊问题,

  1. 更改SvgImageSource.VectorWidthSvgImageSource.VectorHeight
  2. 重新加载图像
protected override void OnSizeAllocated(double width, double height)
{
    if (0 < width && 0 < height && && Source is SvgImageSource imageSource)
    {
        imageSource.VectorWidth = (int)Math.Ceiling(width);
        imageSource.VectorHeight = (int)Math.Ceiling(height);
        svgImage.ReloadImage();

        base.OnSizeAllocated(width, height);
    }
}

根据FFImageLoading source code,SVG图像大小由SvgImageSource.VectorWidthSvgImageSource.VectorHeight决定。

double sizeX = VectorWidth;
double sizeY = VectorHeight;

if (UseDipUnits)
{
    sizeX = VectorWidth.DpToPixels();
    sizeY = VectorHeight.DpToPixels();
}

if (sizeX <= 0 && sizeY <= 0)
{
    if (picture.CullRect.Width > 0)
        sizeX = picture.CullRect.Width;
    else
        sizeX = 400;

    if (picture.CullRect.Height > 0)
        sizeY = picture.CullRect.Height;
    else
        sizeY = 400;
}
else if (sizeX > 0 && sizeY <= 0)
{
    sizeY = (int)(sizeX / picture.CullRect.Width * picture.CullRect.Height);
}
else if (sizeX <= 0 && sizeY > 0)
{
    sizeX = (int)(sizeY / picture.CullRect.Height * picture.CullRect.Width);
}

resolvedData.ImageInformation.SetType(ImageInformation.ImageType.SVG);

using (var bitmap = new SKBitmap(new SKImageInfo((int)sizeX, (int)sizeY)))
using (var canvas = new SKCanvas(bitmap))
using (var paint = new SKPaint())
{
    canvas.Clear(SKColors.Transparent);
    var scaleX = (float)sizeX / picture.CullRect.Width;
    var scaleY = (float)sizeY / picture.CullRect.Height;
    var matrix = SKMatrix.MakeScale(scaleX, scaleY);
    canvas.DrawPicture(picture, ref matrix, paint);
    canvas.Flush();

    token.ThrowIfCancellationRequested();

    return await Decode(picture, bitmap, resolvedData).ConfigureAwait(false);
}

binding 导致像素化,因为视图的初始宽度和高度用作 VectorWidthVectorHeight,即 -1 或您设置为 [=20= 的东西] 用于绑定 属性。因此,您的 svg 图像分辨率一开始设置得太低,然后绑定过程在不重绘 svg 图像的情况下放大视图。