3

我会在 Xamarin.Forms 中放置一个嵌入svg图像,就像这样ImageSourceButton

<Button Text="Button" ImageSource="resource://fullname.svg">
</Button>

可能将转换应用于 svg(来自FFImageLoading.Transformations),但这是一个加号。

我试过这种语法

<Button Text="Button"
  ImageSource="{ext:ImageResourceExtension fullname.svg}" />

C#

    public class ImageResourceExtension : IMarkupExtension
    {
        private static Assembly Assembly = typeof(ImageResourceExtension).GetTypeInfo().Assembly;

        public string Source { get; set; }

        public object ProvideValue(IServiceProvider serviceProvider)
        {
            if (Source == null) return null;
            return SvgImageSource.FromResource(Source, Assembly, 32, 32);

        }
   }

但它不起作用。

此外,我无法使用这种语法

Source="{resource://fullname.svg, Converter={StaticResource SvgImageSourceConverter}}"

有什么帮助吗?谢谢

4

2 回答 2

4

正如 Jason 所说,FFImageLoading支持 SVG 文件。请按照以下步骤操作。

在 Xamarin.Forms 而不是 Android 部件中创建资源文件夹。然后将 SVG 文件添加为嵌入式资源。

在此处输入图像描述

用途:用于SvgCachedImage显示嵌入的 svg 图片,用于TapGestureRecognizer模拟按钮点击事件。

<ffimageloadingsvg:SvgCachedImage
            HeightRequest="50"
            Source="resource://XamarinDemo.Resources.brightness2.svg"
            WidthRequest="50">
            <ffimageloadingsvg:SvgCachedImage.GestureRecognizers>
                <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"></TapGestureRecognizer>
            </ffimageloadingsvg:SvgCachedImage.GestureRecognizers>
        </ffimageloadingsvg:SvgCachedImage>

不要忘记添加命名空间。

xmlns:ffimageloadingsvg="clr-namespace:FFImageLoading.Svg.Forms;assembly=FFImageLoading.Svg.Forms"

在此处输入图像描述

更新:我们可以使用SkiaSharpsvg 文件来绘制图像。

我的控制.cs

public class MyControl : Frame
{
    private readonly SKCanvasView _canvasView = new SKCanvasView();
    public MyControl()
    {
        Padding = new Thickness(0);
        BackgroundColor = Color.Transparent;
        Content = _canvasView;

        _canvasView.PaintSurface += CanvasViewOnPaintSurface;
    }
    public static readonly BindableProperty ImageProperty = BindableProperty.Create(
       nameof(Image), typeof(string), typeof(MyControl), default(string), propertyChanged: RedrawCanvas);

    public string Image
    {
        get => (string)GetValue(ImageProperty);
        set => SetValue(ImageProperty, value);
    }
    private static void RedrawCanvas(BindableObject bindable, object oldvalue, object newvalue)
    {
        MyControl svgIcon = bindable as MyControl;
        svgIcon?._canvasView.InvalidateSurface();
    }
    private void CanvasViewOnPaintSurface(object sender, SKPaintSurfaceEventArgs e)
    {
        SKCanvas canvas = e.Surface.Canvas;
        canvas.Clear();


        using (Stream stream = GetType().Assembly.GetManifestResourceStream(Image))
        {
            SkiaSharp.Extended.Svg.SKSvg svg = new SkiaSharp.Extended.Svg.SKSvg();
            svg.Load(stream);

            SKImageInfo info = e.Info;
            canvas.Translate(info.Width / 2f, info.Height / 2f);

            SKRect bounds = svg.ViewBox;
            float xRatio = info.Width / bounds.Width;
            float yRatio = info.Height / bounds.Height;

            float ratio = Math.Min(xRatio, yRatio);

            canvas.Scale(ratio);
            canvas.Translate(-bounds.MidX, -bounds.MidY);

            canvas.DrawPicture(svg.Picture);

        }
    }
}

用法:

<local:MyControl
            HeightRequest="50"
            Image="XamarinDemo.Resources.brightness2.svg"
            WidthRequest="50" />

你可以TapGestureRecognizer用来模拟按钮点击事件。

于 2020-04-02T08:09:19.623 回答
1

更新了 Xamarin 的原始图像资源扩展类。OP 的课程有两个问题:

  1. 缺少允许跳过“源”属性名称的 ContentProperty 属性。
  2. 部分资源名称转换为完整资源名称的部分。

添加了可选的“Assembly”属性,允许指定不同的程序集。

用法:

<ff:SvgCachedImage Source="{ImageFromResource file_name.svg}" />
<ff:SvgCachedImage Source="{ImageFromResource Icons/file_name.svg}" />
<Image Source="{ImageFromResource file_name.png}" />
<Image Source="{ImageFromResource file_name.png, Assembly=MyAssembly}" />

ImageFromResourceExtension 类:

/// <summary>
/// Get image source from assembly resource by using partial name.
/// </summary>
/// <example>
/// &lt;ff:SvgCachedImage Source="{ImageFromResource file_name.svg}" /&gt;
/// &lt;Image Source="{ImageFromResource file_name.png}" /&gt;
/// &lt;Image Source="{ImageFromResource file_name.png, Assembly=MyAssembly}" /&gt;
/// </example>
/// <remarks>
/// Parameter format without extension:
/// Source="resource://{AssemblyName}.{PathName}.{FileName}"
/// </remarks>
[ContentProperty(nameof(Source))]
public class ImageFromResourceExtension : IMarkupExtension
{

    private static Assembly defaultAssembly = typeof(ImageResourceExtension).GetTypeInfo().Assembly;

    public string Source { get; set; }
    public string Assembly { get; set; }

    public object ProvideValue(IServiceProvider serviceProvider)
    {
        if (string.IsNullOrEmpty(Source))
            return null;
        // Replace folder separators with dots.
        var name = Source.Replace('/', '.');
        // Find full name of the resource by partial name.
        var fullName = defaultAssembly.GetManifestResourceNames()
            .FirstOrDefault(x => x.EndsWith("." + name));
        if (fullName == null)
            return null;
        // Load different assembly if specified.
        var assembly = string.IsNullOrEmpty(Assembly)
            ? defaultAssembly
            : System.Reflection.Assembly.Load(Assembly);
        // Return image source.
        return name.EndsWith(".svg", StringComparison.OrdinalIgnoreCase)
            ? SvgImageSource.FromResource(fullName, assembly)
            : ImageSource.FromResource(fullName, assembly);
    }
}
于 2021-02-10T13:27:01.807 回答