Android OnClickListener - визначте кнопку


134

Я маю діяльність:

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

Як перевірити, яку кнопку було натиснуто?


1
Порівняння п'яти різних способів додавання OnClickListeners для декількох кнопок
Suragch

Відповіді:


199

Ви дізнаєтесь, як це зробити, простим способом, це:

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

Або якщо ви працюєте лише з одним кліком, ви можете зробити:

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

Хоча я не рекомендую робити це так, оскільки вам доведеться додати додаток ifдо кожної кнопки, яку ви використовуєте. Це важко підтримувати.


1
Ну, насправді це не правильно. Viewне є Button, а Buttonє View. Хоча ви можете подати Viewна "a" Button. Майте на увазі, що другий спосіб зробити це не рекомендується ... можливо, що v може бути не кнопкою, яка створить виняток у форматі.
Крістіан

2
Насправді обидва способи не рекомендуються, дивіться мою відповідь
ognian

Його насправді досить просто замінити на if, elses, з одним випадком вимикача випадок, що ви вмикаєте ідентифікатор виду, а випадки - ідентифікатори від R.java
slayton

Цікаво, чому ти все-таки кидаєш v на кнопку. getId () визначений і для Views. Тому я дійсно не рекомендував би другий метод, але віддаю перевагу рішення Крістіана!
нуала

77

Або ви можете спробувати те саме, але без слухачів. Визначення XML кнопки:

android:onClick="ButtonOnClick"

І у своєму коді визначте метод ButtonOnClick:

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

3
Набагато чіткіші за інші відповіді, в яких використовується купа обробників подій, ifвисловлювань та слухачів. Слухачі чудово, якщо кнопки створюються під час виконання, але це часто не так.
Денніс

6
Хоча цікавий інший підхід, гачки XML для слухачів шорсткі по кутах з Fragments, оскільки зворотний виклик повинен знаходитися в активності (а не фрагменті).
donfede

Моя проблема - це не може бути досягнуто doSomething2 (), не кидаючи ні InvocationTargetException, ні NullPointerException (або обидва).
Квазавр

1
Просто сторонне позначення: твердження "без слухачів" тут неправильне. Ви лише оголосили слухача в XML, ось і все.
Губерт Ґшеськовяк

42

Я віддаю перевагу:

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

І потім:

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

Switch- caseпростіше в обслуговуванні, ніж if- else, і ця реалізація не потребує створення багатьох змінних класу.


Це спрацювало чудово. Вам потрібно реалізувати OnClickListener-android.view.View, а не OnClickListener-android.content.DialogInterface
gkiko

16

П'ять способів з'єднати слухача подій - це чудова стаття, в якій розглядається різні способи налаштування одного слухача подій. Дозвольте мені розширити це для кількох слухачів.

1. Клас учасника

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. Тип інтерфейсу

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. Анонімний внутрішній клас

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. Впровадження в діяльність

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. Атрибуція у макеті перегляду подій 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;
        }
    }
}

І в 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

Якщо ви не хочете зберігати екземпляри кнопки 2 у коді класу, дотримуйтесь цього КРАЩЕ (це зрозуміліше та швидше !!):

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

Інший спосіб зробити це одиноким слухачем від діяльності, наприклад, такий:

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

Мені подобається це робити з одним IF, а не комутатором, але якщо ви віддаєте перевагу, то вам слід зробити:

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

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

9

Найкращий спосіб - через switch-ing між v.getId (). Якщо окремий анонімний OnClickListener для кожної кнопки займає більше пам’яті. Кастинг Перегляду на кнопку не потрібний. Використання if-else, коли можливий перемикання, читається повільніше і важче. У джерелі Android часто можна помітити порівняння посилань за допомогою if-else:

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

Не знаю точно, чому вони обрали цей шлях, але це теж працює.


тому що це більше неможливо, оскільки v14, де ідентифікатори не обробляються не постійними
user1324936

@ognian Я пішов сюди, оскільки ви сказали, що головна відповідь використовує застарілі підходи. Сьогодні, коли випущено Android 5.0 Lollipop, ваша відповідь все ще правдива, чи час перетворився на фальшивість, як підказує коментар вище? Я дійсно не знаю, що думати, або в який напрямок взяти звідси.
СебасБМ

7

використовувати setTag ();

подобається це:

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

Я прийшов сюди шукати метод передачі додаткових параметрів обробнику, це саме те, що я хотів. Тег можна оголосити в розмітці.
цессор

4

Окрім відповіді Крістіана С (вибачте, я не маю можливості коментувати), якщо ви зробите один обробник для обох кнопок, ви можете безпосередньо порівняти v до b1 і b2, або якщо ви хочете порівняти за ідентифікатором, ви не потрібно кидати v на Button (у View також є метод getId ()), і таким чином, ви не маєте турбот про виключення cast.


Іншим варіантом буде зробити "if (v instanceof Button) {// Cast to Button and do things here}"
Енді Чжан

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

Перегляньте цю статтю для більш детальної інформації


Це більш-менш лише повторення деяких існуючих відповідей.
Панг
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.