출처 : 

http://blog.naver.com/crowdark7?Redirect=Log&logNo=108184807



이벤트 핸들러 - 여러 가지 이벤트

 

요약

터치입력 이벤트콜백 메서드 처리

키보드입력 이벤트콜백 메서드 처리, keyCode속성, KeyEvent속성

위젯 이벤트리스너 구현 (버튼 별 구현 -> 뷰에 구현해 통합 -> 리스너 객체 선언)

포커스 관리모드 별 포커스 설정일반 모드에서 포커스 이동강제 포커스 요청포커스 이벤트

 

터치 입력

 

 터치 입력이란 손가락이나 스타일러스 펜으로 화면을 누르는 터치 동작을 말한다.

 터치 입력에 대한 콜벡 메서드는 해당 뷰에서 재정의 하므로 이벤트 정보만을 가지지만리스너는 여러 대상에 대해 등록이 가능하기 때문에 이벤트 대상인 v를 전달 받는다.

 

 만약 뷰의 onTouchEvent 콜백 메서드가 처리하지 않았을 경우 액티비티의 콜백이 호출된다.

 두 방법의 차이점은 뷰는 뷰에서의 좌표로 인수가 전달되지만 액티비티는 액티비티의 좌상단을 기준으로 인수가 전달되어 오차가 생길 가능성이 크다. (타이틀 바가 있기 때문에)

 

콜백 메서드 이용

boolean onTouchEvent(MotionEvent event)

인터페이스 이용

boolean onTouch(View v, MotionEvent event)

 

위의 MotionEvent 객체는 두 경우 모두 동일한 역할을 하는데 MotionEvent.getAction 메서드는 사용자가 화면에 대고 어떤 것을 했는지에 대한 정보를 전달한다.

 

MotionEvent의 속성

ACTION_DOWN

화면을 누름

ACTION_MOVE

누른채로 움직였다.

ACTION_UP

화면에서 손가락을 뗐다.

 

아래의 코드는 터치하여 누른 채로 움직였을 경우 그 점들을 선으로 이어주는 코드 중 하나이다. onTouchEvent를 재정의 한 것으로 arVertex라는 ArrayList에 이벤트가 일어난 곳의 좌표를 저장하는 과정이다.

 

 

public boolean onTouchEvent(MotionEvent event) {

 

// getAction을 이용해서 현재 어떤 상태인지 알아내고 그 상태가 화면을 누른 것이라면

// 누른 곳의 좌표를 받아서 ArrayList에 저장한다.

 

                     if (event.getAction() == MotionEvent.ACTION_DOWN) {

                               arVertex.add(new Vertex(event.getX(), event.getY(), false));

                               return true;

                     }

 

// 누른 채로 움직였다면 좌표를 추가하고화면에 표시해주기 위해서 invalidate를 이용한다이는 무효화를 통해서 다시 onDraw를 호출하는 기능을 한다.

 

                     if (event.getAction() == MotionEvent.ACTION_MOVE) {

                               arVertex.add(new Vertex(event.getX(), event.getY(), true));

                               invalidate();

                               return true;

                     }

                     return false;

               }

 

 

키보드 입력

 

 모바일 장비에는 문자 입력을 위한 키보드가 필요한데 쿼티 자판을 가진 장비도 있고 간단한 단추만을 가진 장비도 있다이런 키보드를 누를 때의 이벤트는 아래와 같은 메서드가 처리한다.

 

 만약 뷰에서 키 입력을 처리 하지 않으면 액티비티의 콜백 메서드가 처리하게 되어있다키 입력의 경우 뒤로 버튼까지 액티비티의 핸들러가 받아버리므로 특별히 처리해야 하는 곤란함이 있어서 가능하면 뷰에서 처리하는 것이 좋다.

 

콜백 메서드 이용

boolean onKeyDown(int keyCode, keyEvent event)

인터페이스 이용

boolean onKey (View v, int keyCode, keyEvent event)

 

keyCode의 속성

KEYCODE_DPAD_LEFT

좌측 이동

