How do I load an embedded resource for the Android head ? My code, below works for 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);
}
And, the XAML is
<controls:ExpandableImage
...
Source="UnoTest.Assets.icons.folder_tab.png"
/>
The file resides in UnoTest.Shared/Assets/
and is marked as "embedded resource".
The debug output shows that one of the "names" is
"UnoTest.Droid.Assets.icons.folder_tab.png"
indicating that my URI should be referring to the Android head.
EDIT
Ultimately, in this experiment, I am intending to paint the left part of the bitmap in the left of the target area, the right in the right, and fill the middle with an expansion of a vertical stripe from the bitmap's mid section. Then, draw some text over it.
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);
}
}
The XAML for the control is:
<UserControl
x:Class="UnoTest.Shared.Controls.ExpandableImage"
...
<skia:SKXamlCanvas x:Name="EICanvas" PaintSurface="OnPaintSurface" />
</UserControl>
Do I need to write some code to modify the "generic" URI for the Android case ?
Here's what I ended up doing. It is not 100% robust but pretty close. And it's really simple.
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);
}
And, in the XML file, leave off the project head from the Source path, e.g.:
Source="Assets.icons.folder_tab.png"