Android OnClickListener - Identifizieren Sie eine Schaltfläche


134

Ich habe die Aktivität:

public class Mtest extends Activity {
  Button b1;
  Button b2;
  public void onCreate(Bundle savedInstanceState) {
    ...
    b1 = (Button) findViewById(R.id.b1);
    b2 = (Button) findViewById(R.id.b2);
    b1.setOnClickListener(myhandler);
    b2.setOnClickListener(myhandler);
    ...
  }
  View.OnClickListener myhandler = new View.OnClickListener() {
    public void onClick(View v) {
      // MY QUESTION STARTS HERE!!!
      // IF b1 do this
      // IF b2 do this
      // MY QUESTION ENDS HERE!!!
    }
  }
}

Wie überprüfe ich, auf welche Schaltfläche geklickt wurde?


1
Vergleich von fünf verschiedenen Möglichkeiten , OnClickListeners für mehrere Schaltflächen hinzuzufügen
Suragch

Antworten:


199

Sie werden auf einfache Weise lernen, wie es geht:

public class Mtest extends Activity {
  Button b1;
  Button b2;
  public void onCreate(Bundle savedInstanceState) {
    ...
    b1 = (Button) findViewById(R.id.b1);
    b2 = (Button) findViewById(R.id.b2);
    b1.setOnClickListener(myhandler1);
    b2.setOnClickListener(myhandler2);
    ...
  }
  View.OnClickListener myhandler1 = new View.OnClickListener() {
    public void onClick(View v) {
      // it was the 1st button
    }
  };
  View.OnClickListener myhandler2 = new View.OnClickListener() {
    public void onClick(View v) {
      // it was the 2nd button
    }
  };
}

Wenn Sie nur mit einem Klicklistener arbeiten, haben Sie folgende Möglichkeiten:

View.OnClickListener myOnlyhandler = new View.OnClickListener() {
  public void onClick(View v) {
      switch(v.getId()) {
        case R.id.b1:
          // it was the first button
          break;
        case R.id.b2:
          // it was the second button
          break;
      }
  }
}

Ich empfehle jedoch nicht, dies so zu tun, da Sie iffür jede Schaltfläche, die Sie verwenden , eine hinzufügen müssen. Das ist schwer zu pflegen.


1
Nun, eigentlich ist das nicht richtig. Viewist nicht ein Button, aber Buttonist ein View. Sie können jedoch a Viewzu a werfen Button. Denken Sie daran, dass der zweite Weg nicht empfohlen wird ... Vielleicht ist v kein Button, der eine Cast-Ausnahme generiert.
Cristian

2
Eigentlich sind beide Wege nicht zu empfehlen, siehe meine Antwort
ognian

Es ist eigentlich ganz einfach, das if, elses durch eine einzelne switch case-Anweisung zu ersetzen, dass Sie die ID der Ansicht einschalten und die Fälle IDs von R.java sind
slayton

Ich frage mich nur, warum du v sowieso auf einen Button wirfst. getId () ist auch für Ansichten definiert. Daher würde ich die 2. Methode wirklich nicht empfehlen, sondern Christians Lösung bevorzugen!
Nuala

77

Oder Sie können das gleiche versuchen, aber ohne Zuhörer. Auf Ihrer Schaltfläche XML-Definition:

android:onClick="ButtonOnClick"

Und definieren Sie in Ihrem Code die Methode ButtonOnClick:

public void ButtonOnClick(View v) {
    switch (v.getId()) {
      case R.id.button1:
        doSomething1();
        break;
      case R.id.button2:
        doSomething2();
        break;
      }
}

3
Viel sauberer als die anderen Antworten, die eine Reihe von Ereignishandlern, ifAnweisungen und Listenern verwenden. Listener sind großartig, wenn Schaltflächen zur Laufzeit erstellt werden, aber das ist oft nicht der Fall.
Dennis