KEYCODE_DPAD_RIGHT

우측 이동

KEYCODE_DPAD_UP

위 이동

KEYCODE_DPAD_DOWN

아래 이동

KEYCODE_DPAD_CENTER

중앙버튼

KEYCODE_A

알파벳 키(A to Z)

KEYCODE_0

숫자 키(0~9)

KEYCODE_CALL

통화

KEYCODE_ENDCALL

통화종료

KEYCODE_HOME

KEYCODE_BACK

뒤로

KEYCODE_VOLUME_UP

볼륨 증가

KEYCODE_VOLUME_DOWN

볼륨 감소

 

KeyEvent의 속성

ACTION_DOWN

키를 눌렀음

ACTION_UP

키를 뗐음

ACTION_MULTIPLE

같은 키를 여러 번 눌름

 

아래의 경우는 콜벡 메서드를 재정의하는 경우이다방향 패드를 누를 때마다 mX 속성을 그에 맞게 바꾸게 된다.

 

 

public boolean onKeyDown(int KeyCode, KeyEvent event) {

                                super.onKeyDown(KeyCode, event);

                                if (event.getAction() == KeyEvent.ACTION_DOWN) {

                                          switch (KeyCode) {

                                          case KeyEvent.KEYCODE_DPAD_LEFT:

                                                     mX-=5;

                                                     invalidate();

                                                     return true;

                                          case KeyEvent.KEYCODE_DPAD_RIGHT:

                                                     mX+=5;

                                                     invalidate();

                                                     return true;

                                          case KeyEvent.KEYCODE_DPAD_UP:

                                                     mY-=5;

                                                     invalidate();

                                                     return true;

                                          case KeyEvent.KEYCODE_DPAD_DOWN:

                                                     mY+=5;

                                                     invalidate();

                                                     return true;

                                          case KeyEvent.KEYCODE_DPAD_CENTER:

                                                     if (mColor == Color.BLUE) {

                                                                mColor = Color.RED;

                                                     } else {

                                                                mColor = Color.BLUE;

                                                     }

                                                     invalidate();

                                                     return true;

                                          }

                                }

                                return false;

                     }

 

 

위젯의 이벤트 처

 

 위젯을 등록할 때는 해당 위젯의 클래스를 사용하는 것이 보통이다. 정해진 위젯의 클래스를 이용하기 때문에 상속을 받지 않고 이벤트를 처리할 수 있어야 하므로 인터페이스를 이용해 리스너로 이벤트를 받아야 한다.

 위젯의 경우 터치와 다르게 어느 좌표에서 터치가 이루어 졌는지 등에 대한 정보가 필요 없으므로 클릭된 뷰를 전달하는 것 외에는 별도의 인수가 없다.

 

 아래는 버튼을 클릭하였을 때 이벤트 처리를 구현한 코드 예제이다각 버튼에 대해서 클릭 이벤트를 정의하였다그런데 버튼이 여러 개일 경우 하는 일은 비슷한데 모두 클릭이벤트를 정해야 한다면 상당히 불편할 것이다.

 

버튼 별 인터페이스 구현

 

public class Fruit extends Activity {

           public void onCreate(Bundle savedInstanceState) {

                     super.onCreate(savedInstanceState);

                     setContentView(R.layout.input_fruit);

 

                     Button btnApple=(Button)findViewById(R.id.apple);

                     btnApple.setOnClickListener(new Button.OnClickListener() {

                                public void onClick(View v) {

                                          TextView textFruit=(TextView)findViewById(R.id.fruit);

                                          textFruit.setText("Apple");

                                }

                     });

 

                     Button btnOrange=(Button)findViewById(R.id.orange);

                     btnOrange.setOnClickListener(new Button.OnClickListener() {

                                public void onClick(View v) {

                                          TextView textFruit=(TextView)findViewById(R.id.fruit);

                                          textFruit.setText("Orange");

                                }

                     });

           }

}

 

