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

Answers:


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可能不是Button,它将生成强制转换异常。
克里斯蒂安

2
实际上,不推荐两种方式,请参见我的回答
ognian 2010年

用单个switch case语句替换if,else其实很简单,该语句打开了视图的id,并且case是R.java的id
slayton 2011年

只是想知道为什么将v强制转换为Button。getId()也为视图定义。因此,我真的不推荐第二种方法,而是更喜欢Christian的解决方案!
nuala 2012年

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
虽然这是一种有趣的方法,但是Fragment由于回调必须驻留在活动中(而不是片段中),所以用于侦听器的XML钩子在s 处很粗糙。
donfede 2012年

我的问题是没有抛出InvocationTargetException或NullPointerException(或两者都不抛出)就无法达到doSomething2()。
Quasaur 2013年

1
只是一个旁注:这里的“没有听众”的陈述是错误的。您仅以XML声明了侦听器,仅此而已。
Hubert Grzeskowiak

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- caseif- 易于维护else,并且此实现不需要创建许多类变量。


这工作得很好。您需要实现OnClickListener-android.view.View而不是OnClickListener-android.content.DialogInterface
gkiko 2013年

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

另一种方法是来自activity的单个侦听器,如下所示:

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在v.getId()之间进行-ing处理。每个Button具有单独的匿名OnClickListener会占用更多内存。无需将视图强制转换为按钮。如果可以切换,则使用if-else会更慢且更难阅读。在Android来源中,您经常会注意到通过if-else比较引用:

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

我不知道他们为什么选择这种方式,但这也可以。


因为自v14以来,不再处理ID不固定的情况
因此

@ognian我一直关注到这里,因为您说主要答案使用了不赞成使用的方法。如今,随着Android 5.0 Lollipop的发布,您的答案仍然是正确的,还是像上面的评论所暗示的那样,时间变成了幻想?我真的不知道该怎么想,或者从这里往哪个方向走。
SebasSBM 2015年

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

除了克里斯蒂安·C的答案(对不起,我没有能力发表评论),如果您为两个按钮都设置一个处理程序,则可以直接将v与b1和b2比较,或者如果要通过ID比较,您可以不需要将v强制转换为Button(View也具有getId()方法),这样就不必担心强制转换异常。


另一种选择是执行“ if(v instanceof Button){//转换为Button并在此处进行操作}”
Andy Zhang 2010年

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

查看本文以获取更多详细信息


这或多或少只是一些现有答案的重复。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.