我有一个(希望)简单的问题(我没有找到答案,这符合我的所有搜索)。
我使用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”作为项目资源(在每个项目中)包含在页面上(没有问题)。
我现在想将图像放在一个字节数组中,以将其发送到我们的web服务。
我没有找到任何方法来访问图像“SymbolMann.jpg”(以字节数组加载)或使用(但是)Avatar.Source。
问题:
如何将图像“SymbolMann.jpg”放入字节数组“AvatarErfassung”?
感谢您的每一个答案
Hi Dimitris
感谢您的(快速)重播
正如我写的那样,我与Xamarin合作。表格。
图像存储为资源:
在\ Resources \ Drawable \(对于Android),\ Resources \(对于iOS)和根(对于WP)。
我必须在内容页面上加载图像。
如果我超越了你的代码,那就行了:
var assembly = this.GetType().GetTypeInfo().Assembly;
我有错误信息(翻译成英文):
“System.Type不包含GetTypeInfo方法的定义(使用丢失?)”
我是否必须添加特定的使用?
你写道: //你可以用“typeof(MyType)”替换“this.GetType()”,其中MyType是程序集中的任何类型。
我需要将哪些内容作为类型放置?
= typeof(????)。GetTypeInfo()。汇编:
感谢您的回复。
更新#2:
第一,谢谢你的耐心......
不幸的是在 VS2013 中,我找不到任何显示我缺少使用功能的“解决方案” - 但我已经找到了丢失的使用我自己:-)
与此同时,我补充道
使用System.Reflection;
现在,行: var assembly = this.GetType()。GetTypeInfo()。Assembly;
已解决并编译而没有错误
此外,我已将.jpg的类型从“Android资源”更改为“嵌入式资源” 然后该应用崩溃: 长长度=长度; 因为似乎s为空(我认为找不到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将其发送到我们的网络服务。
如果用户通过mediapicker选择另一个图像,我 访问该流,问题是,从默认图像(在每个平台中)成为字节数组。
再次感谢你的帮助......
答案 0 :(得分:11)
您可以通过从程序集中读取资源流来轻松完成此操作:
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
关键字基本返回的内容)。另一种方法是在项目中包含的任何对象上调用GetType()
方法。
请注意,如果您对项目中未包含的类型调用typeof(X)
,则无法获得正确的程序集。例如。调用typeof(ContentPage).GetTypeInfo().Assembly
将返回ContentPage
类型所在的程序集。不包含您的资源的程序集。我希望这不会令人困惑。如果是,请告诉我。
现在,GetTypeInfo
方法是System.Reflection
命名空间中包含的扩展方法。当Xamarin Studio中的文本编辑器无法识别某些内容时,它会用红色突出显示它。右键单击它将在上下文菜单中为您提供Resolve选项:
如果可以解析类型或方法,它将显示该选项。
有关Xamarin Forms here中图片的更多信息。
答案 1 :(得分:7)
首先,非常感谢Dimitris指导我走向正确的方向! 强>
<强>结论:强>
基数:
我使用VS2013 - 更新2,Xamarin.Forms(1.4.1-Pre1),我的应用程序基于模板“空白应用程序(Xamarin.Forms共享)”(不是PCL)我使用所有平台(Android,iOS,WP)。
在用户注册页面上,用户可以选择图像作为头像(稍后会显示给他的帖子)。根据用户的性别,有两个默认图像(一个用于男性,一个用于女性)。然后,用户可以超过其中一个默认图像或从媒体选择器中选择另一个图像 默认图像存储在内容图像的默认位置(适用于Android,例如 / Resources / Drawable / )。 图像显示在XF-Standard-Image-Object中,Image-Source =“xxx.jpg” 这没有问题。
问题:
由于用户数据(包括头像)存储在SQL-Server上(通过Json-web-service),我必须将图像数据转换为字节数组(然后将其与其他数据一起发送为字符串到网络服务)
问题是,从默认目录加载图像并将其转换为字节数组(从而文件访问是问题 - &gt;无法访问) 。
解决方案:
感谢Dimitris指导我正确的方向,我实施了以下解决方案:
在所有项目(Android,iOS和WP)中,我添加了新目录“\ Embedded \”(直接位于根目录下)。
然后,我将这两个jpg(“SymbolMann.jpg”和“SymbolFrau.jpg”)复制到此目录中(适用于所有平台)。
然后,我已将资源类型更改为来自例如的图像。 “AndroidResource”为“嵌入式资源”(适用于所有平台的相同类型)。
在我的应用程序启动代码(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只是一个全局变量
要检查命名空间名称,我必须右键单击每个平台的项目,并查看已确定的命名空间名称(可能因项目而异)。
.Embedded。是新创建的目录(在所有平台上都是相同的名称)。
此外,我为男性形象(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
然后我将另一个字节数组中的所选字节数组(与显示图像并行)接管(以便稍后以字符串形式上传到Web服务)
AvatarErfassung = GV.ByteSymbolMann;
如果用户更改选择(例如,更改为女性):
Avatar.Source = ImageSource.FromStream(() => new MemoryStream(GV.ByteSymbolFrau));
AvatarErfassung = GV.ByteSymbolFrau;
注意:如果用户从mediapicker中选择另一个图像,我可以直接访问该流,因此这绝不是问题。
此解决方案适用于所有平台(Android,iOS,WP)。
我希望这可以帮助其他一些用户...
并且......最后感谢Dimitris
答案 2 :(得分:7)
感谢@FredWenger和@Dimitris - 这是我的解决方案,基于你的答案:
MyProject\DaffyDuck.jpg
Embedded Resource
(文件属性 - &gt;版本
动作)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();
并查看项目中列出的内容。
答案 3 :(得分:2)
我遇到很多问题。我的项目已在其他地方使用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,但你会很高兴你做到了。
答案 4 :(得分:2)
将您的图片添加到Xamarin.Forms项目的根文件夹,例如MyProject\pizza.png
在Visual Studio中,右键单击图像文件并选择Build Action
- &gt; 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;
}
}
答案 5 :(得分:1)
我使用noelicus给出了想法并打印了ManifestResourceNames数组中的所有名称,我发现我的图像名称为assembly.GetManifestResourceStream("image_name.jpg")
。然后我将方法调用从assembly.GetManifestResourceStream("ProjectName.Droid.image_name.jpeg")
更改为<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")
在那里,您将看到图像的资源名称,然后使用方法
gradle