관리 메뉴

java,javascript,android,php,sql,공부용,메모용

안드로이드 이벤트 처리 TouchEvent, GestureDetector / Android Studio / 안드로이드 앱만들기 공부 13 본문

모바일/안드로이드앱

안드로이드 이벤트 처리 TouchEvent, GestureDetector / Android Studio / 안드로이드 앱만들기 공부 13

yy_dd2 2021. 2. 24. 23:23
반응형

안드로이드의 이벤트 처리 방식

안드로이드는 손가락으로 화면을 터치하는 터치 이벤트 (Touch Event)와

키패드를 누르면 발생하는 키 이벤트 (Key Event)가 있다.

터치 이벤트를 쉽게 처리할 수 있도록 클릭 이벤트(Click Event)를 제공해준다.

OnClickListener 는 이벤트가 발생하면 즉시 동작 할 수 잇도록 만들어준다.

 

 

OnClickListener 패턴 구현

  Button객체   <---   publick boid onClick(View c){
  ...
  }
  OnClickListener 구현 객체
--->   OnclickListener 인터페이스

 

[Code]

boolean onTouchEvent (MotionEvent event)

boolean onKeyDown (int keyCode, KeyEvent event)

boolean onKeyUp (int keyCode, KeyEvent event)

 

화면을 터치하거나 키패드의 키를 하나 누르면 이벤트가 발생하고 파라미터로 필요한 정보들이 전달된다

터치했을 때 발생하는 이벤트는 MotionEvent라 불리며 키를 입력했을 때는 KeyEvent가 전달됩니다.

 

[Code]

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)

 

OnClickListener

- 버튼 같은 객체에 자주 사용된다.

OnTouchListener

- 버튼뿐만 아니라 일반적인 뷰 객체에서도 사용할 수 있다. (사용자와 상호작용이 필요한 경우 많이 사용된다)

- OnTouchListener의 onTouch() 메서드는

  사용자가 손가락으로 터치할 때마다 발생되는 이벤트를 받아서 처리할 수 있다.

OnKeyListener

- OnKeyListener의 OnKey() 메서드는 키 입력이 발생할 때마다 발생되는 이벤트를 받아서 처리함

FocusChange

- OnFocusChangeListener를 사용해 처리한다

 

  속성   설명
  터치 이벤트   화면을 손가락으로 누를 때 발생하는 이벤트
  키 이벤트   키패드나 하드웨어 버튼을 누를 때 발생하는 이벤트
  제스처 이벤트   터치 이벤트 중에서 스크롤과 같이 일정 패턴으로 구분되는 이벤트
  포커스   뷰마다 순서대로 주어지는 포커스
  화면 방향 변경   화면의 방향이 가로와 세로로 바뀜에 따라 발생하는 이벤트

 

Gesture 이벤트

  메서드   이벤트유형
  onDown()   화면이 눌렸을 경우
  onShowPress()   화면이 눌렀다 떼어지는 경우
  onSingleTapUp()   화면이 한 손가락으로 눌렀다 뗴어지는 경우
  onSingleTapConfirmed   화면이 한 손가락으로 눌려지는 경우
  onDoubleTap()   화면이 두 손가락으로 눌려지는 경우
  onDoubleTapEvent()   화면이 두 손가락으로 눌려진 상태에서 떼거나 이동하는 등 세부적인 액션
  onScroll()   화면이 눌린 채 일정한 속도와 방향으로 움직였다 떼는 경우
  onFing()   화면이 눌린 채 가속도를 붙여 손가락을 움직였다 떼는 경우
  onLongPress()   화면을 손가락으로 오래 누르는 경우

제스처 이벤트로 처리하면 단순 터치 이벤트보다 복잡한 이벤트 발동 가능

 


터치 이벤트와 제스쳐 이벤트

1. SampleEvent 프로젝트 생성

2. 최상위 레이아웃 LinearLayout으로 변경

3. 세로로 쌓이도록 LinearLayout의 orientation 속성을 veritcal 변경

- 기본 텍스트뷰 삭제

4. widgets에서 두개의 View / containers 에서 한개의 ScrollView 추가

- 세개의 뷰가 순서대로 공간을 차지하도록 추가

- ScrollView안에 들어 있는 LinearLayout 안에 TextView를 넣어 글자가 보이게 함

- 세개의 뷰를 다 추가하면 layout_height 속성 값을 0dp로 설정

- layout_weight 속성 값은 1로 설정

<?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"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <View
        android:id="@+id/view"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="#2196F3" />

    <View
        android:id="@+id/view2"
        android:layout_width="wrap_content"
        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="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1" />
        </LinearLayout>
    </ScrollView>

</LinearLayout>

 

MainActivity.java

package com.togapp.sampleevent;

