2010-12-16 11 views
17

Używam selektora zdjęć do wyboru obrazu i zapisania go w pliku prywatnym aplikacji. Większość mojego ważnego kodu źródłowego pokazano poniżej. Po naciśnięciu przycisku i wykonaniu pierwszego zamiaru wyboru obrazu, pomyślnie zaktualizuje on widok obrazu. Jednak po ponownym naciśnięciu przycisku wyboru obrazu (w tej samej czynności) obraz NIE aktualizuje się, chyba że wyjdę i ponownie uruchomię działanie. Tak więc wiem, że obraz został pomyślnie zapisany, ale dlaczego obraz w układzie nie był odświeżany lub aktualizowany?ImageView nie odświeża/nie odzwierciedla zmian

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

po uzyskaniu wyniku aktywności, ustawiam identyfikator URI obrazu ImageView dla tego pliku.

Po pierwszym zakończeniu ImageView zmienia się, aby to odzwierciedlić. Jeśli jednak spróbuję wybrać obraz ponownie (ta sama aktywność), ImageView nie zaktualizuje się, dopóki nie wyjdę i nie powrócę ponownie do działania. Nie jestem pewien, dlaczego tak się dzieje, czy to dlatego, że próbuję pisać do temp.jpg za każdym razem? Czy muszę odświeżyć mój układ, aby odzwierciedlić zmiany w ImageView?

+0

Czy brakuje kodu? Z tego, co napisałeś, nie powinno być wymagane otwieranie strumieni wyjściowych do wybranego obrazu. –

+0

Dodałem większość mojego kodu źródłowego. Uważam również, że jeśli po prostu zwrócę wartość z intencji jako bitmapy, to widok obrazu jest aktualizowany. Nadal jednak chcę poznać źródło problemu. – damonkashu

+0

, więc jest coś, czego nie wiem o ImageViews lub intencji selektora obrazu? coś, co nie odzwierciedla zmiany, dopóki nie zostanie ponownie uruchomione działanie? – damonkashu

Odpowiedz

1

Aby wymusić odświeżanie widget/Widok zadzwoń View.invalidate();

+3

Wołam to na ImageView i nie wydaje się, aby to cokolwiek robić – damonkashu

+1

Mam ten sam problem tutaj. Invalidate nie odświeża mojego niestandardowego widoku obrazu. –

18

Sądząc po kodzie źródłowym ImageView The ImageView nie będzie odświeżyć wizerunek jeśli zadzwonisz setImageURI z tego samego URI. Możesz spróbować zmienić URI, pisząc obraz do innego pliku.

+4

Dziękujemy! Spędziłem zbyt wiele godzin próbując to zrozumieć. Po sprawdzeniu źródła i próbie view.requestLayout() i view.invalidate(), które nie działały, doszedłem do wniosku, że ustawienie uri na null przed ponownym ustawieniem jest najlepszym, jeśli nie jedynym sposobem użycia setImageUri do pojedynczego zmieniania pliku obrazu. –

+3

Dziękuję wam za to. Po prostu uratowało mnie to kilka godzin nieporozumień związanych z odświeżaniem obrazu. W moim przypadku chciałem odświeżyć obraz przy aktualizacji ustawień regionalnych, ale najwyraźniej wydaje się, że ponieważ nie zmienia się resId, ImageView po prostu lekceważy twoje żądanie, nie sprawdzając, czy sam zasób się zmienił. Po prostu zrobiłem setImageDrawable (null), a następnie normalny setImageResource (R.drawable.image) i to działa. Musiał być wyborem wdrożenia do celów związanych z wydajnością. – Toryu

+0

Dziękuję @ Pilot_51 i Toryu ... Ustawienie imageUrawable na wartość null, a następnie ustawienie ImageURi po tym, że zadziałało również dla mnie. – Akshat

1

Miałem podobny problem, gdy używałem kamery urządzenia do zrobienia zdjęcia, a następnie chciałbym, aby obraz na oryginalnym ekranie odświeżył się po powrocie do niego. Rozwiązaniem było wywołanie metody View.invalidate() w onResume().

11

ImageView nie przerysuje, jeśli "nowy" URI jest taki sam jak stary. "View.invalidate()" nie będzie działać. Aby "wymusić" aktualizację, możesz:

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

invalidate() nie zadziałał. Spróbuj hackowania:

imageView.setImageURI(null); 
    imageView.setImageURI(newUri); 
Powiązane problemy