Autore Topic: Disegnare su una ImageView  (Letto 899 volte)

Offline Ilgard

  • Utente junior
  • **
  • Post: 64
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Xperia M
  • Sistema operativo:
    Ubuntu 14.04
Disegnare su una ImageView
« il: 18 Giugno 2015, 17:47:51 CEST »
0
Salve a tutti, sto cercando di fare semplici disegni su una ImageView ma senza successo, probabilmente per la struttura della mia activity.
Io ho una FragmentActivity con un ViewPager. Il ViewPager mi serve per scorrere fra vari Fragment che contengono una ImageView. In pratica ho uno slideshow di Fragment.
Quello che vogliono fare è disegnare sull'ImageView dei Fragment quando premo un bottone sulla ActionBar.
Per ora, nel migliore dei casi sono riuscito a disegnare qualcosa sotto l'ImageView del Fragment.
Avete qualche consiglio?

EDIT: preciso, facendo diversi test noto che ho problemi a modificare l'ImageView del Fragment dall'Activity. Ho provato a creare una View personalizzata per modificare la OnDraw. La view personalizzata la imposto nella OnCreate dell'Activity tramite
Codice: [Seleziona]
( (RelativeLayout) findViewById(R.id.relative_layout ).addView(customView);( il ViewPager è all'interno del RelativeLayout).
In generale, quando vado a modificare l'immagine della ImageView (ho provato anche solo a cambiarla senza usare canvas od altro) mi ritrovo tutto nero.

Post unito: [time]18 Giugno 2015, 21:06:52 CEST[/time]
Ho fatto altri tentativi e non capisco il problema nell'aggiornare l'ImageView.
Il mio codice, quando voglio disegnare sull'immagine, è questo:
Citazione
Bitmap b = ((BitmapDrawable)imageView.getDrawable()).getBitmap();      
      Bitmap bitmap = b.copy(b.getConfig(), true);
      Canvas canvas = new Canvas(bitmap);
      Paint paint = new Paint();
      paint.setColor(Color.RED);
      canvas.drawRect(50, 50, 100, 100, paint);
      imageView.setImageBitmap(bitmap);
      imageView.invalidate();
Sono riuscito ad accedere all'ImageView da Fragment, solo che anche qui, dopo che eseguo questo codice, mi diventa tutto nero :/

Post unito: [time]18 Giugno 2015, 22:49:53 CEST[/time]
Dopo altri test ho scoperto che il problema non riguarda tanto il disegnare quanto l'ImageView.
Non riesco ad aggiornarla nemmeno prendendo un'altra immagine già pronta (quindi un banale setImageBitmap). Anche funzioni come invalidate o redraw non servono a niente. Il ridisegno dell'ImageView non avviene mai.
Però re-istanziare il fragment non mi sembra saggio dal punto di vista delle prestazioni. Sapete se c'è un modo alternativo?

ps: preciso che l'alterazione dell'ImageView avviene dopo l'esecuzione di un AsyncTask.
« Ultima modifica: 18 Giugno 2015, 22:51:35 CEST da Ilgard »

Offline arlabs

  • Utente normale
  • ***
  • Post: 430
  • Respect: +49
    • Mostra profilo
  • Dispositivo Android:
    GalaxyS6, Nexus5
  • Play Store ID:
    AR Labs
  • Sistema operativo:
    Windows 10
Re:Disegnare su una ImageView
« Risposta #1 il: 19 Giugno 2015, 19:12:54 CEST »
0
C'è qualcosa che non va...

1. Carichi una BitmapDrawable (con bitmap immutable)
2. Alla prima modifica crei una Bitmap mutable, la modifichi, e la setti di nuovo nell'ImageView (attenzione questa volta non è più una BitmapDrawable)
3. Alla successiva modifica chiedi di nuovo la BitmapDrawable alla ImageView, che nel frattempo non ce l'ha più perché usa la Bitmap appena creata...
4. Ad ogni modifica continui comunque a riallocare e copiare Bitmap. (male)

Non ti conviene fare così: non associare alcun Drawable all'ImageView, ma crearti (e tenerti) una Bitmap e modifichi sempre quella?
Se ti serve precarti una risorsa puoi usare BitmapFactory.decodeResource
Oppure tenerti due immagine in overlay e modifichi solo quella sopra.

Ciao.

Post unito: 19 Giugno 2015, 19:14:12 CEST
Dubbio: dove e come prendi la variabile "imageView" ?

Offline Ilgard

  • Utente junior
  • **
  • Post: 64
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Xperia M
  • Sistema operativo:
    Ubuntu 14.04
Re:Disegnare su una ImageView
« Risposta #2 il: 20 Giugno 2015, 12:56:18 CEST »
0
Grazie delle info, però al momento ho scoperto di avere un problema più di fondo.
Al di là del riuscire a disegnare o meno sull'immagine, non riesco ad alterare in nessun modo l'ImageView.
Per dire, ho provato ad avviare un AsyncTask quando viene premuto un bottone sulla ActionBar. L'AsyncTask semplicemente sostituisce la Bitmap dell'ImageView con un'altra già pronta (il semplice ic_launcher presente tra le risorse di default). Se ci provo non succede nulla e se poi chiamo l'invalidate l'ImageView diventa tutta nera (quindi presumo che il ridisegno non avvenga) ed anche la redraw ha lo stesso effetto.
Non c'è un modo per aggiornare la vista senza reistanziare tutto il Fragment?

Alternativamente, c'è un modo per modificare la onDraw del Fragment?

ps: imageView la prendo con un findViewByID tramite la getActivity().

Offline arlabs

  • Utente normale
  • ***
  • Post: 430
  • Respect: +49
    • Mostra profilo
  • Dispositivo Android:
    GalaxyS6, Nexus5
  • Play Store ID:
    AR Labs
  • Sistema operativo:
    Windows 10
Re:Disegnare su una ImageView
« Risposta #3 il: 22 Giugno 2015, 10:21:52 CEST »
0
L'AsyncTask semplicemente sostituisce la Bitmap dell'ImageView con un'altra già pronta (il semplice ic_launcher presente tra le risorse di default).

Se devi caricare un immagine in modo asincrono, puoi usare l'AsynchTask, ma poi il setImage lo devi chiamare nella onPostExecute (cioé nell'UI thread).


Offline Ilgard

  • Utente junior
  • **
  • Post: 64
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Xperia M
  • Sistema operativo:
    Ubuntu 14.04
Re:Disegnare su una ImageView
« Risposta #4 il: 22 Giugno 2015, 18:49:27 CEST »
0
Il mio problema è che non riesco a modificarla. Questo è il codice che ho inserito nella onPostExecute:
Codice: [Seleziona]
View v = getView();
GestureImageView imageView = (GestureImageView) v.findViewById(R.id.immagineMostrata);
imageView.setImageBitmap(((BitmapDrawable)activity.getResources().getDrawable(R.drawable.ic_launcher, null)).getBitmap());
imageView.setVisibility(View.VISIBLE);
//imageView.redraw();
Se non faccio la redraw non ci sono cambiamenti, se la faccio diventa tutto nero.

Offline arlabs

  • Utente normale
  • ***
  • Post: 430
  • Respect: +49
    • Mostra profilo
  • Dispositivo Android:
    GalaxyS6, Nexus5
  • Play Store ID:
    AR Labs
  • Sistema operativo:
    Windows 10
Re:Disegnare su una ImageView
« Risposta #5 il: 22 Giugno 2015, 21:54:12 CEST »
0
A parte il fatto che se hai un Drawable (anche un BitmapDrawable), puoi usare setImageDrawable (non hai bisogno di estrarre la Bitmap), non ci vedo nulla di strano...
... il problema credo stia da qualche altra parte.

P.S. Per ridisegnare una View è meglio usare invalidate(), che richiede una successiva chiamata alla onDraw. Ma in questo caso non dovrebbe essere necessario.
« Ultima modifica: 23 Giugno 2015, 10:27:29 CEST da arlabs »

Offline Ilgard

  • Utente junior
  • **
  • Post: 64
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Xperia M
  • Sistema operativo:
    Ubuntu 14.04
Re:Disegnare su una ImageView
« Risposta #6 il: 23 Giugno 2015, 10:27:02 CEST »
0
Qui c'è tutta la classe del Fragment. L'unica parte che non mi torna è la onOptionsItemSelected.
L'unica spiegazione che mi viene in mente è che il ViewPager altera alcuni aspetti del comportamento del Fragment.

EDIT: piccola rettifica: così tanto per togliersi il dubbio, ho provato a ruotare lo schermo per vedere se avrebbe ridisegnato ed effettivamente ora ridisegna correttamente (di norma tengo la rotazione automatica disattivata, per questo non ci avevo pensato).
Quindi il problema è che, anche invalidando il componente, non ottengo il ridisegno. C'è un modo per forzarlo?
« Ultima modifica: 23 Giugno 2015, 10:37:11 CEST da Ilgard »

Offline arlabs

  • Utente normale
  • ***
  • Post: 430
  • Respect: +49
    • Mostra profilo
  • Dispositivo Android:
    GalaxyS6, Nexus5
  • Play Store ID:
    AR Labs
  • Sistema operativo:
    Windows 10
Re:Disegnare su una ImageView
« Risposta #7 il: 23 Giugno 2015, 10:45:53 CEST »
0
Personalmente nella onCreateView faccio solo inflate.

Tutto il resto lo faccio nella onActivityCreated, quando l'Activity è pronta.

Inoltre c'è un issue con ViewPager e Fragment, l'ho riportato qui:
http://www.anddev.it/index.php/topic,6717.msg82437.html#msg82437

Ciao.

Offline Ilgard

  • Utente junior
  • **
  • Post: 64
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Xperia M
  • Sistema operativo:
    Ubuntu 14.04
Re:Disegnare su una ImageView
« Risposta #8 il: 23 Giugno 2015, 11:34:17 CEST »
0
Ho provato ad alterare il codice con il tuo ma non gli va bene il  Fragment.instantiate(Activity.this, fragmentClasses.get(position) ) nella getItem, perché non può accedere ad Activity.this.


Comunque non sono sicuro di aver capito il funzionamento: il vettore fragmentClasses è statico? Perché io necessito di allocare un buon numero di fragment, tutti di per sé uguali ma con contenuti diversi (perché è una galleria di immagini) e per questo motivo sfruttavo il FragmentStatePagerAdapter.
Se invece dovessi allocare n fragment alla creazione del pager sprecherei parecchie risorse.
« Ultima modifica: 23 Giugno 2015, 11:38:11 CEST da Ilgard »

Offline arlabs

  • Utente normale
  • ***
  • Post: 430
  • Respect: +49
    • Mostra profilo
  • Dispositivo Android:
    GalaxyS6, Nexus5
  • Play Store ID:
    AR Labs
  • Sistema operativo:
    Windows 10
Re:Disegnare su una ImageView
« Risposta #9 il: 23 Giugno 2015, 16:38:06 CEST »
0
Ho provato ad alterare il codice con il tuo ma non gli va bene il  Fragment.instantiate(Activity.this, fragmentClasses.get(position) ) nella getItem, perché non può accedere ad Activity.this.


Non ti ho detto che devi fare come ho scritto io.
Semplicemente in quel thread ho sollevato un dubbio lecito sull'utilizzo del PagerAdapter (già evidenziato da Slaytanic e undead), il quale non sempre chiama getItem. Bisogna quindi stare attenti a ciò.
In particolare quel thread era un tutorial sul ViewPager che in realtà non funziona correttamente, ed essendo preso ad esempio da diverse persone, ritenevo importante che venisse corretto. Quel codice è solo una proposta di modifica del codice tutorial per ovviare al problema, che però non è stato recepito...

Ti ho dato un riferimento a quel post perché tu potessi verificare di non ricadere in quel problema (abbastanza subdolo).

Tra l'altro il tutorial si focalizzava sul ViewPager usato con poche pagine specifiche, invece che su molte pagine uguali.
Nel tuo caso, per implementare una galleria, non dovresti seguire quel tutorial perché, appunto, hai bisogno di molte pagine tutte uguali (a parte i dati, ovviamente).
Come dici tu in quel caso è più indicato il FragmentStatePagerAdapter.

Io però non ho mai usato il FragmentStatePagerAdapter, non so quindi se ci sono side-effect... non credo di poterti essere utile.

Ciao.

P.S. A prescincedere da tutto... non gli andrà bene Activity.this perché il PagerAdapter non è una inner class di Activity o lo è, ma statica.

Offline Ilgard

  • Utente junior
  • **
  • Post: 64
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Xperia M
  • Sistema operativo:
    Ubuntu 14.04
Re:Disegnare su una ImageView
« Risposta #10 il: 23 Giugno 2015, 16:54:34 CEST »
0
Ok, grazie.
Se invece volessi forzare il comportamento simile a quello ottenuto dalla rotazione senza però avere una rotazione vera e propria come potrei fare? Ovvero, al cambiamento della configurazione si ha effettivamente il ridisegno, quindi questo è possibile, solo che devo capire come averlo senza un cambio di configurazione.

Offline arlabs

  • Utente normale
  • ***
  • Post: 430
  • Respect: +49
    • Mostra profilo
  • Dispositivo Android:
    GalaxyS6, Nexus5
  • Play Store ID:
    AR Labs
  • Sistema operativo:
    Windows 10
Re:Disegnare su una ImageView
« Risposta #11 il: 23 Giugno 2015, 17:37:03 CEST »
0
Fossi in te, seguirei un altra strada... il ridisegno c'è anche all'inizio... semplicemente ci sarà qualcosa di tuo che non è pronto...
Comincia a provare a spostare il codice nel fragment dalla onCreateView alla onActivityCreated.

Offline Ilgard

  • Utente junior
  • **
  • Post: 64
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Xperia M
  • Sistema operativo:
    Ubuntu 14.04
Re:Disegnare su una ImageView
« Risposta #12 il: 23 Giugno 2015, 17:52:13 CEST »
0
Quello l'ho fatto non appena l'hai suggerito.
Visto che comunque il mio obiettivo è disegnare sull'ImageView l'unica alternativa che mi è venuta in mente è di alterare la onDraw del Fragment.

Offline arlabs

  • Utente normale
  • ***
  • Post: 430
  • Respect: +49
    • Mostra profilo
  • Dispositivo Android:
    GalaxyS6, Nexus5
  • Play Store ID:
    AR Labs
  • Sistema operativo:
    Windows 10
Re:Disegnare su una ImageView
« Risposta #13 il: 23 Giugno 2015, 18:33:53 CEST »
0
Mi spiace non esserti stato utile. Sarebbe stato carino capire a cosa era dovuto il problema.

Ciao.

Offline Ilgard

  • Utente junior
  • **
  • Post: 64
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Xperia M
  • Sistema operativo:
    Ubuntu 14.04
Re:Disegnare su una ImageView
« Risposta #14 il: 23 Giugno 2015, 21:21:45 CEST »
0
Non preoccuparti, continuerò comunque a fare qualche tentativo, magari ne esco in qualche modo.
Grazie lo stesso dell'aiuto :-)

Post unito: 24 Giugno 2015, 18:54:06 CEST
Modificando la onDraw sto ottenendo un risultato migliore dal punto di vista delle prestazioni perché alla fine risparmio diverse new, inoltre non ho il problema dell'aggiornamento della vista.
Ho il problema delle coordinate e quindi volevo chiedere: c'è un modo rapido per ricalcolare le coordinate dell'ImageView nel canvas?
Mi spiego meglio: io devo disegnare un cerchio intorno alle facce in un'immagine ed uso la classe FaceDetector di Android. La classe mi trova le coordinate delle facce all'interno dell'immagine e poiché prima usavo come canvas l'immagine stessa non avevo problemi.
Ora il canvas è tutto il fragment quindi le coordinate vanno un po' a farsi benedire: sapresti se nella onDraw posso ottenere rapidamente gli offset tra i due canvas che mi servono per le coordinate corrette?

Altrimenti mi era venuto in mente un secondo modo di agire: posso alterare la onDraw della sola area dell'immagine?
Io al momento per modificare la onDraw ho fatto così nella onCreateView del fragment:
Codice: [Seleziona]
View v = inflater.inflate(R.layout.fragment_show_image, container, false);
        FrameLayout layout = (FrameLayout) v.findViewById(R.id.fragment);       
        myView = new MyView(getActivity());
        layout.addView(myView);       
        return v;
Quindi altero la onDraw del FrameLayout che comprende tutto. Potrei fare la stessa cosa ma della sola ImageView (così da avere i due canvas coincidenti)?
« Ultima modifica: 24 Giugno 2015, 18:54:06 CEST da Ilgard, Reason: Merged DoublePost »