import androidx.appcompat.app.AppCompatActivity;

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)
        view.setOnTouchListener(new View.OnTouchListener(){ 
        // 리스너를 등록 하면 뷰가 터치될 때 onTouch() 메서드가 호출된다
           @Override
           public boolean onTouch(View view, MotionEvent motionEvent) {
               int action = motionEvent.getAction();    
               // 액션 정보, 터치한 곳의 좌표 등은 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;
/*
if문은 switch으로도 사용할 수 있다.
               switch (action) {
                   case MotionEvent.ACTION_DOWN :
                       println("손가락 눌림 : " + curX + ", " + curY);
                       break;
               }
               switch (action) {
                   case MotionEvent.ACTION_MOVE :
                       println ("손가락 움직임 : " + curX + ", " + curY );
               }
               switch (action) {
                   case MotionEvent.ACTION_UP :
                       println("손가락 뗌 : " + curX + ", " + curY);
               }
               return true;
 */
           }
        }); // view.setOnTouchListener(); end


        detector = new GestureDetector(this, new GestureDetector.OnGestureListener() {

            @Override
            public boolean onDown(MotionEvent motionEvent) {
                println("onDown() 호출됨.");
                return true;
            }

            @Override
            public void onShowPress(MotionEvent motionEvent) {
                println("onShowPress() 호출됨.");
            }

            @Override
            public boolean onSingleTapUp(MotionEvent motionEvent) {
                println("onSingleTapUp() 호출됨");
                return true;
            }

            @Override
            public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
                println("onScroll() 호출됨.");
                return true;
            }

            @Override
            public void onLongPress(MotionEvent motionEvent) {
                println("onLongPress() 호출됨");
            }

            @Override
            public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
                println("onFling() 호출됨 : " + v + ", " + v1);
                return true;
            }
        });

        View view2 = findViewById(R.id.view2);
        view2.setOnTouchListener(new View.OnTouchListener(){

            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                detector.onTouchEvent(motionEvent);
                return true;
            }
        });

    }

    public void println (String data) {
        textView.append(data + "\n");
    }


}

view에는 터치 이벤트

view.setOnTouchListener(new View.OnTouchListener(){  }) 

이렇게 OnTouchListener()를 등록하면 뷰가 터치될 때 onTouch() 메서드가 호출됨

 

view2에는 제스처 이벤트 적용

view2.setOnTouchListener(new View.OnTouchListener(){  })

터치 이벤트를 GestureDetector로 전달

 

 


키 이벤트 처리하기 

onKeyDown() 메서드를 재정의해서 처리한다

전달되는 파라미터는 두 개이다.

- KeyCode는 어떤 키가 사용되는지 구별할 때 사용

- KeyEvent는 키 입력 이벤트에 대한 정보를 얻고 싶을 때 사용

- 시스템 버튼인 [BACK] 버튼도 이벤트로 처리 가능

- [HOME] 홈화면 이동 버튼과 [Recent Apps] 최근 실행 앱 목록 버튼은 제어는 안되지만 키가 입력되었는지 정보를 받을 수 있다.

 

[Reference]

boolean onKeyDown(int keyCode, KeyEvent event)

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

뷰의 OnKeyListener 의 인터페이스를 구현할 때 onKey()를 사용한다.

 

  키 코드   설명
  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까지의 키 값

 

ex) KEYCODE_CAMERA / 카메라 미리보기를 하면서 사용하는 [카메라] 버튼

ex) KEYCODE_BACK /  시스템 [BACK] 버튼

시스템 [BACK] 버튼 이벤트는 onKeyDown() 메서드를 사용해 간단히 처리할 수 있다.

** onKeyPressed() 메서드만 다시 정의한다면 void onBackPressed()로 처리할 수 있다.

 

MainActivity.java 파일을 열어서 MainActivity 클래스 우클릭 ->  [Generate... -> Override Methods...]

->onKeyDown() 메서드 선택 -> 코드작성

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {

        if(keyCode == KeyEvent.KEYCODE_BACK) {
            Toast.makeText(this, "시스템 [BACK] 버튼이 눌렸습니다.", Toast.LENGTH_SHORT).show();
            return true;
        }

        return false;
        //return super.onKeyDown(keyCode, event);
    }

 

 


코드 전문 MainActivity.java

더보기

 

package com.togapp.sampleevent;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

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)
        view.setOnTouchListener(new View.OnTouchListener(){ // 리스너룰 등록 하면 뷰가 터치될 때 onTouch() 메서드가 호출된다
           @Override
           public boolean onTouch(View view, MotionEvent motionEvent) {
               int action = motionEvent.getAction();    // 액션 정보, 터치한 곳의 좌표 등은 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;
/*
               switch (action) {
                   case MotionEvent.ACTION_DOWN :
                       println("손가락 눌림 : " + curX + ", " + curY);
                       break;
               }
               switch (action) {
                   case MotionEvent.ACTION_MOVE :
                       println ("손가락 움직임 : " + curX + ", " + curY );
               }
               switch (action) {
                   case MotionEvent.ACTION_UP :
                       println("손가락 뗌 : " + curX + ", " + curY);
               }
               return true;
 */
           }
        }); // view.setOnTouchListener(); end


        detector = new GestureDetector(this, new GestureDetector.OnGestureListener() {

            @Override
            public boolean onDown(MotionEvent motionEvent) {
                println("onDown() 호출됨.");
                return true;
            }

            @Override
            public void onShowPress(MotionEvent motionEvent) {
                println("onShowPress() 호출됨.");
            }

            @Override
            public boolean onSingleTapUp(MotionEvent motionEvent) {
                println("onSingleTapUp() 호출됨");
                return true;
            }

            @Override
            public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
                println("onScroll() 호출됨.");
                return true;
            }

            @Override
            public void onLongPress(MotionEvent motionEvent) {
                println("onLongPress() 호출됨");
            }

            @Override
            public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
                println("onFling() 호출됨 : " + v + ", " + v1);
                return true;
            }
        });

        View view2 = findViewById(R.id.view2);
        view2.setOnTouchListener(new View.OnTouchListener(){

            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                detector.onTouchEvent(motionEvent);
                return true;
            }
        });

    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {

        if(keyCode == KeyEvent.KEYCODE_BACK) {
            Toast.makeText(this, "시스템 [BACK] 버튼이 눌렸습니다.", Toast.LENGTH_SHORT).show();
            return true;
        }

        return false;
        //return super.onKeyDown(keyCode, event);
    }

    public void println (String data) {
        textView.append(data + "\n");
    }


}

 

 

 

반응형
Comments