我想从库中选择一张图片或用相机拍照并将结果显示在视图中(ImageView)
但根据包括this one在内的一些帖子,我使用的MvxHttpImageView需要一个Uri来显示图像(它来自文件系统或相机)。这意味着,将Stream转换为文件并重新获得Uri。
我写了一个完成这项工作的图片服务:
public class PictureService : IPictureService,
IMvxServiceConsumer<IMvxPictureChooserTask>,
IMvxServiceConsumer<IMvxSimpleFileStoreService>
{
private const int MaxPixelDimension = 1024;
private const int DefaultJpegQuality = 92;
public void TakeNewPhoto(Action<string> onSuccess, Action<string> onError)
{
this.GetService<IMvxPictureChooserTask>().TakePicture(
PictureService.MaxPixelDimension,
PictureService.DefaultJpegQuality,
pictureStream =>
{
var newPictureUri = this.Save(pictureStream);
if (!string.IsNullOrWhiteSpace(newPictureUri))
onSuccess(newPictureUri);
else
onError("No picture selected");
},
() => { /* cancel is ignored */ });
}
public void SelectExistingPicture(Action<string> onSuccess, Action<string> onError)
{
this.GetService<IMvxPictureChooserTask>().ChoosePictureFromLibrary(
PictureService.MaxPixelDimension,
PictureService.DefaultJpegQuality,
pictureStream =>
{
var newPictureUri = this.Save(pictureStream);
if (!string.IsNullOrWhiteSpace(newPictureUri))
onSuccess(newPictureUri);
else
onError("No photo taken");
},
() => { /* cancel is ignored */ });
}
private string Save(Stream stream)
{
string fileName = null;
try
{
fileName = Guid.NewGuid().ToString("N");
var fileService = this.GetService<IMvxSimpleFileStoreService>();
fileService.WriteFile(fileName, stream.CopyTo);
}
catch (Exception)
{
fileName = null;
}
return fileName;
}
}
但出于隐私原因,我不想将图片保存在文件系统上。工作流程是:
我的问题是:如何在不保存文件系统的情况下处理包含图片数据的Streams?
或者
如何使用用户无法访问的临时存储系统(忽略“root”设备案例)?
感谢您的帮助。
答案 0 :(得分:3)
您可以尝试创建自己的自定义ImageView
控件:
1。使用MemoryStream
将收到的pictureStream
收集到ViewModel上的byte[]
媒体资源中,例如MyBytes
pictureStream => {
var memoryStream = new MemoryStream();
pictureStream.CopyTo(memoryStream);
TheRawImageBytes = memoryStream.GetBuffer()
}
其中TheRawImageBytes
是:
private byte[] _theRawImageBytes;
public byte[] TheRawImageBytes
{
get { return _theRawImageBytes; }
set { _theRawImageBytes = value; RaisePropertyChanged(() => TheRawImageBytes); }
}
2。创建自己的MyImageView
类派生自ImageView
,添加(context, attr)
构造函数,然后在byte[]
属性上展示MyImageView
属性{1}} - 设置byte[]
后,使用BitmapFactory.DecodeByteArray
和SetBitmap
从传入的字节中呈现图片
private byte[] _rawImage;
public byte[] RawImage
{
get { return _rawImage; }
set
{
_rawImage = value;
if (_rawImage == null)
return;
var bitmap = BitmapFactory.DecodeByteArray(_rawImage, 0,_rawImage.Length);
SetImageBitmap(bitmap);
}
}
3。在axml中使用<yourapp.namespace.to.MyImageView ... />
而非普通<ImageView ... />
4. 在axml中将View byte[]
属性绑定到源ViewModel byte[]
属性。
local:MvxBind="{'RawImage':{'Path':'TheRawImageBytes'}}"
5。就是这样 - 虽然您可能想要添加一些错误处理并进行一些测试
这种方法改编自MvvmCross Android Bind Image from byte[]
的答案正如该问题中所提到的,另一种方法是使用带有自定义绑定的标准ImageView
。
有关基于标准视图/小部件创建自定义视图/小部件的更多信息 - 包括如何使用缩写<yourapp.namespace.to.MyImageView ... />
替换<MyApp.MyImageView ... />
,请参阅http://slodge.blogspot.co.uk/2012/10/creating-custom-views-is-easy-to-do.html