我一直在挖掘Xamarin.Forms.Labs以了解有关如何访问和操作图像的更多信息。将图像保存到Android / iOS照片库工作正常,至少通过用户交互从任一图像中检索图像也是如此。
问题是我希望能够在内部将一些文件保存到程序中。实际上保存文件本身似乎不是问题 - 我已经为此编写了一个接口/ DependencyService解决方案。
我似乎无法做的是使用Xamarin.Forms Image或ImageSource访问图像数据本身的bytes []或流。使用静态方法将流读入ImageSource相对简单,那么如何将这些字节输出以便将文件保存在程序本身中呢?
构建此框架:我正在开发一个应用程序,用户在一个表单中包含/选择图片,并最终将表单发布到网站。因此,能够实际保存图片或访问数据本身以便传输它是非常关键的。
答案 0 :(得分:1)
一种非常黑客的方法是为您的图像编写自定义渲染器。然后渲染器将从本机控件获取byte[]/Stream
。这是一个非常粗略的实现,没有任何错误处理来帮助您入门:
public class MyImage : Image
{
public Func<byte[]> GetBytes { get; set; }
}
以下是 iOS 渲染器:
public class MyImageRenderer : ImageRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
{
base.OnElementChanged(e);
var newImage = e.NewElement as MyImage;
if (newImage != null)
{
newImage.GetBytes = () =>
{
return this.Control.Image.AsPNG().ToArray();
};
}
var oldImage = e.OldElement as MyImage;
if (oldImage != null)
{
oldImage.GetBytes = null;
}
}
}
Android 一个更多参与:
public class MyImageRenderer : ImageRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
{
base.OnElementChanged(e);
var newImage = e.NewElement as MyImage;
if (newImage != null)
{
newImage.GetBytes = () =>
{
var drawable = this.Control.Drawable;
var bitmap = Bitmap.CreateBitmap(drawable.IntrinsicWidth, drawable.IntrinsicHeight, Bitmap.Config.Argb8888);
drawable.Draw(new Canvas(bitmap));
using (var ms = new MemoryStream())
{
bitmap.Compress(Bitmap.CompressFormat.Png, 100, ms);
return ms.ToArray();
}
};
}
var oldImage = e.OldElement as MyImage;
if (oldImage != null)
{
oldImage.GetBytes = null;
}
}
}
最后,用法很明显:
var bytes = myImage.GetBytes?.Invoke();
将想法扩展到支持流应该非常简单。显而易见的警告是,表单控件(MyImage
)通过GetBytes()
保留对其渲染器的引用,但这似乎是不可避免的。