Android在ImageView上从URI设置图像

前端之家收集整理的这篇文章主要介绍了Android在ImageView上从URI设置图像前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

更新了更多代码

我试图抓取刚拍摄的照片并以编程方式将其设置为ImageView.

按下图片按钮,

  1. picture_button.setOnClickListener(new View.OnClickListener() {
  2. public void onClick(View v) {
  3. takePhoto(mTextureView);
  4. }
  5. });

它运行takePhoto方法

  1. public void takePhoto(View view) {
  2. try {
  3. mImageFile = createImageFile();
  4. final ImageView latest_picture = (ImageView) findViewById(R.id.latest_picture);
  5. final RelativeLayout latest_picture_container = (RelativeLayout) findViewById(R.id.latest_picture_container);
  6. final String mImageFileLocationNew = mImageFileLocation.replaceFirst("^/","");
  7. Toast.makeText(getApplicationContext(),"" + mImageFile,Toast.LENGTH_SHORT).show();
  8. Uri uri = Uri.fromFile(mImageFile);
  9. Toast.makeText(getApplicationContext(),""+uri,Toast.LENGTH_LONG).show();
  10. latest_picture.setImageURI(uri);
  11. latest_picture_container.setVisibility(View.VISIBLE);
  12. } catch (IOException e){
  13. e.printStackTrace();
  14. }
  15. lockFocus();
  16. captureStillImage();
  17. }

运行createImageFile()和captureStillImage()

  1. private void captureStillImage() {
  2. try {
  3. CaptureRequest.Builder captureStillBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
  4. captureStillBuilder.addTarget(mImageReader.getSurface());
  5. int rotation = getWindowManager().getDefaultDisplay().getRotation();
  6. captureStillBuilder.set(CaptureRequest.JPEG_ORIENTATION,ORIENTATIONS.get(rotation));
  7. CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback() {
  8. @Override
  9. public void onCaptureCompleted(CameraCaptureSession session,CaptureRequest request,TotalCaptureResult result) {
  10. super.onCaptureCompleted(session,request,result);
  11. //Toast.makeText(getApplicationContext(),"Image Taken",Toast.LENGTH_SHORT).show();
  12. unLockFocus();
  13. }
  14. };
  15. mCameraCaptureSession.capture(captureStillBuilder.build(),captureCallback,null);
  16. } catch (CameraAccessException e) {
  17. e.printStackTrace();
  18. }
  19. }
  20. File createImageFile() throws IOException {
  21. String timestamp = new SimpleDateFormat("yyyyMMdd").format(new Date());
  22. String subFolder = "";
  23. if(pref_session_unique_gallery.equals("yes")){
  24. if(event_name != null){
  25. subFolder = event_name;
  26. } else {
  27. subFolder = timestamp;
  28. }
  29. } else {
  30. subFolder = "_GEN";
  31. }
  32. if(event_name == null){
  33. event_name = "";
  34. } else {
  35. event_name = event_name + "_";
  36. }
  37. String imageFileName = "CPB_"+event_name+timestamp+"_";
  38. File storageDirectory = new File(Environment.getExternalStorageDirectory() + File.separator + "CPB" + File.separator + subFolder);
  39. storageDirectory.mkdir();
  40. File image = File.createTempFile(imageFileName,".jpg",storageDirectory);
  41. mImageFileLocation = image.getAbsolutePath();
  42. return image;
  43. }

