2012-06-25 7 views
15

Potrzebuję getOnClickListener() dla widoków w systemie Android. W ten sposób mogę przypisać tymczasowy OnClickListener do moich widoków. Chcę używać go tak:getOnClickListener() w widoku Androida

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

Problemem jest to, że funkcja ta doen't istnieje. Nie mogę również dziedziczyć z widoku, aby utworzyć tę metodę, ponieważ wszystkie rodzaje widoków mogą być przekazywane do przypisaniaTempListener. Czy istnieje inny sposób korzystania z tego?

Edit: popełniłem mały błąd w kodzie.

+0

chcę przypisać tymczasowy OnClickListener do już wyjście z widoku. Nie mam kontroli, gdzie jest przypisany oryginalny OnClickListener. Więc nie mogę go tam przechowywać. – user969039

Odpowiedz

24

Można to zrobić z ... REFLECTION. * * Rolki bębna

Ta droga jest obarczona ryzyko.

Nie polecam go jako wewnętrzna struktura klasy może się zmienić w każdej chwili, ale oto jak można to zrobić obecnie do Androida 4.2.2, czy to naprawdę nieuniknione:

/** 
* 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

Pracował jak urok. –

1

użycie

oldListener = new view.OnClickListener() { 

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

      v.setOnClickListener(oldListener); 
     } 
    }); 

zamiast

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

getOnClickListener nie jest jakaś metoda View lub Button w patrz Dokumentacja Aktualna API więcej szczegółów

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

+0

Popełniłem błąd: 'oldListener = view.setOnClickListener(); // nie istnieje " musiał być ' oldListener = view.getOnClickListener(); // nie istnieje " – user969039

+0

zobacz moją odpowiedź edit.thanks –

0

Nie!

oldListener w odpowiedziach udzielonych w każdym przypadku jest nowo i to jest stary stan lub definicja jest stracone bez względu na jego nazwę udając inaczej.

obserwuję tę technikę: Get current onClickListener of an Android View object „starych” słuchacz będzie ustawiony w klasie abstrakcyjnej za onClick metody oraz wszelkie tymczasowe słuchacz użyłby setOnClickListener wraz z wezwaniem Super w celu (re) ustawić starą słuchacza gdy jest lub w razie potrzeby

Kod ustawienia tymczasowego odbiornika nie musi wiedzieć, co znaczy "stary" słuchacz, ale musi on być w jakiejś formie koordynacji, aby autor tego lub tych słuchaczy uczynił je abstrakcyjnymi i użył Metoda onClick służy do ustawiania odbiornika typu "kliknij, aby kliknąć", w skrócie, zgodnie z protokołem.

Wyjątkowo może chcesz ominąć zabezpieczoną lub prywatną kwalifikator z onclicklistener Zobacz publiczny: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.1_r2/android/view/View.java#View.0mOnClickListener a następnie zrobić trochę http://www.jguru.com/faq/view.jsp?EID=321191 który będzie Ci słuchacza.

Można nawet chcą napisać własną getOnClickListener ani żadnego getter dla tej sprawy, który wykorzystuje podejście instrospection, jeżeli oczywiście to faktycznie działa :)

:)

2

można zastąpić klasę i zadeklarować onClicklistener dla widoku i pisać setter i getter dla onClickListener polu:

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; 
    } 
} 
Powiązane problemy