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를 추가 하는 5 가지 방법 비교
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, 그러나 ButtonA는 View. 비록, 당신은 전송할 수 있습니다 ViewA를 Button. 두 번째 방법은 권장하지 않는다는 점에 유의하십시오 .v는 캐스트 예외를 생성하는 Button이 아닐 수도 있습니다.
Cristian

2
실제로 두 가지 방법은 권장되지 않습니다. 내 답변 참조
ognian

그 사실은 매우 간단 교체 할 경우, 당신은 뷰의 ID를 전환 한 경우는 ID의 R.java에서이 것을 하나의 스위치 케이스 문를 elses
slayton

어쨌든 v를 왜 버튼에 캐스팅했는지 궁금합니다. getId ()도 Views에 대해 정의됩니다. 따라서 나는 두 번째 방법을 권장하지 않지만 Christian의 솔루션을 선호합니다!
nuala

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명령문 및 리스너 를 사용하는 다른 응답보다 훨씬 깨끗합니다 . 런타임에 버튼을 만들면 리스너가 훌륭하지만 종종 그렇지 않습니다.
Dennis

6
흥미로운 다른 접근 방식이지만 Fragment콜백은 액티비티 (프래그먼트가 아닌)에 있어야 하기 때문에 리스너의 XML 후크는 s 코너에서 거칠습니다 .
동맹

내 문제는 InvocationTargetException 또는 NullPointerException (또는 둘 다)을 throw하지 않고 doSomething2 ()에 도달 할 수 없다는 것입니다.
Quasaur

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-case 보다 유지 관리가 용이하다 if- else,이 구현은 많은 클래스 변수을 필요로하지 않습니다.


이것은 완벽하게 작동했습니다. OnClickListener-android.content.DialogInterface 가 아닌 OnClickListener-android.view.View
gkiko

16

이벤트 리스너를 연결하는 5 가지 방법 를 연결하는 은 단일 이벤트 리스너를 설정하는 다양한 방법을 개괄 한 훌륭한 기사입니다. 여러 리스너를 위해 여기를 확장하겠습니다.

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

switch-else 대신 단일 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

가장 좋은 방법은 switchv.getId () 사이 에서 -ing하는 것입니다 . 각 버튼마다 별도의 익명 OnClickListener가 있으면 더 많은 메모리를 차지합니다. 뷰를 버튼으로 캐스팅 할 필요가 없습니다. 전환이 가능한 경우 if-else를 사용하면 느리고 읽기가 어렵습니다. 안드로이드 소스에서 if-else로 참조를 비교하는 것을 종종 알 수 있습니다.

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

나는 그들이 왜 이런 식으로 선택했는지 모르겠지만 작동합니다.


ID가 일정하지 않은 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

Cristian C의 답변 외에도 (죄송합니다. 댓글을 작성할 수 없습니다.) 두 버튼에 대해 하나의 처리기를 만들면 v를 b1과 b2와 직접 비교하거나 ID로 비교하려는 경우 v를 Button으로 캐스트 할 필요가 없으며 (View에는 getId () 메소드도 있음) 그렇게하면 캐스트 예외에 대한 걱정이 없습니다.


또 다른 옵션은 "if (v instanceof Button) {// 버튼으로 캐스트하고 여기서 수행}}을 수행하는 것입니다.
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();
    }
}

자세한 내용은이 기사를 확인하십시오.


이것은 기존 답변 중 일부의 반복입니다.
Pang
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.