6
Während es sich um einen interessanten anderen Ansatz handelt, sind XML-Hooks für Listener mit Fragments um die Ecke rau , da sich der Rückruf in der Aktivität befinden muss (nicht im Fragment).
Donfede

Mein Problem ist, dass doSomething2 () nicht erreicht werden kann, ohne eine InvocationTargetException oder eine NullPointerException (oder beides) auszulösen.
Quasaur

1
Nur eine Randnotiz: Die Aussage "ohne Zuhörer" hier ist falsch. Sie deklarieren den Listener nur in XML, das ist alles.
Hubert Grzeskowiak

42

Ich bevorzuge:

class MTest extends Activity implements OnClickListener {
    public void onCreate(Bundle savedInstanceState) {
    ...
    Button b1 = (Button) findViewById(R.id.b1);
    Button b2 = (Button) findViewById(R.id.b2);
    b1.setOnClickListener(this);
    b2.setOnClickListener(this);
    ...
}

Und dann:

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.b1:
            ....
            break;
        case R.id.b2:
            ....
            break;
    }   
}

Switch- caseist einfacher zu warten als if- elseund für diese Implementierung müssen nicht viele Klassenvariablen erstellt werden.


Das hat perfekt funktioniert. Sie müssen OnClickListener-android.view.View und nicht OnClickListener-android.content.DialogInterface implementieren
gkiko

16

Fünf Möglichkeiten, einen Ereignis-Listener zu verkabeln ist ein großartiger Artikel, in dem die verschiedenen Möglichkeiten zum Einrichten eines einzelnen Ereignis-Listeners beschrieben werden. Lassen Sie mich das hier für mehrere Hörer erweitern.

1. Mitgliedsklasse

public class main extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //attach an instance of HandleClick to the Button
        HandleClick handleClick = new HandleClick();
        findViewById(R.id.button1).setOnClickListener(handleClick);
        findViewById(R.id.button2).setOnClickListener(handleClick);
    }    
    private class HandleClick implements OnClickListener{
        public void onClick(View view) {
            switch(view.getId()) {
            case R.id.button1:
                // do stuff
                break;
            case R.id.button2:
                // do stuff
                break;
            }
        }
    }
}

2. Schnittstellentyp

public class main extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        findViewById(R.id.button1).setOnClickListener(handleClick);
        findViewById(R.id.button2).setOnClickListener(handleClick);
    }
    private OnClickListener handleClick = new OnClickListener() {
        public void onClick(View view) {
            switch (view.getId()) {
            case R.id.button1:
                // do stuff
                break;
            case R.id.button2:
                // do stuff
                break;
            }
        }
    };
}

3. Anonyme innere Klasse

public class main extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
            public void onClick(View view) {
                // do stuff
            }
        });
        findViewById(R.id.button2).setOnClickListener(new OnClickListener() {
            public void onClick(View view) {
                // do stuff
            }
        });
    }
}

4. Implementierung in Aktivität

public class main extends Activity implements OnClickListener {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        findViewById(R.id.button1).setOnClickListener(this);
        findViewById(R.id.button2).setOnClickListener(this);
    }
    public void onClick(View view) {
        switch (view.getId()) {
        case R.id.button1:
            // do stuff
            break;
        case R.id.button2:
            // do stuff
            break;
        }
    }
}

5. Attribut im Ansichtslayout für OnClick-Ereignisse

public class main extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    public void HandleClick(View view) {
        switch (view.getId()) {
        case R.id.button1:
            // do stuff
            break;
        case R.id.button2:
            // do stuff
            break;
        }
    }
}

Und in XML:

<Button
    android:id="@+id/button1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="HandleClick" />
<Button
    android:id="@+id/button2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="HandleClick" />

12

Wenn Sie keine Instanzen der Schaltfläche 2 im Klassencode speichern möchten, gehen Sie wie folgt BESSER vor (dies ist klarer und schneller !!):

