Android OnClickListener - identifikasi tombol

134

Saya memiliki aktivitas:

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

Bagaimana cara memeriksa tombol mana yang telah diklik?

xpepermint.dll
sumber
1
Perbandingan lima cara berbeda untuk menambahkan OnClickListeners untuk beberapa tombol
Suragch

Jawaban:

199

Anda akan mempelajari cara melakukannya, dengan cara yang mudah, adalah:

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

Atau, jika Anda bekerja hanya dengan satu pendengar klik, Anda dapat melakukan:

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

Padahal, saya tidak menyarankan melakukannya dengan cara itu karena Anda harus menambahkan ifuntuk setiap tombol yang Anda gunakan. Itu sulit untuk dipertahankan.

Cristian
sumber
1
Sebenarnya itu tidak benar. Viewbukan a Button, tapi Buttona View. Padahal, Anda dapat mentransmisikan Viewke Button. Perlu diingat bahwa cara kedua untuk melakukannya tidak disarankan ... mungkin v mungkin bukan Tombol, yang akan menghasilkan pengecualian cast.
Cristian
2
Sebenarnya kedua cara tidak disarankan, lihat jawaban saya
ognian
Sebenarnya cukup mudah untuk mengganti if, elses dengan pernyataan kasus sakelar tunggal yang Anda aktifkan id tampilan dan kasingnya adalah id dari R.java
slayton
Hanya ingin tahu mengapa Anda tetap mentransmisikan v ke Tombol. getId () juga didefinisikan untuk Tampilan. Oleh karena itu saya benar-benar tidak akan merekomendasikan metode kedua tetapi lebih memilih solusi Christian!
nuala
77

Atau Anda dapat mencoba hal yang sama tetapi tanpa pendengar. Pada definisi XML tombol Anda:

android:onClick="ButtonOnClick"

Dan dalam kode Anda tentukan metode ButtonOnClick:

public void ButtonOnClick(View v) {
    switch (v.getId()) {
      case R.id.button1:
        doSomething1();
        break;
      case R.id.button2:
        doSomething2();
        break;
      }
}
Chronos
sumber
3
Jauh lebih bersih daripada jawaban lain yang menggunakan sekelompok penangan kejadian, ifpernyataan, dan pendengar. Pendengar bagus jika tombol dibuat saat runtime, tetapi seringkali tidak demikian.
Dennis
6
Meskipun merupakan pendekatan berbeda yang menarik, kait XML untuk listener tidak cocok dengan Fragments, karena callback harus berada dalam aktivitas (bukan fragmen).
donfede
Masalah saya adalah doSomething2 () tidak dapat dicapai tanpa membuang InvocationTargetException atau NullPointerException (atau keduanya).
Quasaur
1
Sekadar catatan samping: pernyataan "tanpa pendengar" di sini salah. Anda hanya mendeklarasikan listener dalam XML, itu saja.
Hubert Grzeskowiak
42

Aku lebih memilih:

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

Lalu:

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

Switch- caselebih mudah dipelihara daripada if- else, dan implementasi ini tidak memerlukan pembuatan banyak variabel kelas.

Saad Farooq
sumber
Ini bekerja dengan sempurna. Anda perlu mengimplementasikan OnClickListener-android.view.View dan bukan OnClickListener-android.content.DialogInterface
gkiko
16

Lima Cara untuk Mempersiapkan Pemroses Acara adalah artikel bagus yang menjelaskan berbagai cara untuk menyiapkan pendengar acara tunggal. Izinkan saya mengembangkannya di sini untuk banyak pendengar.

1. Kelas Anggota

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. Jenis Antarmuka

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. Kelas Batin Anonim

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. Implementasi dalam Aktivitas

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. Atribut dalam Tata Letak Tampilan untuk Acara 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;
        }
    }
}

Dan dalam 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" />
Suragch
sumber
12

Jika Anda tidak ingin menyimpan contoh tombol 2 di kode kelas, ikuti cara LEBIH BAIK ini (ini lebih jelas dan cepat !!):

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;
  }
}
lory105
sumber
12

Cara lain untuk melakukannya adalah pendengar tunggal dari aktivitas, seperti ini:

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

Saya suka melakukannya dengan satu IF daripada dengan switch-else, tetapi jika Anda lebih suka itu, Anda harus melakukan:

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

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

Cara terbaik adalah dengan switch-ing antara v.getId (). Memiliki OnClickListener anonim yang terpisah untuk setiap Tombol menggunakan lebih banyak memori. Mentransmisikan Tampilan ke Tombol tidak diperlukan. Menggunakan if-else saat pengalih dimungkinkan lebih lambat dan lebih sulit untuk dibaca. Di sumber Android, Anda sering kali dapat melihat perbandingan referensi dengan if-else:

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

Saya tidak tahu persis mengapa mereka memilih cara ini, tetapi berhasil juga.

ognian
sumber
karena tidak mungkin lagi sejak v14 di mana id diperlakukan tidak konstan
user1324936
@ognian Saya menindaklanjuti ke sini karena Anda mengatakan jawaban utama menggunakan pendekatan yang tidak berlaku lagi. Saat ini dengan rilis Android 5.0 Lollipop, apakah jawaban anda masih benar atau sudah waktunya menjadi falacy, seperti saran komentar di atas? Saya benar-benar tidak tahu harus berpikir apa, atau arah mana yang harus diambil dari sini.
SebasSBM
7

gunakan setTag ();

seperti ini:

@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;   
    }     
}     
pengguna2644305
sumber
Saya datang ke sini mencari metode untuk meneruskan parameter tambahan ke penangan, inilah yang saya inginkan. Tag dapat dideklarasikan di Markup.
cessor
4

Selain jawaban Cristian C (maaf, saya tidak memiliki kemampuan untuk memberikan komentar), jika Anda membuat satu penangan untuk kedua tombol, Anda dapat langsung membandingkan v dengan b1 dan b2, atau jika Anda ingin membandingkan dengan ID, Anda tidak perlu mentransmisikan v ke Button (View memiliki metode getId (), juga), dan dengan demikian tidak perlu khawatir akan pengecualian cast.

DonSteep
sumber
Pilihan lainnya adalah melakukan "if (v instanceof Button) {// Cast to Button and do stuff here}"
Andy Zhang
4
Button mybutton = new Button(ViewPagerSample.this);
mybutton.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
            // TODO Auto-generated method stub
    }
});
Tai Nguyen
sumber
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();
    }
}

Lihat artikel ini untuk lebih jelasnya

pengguna7925882
sumber
Ini kurang lebih hanyalah pengulangan dari beberapa jawaban yang ada.
Pang