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

Или, если вы работаете только с одним clicklistener, вы можете сделать:

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к Button. Имейте в виду, что второй способ сделать это не рекомендуется ... возможно, что v не может быть кнопкой, которая сгенерирует исключение приведения.
Кристиан

2
На самом деле оба пути не рекомендуются, см. Мой ответ
Огнян

На самом деле довольно просто заменить if, elses с помощью единственного оператора case переключателя, в котором вы включаете id представления, а падежи - это идентификаторы из 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 вместо switch-else, но если вы предпочитаете это, то вам следует сделать:

//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, ваш ответ все еще верен, или время сделало его ошибочным, как предполагает приведенный выше комментарий? Я действительно не знаю, что думать, или какое направление выбрать отсюда.
SebasSBM

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

Я пришел сюда в поисках метода для передачи дополнительных параметров обработчику, это именно то, что я хотел. Тег можно объявить в разметке.
cessor

4

В дополнение к ответу Кристиана С. (извините, у меня нет возможности комментировать), если вы сделаете один обработчик для обеих кнопок, вы можете напрямую сравнить v с b1 и b2, или если вы хотите сравнить по идентификатору, вы не нужно приводить v к кнопке (View также имеет метод getId ()), и в этом случае не нужно беспокоиться об исключении приведения.


Другой вариант - сделать «если (v instanceof Button) {// Привести к кнопке и делать что-то здесь}»
Энди Чжан,

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.