CH Park
by CH Park

Categories

  • Android Application

Tags

  • Android
  • Android Studio
  • Application
  • GestureDetector
  • KeyEvent
  • event
  • onTouchListener


이벤트 처리 방법

  • 클릭 이벤트의 경우 두 가지의 적용 방법이 있다.
    • 버튼 태그에 ‘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까지의 키 값