Android OnClickListener: identifica un pulsante


134

Ho l'attività:

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!!!
    }
  }
}

Come posso verificare quale pulsante è stato cliccato?


1
Confronto tra cinque diversi modi per aggiungere OnClickListeners per più pulsanti
— Suragch

Risposte:


199

Imparerai come farlo, in modo semplice, è:

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

Oppure, se lavori con un solo listener di clic, puoi fare:

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

Tuttavia, non ti consiglio di farlo in questo modo poiché dovrai aggiungere un ifper ogni pulsante che usi. È difficile da mantenere.


1
Bene, in realtà non è corretto. Viewnon è un Button, ma Buttonè un View. Tuttavia, puoi lanciare Viewa a Button. Tieni presente che il secondo modo per farlo non è raccomandato ... forse v potrebbe non essere un pulsante, che genererà un'eccezione di trasmissione.
— Cristian,

2
In realtà entrambi i modi non sono raccomandati, vedi la mia risposta
— ognian

In realtà è abbastanza semplice sostituire if, elses con una singola istruzione case switch che attiva l'id della vista e i casi sono id di R.java
— slayton

Mi chiedo solo perché hai lanciato v su un pulsante comunque. getId () è definito anche per Views. Quindi non consiglierei davvero il secondo metodo, ma preferisco la soluzione di Christian!
— nuala,

77

Oppure puoi provare lo stesso ma senza ascoltatori. Sul tuo pulsante Definizione XML:

android:onClick="ButtonOnClick"

E nel tuo codice definisci il metodo ButtonOnClick:

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

3
Molto più pulito delle altre risposte che usano un sacco di gestori di eventi, ifdichiarazioni e ascoltatori. Gli ascoltatori sono fantastici se i pulsanti vengono creati in fase di esecuzione, ma spesso non è così.
— Dennis,

6
Mentre un approccio diverso e interessante, gli hook XML per i listener sono approssimativi con Fragments, poiché il callback deve risiedere nell'attività (non nel frammento).
— donfede,

Il mio problema è che doSomething2 () non può essere raggiunto senza lanciare InvocationTargetException o NullPointerException (o entrambi).
— Quasaur,

1
Solo un sidenote: l'affermazione "senza ascoltatori" qui è sbagliata. Stai solo dichiarando l'ascoltatore in XML, tutto qui.
— Hubert Grzeskowiak,

42

Preferisco:

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

E poi:

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

Switch- caseè più facile da mantenere di if- elsee questa implementazione non richiede la creazione di molte variabili di classe.


Questo ha funzionato perfettamente. Devi implementare OnClickListener-android.view.View e non OnClickListener-android.content.DialogInterface
— gkiko

16

Cinque modi per collegare un ascoltatore di eventi è un ottimo articolo che riassume i vari modi per impostare un singolo listener di eventi. Vorrei espanderlo qui per più ascoltatori.

1. Classe membro

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. Tipo di interfaccia

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. Classe interna anonima

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. Implementazione in Attività

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. Attributo in Visualizza layout per eventi OnClick

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

E 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

Se non vuoi salvare le istanze del pulsante 2 nel codice della classe, segui questo MEGLIO modo (questo è più chiaro e veloce !!):

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

Un altro modo di farlo è un singolo ascoltatore per attività, in questo modo:

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

Mi piace farlo con IF singolo invece di switch-else, ma se lo preferisci, allora dovresti fare:

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

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

9

Il modo migliore è switch-ing tra v.getId (). Avere OnClickListener anonimo separato per ciascun pulsante sta occupando più memoria. Casting View to Button non è necessario. L'uso di if-else quando è possibile il passaggio è più lento e più difficile da leggere. Nella fonte di Android puoi spesso notare il confronto dei riferimenti con if-else:

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

Non so esattamente perché abbiano scelto in questo modo, ma funziona anche.


perché non è più possibile dal v14 in cui gli id ​​non sono trattati non costanti
— user1324936

@ognian Ho seguito fino a qui perché hai detto che la risposta principale utilizza approcci deprecati. Al giorno d'oggi con Android 5.0 Lollipop rilasciato, la tua risposta è ancora vera o il tempo è diventato falso, come suggerisce il commento sopra? Non so davvero cosa pensare o quale direzione prendere da qui.
— SebasSBM,

7

usa setTag ();

come questo:

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

Sono venuto qui alla ricerca di un metodo per passare parametri aggiuntivi a un gestore, questo è esattamente quello che volevo. Il tag può essere dichiarato in Markup.
— cessatore

4

Oltre alla risposta di Cristian C (mi dispiace, non ho la possibilità di commentare), se crei un gestore per entrambi i pulsanti, puoi confrontare direttamente v con b1 e b2 o se vuoi confrontare con l'ID, tu non è necessario eseguire il cast di v su Button (View ha anche il metodo getId ()), e in questo modo non si deve preoccupare dell'eccezione di cast.


Un'altra opzione sarebbe quella di fare un "if (v instanceof Button) {// Cast to Button e fare cose qui}"
— 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();
    }
}

Controlla questo articolo per maggiori dettagli


Questo è più o meno solo una ripetizione di alcune delle risposte esistenti.
— Pang
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.