CHAP 6. 이벤트 처리
폴링과 이벤트 구동 방식
안드로이드에서의 이벤트 처리 방법 뷰 클래스의 이벤트 처리 메소드를 재정의 이벤트 처리 객체를 생성하여 컴포넌트에 등록 커스텀 뷰를 작성하는 경우: (예) 게임 이벤트 처리 객체를 생성하여 컴포넌트에 등록 일반적인 방법
이벤트 처리 메소드 재정의
재정의할 수 있는 콜백 메소드 onKeyDown(int, KeyEvent) onKeyUp(int, KeyEvent) onTrackballEvent(MotionEvent) onTouchEvent(MotionEvent) onFocusChanged(boolean, int, Rect)
예제 ... class MyView extends View { int key; String str; public MyView(Context context) { super(context); setBackgroundColor(Color.YELLOW); } public boolean onKeyDown(int keyCode, KeyEvent event) { str = "" + keyCode; invalidate(); return super.onKeyDown(keyCode, event); @Override protected void onDraw(Canvas canvas) { Paint paint = new Paint(); canvas.drawText("키코드 = " + str, 0, 20, paint);
예제 public class MyViewEventActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MyView w = new MyView(this); w.setFocusable(true); setContentView(w); } …
콜백 메소드를 재정의할 때 편리한 기능 [Source] → [Override/Implements Methods…] 사용!
이벤트 처리 객체 사용 버튼에 붙은 리스너 객체가 이벤트를 처리한다.
리스너의 종류
리스너 객체를 생성하는 방법 리스너 클래스를 내부 클래스로 정의한다. 리스너 클래스를 무명 클래스로 정의한다. 리스너 인터페이스를 액티비티 클래스에 구현한다. 가장 많이 사용되는 방법!
무명 클래스로 이벤트를 처리하는 예제 ... public class ButtonEvent2Activity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new OnClickListener() { public void onClick(View v) { Toast.makeText(getApplicationContext(), "버튼이 눌려졌습니다", Toast.LENGTH_SHORT).show(); } });
무명 클래스 클래스 몸체는 정의되지만 이름이 없는 클래스이다. 무명 클래스는 클래스를 정의하면서 동시에 객체를 생성하게 된다. 무명 클래스는 클래스를 정의하면서 동시에 객체를 생성하게 된다. class ClickListener implements OnClickListener { ... } obj = new ClickListener(); obj = new OnClickListener() { .... };
코드 분석 무명 클래스 사용 ... public class ButtonEvent2Activity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new OnClickListener() { public void onClick(View v) { Toast.makeText(getApplicationContext(), "버튼 눌려졌습니다", Toast.LENGTH_SHORT).show(); } });
XML을 이용한 이벤트 처리 메소드 이름을 적어준다. <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="myClickListener" android:padding="10dp" android:text="버튼을 눌러보세요" /> </LinearLayout> 메소드 이름을 적어준다.
XML을 이용한 이벤트 처리 XML에서 호출된다. ... public class ButtonEvent4Activity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } public void myClickListener(View target) { Toast.makeText(getApplicationContext(), "버튼이 눌려졌습니다", Toast.LENGTH_SHORT).show(); XML에서 호출된다.
폼 위젯
에디트 텍스트 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <EditText android:id="@+id/edittext" android:layout_height="wrap_content" /> </LinearLayout>
에디트 텍스트의 이벤트 처리 ... public class EditTextActivity extends Activity { @Override public void onCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); final EditText edittext = (EditText) findViewById(R.id.edittext); edittext.setOnKeyListener(new OnKeyListener() { public boolean onKey(View v, int keyCode, KeyEvent event) { if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) { Toast.makeText(getApplicationContext(), edittext.getText(), Toast.LENGTH_SHORT).show(); return true; } return false; });
체크 박스 XML로 체크 박스를 선언한다. ... <CheckBox android:id="@+id/checkbox" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="check it out" />
체크박스의 이벤트 처리 ... final CheckBox checkbox = (CheckBox) findViewById(R.id.checkbox); checkbox.setOnClickListener(new OnClickListener() { public void onClick(View v) { // 체크 박스가 클릭되면 호출된다. 체크 여부를 확인한다. if (((CheckBox) v).isChecked()) { Toast.makeText(CheckBoxTest.this, "Selected", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(CheckBoxTest.this, "Not selected", } });
라디오 버튼 XML로 라디오 버튼을 정의한다. ... <RadioGroup android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" > <RadioButton android:id="@+id/radio_red" android:layout_width="wrap_content" android:text="Red"/> android:id="@+id/radio_blue" android:text="Blue"/> </RadioGroup>
라디오 버튼의 이벤트 처리 ... public class RadioButtonTest extends Activity { private OnClickListener radio_listener = new OnClickListener() { public void onClick(View v) { RadioButton rb = (RadioButton) v; Toast.makeText(RadioButtonTest.this, rb.getText(), Toast.LENGTH_SHORT).show(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); final RadioButton red = (RadioButton) findViewById(R.id.radio_red); final RadioButton blue = (RadioButton)findViewById(R.id.radio_blue); red.setOnClickListener(radio_listener); blue.setOnClickListener(radio_listener);
토글 버튼 XML로 라디오 버튼을 정의한다. ... <ToggleButton android:id="@+id/togglebutton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textOn="Vibrate on" android:textOff="Vibrate off" />
토글 버튼 ... final ToggleButton togglebutton = (ToggleButton) findViewById(R.id.togglebutton); togglebutton.setOnClickListener(new OnClickListener(){ public void onClick(View v){ if(togglebutton.isChecked()){ Toast.makeText(ToggleButtonTest.this,"Checked", Toast.LENGTH_SHORT).show(); } else{ Toast.makeText(ToggleButtonTest.this,"Not checked", Toast.LENGTH_SHORT).show() }});
레이팅바 XML로 라디오 버튼을 정의한다. ... <RatingBar android:id="@+id/ratingbar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:numStars="5" android:stepSize="1.0" />
레이팅바 … public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final RatingBar ratingbar = (RatingBar) findViewById(R.id.ratingbar); ratingbar.setOnRatingBarChangeListener(new OnRatingBarChangeListener() { public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) { Toast.makeText(getApplicationContext(), "New Rating: " + rating, Toast.LENGTH_SHORT).show(); } }); }
커스텀 버튼 버튼 위에 텍스트 대신에 이미지가 그려져 있는 버 튼
커스텀 버튼 정의 XML로 버튼에 사용되는 이미지를 등록한다. /res/drawable/android_button.xml <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/android_pressed" android:state_pressed="true" /> <item android:drawable="@drawable/android_focused" android:state_focused="true" /> <item android:drawable="@drawable/android_normal" /> </selector>
레이아웃 파일 레이아웃 파일에 버튼을 정의한다. /res/layout/main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/android_button" android:padding="10dp" /> </LinearLayout>
커스텀 버튼 public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); final Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new OnClickListener() { public void onClick(View v) { Toast.makeText(getApplicationContext(), "Beep Bop", Toast.LENGTH_SHORT).show(); } });
키이벤트 키 이벤트를 받으려면 OnKeyListener 리스너를 구현 키를 누르면 사각형이 이동하는 예제를 작성하여 보 자.
커스텀 뷰를 정의 ... public class KeyEventActivity extends Activity { int x = 100, y = 100; protected class MyView extends View { public MyView(Context context) { super(context); setBackgroundColor(Color.YELLOW); } @Override protected void onDraw(Canvas canvas) { Paint paint = new Paint(); canvas.drawRect(x, y, x+50, y+50, paint);
커스텀 뷰를 정의 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MyView w = new MyView(this); w.setFocusable(true); w.setFocusableInTouchMode(true); setContentView(w); w.setOnKeyListener(new OnKeyListener() { public boolean onKey(View v, int keyCode, KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_UP) { switch (keyCode) { case KeyEvent.KEYCODE_DPAD_LEFT: x -= 30; break; case KeyEvent.KEYCODE_DPAD_RIGHT: x += 30; } v.invalidate(); return true; return false; }); }}
키 포커스 포커스를 가진 위젯 만이 키패드를 통하여 입력을 받을 수 있다.
키 포커스를 위젯에 설정하려면 w.setFocusable(true); w.setFocusableInTouchMode(true);
터치 이벤트 일반적으로 커스텀 뷰를 정의하고 onTouchEvent() 재정의 class MyView extends View { ... @Override public boolean onTouchEvent(MotionEvent event) { x = (int) event.getX(); y = (int) event.getY(); ... }
터치 이벤트의 종류
터치 이벤트 예제 public class TouchEventActivity extends Activity { protected class MyView extends View { int x = 100, y = 100; String str; public MyView(Context context) { super(context); setBackgroundColor(Color.YELLOW); } @Override protected void onDraw(Canvas canvas) { Paint paint = new Paint(); paint.setColor(Color.MAGENTA); canvas.drawRect(x, y, x + 50, y + 50, paint); canvas.drawText("액션의 종류: " + str, 0, 20, paint);
터치 이벤트 예제 @Override public boolean onTouchEvent(MotionEvent event) { x = (int) event.getX(); y = (int) event.getY(); if (event.getAction() == MotionEvent.ACTION_DOWN) str = "ACTION_DOWN"; if (event.getAction() == MotionEvent.ACTION_MOVE) str = "ACTION_MOVE"; if (event.getAction() == MotionEvent.ACTION_UP) str = "ACTION_UP"; invalidate(); return true; } public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MyView w = new MyView(this); setContentView(w);
실행결과