Android OnClickListener - xác định một nút


134

Tôi có hoạt động:

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

Làm cách nào để kiểm tra nút nào đã được nhấp?


1
So sánh năm cách khác nhau để thêm OnClickListener cho nhiều nút
Suragch

Câu trả lời:


199

Bạn sẽ học được cách để làm điều đó, một cách dễ dàng, là:

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

Hoặc, nếu bạn đang làm việc chỉ với một người nghe, bạn có thể làm:

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

Mặc dù vậy, tôi không khuyên bạn nên làm theo cách đó vì bạn sẽ phải thêm một ifnút cho mỗi nút bạn sử dụng. Điều đó thật khó để duy trì.


1
Chà, thực ra điều đó không đúng. Viewkhông phải là a Button, mà Buttonlà a View. Mặc dù, bạn có thể bỏ Viewa Button. Hãy nhớ rằng cách thứ hai để làm điều đó không được khuyến khích ... có thể v có thể không phải là Nút, sẽ tạo ra ngoại lệ truyền.
Cristian

2
Trên thực tế cả hai cách đều không được khuyến nghị, hãy xem câu trả lời của tôi
thức

Nó thực sự khá đơn giản để thay thế if, elses bằng một câu lệnh trường hợp chuyển đổi duy nhất mà bạn bật id của chế độ xem và các trường hợp là id từ R.java
slayton

Chỉ cần tự hỏi tại sao bạn cast v đến một Nút nào. getId () cũng được định nghĩa cho Lượt xem. Do đó, tôi thực sự không khuyến nghị phương pháp thứ 2 mà thích giải pháp của Christian!
nours

77

Hoặc bạn có thể thử tương tự nhưng không có người nghe. Trên nút định nghĩa XML của bạn:

android:onClick="ButtonOnClick"

Và trong mã của bạn xác định phương thức ButtonOnClick:

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

3
Sạch sẽ hơn nhiều so với các câu trả lời khác sử dụng một loạt các trình xử lý sự kiện, ifcâu lệnh và người nghe. Trình nghe rất tuyệt nếu các nút được tạo trong thời gian chạy, nhưng đó thường không phải là trường hợp.
Dennis

6
Mặc dù là một cách tiếp cận khác nhau thú vị, các móc nối XML cho người nghe rất thô quanh các góc với Fragments, vì cuộc gọi lại phải nằm trong hoạt động (không phải là đoạn).
donfede

Thử nghiệm của tôi là doS Something2 () không thể đạt được mà không cần ném InvocationTargetException hoặc NullPulumException (hoặc cả hai).
Quasaur

1
Chỉ là một sidenote: tuyên bố "không có người nghe" ở đây là sai. Bạn chỉ khai báo trình nghe bằng XML, thế thôi.
Hubert Grzeskowiak

42

Tôi thích:

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

Và sau đó:

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

Switch- casedễ bảo trì hơn if- elsevà việc triển khai này không yêu cầu tạo nhiều biến lớp.


Điều này làm việc hoàn hảo. Bạn cần triển khai OnClickListener-android.view.View chứ không phải OnClickListener-android.content.DialogInterface
gkiko

16

Năm cách để kết nối một Trình lắng nghe sự kiện là một bài viết tuyệt vời tổng quan về các cách khác nhau để thiết lập một trình lắng nghe sự kiện. Hãy để tôi mở rộng điều đó ở đây cho nhiều người nghe.

1. Lớp thành viên

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. Loại giao diện

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. Lớp bên trong vô danh

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. Thực hiện trong hoạt động

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. Thuộc tính trong Giao diện xem cho các sự kiện 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;
        }
    }
}

Và trong 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

Nếu bạn không muốn lưu các thể hiện của nút 2 trong mã lớp, hãy làm theo cách TỐT HƠN này (cách này rõ ràng và nhanh hơn !!):

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

Một cách khác để làm điều đó là một người nghe duy nhất từ ​​hoạt động, như thế này:

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

Tôi thích làm điều đó với IF đơn thay vì chuyển đổi khác, nhưng nếu bạn thích điều đó, thì bạn nên làm:

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

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

9

Cách tốt nhất là bằng cách switch-ing giữa v.getId (). Có OnClickListener ẩn danh riêng cho mỗi Nút sẽ chiếm nhiều bộ nhớ hơn. Casting View to Button là không cần thiết. Sử dụng if-other khi chuyển đổi là có thể chậm hơn và khó đọc hơn. Trong nguồn của Android, bạn thường có thể nhận thấy việc so sánh các tham chiếu bằng if-other:

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

Tôi không biết chính xác tại sao họ chọn cách này, nhưng nó cũng hoạt động.


bởi vì nó không còn có thể kể từ v14 khi id không được xử lý không đổi
user1324936

@ognian Tôi theo dõi đến đây vì bạn nói câu trả lời chính sử dụng các phương pháp không dùng nữa. Ngày nay với Android 5.0 Lollipop được phát hành, câu trả lời của bạn có còn đúng không, hay thời gian đã khiến nó trở thành một điều đáng tiếc, như nhận xét trên cho thấy? Tôi thực sự không biết phải nghĩ gì, hoặc nên đi theo hướng nào từ đây.
SebasSBM

7

sử dụng setTag ();

như thế này:

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

Tôi đến đây để tìm kiếm một phương thức để truyền các tham số bổ sung cho một trình xử lý, đây chính xác là những gì tôi muốn. Thẻ có thể được khai báo trong Markup.
giám khảo

4

Ngoài câu trả lời của Cristian C (xin lỗi, tôi không có khả năng đưa ra nhận xét), nếu bạn tạo một trình xử lý cho cả hai nút, bạn có thể so sánh trực tiếp v với b1 và b2 hoặc nếu bạn muốn so sánh bằng ID, bạn không cần truyền v sang Nút (Chế độ xem cũng có phương thức getId ()) và theo cách đó, không có lo lắng về ngoại lệ truyền.


Một tùy chọn khác là thực hiện "if (v instanceof Nút) {// Truyền tới nút và thực hiện công cụ ở đây}"
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();
    }
}

Kiểm tra bài viết này để biết thêm chi tiết


Điều này ít nhiều chỉ là sự lặp lại của một số câu trả lời hiện có.
Pang
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.