和图像保存在这里:

  1. private static class ImageSaver implements Runnable {
  2. private final Image mImage;
  3. private ImageSaver(Image image) {
  4. mImage = image;
  5. }
  6. @Override
  7. public void run() {
  8. ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer();
  9. byte[] bytes = new byte[byteBuffer.remaining()];
  10. byteBuffer.get(bytes);
  11. FileOutputStream fileOutputStream = null;
  12. try {
  13. fileOutputStream = new FileOutputStream(mImageFile);
  14. fileOutputStream.write(bytes);
  15. } catch (IOException e) {
  16. e.printStackTrace();
  17. } finally {
  18. mImage.close();
  19. if(fileOutputStream != null){
  20. try {
  21. fileOutputStream.close();
  22. } catch (IOException e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. }

我在createImageFile()之后获取了正确的图像路径并将其烘烤以显示每次都是什么.但即使是latest_picture_container上的setVisibility也没有工作……如果我注释掉InputStream,Bitmap和setImageBitmap,那么latest_picture_container就会正常显示.不知道为什么这是错的.

出于某种原因,URI在文件后面会有三个斜杠,

  1. file:///storage/0/...
最佳答案
AssetManager#open()方法仅适用于您应用的资产;即项目的/ assets文件夹中的文件.由于您尝试打​​开外部文件,因此应该在从路径创建的File对象上使用FileInputStream.此外,takePhoto()方法在将任何内容写入文件之前在ImageView上设置图像,这将导致空的ImageView.

由于您的应用程序直接使用相机,我们可以从正在写入图像文件的相同字节数组中解码图像,并为自己节省不必要的存储读取.此外,在您的代码示例中,文件写入发生在单独的线程上,因此我们不妨利用它来执行图像解码,因为它将最小化对UI线程的影响.

首先,我们将创建一个接口,ImageSaver可以通过该接口将图像传递回活动以在ImageView中显示.

  1. public interface OnImageDecodedListener {
  2. public void onImageDecoded(Bitmap b);
  3. }

然后我们需要稍微改变ImageSaver类以在构造函数获取Activity参数.我还添加了一个File参数,因此Activity的相应字段不必是静态的.

  1. private static class ImageSaver implements Runnable {
  2. private final Activity mActivity;
  3. private final Image mImage;
  4. private final File mImageFile;
  5. public ImageSaver(Activity activity,Image image,File imageFile) {
  6. mActivity = activity;
  7. mImage = image;
  8. mImageFile = imageFile;
  9. }
  10. @Override
  11. public void run() {
  12. ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer();
  13. byte[] bytes = new byte[byteBuffer.remaining()];
  14. byteBuffer.get(bytes);
  15. final Bitmap b = BitmapFactory.decodeByteArray(bytes,bytes.length);
  16. mActivity.runOnUiThread(new Runnable() {
  17. @Override
  18. public void run() {
  19. ((OnImageDecodedListener) mActivity).onImageDecoded(b);
  20. }
  21. }
  22. );
  23. FileOutputStream fileOutputStream = null;
  24. ...
  25. }
  26. }

一旦我们在字节数组中获取图像数据,我们就将其解码并将其传递回Activity,因此它不必等待文件写入,这可以在后台安静地进行.我们需要在UI线程上调用接口方法,因为我们在那里“触摸”了视图.

Activity需要实现接口,我们可以将与视图相关的东西从takePhoto()移动到onImageDecoded()方法.

  1. public class MainActivity extends Activity
  2. implements ImageSaver.OnImageDecodedListener {
  3. ...
  4. @Override
  5. public void onImageDecoded(Bitmap b) {
  6. final ImageView latest_picture =
  7. (ImageView) findViewById(R.id.latest_picture);
  8. final RelativeLayout latest_picture_container =
  9. (RelativeLayout) findViewById(R.id.latest_picture_container);
  10. latest_picture.setImageBitmap(b);
  11. latest_picture_container.setVisibility(View.VISIBLE);
  12. }
  13. public void takePhoto(View view) {
  14. try {
  15. mImageFile = createImageFile();
  16. captureStillImage();
  17. lockFocus();
  18. }
  19. catch (IOException e) {
  20. e.printStackTrace();
  21. }
  22. }
  23. ...
  24. }

最后,我们需要在ImageReader的onImageAvailable()方法中实际执行ImageSaver.再次按照这个例子,它会是这样的.

  1. private final ImageReader.OnImageAvailableListener mOnImageAvailableListener =
  2. new ImageReader.OnImageAvailableListener() {
  3. @Override
  4. public void onImageAvailable(ImageReader reader) {
  5. mBackgroundHandler.post(new ImageSaver(MainActivity.this,reader.acquireNextImage(),mImageFile)
  6. );
  7. }
  8. };

猜你在找的Android相关文章