5 Stimmen

Android - Zwei onClick-Listener und eine Schaltfläche

Ich habe einen benutzerdefinierten TextView, der anklickbar ist. Es definiert seinen eigenen onClick-Handler, um sein Aussehen basierend auf Klicks zu ändern. Wenn ich jedoch einen zweiten onClick-Handler in meiner Aktivität definiere, um basierend auf den angeklickten Button etwas zu tun, wird nur eine der onClick-Funktionen aufgerufen. onClick ist eine void-Funktion - gibt es einen Weg zu sagen, dass ich diesen Klick nicht bearbeitet habe, bitte leite ihn an andere onClick-Handler weiter?

Um genauer zu sein, hier ist der Code:

Im Inneren von MyCheckButton, das TextView erweitert, habe ich:

    setOnClickListener( mClickListener );

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

Wenn ich jedoch MyCheckButton in meine Aktivität einbinde und natürlich etwas tun muss, wenn darauf geklickt wird, hefte ich einen anderen OnClickListener daran:

MyCheckButton button= (MyCheckButtonButton) findViewById(R.id.cb);
button.setOnClickListener(new OnClickListener(){
    @Override
    public void onClick(View v) {
        // etwas in der App tun
    }

});

Indem ich setOnClickListener zweimal aufrufe, scheint es, dass ich den ursprünglichen Listener ersetze, sodass toggle(), das das Aussehen ändert, nie aufgerufen wird. Wie kann ich etwas in meiner Aktivität tun, wenn auf diesen Button geklickt wird, wenn er bereits den onClick-Handler verwendet, um sein Aussehen zu ändern? Ich dachte, ich würde einfach beide OnClickListeners sehen, die aufgerufen werden.

7voto

Chris Thompson Punkte 34220

Dies ist ein wenig schmutzig, aber so würde ich es machen, wenn Sie mehrere Zuhörer benötigen, einen registrieren, der von dem anderen weiß. Der erste (der tatsächlich registriert ist) muss dann wissen, wann er basierend auf den Bedingungen des Ereignisses an den anderen Zuhörer delegieren soll. Tatsächlich besteht in Wirklichkeit keine wirkliche Notwendigkeit, zwei OnClickListener-Klassen zu haben. Die zweite Klasse kann implementieren, was auch immer Schnittstelle Sie möchten. Darüber hinaus besteht keine Notwendigkeit, eine spezielle Schnittstelle für das zu erstellen, was Sie benötigen.

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

Dann würden Sie in Ihrem Code für Ihre Aktivität das hier tun

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

Gibt es einen Grund, warum das für Sie nicht funktionieren würde?

Alternativ dazu könnte die zweite Klasse auch das OnClickListener-Interface implementieren.

Zusätzlich, wenn Sie echtes Bubbling benötigen, könnten Sie Ihre eigene Schnittstelle definieren, die das Hinzufügen mehrerer Klick-Zuhörer zu einer Zwischenklasse unterstützt, die zufälligerweise das OnClickListener-Interface implementiert. Von dort aus würden Sie in der onClick()-Methode dieser Klasse durch die registrierten Zuhörer iterieren und die entsprechende Methode aufrufen.

4voto

Miguel Hughes Punkte 107

Ein sauberer Ansatz wäre die Verwendung des CompositeListener-Musters.

Entnommen aus: Wie kann ich mehrere Listener für ein Event einrichten?

Sie müssten diese Klasse in Ihr Projekt einfügen:

/**
 * Hilfsklasse zum Sammeln mehrerer Klick-Listener.
 */
class CompositeListener implements OnClickListener {
    private List registeredListeners = new ArrayList();

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

    @Override
    public void onClick(View v) {

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

Dann fügen Sie dies zu Ihrem MyCheckButton hinzu

private CompositeListener clickListener = new CompositeListener();

public MyCheckButton()
{
    super.setOnClickListener(clickListener); //Initialisierung des Multi-Event-Listeners
}

@Override
public void setOnClickListener(OnClickListener l) {
    clickListener.registerListener(l);
}

Beide Aufrufe von setOnClickListener würden über diese Überschreibung gehen, der Liste hinzugefügt werden und beim Auslösen des Events aufgerufen werden. Hoffe es hilft.

1voto

Da anscheinend pro Ansicht nur ein onClickListener zulässig ist, muss ich wahrscheinlich eine Schnittstelle definieren:

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

Implementieren Sie es in meiner Aktivität und überschreiben Sie die Funktion onMyClick, um zu tun, was ich möchte. Im MyCheckButton-Klasse muss ich dann einen MyOnClickListener im Konstruktor übergeben, speichern und listener.onMyClick im onClick-Handler aufrufen.

Lassen Sie mich wissen, ob es einen besseren Weg gibt. Ich habe daran gedacht, den onTouch-Handler in der Aktivität oder der MyCheckButton-Klasse zu verwenden, aber später könnte es zu einem schwer zu bemerkenden Fehler kommen, wenn ich entweder onTouch oder onClick hinzufüge.

Meine Idee funktioniert nicht, weil ich nicht weiß, wie ich im Konstruktor eine Referenz auf die Aktivität bekomme:

public class TVCheckButton extends TextView {

    private MyOnClickListener mListener;

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

        mListener = ???;
    }
}

1voto

Gideon Bar Punkte 11

Da nur ein OnclickListener auf Android 2.1 funktioniert (ich weiß nicht, wie es bei späteren Versionen aussieht), machen Sie die Ansicht privat und statisch und erstellen Sie eine statische Funktion, die sie ändern kann, z. B.

public class ExampleActivity extends Activity{

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

}

0voto

Lorne Laliberte Punkte 6121

Ein schöner generischer Ansatz besteht darin, eine Liste von Zuhörern zu verwenden, wie z.B. ListenerList und WeakListenerList aus der Beryl-Bibliothek.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X