2011-01-06 4 views
4

Ich habe eine benutzerdefinierte TextView, die anklickbar ist. Es definiert seinen eigenen onClick-Handler, um seine Darstellung basierend auf Klicks zu ändern. Wenn ich dann jedoch einen zweiten onClick-Handler in meiner Aktivität definiere, um etwas basierend auf der angeklickten Schaltfläche zu tun, wird nur eine der onClick-Funktionen aufgerufen. onClick ist eine void-Funktion - gibt es eine Möglichkeit zu sagen, dass ich diesen Klick nicht verarbeitet habe, bitte weiterleiten an andere onClick-Handler?Android - Zwei onClick-Listener und eine Schaltfläche

Um hier mehr klar ist der Code:

Innen MyCheckButton die Textview erweitert ich habe:

setOnClickListener(mClickListener); 

    private OnClickListener mClickListener = new OnClickListener() { 
     public void onClick(View v) { 
      toggle(); 
     } 
    }; 

aber ich MyCheckButton in meiner Tätigkeit gehören, und natürlich muss ich etwas tun, wenn seine so lege ich ein anderes OnClickListener es angeklickt:

MyCheckButton button= (MyCheckButtonButton) findViewById(R.id.cb); 
button.setOnClickListener(new OnClickListener(){ 
    @Override 
    public void onClick(View v) { 
     // do something in the app 
    } 

}); 

Durch den Aufruf setOnClickListener zweimal scheint es, dass ich die Original-Hörer bin ersetzt so tog gle(), das die Erscheinung ändert, wird nie aufgerufen. Wie kann ich etwas in meiner Aktivität tun, wenn diese Schaltfläche angeklickt wird, wenn sie bereits den onClick-Handler verwendet, um ihre Darstellung zu ändern? Ich dachte, ich würde einfach sehen, dass beide OnClickListeners angerufen werden.

+0

yeah Ich denke, Sie haben Recht damit, Sie könnten auch versuchen, ein onClick-Attribut in Ihrer XML-Datei zu geben und zu sehen, ob es Ihre Methode nach dem Setzen eines onClickListeners noch aufrufen würde. – schwiz

+0

Ich vermute, das ist kein Event-Bubbling-Problem und mein Problem ist, dass Sie nicht zwei OnClickListeners zur gleichen Ansicht hinzufügen können ??? Das ist anderswo Standard, also bin ich verwirrt. – Mark

+0

Wenn ich das xml onClick verwende, setzt setOnClickListener es außer Kraft. – Mark

Antwort

4

Dies ist ein bisschen schmutzig, aber die Art, wie ich dies tun würde, wenn Sie brauchen mehrere Listener, um einen zu registrieren, der über den anderen weiß. Der erste (der tatsächlich registrierte) muss dann wissen, wann er basierend auf den Bedingungen des Ereignisses an den anderen Listener delegiert werden muss. Tatsächlich gibt es in Wirklichkeit keine Notwendigkeit, zwei Klassen zu haben. Die zweite Klasse kann die von Ihnen gewünschte Schnittstelle implementieren. Darüber hinaus müssen Sie keine spezielle Schnittstelle für Ihre Anforderungen erstellen.

public class MyClickListener implements OnClickListener{ 
    private SomeCustomClass mSecondListener = new SomeCustomClass(); 
    public void onClick(View v){ 
    if (needToForward){ 
     mSecondListener.handleClick(v); 
    }else{ 
     //handle the click 
    } 
    } 
} 

Dann für Ihre Tätigkeit in Ihrem Code, würden Sie dies tun

MyClickListener lstn = new MyClickListener(); 
mCheckBox.setOnClickListener(lstn); 

Gibt es einen Grund, dies würde nicht für Sie arbeiten?

Alternativ, wenn Sie wollten, könnte die zweite Klasse auch die OnClickListener Schnittstelle implementieren.

Wenn Sie True Bubbling benötigen, können Sie darüber hinaus eine eigene Schnittstelle definieren, die das Hinzufügen mehrerer Klick-Listener zu einer Zwischenklasse unterstützt, die die OnClickListener-Schnittstelle implementiert. Von dort aus durchlaufen Sie in der onClick()-Klasse dieser Klasse die registrierten Listener, die die entsprechende Methode aufrufen.

+0

Ich schaue mal, ich bin neu in Java, also ist es für mich nicht sofort offensichtlich. Die letzte Option kann nützlich sein, falls dies häufiger vorkommt. Ich erwäge auch, das Anwendungsobjekt zu verwenden, um Listener zu registrieren. – Mark

+0

Der erste Vorschlag hier ist wahrscheinlich die sauberste einfachste Lösung. – Mark

-1

Sie können einen OnClick Zuhörer auf die Schaltfläche in der folgenden Art und Weise befestigen:

Button button= (Button) findViewById(R.id.button1); 
    button.setOnClickListener(new OnClickListener(){ 
     @Override 
     public void onClick(View v) { 
      // do something 
     } 

    }); 

Ähnlich sollte Ihr Textview haben es auf OnClick Zuhörer.

+0

Mein Problem ist zwei OnClickListeners und eine Schaltfläche, wo meine Schaltfläche eine TextView ist, die ich erweitert habe. – Mark

+0

Sie können nicht 2 clickListeners in einer Ansicht haben. – Falmarri

