22

I'm using a photo picker intent to choose an image and write it to an application-private file. Most of my important source code is shown below. Once I press a button and perform the first image selection intent, then it successfully updates the image view. However, once I press the image selection button again (in the same activity), then the image view does NOT update, unless I exit and restart the activity. So I know the image is getting successfully saved, but why would the ImageView in the layout not refresh or update?

public void onResume() {
    super.onResume();
    ImageView myImageView = (ImageView)findViewById(R.id.contact_image);
    if (hasImage) {
      myImageView.setImageURI(Uri.fromFile(getFileStreamPath(TEMP_PHOTO_FILE)));
    }
  }

  @Override
  public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
    case PHOTO_PICKED:
      if (resultCode == RESULT_OK) {
        if (data != null) {
          Bundle extras = data.getExtras();
          if (extras != null) {
            hasImage = true;
            bmp = (Bitmap) extras.get("data");
          }
        }
      }
      break;
    }
  }

  private OnClickListener mChooseImage = new OnClickListener() {
    @Override
    public void onClick(View v) {
      try {
        // Launch picker to choose photo for selected contact
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
        intent.setType("image/*");
        intent.putExtra("crop", "true");
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);
        intent.putExtra("outputX", ICON_SIZE);  
        intent.putExtra("outputY", ICON_SIZE);
        intent.putExtra("scale", true);
        intent.putExtra("return-data", false);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(getTempFile()));
        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
        startActivityForResult(intent, PHOTO_PICKED);
      } catch (ActivityNotFoundException e) {
        // LOG THIS
      }
    }
  };

private File getTempFile() {
    try {
      if (!hasImage) {
        FileOutputStream fos = openFileOutput(TEMP_PHOTO_FILE, MODE_WORLD_WRITEABLE);
        fos.close();
      }
      return getFileStreamPath(TEMP_PHOTO_FILE);
    } catch (FileNotFoundException e) {
      // To be logged later
      return null;
    } catch (IOException e) {
      // To be logged later
      return null;
    }
  }

upon activity result, I set the ImageView's image URI to this file.

When it first completes, the ImageView changes to reflect this. However, if I attempt to choose the image again (same activity), the ImageView will not update until I exit and re-enter the activity. I'm not sure why this happens, is it because I'm trying to write to the temp.jpg everytime? Or do I need to refresh my layout somehow to reflect changes in the ImageView?

damonkashu
  • 1,813
  • 5
  • 19
  • 25
  • Is there some code missing? From what you wrote it shouldn't be required to open output streams to the selected image. – Sebastian Roth Dec 16 '10 at 08:26
  • I have added a majority of my source code. I also find that if I just return the value from the intent as a bitmap, then the image view successfully updates. However, I still want to know the source of the problem. – damonkashu Dec 16 '10 at 10:21
  • so is there something I don't know about ImageViews or the image picker intent? something which does not reflect the change until restarting the activity? – damonkashu Dec 17 '10 at 08:43

9 Answers9

20

Judging by the ImageView source code, the ImageView won't reload the image if you call setImageURI with the same URI. You could try changing the URI by writing your image to another file.

claesv
  • 2,075
  • 13
  • 28
  • 5
    Thank you! I spent too many hours trying to figure this out. After looking at the source myself and trying view.requestLayout() and view.invalidate() which didn't work, I've concluded that setting the uri to null before setting it again is the best if not the only way to use setImageUri for a single changing image file. – Pilot_51 Nov 23 '12 at 22:13
  • 3
    Thank you both for this. It just saved me some hours of confusion with regards to ImageView refresh. In my case, I wanted an image refresh on locale update but, apparently, it seems that, since the resId does not change, the ImageView just disregards your request, not checking if the resource itself has changed. Just did a setImageDrawable(null) followed by the regular setImageResource(R.drawable.image) and it works. Must have been an implementation choice for performance purposes. – Toryu Mar 17 '13 at 14:03
  • Thank you @Pilot_51 and Toryu ... Setting the imageDrawable to null and then setting the ImageURi after that worked for me too. – Akshat Jun 25 '14 at 17:00
19

ImageView will not redraw if "new" URI is the same like old one. "View.invalidate()" will not work. To "force" update you can do:

public void onResume() {
  super.onResume();
  ImageView myImageView = (ImageView)findViewById(R.id.contact_image);
  if (hasImage) {
    myImageView.setImageDrawable(null); // <--- added to force redraw of ImageView
    myImageView.setImageURI(Uri.fromFile(getFileStreamPath(TEMP_PHOTO_FILE)));
  }
}
mdolanci
  • 385
  • 2
  • 5
8

invalidate() not worked. Try hack :

    imageView.setImageURI(null);
    imageView.setImageURI(newUri);
tim4dev
  • 2,846
  • 2
  • 24
  • 30
1

I had a similar problem where I was using the devices camera to take a picture and then wanting the imageView in the original screen to refresh when I returned to it. The solution was to call View.invalidate() in onResume().

1

To force redrawing your widget/View just call View.invalidate();

Barmaley
  • 16,638
  • 18
  • 73
  • 146
0

For me, it refreshed my ImageView with this

 @Override
    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == PICK_PHOTO && resultCode == RESULT_OK && data != null && data.getData() != null) {

            filePath = data.getData();

            try {
                mProfilePic.setImageURI(null);
                mProfilePic.setImageURI(filePath);
                Bitmap imageBitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), filePath);

                mProfilePic.setImageBitmap(imageBitmap);

            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
Gastón Saillén
  • 12,319
  • 5
  • 67
  • 77
0

I would suggest this thing solution. After trying lot of solutions i found this one worked for me.

final Handler handler = new Handler();
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            //Do something after 1000ms
                            ivProfilePic.setImageBitmap(bitImage);

                        }
                    }, 1000);
Mandeep Singh
  • 857
  • 8
  • 13
0
        UIView.transition(with: bannerImageView, duration: 0.3, options: [.transitionCrossDissolve], animations: { [weak self] in
            self?.exampleImageView.image = newImage
        })

Use this func in your view controller

0

If you are also setting the image using Glide then check if the url is setting up the image or not. If the Glide fails and sets the error Image then setImageURI won't change the image.

This happened in one of my projects. I though this might help someone.