拍摄/选择图片并在不先保存的情况下在ImageView中显示(使用MvvmCross) [英] Take/Select picture and show it in ImageView without saving first (using MvvmCross)

查看:208
本文介绍了拍摄/选择图片并在不先保存的情况下在ImageView中显示(使用MvvmCross)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从照片库中选择图片或使用相机拍照,然后将结果显示到视图(ImageView)

I want to choose a picture from library or take a picture with the camera and show the result to the view (ImageView)

但是根据一些帖子,包括这个,我使用的MvxHttpImageView需要一个Uri来显示图像(但它来自文件系统还是相机).这意味着将Stream转换为文件并重新获得Uri.

But according to a few posts including this one, the MvxHttpImageView I use needs a Uri to show the image (wheter it comes from file systemor camera). This implies, converting the Stream into a file and getting the Uri back.

我写了一个图片服务来完成这项工作:

I wrote a Picture Service that does the job:

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;
    }

}

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

But for privacy reason, I do not want to save the picture on filesystem. The workflow is:

  1. 拍摄或选择图片
  2. 在屏幕上显示(带有其他信息)
  3. 将模型保存在将图像发送到云的服务器上:不跟踪 设备
  1. Take or select picture
  2. Show it on screen (with additional info)
  3. Save my model on server sending image to the cloud: not trace on the device

我的问题是:如何在不保存文件系统的情况下处理包含图片数据的流?

My question is: how can I handle the Streams containing picture data without saving on filesystem?

如何使用用户无法访问的临时存储系统(忽略有根"设备的情况)?

How to use a temporary storage system that is not accessible to user (ignore "rooted" device case)?

感谢您的帮助.

推荐答案

您可以尝试创建自己的自定义ImageView控件:

You could try creating your own custom ImageView control:

1..使用MemoryStream将接收到的pictureStream收集到ViewModel的byte[]属性中,例如MyBytes

1. Use a MemoryStream to collect the received pictureStream into a byte[] property on the ViewModel, e.g. 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..创建自己的从ImageView派生的MyImageView类,添加(context, attr)构造函数,然后在MyImageView上公开byte[]属性-当该byte[]设置,然后使用BitmapFactory.DecodeByteArraySetBitmap从传入的字节中渲染图片

2. Create your own MyImageView class derived from ImageView, add the (context, attr) constructor, then expose a byte[] property on the MyImageView - when that byte[] is set then use BitmapFactory.DecodeByteArray and SetBitmap to render the picture from the incoming bytes

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 ... />

3. Use <yourapp.namespace.to.MyImageView ... /> in the axml instead of the normal <ImageView ... />

4..在axml中,将View byte[]属性绑定到源ViewModel byte[]属性.

4. In the axml bind the View byte[] property to the source ViewModel byte[] property.

local:MvxBind="{'RawImage':{'Path':'TheRawImageBytes'}}"

5.就这样-尽管您可能想添加一些错误处理并进行一些测试

5. That's it - although you might want to add some error handling and do some testing

此方法根据答案改编为 Mvvm跨字节绑定Android绑定图像[]

This approach is adapted from the answer to MvvmCross Android Bind Image from byte[]

如该问题所述,另一种方法是使用带有自定义绑定的标准ImageView.

As mentioned in that question, an alternative approach would be to use a standard ImageView with a custom binding instead.

有关基于标准视图/小部件创建自定义视图/小部件的更多信息-包括有关如何用缩写<MyApp.MyImageView ... />替换<yourapp.namespace.to.MyImageView ... />的信息,请参见

For more on creating custom views/widgets based on standard views/widgets - including on how to replace <yourapp.namespace.to.MyImageView ... /> with an abbreviation <MyApp.MyImageView ... />, see http://slodge.blogspot.co.uk/2012/10/creating-custom-views-is-easy-to-do.html

这篇关于拍摄/选择图片并在不先保存的情况下在ImageView中显示(使用MvvmCross)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