Xamarin.Forms: 如何将资源中的图像加载到字节数组中?
Xamarin.Forms: How to load an image from Resources into a byte-array?
我有一个(希望如此)简单的问题(我没有找到适合我所有搜索的答案)。
我使用 Xamarin.Forms 1.4.1-Pre-1。
在我的应用程序中,我有:
byte[] AvatarErfassung; // Bytearray, to later update the webservice
var Avatar = new Image { HeightRequest = 71, WidthRequest = 61, HorizontalOptions = LayoutOptions.Start };
Avatar.Source = "SymbolMann.jpg";
图像“SymbolMann.jpg”作为项目资源包含在内(在每个项目中)并显示在页面上(没有问题)。
我现在想将图像放入一个字节数组中以将其发送到我们的网络服务。
我没有找到任何方法来访问图像 "SymbolMann.jpg"(将其加载到字节数组中)或使用(但是)Avatar.Source 因此。
问题:
如何将图像“SymbolMann.jpg”放入字节数组“AvatarErfassung”?
感谢您的每一个回答
嗨迪米特里斯
感谢您的(快速)回放。
如我所写,我使用 Xamarin.Forms.
图像存储为 资源:
在 \Resources\Drawable\(对于 Android)、\Resources\(对于 iOS)和根目录(对于 WP)。
我必须在内容页面上加载图像。
如果我超越你的代码,到行:
var assembly = this.GetType().GetTypeInfo().Assembly;
我有错误信息(翻译成英文):
“System.Type 不包含 GetTypeInfo 方法的定义(是否缺少 using?)”
我必须添加特定的使用吗?
你写:
// 您可以将 "this.GetType()" 替换为 "typeof(MyType)",其中 MyType 是程序集中的任何类型。
我必须放置什么类型?
= typeof(???).GetTypeInfo().Assembly:
感谢您的进一步回复。
更新#2:
首先,感谢您的耐心等待……
不幸的是,在 VS2013 中,我没有找到任何函数“resolve”显示我使用的缺失 - 但我已经使用我自己找到了缺失 :-)
同时我添加了
使用 System.Reflection;
现在,行:
var assembly = this.GetType().GetTypeInfo().Assembly;
解析编译无错
此外,我已将 .jpg 的类型从“Android 资源”更改为“嵌入式资源”。
该应用程序然后 崩溃 行:
长长度 = s.Length;
好像s是null(我觉得是找不到jpg)
进一步 - 如果我将类型更改为“嵌入式资源” - Xamarin.Forms 不再找到图像(Avatar.Source = "SymbolMann.jpg";)
如果我将 .jpg 的类型更改为“编译”,我将无法编译该应用程序。
错误信息:
命名空间不能直接包含字段或方法等成员。
那么……资源的正确类型是什么(以便它可以用 assembly.GetManifestResourceStream() 加载?
我是否必须在文件名中添加一些内容 (SymbolMann.jpg) 才能找到它?
如何更改 Avatar.Source = "SymbolMann.jpg" 以便找到它(如果我将类型从“Android 资源”更改为其他类型)?
再说一次我的需求:
在注册页面上,默认图像(符号)以标准 Xamarin.Forms 图像(avatar.source = “SymbolMann.jpg” / “SymbolFrau.jpg”)。
.jpg 存储在每个项目(Android、iOS 和 WP)的标准目录中,可以从图像对象毫无问题地访问它们。
然后,用户可以使用一张默认图像或通过 mediapicker 加载另一张。
如果用户点击“注册”按钮,我必须从图像创建一个字节数组,然后通过 json 将其发送到我们的网络服务。
如果用户 select 通过 mediapicker 另一个图像,我 有 访问流,问题是,从默认图像变成字节数组(在每个平台) .
再次感谢您的帮助...
您可以通过从程序集中读取资源流轻松地做到这一点:
var assembly = this.GetType().GetTypeInfo().Assembly; // you can replace "this.GetType()" with "typeof(MyType)", where MyType is any type in your assembly.
byte[] buffer;
using (Stream s = assembly.GetManifestResourceStream("SymbolMann.jpg”))
{
long length = s.Length;
buffer = new byte[length];
s.Read(buffer, 0, (int)length);
}
// Do something with buffer
编辑:
要获取包含项目嵌入式资源的程序集,您需要对该程序集中包含的类型调用 GetTypeInfo
方法。因此,typeof(X)
,其中 "X" 是程序集中的任何类型。例如,如果您使用名为 MyCustomPage
:
的自定义页面
public class MyCustomPage : ContentPage {}
...这就是您要传递的内容:typeof(MyCustomPage)
您需要类型为 Type
的任何实例(这基本上就是 typeof
关键字 return 的内容)。另一种方法是对项目中包含的任何对象调用 GetType()
方法。
请注意,如果您对项目中未包含的类型调用 typeof(X)
,您将无法获得正确的程序集。例如。调用 typeof(ContentPage).GetTypeInfo().Assembly
,会 return ContentPage
类型所在的程序集。 而不是 包含您的资源的程序集。我希望这不会造成混淆。如果是,请告诉我。
现在,GetTypeInfo
方法是包含在 System.Reflection
命名空间中的扩展方法。当 Xamarin Studio 中的文本编辑器无法识别某些内容时,它会以红色突出显示。右键单击它会在上下文菜单中为您提供解决选项:
如果可以解析类型或方法,它将显示该选项。
有关 Xamarin Forms 图像的更多信息 here。
首先,非常感谢Dimitris,他指引了我正确的方向!
结论:
基数:
我使用 VS2013 - 更新 2,Xamarin.Forms (1.4.1-Pre1),我的应用程序基于模板 “空白应用程序(Xamarin.Forms 共享)” (不是 PCL)并且我使用所有平台(Android、iOS、WP)。
在用户注册页面上,用户可以 select 图像作为头像(稍后会显示在他的帖子中)。根据用户的性别,会显示两张默认图像(一张用于男性,一张用于女性)。然后,用户可以从媒体选择器中选择一个默认图像或 select 另一个图像。
默认图像存储在内容图像的默认位置(对于 Android,例如 /Resources/Drawable/)。
图像显示在 XF-Standard-Image-Object 中,Image-Source = “xxx.jpg”。
这没有问题。
问题:
由于用户数据(包括头像)存储在 SQL-服务器(通过 Json-网络服务),我必须将图像数据转换为字节数组(以发送然后它与其他数据一起作为网络服务的字符串)。
问题是,从默认目录加载图像并将其转换为字节数组(因此文件访问是问题所在 -> 无法访问)。
解决方法:
感谢 Dimitris,它引导我朝着正确的方向前进,我已经实施了以下解决方案:
在所有项目(Android、iOS和WP)中,我添加了一个新目录“\Embedded\”(直接在根目录下).
然后,我在这个目录中复制了我的两个 jpg(“SymbolMann.jpg”和“SymbolFrau.jpg”)(适用于所有平台)。
然后,我将资源类型更改为图像,例如“AndroidResource”到“Embedded Resource”(对于相同类型的所有平台)。
在我的应用程序启动代码 (app.cs) 中,我添加了:
//
string cNameSpace = "";
switch (Device.OS)
{
case TargetPlatform.WinPhone:
cNameSpace = "MatrixGuide.WinPhone";
break;
case TargetPlatform.iOS:
cNameSpace = "MatrixGuide.iOS";
break;
case TargetPlatform.Android:
cNameSpace = "MatrixGuide.Droid";
break;
}
GV.cEmbeddedAblage = cNameSpace + ".Embedded.";
其中 GV.cEmbeddedAblage 只是一个全局变量。
要检查命名空间名称,我必须右键单击每个平台的项目并查看已确定的命名空间名称(可能因项目而异)。
.嵌入式。是新创建的目录(在所有平台上名称相同)。
此外,我还为男性图像 (GV.ByteSymbolMann) 和女性图像 (GV.ByteSymbolFrau) 创建了全局字节数组。
在注册页面的启动代码中,我添加了:
string cFilename = "";
if (GV.ByteSymbolMann == null) // not yet loaded
{
cFilename = GV.cEmbeddedAblage + "SymbolMann.jpg";
var assembly = this.GetType().GetTypeInfo().Assembly;
byte[] buffer;
using (Stream s = assembly.GetManifestResourceStream(cFilename))
{
long length = s.Length;
buffer = new byte[length];
s.Read(buffer, 0, (int)length);
GV.ByteSymbolMann = buffer; // Overtake byte-array in global variable for male
}
}
//
if (GV.ByteSymbolFrau == null) // not yet loaded
{
cFilename = GV.cEmbeddedAblage + "SymbolFrau.jpg";
var assembly = this.GetType().GetTypeInfo().Assembly;
byte[] buffer;
using (Stream s = assembly.GetManifestResourceStream(cFilename))
{
long length = s.Length;
buffer = new byte[length];
s.Read(buffer, 0, (int)length);
GV.ByteSymbolFrau = buffer; // Overtake byte-array in global variable for female
}
}
将 .jpg 加载到图像对象中的代码,我必须更改为:
//Avatar.Source = "SymbolMann.jpg"; // Load from default directory
至
Avatar.Source = ImageSource.FromStream(() => new MemoryStream(GV.ByteSymbolMann)); // Load (stream) from byte-array
然后我在另一个字节数组中接管 selected 字节数组(与显示图像并行)(稍后作为字符串上传到网络服务)
AvatarErfassung = GV.ByteSymbolMann;
如果用户更改select离子(例如更改为女性):
Avatar.Source = ImageSource.FromStream(() => new MemoryStream(GV.ByteSymbolFrau));
AvatarErfassung = GV.ByteSymbolFrau;
注意:如果用户 select 来自 mediapicker 的另一个图像,我可以直接访问流,所以这从来都不是问题。
此解决方案适用于所有平台(Android、iOS、WP)。
希望这对其他用户有帮助…
还有...最后感谢 Dimitris
感谢@FredWenger 和@Dimitris - 这是我基于你们两个答案的解决方案:
- 将图像添加到 Xamarin Forms (Portable) 项目中的任意位置。我只是
去找根:
MyProject\DaffyDuck.jpg
- 将图像标记为
Embedded Resource
(文件属性 -> 构建
动作)
- 像这样调用引用嵌入式资源的函数:
ImageDataFromResource("MyProject.DaffyDuck.jpg")
请注意,您需要包含项目名称以获取程序集名称 *.
这是函数:
public byte[] ImageDataFromResource(string r)
{
// Ensure "this" is an object that is part of your implementation within your Xamarin forms project
var assembly = this.GetType().GetTypeInfo().Assembly;
byte[] buffer = null;
using (System.IO.Stream s = assembly.GetManifestResourceStream(r))
{
if (s != null)
{
long length = s.Length;
buffer = new byte[length];
s.Read(buffer, 0, (int)length);
}
}
return buffer;
}
如果您需要在 ImageView 控件中引用加载的数据,请执行
因此:
ImageView.Source = ImageSource.FromStream(() => new MemoryStream(imageData));
*注意:如果第 3 步不起作用并且您想检查您的嵌入式资源名称,请调用此:var names = assembly.GetManifestResourceNames();
并查看您的项目中列出的内容。
我使用 noelicus 给出的想法并打印了 ManifestResourceNames 数组中的所有名称,我在那里找到了我的图像名称 ProjectName.Droid.image_name.jpeg
。然后我只是将方法调用从 assembly.GetManifestResourceStream("image_name.jpg")
更改为 assembly.GetManifestResourceStream("ProjectName.Droid.image_name.jpeg")
. 它奏效了。
所以正确答案是:
- 将图像存储在 PCL 的根文件夹中。
- 在属性中将其生成操作作为嵌入式资源。
然后打印 <b><i>var names = assembly.GetManifestResourceNames()</i></b>
数组,这将是一个字符串数组,可以使用
打印
foreach(var data in names){Debug.WriteLine(data);}
在那里你会看到图像的资源名称,然后使用方法
Stream s = assembly.GetManifestResourceStream("resource_name_you_found.format")
我在让它工作时遇到了很多问题。我的项目已经在别处使用 FFImageLoading,我发现这是将 .png 作为流加载的最简单方法:
using (var stream = await ImageService.Instance.LoadCompiledResource("resource_image.png").AsPNGStreamAsync())
{
localBitmap = SKBitmap.Decode(stream);
}
确保您的资源文件在 iOS 和 Droid 项目中具有相同的名称。他们可能已经将构建操作设置为 'BundleResource' (iOS) 或 'AndroidResource' (Droid)。
当然,您必须安装 FFImageLoading Nuget,但您会很高兴自己安装了。
添加到 :
设置
将您的图像添加到 Xamarin.Forms 项目的根文件夹中,例如MyProject\pizza.png
在Visual Studio中右击图片文件然后selectBuild Action
->EmbeddedResource
代码
public byte[] GetImageFromFile(string fileName)
{
var applicationTypeInfo = Application.Current.GetType().GetTypeInfo();
byte[] buffer;
using (var stream = applicationTypeInfo.Assembly.GetManifestResourceStream($"{applicationTypeInfo.Namespace}.fileName"))
{
if (stream != null)
{
long length = stream.Length;
buffer = new byte[length];
stream.Read(buffer, 0, (int)length);
}
}
return buffer;
}
例子
public class MyPage() : ContentPage
{
public MyPage()
{
var imageAsByteArray = GetImageFromFile("pizza.png");
var pizzaImage = new Image();
pizzaImage.Source = ImageSource.FromStream(() => new MemoryStream(imageAsByteArray));
Content = pizzaImage;
}
byte[] GetImageFromFile(string fileName)
{
var applicationTypeInfo = Application.Current.GetType().GetTypeInfo();
byte[] buffer;
using (var stream = applicationTypeInfo.Assembly.GetManifestResourceStream($"{applicationTypeInfo.Namespace}.fileName"))
{
if (stream != null)
{
long length = stream.Length;
buffer = new byte[length];
stream.Read(buffer, 0, (int)length);
}
}
return buffer;
}
}
我有一个(希望如此)简单的问题(我没有找到适合我所有搜索的答案)。
我使用 Xamarin.Forms 1.4.1-Pre-1。 在我的应用程序中,我有:
byte[] AvatarErfassung; // Bytearray, to later update the webservice
var Avatar = new Image { HeightRequest = 71, WidthRequest = 61, HorizontalOptions = LayoutOptions.Start };
Avatar.Source = "SymbolMann.jpg";
图像“SymbolMann.jpg”作为项目资源包含在内(在每个项目中)并显示在页面上(没有问题)。
我现在想将图像放入一个字节数组中以将其发送到我们的网络服务。
我没有找到任何方法来访问图像 "SymbolMann.jpg"(将其加载到字节数组中)或使用(但是)Avatar.Source 因此。
问题:
如何将图像“SymbolMann.jpg”放入字节数组“AvatarErfassung”?
感谢您的每一个回答
嗨迪米特里斯
感谢您的(快速)回放。
如我所写,我使用 Xamarin.Forms.
图像存储为 资源:
在 \Resources\Drawable\(对于 Android)、\Resources\(对于 iOS)和根目录(对于 WP)。
我必须在内容页面上加载图像。
如果我超越你的代码,到行:
var assembly = this.GetType().GetTypeInfo().Assembly;
我有错误信息(翻译成英文):
“System.Type 不包含 GetTypeInfo 方法的定义(是否缺少 using?)”
我必须添加特定的使用吗?
你写: // 您可以将 "this.GetType()" 替换为 "typeof(MyType)",其中 MyType 是程序集中的任何类型。
我必须放置什么类型?
= typeof(???).GetTypeInfo().Assembly:
感谢您的进一步回复。
更新#2:
首先,感谢您的耐心等待……
不幸的是,在 VS2013 中,我没有找到任何函数“resolve”显示我使用的缺失 - 但我已经使用我自己找到了缺失 :-)
同时我添加了
使用 System.Reflection;
现在,行: var assembly = this.GetType().GetTypeInfo().Assembly;
解析编译无错
此外,我已将 .jpg 的类型从“Android 资源”更改为“嵌入式资源”。
该应用程序然后 崩溃 行:
长长度 = s.Length;
好像s是null(我觉得是找不到jpg)
进一步 - 如果我将类型更改为“嵌入式资源” - Xamarin.Forms 不再找到图像(Avatar.Source = "SymbolMann.jpg";)
如果我将 .jpg 的类型更改为“编译”,我将无法编译该应用程序。
错误信息:
命名空间不能直接包含字段或方法等成员。
那么……资源的正确类型是什么(以便它可以用 assembly.GetManifestResourceStream() 加载?
我是否必须在文件名中添加一些内容 (SymbolMann.jpg) 才能找到它?
如何更改 Avatar.Source = "SymbolMann.jpg" 以便找到它(如果我将类型从“Android 资源”更改为其他类型)?
再说一次我的需求:
在注册页面上,默认图像(符号)以标准 Xamarin.Forms 图像(avatar.source = “SymbolMann.jpg” / “SymbolFrau.jpg”)。
.jpg 存储在每个项目(Android、iOS 和 WP)的标准目录中,可以从图像对象毫无问题地访问它们。
然后,用户可以使用一张默认图像或通过 mediapicker 加载另一张。
如果用户点击“注册”按钮,我必须从图像创建一个字节数组,然后通过 json 将其发送到我们的网络服务。
如果用户 select 通过 mediapicker 另一个图像,我 有 访问流,问题是,从默认图像变成字节数组(在每个平台) .
再次感谢您的帮助...
您可以通过从程序集中读取资源流轻松地做到这一点:
var assembly = this.GetType().GetTypeInfo().Assembly; // you can replace "this.GetType()" with "typeof(MyType)", where MyType is any type in your assembly.
byte[] buffer;
using (Stream s = assembly.GetManifestResourceStream("SymbolMann.jpg”))
{
long length = s.Length;
buffer = new byte[length];
s.Read(buffer, 0, (int)length);
}
// Do something with buffer
编辑:
要获取包含项目嵌入式资源的程序集,您需要对该程序集中包含的类型调用 GetTypeInfo
方法。因此,typeof(X)
,其中 "X" 是程序集中的任何类型。例如,如果您使用名为 MyCustomPage
:
public class MyCustomPage : ContentPage {}
...这就是您要传递的内容:typeof(MyCustomPage)
您需要类型为 Type
的任何实例(这基本上就是 typeof
关键字 return 的内容)。另一种方法是对项目中包含的任何对象调用 GetType()
方法。
请注意,如果您对项目中未包含的类型调用 typeof(X)
,您将无法获得正确的程序集。例如。调用 typeof(ContentPage).GetTypeInfo().Assembly
,会 return ContentPage
类型所在的程序集。 而不是 包含您的资源的程序集。我希望这不会造成混淆。如果是,请告诉我。
现在,GetTypeInfo
方法是包含在 System.Reflection
命名空间中的扩展方法。当 Xamarin Studio 中的文本编辑器无法识别某些内容时,它会以红色突出显示。右键单击它会在上下文菜单中为您提供解决选项:
如果可以解析类型或方法,它将显示该选项。
有关 Xamarin Forms 图像的更多信息 here。
首先,非常感谢Dimitris,他指引了我正确的方向!
结论:
基数:
我使用 VS2013 - 更新 2,Xamarin.Forms (1.4.1-Pre1),我的应用程序基于模板 “空白应用程序(Xamarin.Forms 共享)” (不是 PCL)并且我使用所有平台(Android、iOS、WP)。
在用户注册页面上,用户可以 select 图像作为头像(稍后会显示在他的帖子中)。根据用户的性别,会显示两张默认图像(一张用于男性,一张用于女性)。然后,用户可以从媒体选择器中选择一个默认图像或 select 另一个图像。
默认图像存储在内容图像的默认位置(对于 Android,例如 /Resources/Drawable/)。
图像显示在 XF-Standard-Image-Object 中,Image-Source = “xxx.jpg”。
这没有问题。
问题:
由于用户数据(包括头像)存储在 SQL-服务器(通过 Json-网络服务),我必须将图像数据转换为字节数组(以发送然后它与其他数据一起作为网络服务的字符串)。
问题是,从默认目录加载图像并将其转换为字节数组(因此文件访问是问题所在 -> 无法访问)。
解决方法:
感谢 Dimitris,它引导我朝着正确的方向前进,我已经实施了以下解决方案:
在所有项目(Android、iOS和WP)中,我添加了一个新目录“\Embedded\”(直接在根目录下).
然后,我在这个目录中复制了我的两个 jpg(“SymbolMann.jpg”和“SymbolFrau.jpg”)(适用于所有平台)。
然后,我将资源类型更改为图像,例如“AndroidResource”到“Embedded Resource”(对于相同类型的所有平台)。
在我的应用程序启动代码 (app.cs) 中,我添加了:
//
string cNameSpace = "";
switch (Device.OS)
{
case TargetPlatform.WinPhone:
cNameSpace = "MatrixGuide.WinPhone";
break;
case TargetPlatform.iOS:
cNameSpace = "MatrixGuide.iOS";
break;
case TargetPlatform.Android:
cNameSpace = "MatrixGuide.Droid";
break;
}
GV.cEmbeddedAblage = cNameSpace + ".Embedded.";
其中 GV.cEmbeddedAblage 只是一个全局变量。
要检查命名空间名称,我必须右键单击每个平台的项目并查看已确定的命名空间名称(可能因项目而异)。
.嵌入式。是新创建的目录(在所有平台上名称相同)。
此外,我还为男性图像 (GV.ByteSymbolMann) 和女性图像 (GV.ByteSymbolFrau) 创建了全局字节数组。
在注册页面的启动代码中,我添加了:
string cFilename = "";
if (GV.ByteSymbolMann == null) // not yet loaded
{
cFilename = GV.cEmbeddedAblage + "SymbolMann.jpg";
var assembly = this.GetType().GetTypeInfo().Assembly;
byte[] buffer;
using (Stream s = assembly.GetManifestResourceStream(cFilename))
{
long length = s.Length;
buffer = new byte[length];
s.Read(buffer, 0, (int)length);
GV.ByteSymbolMann = buffer; // Overtake byte-array in global variable for male
}
}
//
if (GV.ByteSymbolFrau == null) // not yet loaded
{
cFilename = GV.cEmbeddedAblage + "SymbolFrau.jpg";
var assembly = this.GetType().GetTypeInfo().Assembly;
byte[] buffer;
using (Stream s = assembly.GetManifestResourceStream(cFilename))
{
long length = s.Length;
buffer = new byte[length];
s.Read(buffer, 0, (int)length);
GV.ByteSymbolFrau = buffer; // Overtake byte-array in global variable for female
}
}
将 .jpg 加载到图像对象中的代码,我必须更改为:
//Avatar.Source = "SymbolMann.jpg"; // Load from default directory
至
Avatar.Source = ImageSource.FromStream(() => new MemoryStream(GV.ByteSymbolMann)); // Load (stream) from byte-array
然后我在另一个字节数组中接管 selected 字节数组(与显示图像并行)(稍后作为字符串上传到网络服务)
AvatarErfassung = GV.ByteSymbolMann;
如果用户更改select离子(例如更改为女性):
Avatar.Source = ImageSource.FromStream(() => new MemoryStream(GV.ByteSymbolFrau));
AvatarErfassung = GV.ByteSymbolFrau;
注意:如果用户 select 来自 mediapicker 的另一个图像,我可以直接访问流,所以这从来都不是问题。
此解决方案适用于所有平台(Android、iOS、WP)。
希望这对其他用户有帮助…
还有...最后感谢 Dimitris
感谢@FredWenger 和@Dimitris - 这是我基于你们两个答案的解决方案:
- 将图像添加到 Xamarin Forms (Portable) 项目中的任意位置。我只是
去找根:
MyProject\DaffyDuck.jpg
- 将图像标记为
Embedded Resource
(文件属性 -> 构建 动作) - 像这样调用引用嵌入式资源的函数:
ImageDataFromResource("MyProject.DaffyDuck.jpg")
请注意,您需要包含项目名称以获取程序集名称 *. 这是函数:
public byte[] ImageDataFromResource(string r) { // Ensure "this" is an object that is part of your implementation within your Xamarin forms project var assembly = this.GetType().GetTypeInfo().Assembly; byte[] buffer = null; using (System.IO.Stream s = assembly.GetManifestResourceStream(r)) { if (s != null) { long length = s.Length; buffer = new byte[length]; s.Read(buffer, 0, (int)length); } } return buffer; }
如果您需要在 ImageView 控件中引用加载的数据,请执行 因此:
ImageView.Source = ImageSource.FromStream(() => new MemoryStream(imageData));
*注意:如果第 3 步不起作用并且您想检查您的嵌入式资源名称,请调用此:var names = assembly.GetManifestResourceNames();
并查看您的项目中列出的内容。
我使用 noelicus 给出的想法并打印了 ManifestResourceNames 数组中的所有名称,我在那里找到了我的图像名称 ProjectName.Droid.image_name.jpeg
。然后我只是将方法调用从 assembly.GetManifestResourceStream("image_name.jpg")
更改为 assembly.GetManifestResourceStream("ProjectName.Droid.image_name.jpeg")
. 它奏效了。
所以正确答案是:
- 将图像存储在 PCL 的根文件夹中。
- 在属性中将其生成操作作为嵌入式资源。
然后打印
打印<b><i>var names = assembly.GetManifestResourceNames()</i></b>
数组,这将是一个字符串数组,可以使用foreach(var data in names){Debug.WriteLine(data);}
在那里你会看到图像的资源名称,然后使用方法
Stream s = assembly.GetManifestResourceStream("resource_name_you_found.format")
我在让它工作时遇到了很多问题。我的项目已经在别处使用 FFImageLoading,我发现这是将 .png 作为流加载的最简单方法:
using (var stream = await ImageService.Instance.LoadCompiledResource("resource_image.png").AsPNGStreamAsync())
{
localBitmap = SKBitmap.Decode(stream);
}
确保您的资源文件在 iOS 和 Droid 项目中具有相同的名称。他们可能已经将构建操作设置为 'BundleResource' (iOS) 或 'AndroidResource' (Droid)。
当然,您必须安装 FFImageLoading Nuget,但您会很高兴自己安装了。
添加到
设置
将您的图像添加到 Xamarin.Forms 项目的根文件夹中,例如
MyProject\pizza.png
在Visual Studio中右击图片文件然后select
Build Action
->EmbeddedResource
代码
public byte[] GetImageFromFile(string fileName)
{
var applicationTypeInfo = Application.Current.GetType().GetTypeInfo();
byte[] buffer;
using (var stream = applicationTypeInfo.Assembly.GetManifestResourceStream($"{applicationTypeInfo.Namespace}.fileName"))
{
if (stream != null)
{
long length = stream.Length;
buffer = new byte[length];
stream.Read(buffer, 0, (int)length);
}
}
return buffer;
}
例子
public class MyPage() : ContentPage
{
public MyPage()
{
var imageAsByteArray = GetImageFromFile("pizza.png");
var pizzaImage = new Image();
pizzaImage.Source = ImageSource.FromStream(() => new MemoryStream(imageAsByteArray));
Content = pizzaImage;
}
byte[] GetImageFromFile(string fileName)
{
var applicationTypeInfo = Application.Current.GetType().GetTypeInfo();
byte[] buffer;
using (var stream = applicationTypeInfo.Assembly.GetManifestResourceStream($"{applicationTypeInfo.Namespace}.fileName"))
{
if (stream != null)
{
long length = stream.Length;
buffer = new byte[length];
stream.Read(buffer, 0, (int)length);
}
}
return buffer;
}
}