public void buttonPress(View v) {
  switch (v.getId()) {
    case R.id.button_one:
        // do something
        break;
    case R.id.button_two:
        // do something else
        break;
    case R.id.button_three:
        // i'm lazy, do nothing
        break;
  }
}

12

Eine andere Möglichkeit ist ein einzelner Zuhörer aus einer Aktivität wie dieser:

public class MyActivity extends Activity implements OnClickListener {
    .......  code

    //my listener
    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.mybutton) { 
            DoSomething();
            return;
        }

        if (v.getId() == R.id.mybutton2) { 
            DoSomething2();
            return;
        }
    }
}

Ich mache es gerne mit einer einzelnen ZF anstelle von switch-else, aber wenn Sie das bevorzugen, sollten Sie Folgendes tun:

//my listener
@Override
public void onClick(View v) {
    switch(v.getId()) {
        case R.id.mybutton:
        { 
             DoSomething();
             break;
        }

        case R.id.mybutton2:
        {
            DoSomething();
            break;
        }
    }
}

9

Der beste Weg ist, switchzwischen v.getId () zu wechseln. Ein separater anonymer OnClickListener für jede Schaltfläche beansprucht mehr Speicher. Das Umwandeln der Ansicht in die Schaltfläche ist nicht erforderlich. Die Verwendung von if-else, wenn ein Wechsel möglich ist, ist langsamer und schwerer zu lesen. In der Android-Quelle können Sie häufig feststellen, dass Sie die Referenzen mit if-else vergleichen:

if (b1 == v) {
 // ...
} else if (b2 == v) {

Ich weiß nicht genau, warum sie diesen Weg gewählt haben, aber es funktioniert auch.


weil es seit v14 nicht mehr möglich ist, wo IDs nicht konstant behandelt werden
user1324936

@ognian Ich bin hier weitergegangen, weil Sie sagten, dass die Hauptantwort veraltete Ansätze verwendet. Ist Ihre Antwort heutzutage mit Android 5.0 Lollipop immer noch wahr oder wurde sie mit der Zeit zu einem Irrtum, wie der obige Kommentar nahelegt? Ich weiß wirklich nicht, was ich denken soll oder welche Richtung ich von hier aus einschlagen soll.
SebasSBM

7

benutze setTag ();

so was:

@Override    
public void onClick(View v) {     
    int tag = (Integer) v.getTag();     
    switch (tag) {     
    case 1:     
        System.out.println("button1 click");     
        break;     
    case 2:     
        System.out.println("button2 click");     
       break;   
    }     
}     

Ich bin hierher gekommen, um nach einer Methode zu suchen, mit der zusätzliche Parameter an einen Handler übergeben werden können. Genau das wollte ich. Das Tag kann in Markup deklariert werden.
Prozessor

4

Zusätzlich zur Antwort von Cristian C (Entschuldigung, ich kann keine Kommentare abgeben) können Sie v direkt mit b1 und b2 vergleichen, wenn Sie einen Handler für beide Schaltflächen erstellen, oder wenn Sie anhand der ID vergleichen möchten Sie müssen v nicht in Button umwandeln (View hat auch die Methode getId ()), und auf diese Weise besteht keine Sorge vor einer Cast-Ausnahme.


Eine andere Möglichkeit wäre, ein "if (v instanceof Button) {// Cast to Button und mache hier Sachen}"
Andy Zhang

4
Button mybutton = new Button(ViewPagerSample.this);
mybutton.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
            // TODO Auto-generated method stub
    }
});

1
Button button1 = (Button)findViewById(R.id.button1);
button1.setOnClickListener(this);

@Override
public void onClick(View v) {
    // TODO Auto-generated method stub
    if(v.getId() == R.id.button1){
        Toast.makeText(context, "Button 1 Click", Toast.LENGTH_LONG).show();
    }
}

Weitere Informationen finden Sie in diesem Artikel


Dies ist mehr oder weniger nur eine Wiederholung einiger der vorhandenen Antworten.
Pang
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.