본문 바로가기
공부/안드로이드

Android - 이벤트 처리하기

by xladmt 2022. 4. 18.

이벤트 처리하기 : 사용자의 화면 터치에 대한 이벤트를 처리해야 여러 기능을 구현할 수 있다.

 

안드로이드의 이벤트는 윈도우 이벤트와 조금 다르다. 윈도우는 주로, 마우스와 키보드로 조작하지만 안드로이드는 손가락 터치 방식으로 조작한다. 

 

MotionEvent

ACTION_DOWN : 처음 눌렸을 때

ACTION_MOVE : 누르고 움직였을 때

ACTION_UP : 누른걸 땠을 때

// 이벤트 예시 코드
View view = findViewById(R.id.view);
view.setOnTouchListener(new View.OnTouchListener() {
	@Override
	public boolean onTouch(View view, MotionEvent motionEvent) {
		int action = motionEvent.getAction();
		float curX = motionEvent.getX();
		float curY = motionEvent.getY();
        
		if (action == MotionEvent.ACTION_DOWN) {
			println("손가락 눌림 : " + curX + ", " + curY);
		} else if (action == MotionEvent.ACTION_MOVE) {
			println("손가락 움직임: " + curX + ", " + curY);
		} else if (action == MotionEvent.ACTION_UP) {
			println("손가락 뗌 : " + curX + ", " + curY);
		}
            
		return true;
	}
});

 

 

뷰의 이벤트 처리 방법

- 각 방법마다 효율성/가독성의 차이가 있으므로 적절한 방법 선택 필요

1. 콜백 메소드 정의

2. 리스너 인터페이스 구현하는 클래스 사용

3. 액티비티가 리스너 구현

4. 뷰가 리스너 구현

5. 익명 내부 클래스 사용

 

 

1) 콜백 메소드 정의

 - 콜백 메소드란 특정 이벤트 발생 시 시스템에 의해 자동으로 호출되는 메소드 

 - 해당 클래스를 상속 받아 콜백 메소드를 재정의.

   · 사용자와 상호작용하는 주체가 뷰이므로 이벤트 콜백은 주로 뷰가 제공.

 - 주요 콜백 메소드

  boolean onTouchEvent(MotionEvent event)
  boolean onKeyDown(int KeyCode, KeyEvent event)
  boolean onKeyUp(int KeyCode, KeyEvent event)
  boolean onTrackball Event()

 

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Budgle savedInstanceState) {
    	super.onCreate(savedInstanceState);
        // setContentView(R.layout.activity_main);
        
        View view = new MyView(context: this);
        setContentView(view);
    }
    
    // View를 상속받는 MyView 클래스 정의
    class MyView extends View{
    	public MyView(Context context) {
        	super(context);
        }
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) { //움직이는 모든 이벤트들을 받음(move, down, up)
    	super.onTouchEvent(event);
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
        	Toast.makeText(context:MainActivity.this, text:"Touch Event Received", Toast.LENGTH_LONG).show();
        }
        return false;
    }
}

- 장점

  이벤트 처리를 위한 간단하고 직관적인 방법

- 단점 

  메소드 재정의 위해 상속 필요

  기존 위젯의 경우 바로 처리 불가

  모든 이벤트에 대해 콜백이 정의되어 있지 않음.

 

 

2) 리스너 인터페이스 구현

1. 리스너를 구현하는 클래스를 선언하고 추상 메소드를 구현

  View.OnTouchListener : boolean onTouch(View v, MotionEvent event)
  View.OnKeyListener : boolean onKey(View v, int keyCode, KeyEvent event) // 키보드 눌렀을 때
  View.OnClickListener : void onClick(View v) // 클릭되면 다
  View.OnFocusChangeListener : void onFocusChange(View v, boolean hasFocus)

2. 리스너로 구현된 클래스 객체 생성

3. 이벤트를 감지할 수 있도록 리스너 등록 (버튼이랑 이벤트 처리하는 부분이랑 연결)

 void setOnTouchListener(View.OnTouchList listener)
 void setOnKeyListener(View.OnKeyListener listener)
 void setOnClickListener(View.OnClickListener listener)
 void setOnLongClickListener(View.OnLongClickListener listener)
 void setOnFocusChangeListener(View.OnFocusChangeListener listener)
public class MainActivity extends AppCompatActivity {

    Button button;
    @Override
    protected void onCreate(Budgle savedInstanceState) {
    	super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        button = findViewById(R.id.button);
        // 2) 이벤트 리스너 객체 생성
        MyListener myListener = new MyListener();
        // 3) 버튼 위젯에 리스너 객체 설정
        button.setOnTouchListener(myListener);
    }
    
    // 1) 리스너 구현 내부 클래스 선언
    class MyListener implements View.OnTouchListener {
    
        @Override
    	public boolean onTouch(View view, MotionEvent event) {
            if(event.getAction() == MotionEvent.ACTION_DOWN) {
                Toast.makeText(context:MainActivity.this, text:"Touch Event Received", Toast.LENGTH_LONG).show();
                return true;
            }
            return false;
        }
    }
}

 

 

3) 무명(익명)클래스로 리스너 구현

 - 리스너를 구현하는 클래스를 따로 만들지 않는다.

 - 장점

   별도의 클래스 작성 불필요

   별도의 객체 생성 불필요

 - 단점

   중복된 코드가 많아질 수 있음

