이벤트 처리 방법
- 클릭 이벤트의 경우 두 가지의 적용 방법이 있다.
- 버튼 태그에 ‘onClick’ 속성을 추가하고, 그 안에 소스 코드에서 정의할 메소드를 넣으면 지정이 가능하다.
- XML 파일이 아니라 자바 소스 코드에서 클릭 이벤트를 처리하기 위해서는 버튼의 setOnClickListener() 메소드를 사용한다.
- 이벤트 유형
- 터치 이벤트: 화면을 손가락으로 누를 때 발생하는 이벤트
- 키 이벤트: 키패드나 하드웨어 버튼을 누를 때 발생하는 이벤트
- 제스처 이벤트: 터치 이벤트 중에서 스크롤과 같이 일정 패턴으로 구분되는 이벤트
- 포커스: 뷰마다 순서대로 주어지는 포커스
- 화면 방향 변경: 화면의 방향이 가로와 세로로 바뀜에 따라 발생하는 이벤트
터치 이벤트
<!--[activity_main.xml]-->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<View
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#57B8DD" />
<View
android:id="@+id/view2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#FF9800" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</ScrollView>
</LinearLayout>
<!--[MainActivity.java]-->
package com.example.event;
import androidx.appcompat.app.AppCompatActivity;
import android.gesture.Gesture;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
TextView textView;
GestureDetector detector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
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;
}
});
}
public void println(String data) {
textView.append(data + "\n");
}
}
- 위의 소스 코드는 LinearLayout을 vertical로 삼등분하여 위에 두 개의 View를 놓고 아래에 하나의 스크롤뷰를 둔 것이다. 위의 두 뷰에 onTouchListener를 두고 이 영역에 주어지는 터치에 따라 스크롤뷰의 TextView에 Touch에 대한 내용이 기입된다.
- 영역 구분을 위해 두 개의 View에는 각각 다른 색으로 배경색을 지정하였다.
- 가장 위에 있는 뷰에 setOnTouchListener() 메소드를 호출하고, 이 때 파라미터로 리스너 객체를 전달한다. 그렇게 뷰가 터치가 되면 리스너 객체의 onTouch() 메소드가 자동으로 호출된다.
- onTouch() 메소드로는 MotionEvent 객체가 파라미터로 전달되며, 이 객체에는 액션 정보나 터치한 곳의 좌표를 알 수 있도록 하였다.
- getAction(): 액션 정보 확인
- getX or getY: 터치한 곳의 좌표 확인
- MotionEvent.ACTION_DOWN: 손가락이 눌렸다는 의미의 상수
- MOtionEvent.ACTION_MOVE: 손가락이 눌린 상태로 움직였다는 의미의 상수
- MotionEvent.ACTION_UP: 손가락이 떼졌을 때의 상수
제스쳐 이벤트
<!--[MainActivity.java](터치 이벤트 예시의 onCreate 부분에 추가됨)-->
detector = new GestureDetector(this, new GestureDetector.OnGestureListener() {
@Override
public boolean onDown(MotionEvent e) {
println("onDown() 호출됨.");
return true;
}
@Override
public void onShowPress(MotionEvent e) {
println("onShowPress() 호출됨.");
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
println("onSingleTapUp() 호출됨.");
return true;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
println("onScroll() 호출됨 : " + distanceX + ", " + distanceY);
return true;
}
@Override
public void onLongPress(MotionEvent e) {
println("onLongPress() 호출됨.");
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
println("onFling() 호출됨 : " + velocityX + ", " + velocityY);
return true;
}
});
View view2 = findViewById(R.id.view2);
view2.setOnTouchListener(new View.OnTouchListener(){
@Override
public boolean onTouch(View v, MotionEvent event) {
detector.onTouchEvent(event);
return true;
}
});
- 제스처 이벤트를 처리해주는 클래스는 GestureDetector이다.
- GestureDetector에서 처리할 수 있는 이벤트는 다음과 같다.
- onDown(): 화면이 눌렸을 경우
- onShowPress(): 화면이 눌렸다 떼어지는 경우
- onSingleTapUp(): 화면이 한 손가락으로 눌렸다 떼어지는 경우
- onSingleTapConfirmed(): 화면이 한 손가락으로 눌려지는 경우
- onDoubleTap(): 화면이 두 손가락으로 눌려지는 경우
- onDoubleTapEvenet(): 화면이 두 손가락으로 눌려진 상태에서 떼거나 이동하는 등 세부적인 액션을 취하는 경우
- onScroll(): 화면이 눌린 채 일정한 속도와 방향으로 움직였다 떼는 경우
- onFling(): 화면이 눌린 채 가속도를 붙여 손가락을 움직였다 떼는 경우
- onLongPress(): 화면을 손가락으로 오래 누르는 경우
키 이벤트
<!--[MainActivity.java](MainActivity에 추가)-->
<!--시스템 BACK 키가 눌렸을 때 Toast를 출력하는 예시-->
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
Toast.makeText(this, "시스템 [BACK] 버튼이 눌렸습니다.", Toast.LENGTH_LONG).show();
return true;
}
return false;
}
- 키 이벤트를 처리하는 방법은 두 가지가 있다.
- onKeyDown() 메소드를 재정의하여 처리할 수 있다. 이 때 주어지는 파라미터 두 개 중 keyCode는 어떤 키가 사용되는지 구별할 때 사용되고, KeyEvent는 키 입력 이벤트에 대한 정보를 알고 싶을 때 사용된다.
- 뷰의 OnKeyListener 인터페이스를 구현할 때 onKey() 메소드를 지정하여 처리할 수 있다.
- 키 입력 이벤트는 하드웨어 키보드와 소프트 키패드에 상관 없이 동일한 이벤트로서 전달된다.
- 시스템 버튼인 ‘HOME’, ‘Recent Apps’, ‘BACK’도 모두 이벤트로서 인지가 가능하지만, ‘HOME’과 ‘Recent Apps’의 경우는 앱에서 따로 제어는 불가능하다.
- keyCode 정수 값으로 구분할 수 있는 대표적인 키 값은 아래와 같다.
- KEYCODE_DPAD_LEFT: 왼쪽 화살표
- KEYCODE_DPAD_RIGHT: 오른쪽 화살표
- KEYCODE_DPAD_UP: 위쪽 화살표
- KEYCODE_DPAD_DOWN: 아래쪽 화살표
- KEYCODE_DPAD_CENTER: [중앙] 버튼
- KEYCODE_CALL: [통화] 버튼
- KEYCODE_ENDCALL: [통화 종료] 버튼
- KEYCODE_BACK: [뒤로 가기] 버튼
- KEYCODE_VOLUME_UP: [소리 크기 증가] 버튼
- KEYCODE_VOLUME_DOWN: [소리 크기 감소] 버튼
- KEYCODE_0 ~ KEYCODE_9: 숫자 0부터 9까지의 키 값
- KEYCODE_A ~ KEYCODE_Z: 알파벳 A부터 Z까지의 키 값