뷰에 통합 + 리스너 객체 선언

 비슷한 코드가 반복 되기 때문에 통합한 코드가 바로 아래의 코드이다안드로이드에서는 하나의 리스너를 여러 뷰에 등록하는 것을 허락하기 때문에 통합이 가능하다또한 액티비티는 그대로 두고 리스너 객체를 멤버로 선언한 후에 이것을 리스너로 사용하는 것이 좋다.

(this --> mClickListener)

 

public class Fruit extends Activity {

           public void onCreate(Bundle savedInstanceState) {

                     super.onCreate(savedInstanceState);

                     setContentView(R.layout.input_fruit);

 

                     findViewById(R.id.apple).setOnClickListener(mClickListener);

                     findViewById(R.id.orange).setOnClickListener(mClickListener);

           }

 

           Button.OnClickListener mClickListener = new View.OnClickListener() {

                     public void onClick(View v) {

                                TextView textFruit=(TextView)findViewById(R.id.fruit);

                                switch (v.getId()) {

                                case R.id.apple:

                                          textFruit.setText("Apple");

                                          break;

                                case R.id.orange:

                                          textFruit.setText("Orange");

                                          break;

                                }

                     }

           };

}

 

 

포커스 관리

 

 키보드 이벤트는 포커스를 가지고 있는 뷰에게만 전달이 된다그리고 특정 시점에서 입력을 받을 수 있는 뷰는 하나밖에 없다그래서 포커스는 입력을 받을 뷰가 어떤 것인지 가리키며 다른 뷰와 다르게 표시한다.

 안드로이드에선 일반적으로 버튼은 주황색으로 표현하며 에디트는 경계선이 굵은 주황색으로 표시한다.

 

안드로이드는 포커스를 표시할 때 모드 별로 차이가 있다.

터치 모드에서는 포커스를 표시하지 않고

일반 모드일 때는 포커스를 표시한다일반 모드는 키를 이용해서 이동하게 되는 경우이다.

 

 현재 터치모드인지를 확인하는 메서드는 IsInTouchMode가 있다이 메서드로 현재의 상황을 조사하고 위젯에 포커스가 가능한지 아닌지를 정할 수 있다.

 

모드

XML속성

포커스 설정

포커스 조사

일반

focusable

setFocusable

isFocusable

터치

focusableInTouchMode

setFocusableInTouchMode

isFocusableInTouchMode

 

 만약 위의 setFocusable setFocusableInTouchMode를 생략하면 해당 뷰가 포커스를 받지 못하므로 키 입력이벤트는 전달되지 않는다. setFocusableInTouchMode는 없어도 된다고 생각할 수도 있으나 일반 모드에서 터치 모드로 변경될 때를 위해서 필요하다.

 

일반 모드에서 포커스 이동방식

 

디폴트

키보드를 이용해서 이동하게 되면 가장 가까운 위젯으로 포커스를 옮기게 되어 있다.

최초 실행 시에 터치모드라면 아무도 포커스를 가지지 않고

일반 모드라면 첫 번째 위젯이 포커스를 가진다.

 

특정 이동 지정

속성

메서드

설명

nextFocusLeft

setNextFocusLeftId

왼쪽 이동 시의 위젯

nextFocusRight

setNextFocusRightId

오른쪽 이동 시의 위젯

nextFocusUp

setNextFocusUpId

위쪽 이동 시의 위젯

nextFocusDown

setNextFocusDownId

아래쪽 이동 시의 위젯

 

특정 뷰로 강제 포커스 이동

이럴 경우는 원하는 뷰의 requestFocus 메서드를 호출하면 된다.

포커스 변경 시에는 onFocusChanged이벤트가 발생하는데 포커스가 변경하게 될 경우에 수행하게 되는 동작을 처리한다포커스 이동을 하게 되면 별표로 강조를 하는 경우이 이벤트 핸들러를 사용해서 변경시키는 것이다.

 

*본 포스트는 김상형 저, <안드로이드 프로그래밍 정복>, 한빛미디어를 참고하였습니다. 

책에서는 더 많은 내용을 보실 수 있습니다. 안적은 것들이 많아요 ㅠㅠ

+ Recent posts