public class MainActivity extends AppCompatActivity {

    Button button2, button3;
    @Override
    protected void onCreate(Budgle savedInstanceState) {
    	super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        button2 = findViewById(R.id.button2);
        button3 = findViewById(R.id.button3);
        
        // 각 버튼 위젯별 무명클래스를 이용해서 버튼을 터치할 때 동작하도록 리스너 설정 처리
        button2.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                Toast.makeText(context:MainActivity.this,text:"love",Toast.LENGTH_LONG).show();
                return true;
            }
        });
        
        button3.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                Toast.makeText(context:MainActivity.this,text:"hope",Toast.LENGTH_LONG).show();
                return true;  //반환타입이 boolean이라서 꼭 return 해줘야함.
            }
        }); 
    }
}

 

 

4) 하나의 리스너 객체로 여러 개의 버튼 처리

 - 리스너를 구현하는 클래스를 따로 작성한다.

 - 각 버튼 위젯을 하나의 리스너 객체의 등록하여 사용한다.

 - 이때 버튼을 터치하게 되면 View 클래스의 객체를 매개변수로 받아 콜백 메소드 onTouch()메소드가 실행된다.

 - View 클래스의 getId()메소드를 사용하여 터치된 버튼의 id를 얻을 수 있다. 

 - 획득한 id를 switch구문을 사용하여 터치된 버튼에 따라 각각 실행되도록 한다.

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Budgle savedInstanceState) {
    	super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        findViewById(R.id.b1).setOnClickListener(myClick);
        findViewById(R.id.b2).setOnClickListener(myClick);
        findViewById(R.id.b3).setOnClickListener(myClick);
    }
    // 무명 클래스를 사용해서 리스너 인터페이스를 구현함
    View.OnClickListener myClick = new View.OnClickListener() {
        @Override
    	public void onClick(View v) {
            switch (v.getId()) {
            	case R.id.b1;
                    Toast.makeText(context:MainActivity.this,text:"사랑은 사랑을 낳는다.", Toast.LENGTH_LONG).show();
                    break;
                case R.id.b2;
                    Toast.makeText(context:MainActivity.this,text:"자만은 추락을 가지게 된다.", Toast.LENGTH_LONG).show();
                    break;
                case R.id.b3;
                    Toast.makeText(context:MainActivity.this,text:"일찍 일어나는 새가 벌레를 잡는다.", Toast.LENGTH_LONG).show();
                    break;
            }
        }
    };
}

 

 

5) xml의 onClick 속성을 이용하는 방법

 - xml파일에서 Button 위젯에 속성 onClick 속성 값으로 이벤트를 처리하는 메소드 이름을 적는 방법이다. 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="한국의 수도는?"
        android:onClick="showCapital" />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="한국의 꽃은?"
        android:onClick="showFlower" />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="한국의 제일 큰 강은?"
        android:onClick="showRiver" />

</LinearLayout>
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Budgle savedInstanceState) {
    	super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);     
    }
    
    public void showCaplital(View v) {
		 Toast.makeText(context:MainActivity.this,text:"서울", Toast.LENGTH_SHORT).show();
    }
    public void showFlower(View v) {
		 Toast.makeText(context:MainActivity.this,text:"무궁화", Toast.LENGTH_SHORT).show();
    }
    public void showRiver(View v) {
		 Toast.makeText(context:MainActivity.this,text:"한강", Toast.LENGTH_SHORT).show();
    }
}



뷰의 이벤트 처리 구조

- 뷰의 이벤트 처리는 이벤트 소스와 이벤트 핸들러로 역할이 나뉘며 이 둘을 리스너로 연결해야 이벤트를 처리할 수 있음

  -> 이벤트 소스 : 이벤트가 발생한 객체

  -> 이벤트 핸들러 : 이벤트 발생 시 실행할 로직이 구현된 객체

  -> 리스너 : 이벤트 소스와 이벤트 핸들러를 연결해주는 메소드

 

 - 체크 박스 이벤트 처리

// 동의함 체크박스의 체크가 변경되면
chkAgree.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
        // 체크되면 모두 보이도록 설정
    	if (chkAgree.isChecked() == true) {
            text2.setVisibility(android.view.View.VISIBLE);
            rGroup1.setVisibility(android.view.View.VISIBLE);
            btnOK.setVisibility(android.view.View.VISIBLE);
            imgPet.setVisibility(android.view.View.VISIBLE);
        } else {
            text2.setVisibility(android.view.View.INVISIBLE);
            rGroup1.setVisibility(android.view.View.INVISIBLE);
            btnOK.setVisibility(android.view.View.INVISIBLE);
            imgPet.setVisibility(android.view.View.INVISIBLE);
        }
    }   
});

 

 

 

[출처] Do it! 안드로이드 앱 프로그래밍(도서)

'공부 > 안드로이드' 카테고리의 다른 글

Android - 액티비티 수명 주기  (0) 2022.04.22
Android - 기본  (0) 2022.04.21
Android - 여러 화면 간 전환하기  (0) 2022.04.19
Android - 알림 대화상자 보여주기  (0) 2022.04.18
Android - 드로어블 만들기  (2) 2022.04.18