+0

Ich frage mich, warum, da jedes andere UI-System mehrere Event-Handler unterstützt - daher meine Tagging diese Frage als 'Event-Bubbling' – Mark

1

Da es scheint, ich kann nur einen OnClickListener pro View haben. Was ich denke, was ich tun muß, ist, eine Schnittstelle zu definieren:

public interface MyOnClickListener { 
    public void onMyClick(View v); 
} 

es aus meiner Tätigkeit umzusetzen und die onMyClick Funktion außer Kraft zu tun, was ich will, und in der MyCheckButton Klasse Ich werde einen MyOnClickListener im Konstruktor übergeben muß Speichern Sie es und rufen listener.onMyClick innerhalb des onClick-Handlers auf.

Lassen Sie mich wissen, wenn es einen besseren Weg gibt. Ich habe überlegt, den onTouch-Handler entweder in der Aktivität oder in der MyCheckButton-Klasse zu verwenden, aber später, wenn ich onTouch oder onClick zu einem hinzufüge, werde ich einen schwer zu merkenden Bug bekommen.

Meine Idee funktioniert nicht, weil ich nicht weiß, wie man einen Hinweis auf die Aktivität von meinem Konstruktor zu bekommen:

public class TVCheckButton extends TextView { 

    private MyOnClickListener mListener; 

    public TVCheckButton(Context context, AttributeSet attrs) { 
     super(context, attrs); 

     mListener = ???; 
    } 
} 
+0

Dies funktioniert nicht, weil ich nicht wissen kann, wie Sie der MyCheckButton-Klasse hinzufügen Ich instanziiere die Ansicht MyCheckButton in der XML. Können Sie das Argument Context auf Ihre Aktivität anwenden? – Mark

1

Da nur ein OnclickListener auf Android 2.1 funktioniert [Ich weiß nichts über spätere Versionen], mache die Ansicht privat und statisch und erstelle eine statische Funktion, die sie z.

public class ExampleActivity erstreckt Aktivität {

private SomeOtherclass someOtherClass; 
private static Button b_replay; 

public void onCreate(Bundle savedInstanceState){ 
    someOtherClass = new SomeOtherclass(); 

    b_replay = (Button) findViewById(R.id.b_replay); 
    b_replay.setOnClickListener(someOtherClass); 
} 

public static void changeReplayText(String text){ 
    b_replay.setText(text); 
} 

}

2

Ein sauberer Ansatz wäre, das CompositeListener Muster zu verwenden.

von Genommen: how can I set up multiple listeners for one event?

Sie haben würde diese Klasse in einem Projekt hinzuzufügen:

/** 
* Aux class to collect multiple click listeners. 
*/ 
class CompositeListener implements OnClickListener { 
    private List<OnClickListener> registeredListeners = new ArrayList<OnClickListener>(); 

    public void registerListener (OnClickListener listener) { 
     registeredListeners.add(listener); 
    } 

    @Override 
    public void onClick(View v) { 

     for(OnClickListener listener:registeredListeners) { 
      listener.onClick(View v); 
     } 
    } 
} 

Dann ist dieses

Sowohl Ihre Anrufe zu setOnClickListener hinzufügen MyCheckButton

private CompositeListener clickListener = new CompositeListener(); 

public MyCheckButton() 
{ 
    super.setOnClickListener(clickListener); //multi event listener initialization 
} 

@Override 
public void setOnClickListener(OnClickListener l) { 
    clickListener.registerListener(l); 
} 
auf würde diese Überschreibung durchlaufen, zur Liste hinzugefügt werden und beim Auslösen des Ereignisses aufgerufen werden. Ich hoffe es hilft.

0

Aus irgendeinem Grund konnte ich die obigen Antworten nicht verwenden, also hier ist eine Alternative: // Ich hatte all dies in einer Methode, wo ich zwei Tasten hatte, und auf externen Faktoren würde man sichtbar sein und andere nicht aka "weg". Also, ich hatte das überprüft! Hoffe es hilft jemandem !!

Button b = (Button) findViewById(R.id.b_reset); 
Button breakk = (Button) findViewById(R.id.b_break); 

    if ((findViewById(R.id.b_reset)).getVisibility() == View.VISIBLE) { 
     b.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 

// einige Code und Methoden ...

  } 
     }); 
    } else if ((findViewById(R.id.b_break)).getVisibility() == View.VISIBLE) { 

     breakk.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 

// einige Code und Methoden ...

  } 
     }); 
    } 
0

In der ersten Klasse, definieren eine virtuelle Taste:

private static Button myVirtualButton = new Button(context); 

... und eine öffentliche Methode, um es zu registrieren :

public static void registerMyVirtualButton(Button b) { myVirtualButton = b;} 

Im OnClickListener tun, was Aktion gewünscht wird, und am Ende, Softclick die virtuelle Taste:

if (myVirtualButton!=null) { myVirtualButton.callOnClick(); } 

In der zweiten Klasse, definiert einen Knopf und seine OnClickListener mit dem, was Aktion zusätzlich gewünscht.

Übermitteln Sie die Schaltfläche an die erste Klasse über registerMyVirtualButton. Nach dem Klicken auf das Objekt der ersten Klasse werden beide Aktionen ausgeführt.