拍摄/选择照片并在ImageView中显示而不先保存(使用MvvmCross)

时间:2013-01-16 22:20:50

标签: c# xamarin.ios xamarin.android mvvmcross

我想从库中选择一张图片或用相机拍照并将结果显示在视图中(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;
    }

}

但出于隐私原因,我不想将图片保存在文件系统上。工作流程是:

  1. 拍摄或选择照片
  2. 在屏幕上显示(附加信息)
  3. 将我的模型保存在服务器上,将图像发送到云端:不跟踪 设备
  4. 我的问题是:如何在不保存文件系统的情况下处理包含图片数据的Streams?

    或者

    如何使用用户无法访问的临时存储系统(忽略“root”设备案例)?

    感谢您的帮助。

1 个答案:

答案 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.DecodeByteArraySetBitmap从传入的字节中呈现图片

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