2012-06-25 17 views
15

Ho bisogno di un getOnClickListener() per le visualizzazioni in Android. In questo modo posso assegnare un OnClickListener temporaneo alle mie viste. voglio usare in questo modo:getOnClickListener() nelle viste Android

private View.OnClickListener oldListener; 

public void assignTempListener(View view) { 
    oldListener = view.getOnClickListener(); // doesn't exist 

    view.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      // some code 

      v.setOnClickListener(oldListener); 
     } 
    }); 
} 

Il problema è che questa funzione doen't esiste. Inoltre, non posso ereditare da View per creare questo metodo, poiché tutti i tipi di Views possono essere passati a assignTempListener. C'è un altro modo per usarlo?

Modifica: fatto un piccolo errore nel mio codice.

+0

voglio assegnare un OnClickListener temporanea ad un già Vista in uscita. Non ho il controllo su dove è assegnato OnClickListener originale. Quindi non posso conservarlo lì. – user969039

risposta

24

È possibile farlo con ... RIFLESSIONE. * drum roll *

Questo percorso è irto di pericoli.

Non lo consiglio, in quanto la struttura interna della classe può cambiare in qualsiasi momento, ma ecco come è possibile farlo attualmente fino ad Android 4.2.2 se è veramente inevitabile:

/** 
* Returns the current View.OnClickListener for the given View 
* @param view the View whose click listener to retrieve 
* @return the View.OnClickListener attached to the view; null if it could not be retrieved 
*/ 
public View.OnClickListener getOnClickListener(View view) { 
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 
     return getOnClickListenerV14(view); 
    } else { 
     return getOnClickListenerV(view); 
    } 
} 

//Used for APIs lower than ICS (API 14) 
private View.OnClickListener getOnClickListenerV(View view) { 
    View.OnClickListener retrievedListener = null; 
    String viewStr = "android.view.View"; 
    Field field; 

    try { 
     field = Class.forName(viewStr).getDeclaredField("mOnClickListener"); 
     retrievedListener = (View.OnClickListener) field.get(view); 
    } catch (NoSuchFieldException ex) { 
     Log.e("Reflection", "No Such Field."); 
    } catch (IllegalAccessException ex) { 
     Log.e("Reflection", "Illegal Access."); 
    } catch (ClassNotFoundException ex) { 
     Log.e("Reflection", "Class Not Found."); 
    } 

    return retrievedListener; 
} 

//Used for new ListenerInfo class structure used beginning with API 14 (ICS) 
private View.OnClickListener getOnClickListenerV14(View view) { 
    View.OnClickListener retrievedListener = null; 
    String viewStr = "android.view.View"; 
    String lInfoStr = "android.view.View$ListenerInfo"; 

    try { 
     Field listenerField = Class.forName(viewStr).getDeclaredField("mListenerInfo"); 
     Object listenerInfo = null; 

     if (listenerField != null) { 
      listenerField.setAccessible(true); 
      listenerInfo = listenerField.get(view); 
     } 

     Field clickListenerField = Class.forName(lInfoStr).getDeclaredField("mOnClickListener"); 

     if (clickListenerField != null && listenerInfo != null) { 
      retrievedListener = (View.OnClickListener) clickListenerField.get(listenerInfo); 
     } 
    } catch (NoSuchFieldException ex) { 
     Log.e("Reflection", "No Such Field."); 
    } catch (IllegalAccessException ex) { 
     Log.e("Reflection", "Illegal Access."); 
    } catch (ClassNotFoundException ex) { 
     Log.e("Reflection", "Class Not Found."); 
    } 

    return retrievedListener; 
} 
+0

ha funzionato come un fascino. –

1

uso

oldListener = new view.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      // some code 

      v.setOnClickListener(oldListener); 
     } 
    }); 

anziché

oldListener = view.getOnClickListener(); // doesn't exist 

getOnClickListener non è un qualsiasi metodo per View o per Button in vedi Documentazione API attuale per maggiori dettagli

http://developer.android.com/reference/android/view/View.OnClickListener.html

+0

Ho fatto un errore: 'oldListener = view.setOnClickListener(); // non esiste' doveva essere 'oldListener = view.getOnClickListener(); // non esiste' – user969039

+0

vedere la mia modifica answer.thanks –

0

Niet!

Il oldListener nelle risposte fornite viene in ogni caso ridefinito ed è vecchio stato o la definizione viene persa indipendentemente dal suo nome che pretende il contrario.

A seguito di questa tecnica: Get current onClickListener of an Android View object l'ascoltatore 'vecchio' dovrebbe essere impostato nel metodo onClick della classe astratta e qualsiasi ascoltatore temporanea userebbe setOnClickListener insieme con una chiamata a super al fine di (ri) impostare la vecchia ascoltatore quando o come appropriato

Il codice di impostazione del listener temporaneo non ha bisogno di sapere cosa sia il "vecchio" listener, tuttavia ci deve ancora essere una qualche forma di coordinamento affinché l'autore o gli ascoltatori li rendano astratti e utilizzino il metodo onClick per impostare il listener in clic, in breve, per seguire un protocollo.

Eccezionalmente si potrebbe desiderare di bypassare il qualificatore del membro View onclicklistener protetto o privato: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.1_r2/android/view/View.java#View.0mOnClickListener e poi fare un po 'http://www.jguru.com/faq/view.jsp?EID=321191 che vi porterà l'ascoltatore.

Si potrebbe anche voler scrivere il proprio getOnClickListener, o qualsiasi getter per quella materia, che utilizza l'approccio introspezione, se ovviamente in realtà funziona :)

:)

2

è possibile ignorare la classe e dichiarare un'onClicklistener per la visualizzazione e scrivere setter e getter per onClickListener campo:

public class SAutoBgButton extends ImageButton { 

    public View.OnClickListener mOnClickListener; 

    @Override 
    public void setOnClickListener(OnClickListener l) { 
    super.setOnClickListener(l); 
    mOnClickListener = l; 
    } 
    public OnClickListener getmOnClickListener() { 
    return mOnClickListener; 
    } 
} 
Problemi correlati