Uno平台:加载嵌入式资源文件

Uno platform: load embedded resource file

如何为 Android 头部加载嵌入资源?我的代码,下面适用于 UWP:

  Assembly assembly = GetType ().GetTypeInfo ().Assembly;
  string[] names = assembly.GetManifestResourceNames ();
  Console.WriteLine ("Resource Names");
  foreach (var name in names)
    Console.WriteLine ("  " + name);
  using (var stream = assembly.GetManifestResourceStream (Source))
  {
    bmpSrc = SKBitmap.Decode (stream);
  }

而且,XAML 是

  <controls:ExpandableImage 
    ...
    Source="UnoTest.Assets.icons.folder_tab.png"
  />

文件位于 UnoTest.Shared/Assets/ 中并被标记为“嵌入资源”。

调试输出显示“名称”之一是

"UnoTest.Droid.Assets.icons.folder_tab.png"

表明我的 URI 应该指的是 Android 头部。

编辑

最终,在这个实验中,我打算在目标区域的左侧绘制位图的左侧部分,在右侧绘制右侧,并在位图的垂直条纹的扩展填充中间中间部分。然后,在上面画一些文字。

private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e)
{
  ...
  // identify left, right halves and a 10px wide swath of the middle of the source bitmap
  SKRect rectSrcLeft = new SKRect(0, 0, bmpSrc.Width / 2, bmpSrc.Height);
  SKRect rectSrcRight = new SKRect(bmpSrc.Width / 2, 0, bmpSrc.Width, bmpSrc.Height);
  SKRect rectSrcMid = new SKRect(bmpSrc.Width / 2 - 5, 0, bmpSrc.Width / 2 + 5, bmpSrc.Height);

  // create a new bitmap containing a 10 pixel wide swatch from middle of bmpSrc
  SKBitmap bmpSrcMid = new SKBitmap(10, bmpSrc.Height);
  using (SKCanvas tempCanvas = new SKCanvas(bmpSrcMid))
  {
    SKRect rectDest = new SKRect(0, 0, rectSrcMid.Width, rectSrcRight.Height);
    tempCanvas.DrawBitmap(bmpSrc, rectSrcMid, rectDest);
  }

  var canvas = e.Surface.Canvas;

  using (SKPaint paint = new SKPaint())
  {
    canvas.Save();
    float hDest = canvas.DeviceClipBounds.Height;
    float scale = hDest / (float)bmpSrc.Height;
    canvas.Scale(scale);

    paint.IsAntialias = true;

    // determine dest rect for middle section
    float rightDest = (float)textBounds.Width / scale; // rightmost point of whole target area
    SKRect rectDestMid = new SKRect(rectSrcLeft.Width, 0, rightDest - rectSrcRight.Width, rectSrcRight.Height);

    // left part of tab
    canvas.DrawBitmap(bmpSrc, rectSrcLeft, rectSrcLeft, paint);

    // right part of tab
    {
      SKRect rectDest = new SKRect(rectDestMid.Right, 0, rightDest, rectSrcRight.Height);
      canvas.DrawBitmap(bmpSrc, rectSrcRight, rectDest, paint);
    }

    // mid part of tab
    paint.Shader = SKShader.CreateBitmap(bmpSrcMid,
                                         SKShaderTileMode.Repeat,
                                         SKShaderTileMode.Repeat);
    canvas.DrawRect(rectDestMid, paint);

    canvas.Restore(); // back to orig scale
  }

  using (SKPaint paint = new SKPaint { Color = SKColors.Black })
  {
    float leftText = 20; // matches padding in ListPage.xaml
    float bottomText = canvas.DeviceClipBounds.Height / 2 + textCoreHeight / 2;
    canvas.DrawText(Label, new SKPoint(leftText, bottomText), paint);
  }
}

控件的XAML是:

<UserControl
  x:Class="UnoTest.Shared.Controls.ExpandableImage"
  ...
  <skia:SKXamlCanvas x:Name="EICanvas" PaintSurface="OnPaintSurface" />
</UserControl>

我是否需要编写一些代码来修改 Android 案例的“通用”URI?

共享项目中定义的嵌入式资源正在共享引用该共享项目的项目的默认命名空间,这使得文件名在 Uno 模板中默认情况下在所有项目中都不同。

您有多个选择:

  • 将默认命名空间更改为在所有项目中都相同。
  • 跳过前两个点,以此为底
  • 使用不同的项目(.NET Standard 2.0 项目即可)并将您的资源放在那里

这是我最后做的。它不是 100% 稳健但非常接近。而且真的很简单。

  if (Source == null)
    return;

  string sourceWithNameSpace = null;
  Assembly assembly = GetType ().GetTypeInfo ().Assembly;
  string[] names = assembly.GetManifestResourceNames ();
  foreach (var name in names)
  {
    if (name.EndsWith (Source))
    {
      sourceWithNameSpace = name;
      break;
    }
  }
  if (sourceWithNameSpace == null)
    return;

  using (var stream = assembly.GetManifestResourceStream (sourceWithNameSpace))
  {
    bmpSrc = SKBitmap.Decode (stream);
  }

并且,在 XML 文件中,从源路径中删除项目头,例如:

    Source="Assets.icons.folder_tab.png"