Handling UI Events

On Android, there's more than one way to intercept the events from a user's interaction with your application. When considering events within your user interface, the approach is to capture the events from the specific View object that the user interacts with. The View class provides the means to do so.

안드로이드에는, 여러분의 애플리케이션과 사용자 간의 상호작용으로부터 이벤트를 가로채기 위한 한 가지 이상의 방법이 있다. 여러분의 사용자 인터페이스 내의 이벤트를 고려할 때, 그 접근법은 사용자가 상호작용하는 특정 뷰 오브젝트의 이벤트를 획득하는 것이다. 뷰 클래스는 그렇게 하기 위한 수단을 제공한다.

Within the various View classes that you'll use to compose your layout, you may notice several public callback methods that look useful for UI events. These methods are called by the Android framework when the respective action occurs on that object. For instance, when a View (such as a Button) is touched, the onTouchEvent() method is called on that object. However, in order to intercept this, you must extend the class and override the method. However, extending every View object in order to handle such an event would not be practical. This is why the View class also contains a collection of nested interfaces with callbacks that you can much more easily define. These interfaces, called event listeners, are your ticket to capturing the user interaction with your UI.

레이아웃을 구성하기 위해 사용하는 다양한 뷰 클래스 안에서, 여러분은 아마도 UI 이벤트를 처리하는 데 도움이 되는 몇 가지 퍼블릭public 콜백 메쏘드를 주목할 것이다. 이러한 메쏘드들은 그 오브젝트에 각각의 액션이 발생할 때, 안드로이드 프레임워크에 의해 호출된다. 예를 들어 버튼과 같은 뷰가 터치되게 될 때, onTouchEvent() 메쏘드가 그 오브젝트에서 호출된다. 하지만 이것을 가로채기 위해서는 해당 클래스를 확장extend해서 메쏘드를 오버라이드해야 한다. 명백하게 (단지 이벤트만을 제어하기 위해) 여러분이 사용하고자 하는 모든 뷰 오브젝트를 확장하는 것은 불합리할 수 있다. 이것이 뷰View 클래스가 여러분이 훨씬 더 쉽게 정의할 수 있는 콜백을 가진 네스티드nested 인터페이스 모음을 또한 포함하는 이유이다. 이벤트 리스너event listener라고 불리는 이러한 인터페이스들은 여러분의 UI와의 사용자 간의 상호작용을 캡쳐하기 위한 여러분의 티켓이다.

While you will more commonly use the event listeners to listen for user interaction, there may come a time when you do want to extend a View class, in order to build a custom component. Perhaps you want to extend the Button class to make something more fancy. In this case, you'll be able to define the default event behaviors for your class using the class event handlers.

여러분은 사용자와의 상호작용을 청취하기 위해 보다 일반적으로는 이벤트 리스너를 사용하려 하겠지만, 커스텀 컴포넌트를 만들기 위해 뷰 클래스를 확장하고자 할 때가 있을 수 있다. 아마 여러분은 버튼을 더 보기 좋게 하기 위해 버튼Button 클래스를 확장extend하고자 할 수 있다. 이런 경우에, 여러분은 이벤트 핸들러event handler 클래스를 사용하여 여러분의 클래스에 대한 디폴트 이벤트 동작구조를 정의할 수 있을 것이다.

Event Listeners

An event listener is an interface in the View class that contains a single callback method. These methods will be called by the Android framework when the View to which the listener has been registered is triggered by user interaction with the item in the UI.

이벤트 리스너listener는 하나의 콜백 메쏘드를 포함하는 뷰 클래스 내의 인터페이스이다. 이 메쏘드는 리스너가 등록된 뷰의 UI 내의 아이템과 사용자 간의 상호작용이 발생할 때, 안드로이드 프레임워크에 의해 호출된다.

Included in the event listener interfaces are the following callback methods:

아래의 콜백 메쏘드들이 이벤트 리스너 인터페이스에 포함된다.

onClick()
From View.OnClickListener. This is called when the user either touches the item (when in touch mode), or focuses upon the item with the navigation-keys or trackball and presses the suitable "enter" key or presses down on the trackball.
onLongClick()
From View.OnLongClickListener. This is called when the user either touches and holds the item (when in touch mode), or focuses upon the item with the navigation-keys or trackball and presses and holds the suitable "enter" key or presses and holds down on the trackball (for one second).
onFocusChange()
From View.OnFocusChangeListener. This is called when the user navigates onto or away from the item, using the navigation-keys or trackball.
onKey()
From View.OnKeyListener. This is called when the user is focused on the item and presses or releases a key on the device.
onTouch()
From View.OnTouchListener. This is called when the user performs an action qualified as a touch event, including a press, a release, or any movement gesture on the screen (within the bounds of the item).
onCreateContextMenu()
From View.OnCreateContextMenuListener. This is called when a Context Menu is being built (as the result of a sustained "long click"). See the discussion on context menus in Creating Menus for more information.
onClick()
View.OnClickListener로부터 콜백됨. 이것은 터치모드일 때 사용자가 아이템을 터치하거나 또는 네비게이션 키나 트랙볼trackball로 그 아이템을 포커스하여 “enter” 키를 누르거나 트랙볼을 눌렀을 때 호출된다.
onLongClick()
View.OnFocusChangeListener로부터 콜백됨. 이것은 터치모드일 때 사용자가 아이템을 터치해서 잡거나 또는 네비게이션-키나 트랙볼trackball로 해당 아이템을 포커스하여 적당한 “enter” 키를 누르고 있거나 또는 1초동안 트랙볼을 누르고 있을 때 호출된다.
onFocusChange()
View.OnFocusChangeListener로부터 콜백됨. 이것은 사용자가 네비게이션-키 또는 트랙볼trackball을 사용하여 아이템 위로 움직이거나, 또는 그것으로부터 벗어날 때 호출된다.
onKey()
View.OnKeyListener로부터 콜백됨. 이것은 사용자가 아이템을 포커스를 하여, 디바이스에 있는 키를 누르거나 놓았을 때 호출된다.
onTouch()
View.OnTouchListener로부터 콜백됨. 이것은 사용자가 아이템의 경계내에서 스크린을 누르고, 놓고, 또는 어떤 움직임 행위를 포함하는 터치 이벤트로써 적격한 액션을 수행할 때 호출된다.
onCreateContextMenu()
View.OnCreateContextMenuListener로부터 콜백됨. 이것은 일관된 “오랜시간 클릭long click”의 결과로, 컨텍스트 메뉴가 만들어져 있을 때 호출된다. 컨텍스트 메뉴에 대한 더 많은 정보에 대해서는 “메뉴 생성하기”를 보라.

These methods are the sole inhabitants of their respective interface. To define one of these methods and handle your events, implement the nested interface in your Activity or define it as an anonymous class. Then, pass an instance of your implementation to the respective View.set...Listener() method. (E.g., call setOnClickListener() and pass it your implementation of the OnClickListener.)

이러한 메쏘드들은 그것들에 대응되는 인터페이스에 대한 단독 상주물sole inhabitant이다. 이러한 메쏘드 중 하나를 정의하고 여러분의 이벤트를 처리하기 위해, 여러분의 액티비티 내에 네스티드nested된 인터페이스를 구현하거나 익명의 클래스로 그것을 정의하라. 그런 다음에, 대응되는 View.set...Listener() 메쏘드에 여러분이 구현한 것을 파라미터로 전달하라(예를 들어 setOnClickListener()를 호출하고, 그것에 여러분이 구현한 OnClickListener를 파라미터로 전달하라).

The example below shows how to register an on-click listener for a Button.

아래의 예제는, 버튼에 대한 on-click 리스너를 등록하는 방법을 보여준다.

// Create an anonymous implementation of OnClickListener
private OnClickListener mCorkyListener = new OnClickListener() {
    public void onClick(View v) {
      // do something when the button is clicked
    }
};

protected void onCreate(Bundle savedValues) {
    ...
    // Capture our button from layout
    Button button = (Button)findViewById(R.id.corky);
    // Register the onClick listener with the implementation above
    button.setOnClickListener(mCorkyListener);
    ...
}

You may also find it more convenient to implement OnClickListener as a part of your Activity. This will avoid the extra class load and object allocation. For example:

여러분은 또한 OnClickListener를 액티비티의 일부로써 구현하는 것이 더 편리하다는 것을 아마도 알게 될 것이다. 이것은 별도의 클래스 로드load와 오브젝트 할당을 피할 것이다. 예를 들어 다음과 같다.

public class ExampleActivity extends Activity implements OnClickListener {
    protected void onCreate(Bundle savedValues) {
        ...
        Button button = (Button)findViewById(R.id.corky);
        button.setOnClickListener(this);
    }

    // Implement the OnClickListener callback
    public void onClick(View v) {
      // do something when the button is clicked
    }
    ...
}

Notice that the onClick() callback in the above example has no return value, but some other event listener methods must return a boolean. The reason depends on the event. For the few that do, here's why:

앞에 있는 예제 안의 onClick() 콜백은 어떤 리턴 값도 가지지 않음에 주의하라. 하지만 다른 어떤 이벤트 리스너 메쏘드는 불리언Boolean 값을 반환해야 한다. 그 이유는 해당 이벤트에 의존한다. 그렇게 하는 몇가지 것에 대한 이유가 여기 있다.

  • onLongClick() - This returns a boolean to indicate whether you have consumed the event and it should not be carried further. That is, return true to indicate that you have handled the event and it should stop here; return false if you have not handled it and/or the event should continue to any other on-click listeners.
  • onKey() - This returns a boolean to indicate whether you have consumed the event and it should not be carried further. That is, return true to indicate that you have handled the event and it should stop here; return false if you have not handled it and/or the event should continue to any other on-key listeners.
  • onTouch() - This returns a boolean to indicate whether your listener consumes this event. The important thing is that this event can have multiple actions that follow each other. So, if you return false when the down action event is received, you indicate that you have not consumed the event and are also not interested in subsequent actions from this event. Thus, you will not be called for any other actions within the event, such as a fingure gesture, or the eventual up action event.
  • onLongClick() - 이것은 여러분이 그 이벤트를 소비해서 그것이 더 이상 전달되어서는 안되는지 여부를 가리키는 불리언Boolean 값을 리턴한다. 그것은 여러분이 그 이벤트를 처리해서 그것이 여기에서 멈춰야 한다는 것을 가리키기 위해서는 참true을 리턴한다. 만약 여러분이 그것을 처리하지 않았다면, 그리고/또는 그 이벤트가 어떤 다른 on-click 리스너에게 계속되어야 한다면 거짓false을 리턴한다.
  • onKey() - 이것은 여러분이 그 이벤트를 소비해서 그것이 더 이상 전달되어서는 안되는지 여부를 가리키는 불리언Boolean 값을 리턴한다. 그것은 여러분이 해당 이벤트를 처리해서 그것이 여기에서 멈춰야한다는 것을 가리키기 위해서는 참true를 리턴한다. 만약 여러분이 그것을 처리하지 않았다면, 그리고/또는 그 이벤트가 어떤 다른 on-key 리스너에게 계속되어야 한다면 거짓false를 리턴한다.
  • onTouch() - 이것은 여러분이 그 이벤트를 사용했는지 여부를 가리키는 불리언Boolean 값을 리턴한다. 중요한 것은, 이 이벤트는 각기 다른 것을 수반하는 복수의 액션을 가질 수 있다는 것이다. 그러므로 여러분이 다운down 액션 이벤트가 수신될 때 거짓false을 리턴하면, 여러분은 그 이벤트를 사용하지 않았고, 또한 이 이벤트에 수반되는 액션에 관심이 없음을 가리킨다. 따라서, 여러분은 손가락 제스쳐gesture나 업up 액션 이벤트와 같은 어떤 다른 액션도 그 이벤트 내에서 호출받지 못할 것이다.

Remember that key events are always delivered to the View currently in focus. They are dispatched starting from the top of the View hierarchy, and then down, until they reach the appropriate destination. If your View (or a child of your View) currently has focus, then you can see the event travel through the dispatchKeyEvent() method. As an alternative to capturing key events through your View, you can also receive all of the events inside your Activity with onKeyDown() and onKeyUp().

핵심key 이벤트들이 항상 현재 포커스되어 있는 뷰에 전달된다는 것을 잊지 말아라. 그것들은 뷰 계층구조의 최상위에서 시작해서, 그것이 적절한 목적지에 도착할 때까지 내려가면서 전달dispatch된다. 만약 현재 여러분의 뷰 또는 그 뷰의 자식child이 포커스를 가지고 있다면, 여러분은 dispatchKeyEvent() 메쏘드를 통해 이벤트 전달 경로를 볼 수 있다. 여러분의 뷰에서 키 이벤트들을 얻기 위한 별도의 대안으로써, 여러분은 또한 onKeyDown()와 onKeyUp()를 사용해서 여러분의 액티비티 내부의 모든 키Key 이벤트를 수신할 수 있다.

Note: Android will call event handlers first and then the appropriate default handlers from the class definition second. As such, returning true from these event listeners will stop the propagation of the event to other event listeners and will also block the callback to the default event handler in the View. So be certain that you want to terminate the event when you return true.

Note: 안드로이드는 첫 번째로 이벤트 핸들러를 호출할 것이다. 그리고 나서 그 클래스 정의로 부터 적합한 디폴트 핸들러를 두 번째로 호출할 것이다. 따라서, 이러한 이벤트 리스너로부터 참true을 리턴하는 것은 다른 이벤트 리스너들에게 이벤트를 전달하는 것을 중지시킬 것이며, 뷰에 있는 기본 이벤트 핸들러에 대한 콜백도 차단할 것이다. 그러므로 여러분이 참true을 리턴할 때, 여러분이 이벤트를 종료시키길 원하는 지를 확인하라.

Event Handlers

If you're building a custom component from View, then you'll be able to define several callback methods used as default event handlers. In the document on Building Custom Components, you'll learn see some of the common callbacks used for event handling, including:

만약 여러분이 뷰View에 대한 커스텀 컴포넌트를 만든다면, 여러분은 디폴트 이벤트 핸들러로 사용되는 몇몇 콜백 메쏘드를 정의하는 것이 가능할 것이다. “커스텀 컴포넌트 만들기” 섹션에서, 여러분은 아래와 같은 이벤트 처리를 위해 사용되는 몇 가지 일반적인 콜백들을 보고 배울 것이다.

  • onKeyDown(int, KeyEvent) - 신규 키 이벤트가 발생할 때 호출된다.
  • onKeyUp(int, KeyEvent) - 키 업(up) 이벤트가 발생할 때 호출된다.
  • onTrackballEvent(MotionEvent) - 트랙볼trackball 모션 이벤트가 발생할 때 호출된다.
  • onTouchEvent(MotionEvent) - 터치 스크린 모션 이벤트가 발생할 때 호출된다.
  • onFocusChanged(boolean, int, Rect) - 뷰가 포커스를 얻거나 잃게될 때 호출된다.

There are some other methods that you should be aware of, which are not part of the View class, but can directly impact the way you're able to handle events. So, when managing more complex events inside a layout, consider these other methods:

여러분이 알아야 하는 약간의 그 밖의 메쏘드들이 있다. 그것은 뷰 클래스의 일부분은 아니지만, 이벤트를 처리할 수 있는 방법에 직접적으로 영향을 미칠 수 있다. 그러므로 레이아웃 내부에서 보다 더 복잡한 이벤트를 관리할 때, 이러한 또 다른 메쏘드들을 고려하라.

  • Activity.dispatchTouchEvent(MotionEvent) - 이것은 터치 이벤트가 윈도우로 전달되기 전에 여러분의 액티비티가 그것들을 가로채는 것을 허용한다.
  • ViewGroup.onInterceptTouchEvent(MotionEvent) - 이것은 이벤트가 자식child 뷰에게 전달될 때 해당 이벤트를 그것의 부모parent 뷰가 감시하는 것을 허용한다.
  • ViewParent.requestDisallowInterceptTouchEvent(boolean) - 부모 뷰가 onInterceptTouchEvent(MotionEvent)를 사용해서 터치 이벤트를 가로채서는 안된다는 것을 가리키기 위해서는 이것을 호출하라.

Touch Mode

When a user is navigating a user interface with directional keys or a trackball, it is necessary to give focus to actionable items (like buttons) so the user can see what will accept input. If the device has touch capabilities, however, and the user begins interacting with the interface by touching it, then it is no longer necessary to highlight items, or give focus to a particular View. Thus, there is a mode for interaction named "touch mode."

사용자가 방향 키 또는 트랙볼을 사용해서 사용자 인터페이스를 네비게이션할 때, 입력을 받아들일 수 있는 것을 사용자가 볼 수 있도록 하기 위해 버튼과 같이 액션이 가능한 아이템에 포커스를 주는 것이 필요하다. 하지만 만약 디바이스가 터치 기능을 가지고 있고 사용자가 그 디바이스를 터치함으로써 인터페이스와 상호작용을 시작한다면, 더 이상 아이템들을 하이라이트하거나 특정 뷰에 포커스를 줄 필요는 없다. 따라서 “터치 모드touch mode”라고 명명된 상호작용에 대한 모드가 있다.

For a touch-capable device, once the user touches the screen, the device will enter touch mode. From this point onward, only Views for which isFocusableInTouchMode() is true will be focusable, such as text editing widgets. Other Views that are touchable, like buttons, will not take focus when touched; they will simply fire their on-click listeners when pressed.

터치 기능을 가진 디바이스에서, 일단 사용자가 스크린을 터치하면 디바이스는 터치 모드로 진입하게 될 것이다. 이 시점부터는, 텍스트 편집 위젯과 같이 isFocusableInTouchMode()가 참true인 뷰들만이 포커스될 것이다. 버튼들과 같이 터치가 가능한 그 밖의 뷰들은 터치되었을 때, 포커스를 가지지 않을 것이다; 그것들이 눌려질 때, 그것들은 자신의 on-click 리스너를 간단하게 실행할 것이다.

Any time a user hits a directional key or scrolls with a trackball, the device will exit touch mode, and find a view to take focus. Now, the user may resume interacting with the user interface without touching the screen.

사용자가 방향 키를 누르거나 또는 트랙볼을 가지고 스크롤을 하면 언제든 해당 디바이스는 터치모드를 빠져나갈 것이고, 그리고 나서 포커스를 가질 뷰를 찾을 것이다. 이제 사용자는 스크린 터치없이 사용자 인터페이스와의 상호작용을 재개resume할 수 있다.

The touch mode state is maintained throughout the entire system (all windows and activities). To query the current state, you can call isInTouchMode() to see whether the device is currently in touch mode.

터치 모드 상태는 전체 시스템(모든 윈도우들과 액티비티들)에 걸쳐 유지된다. 여러분은 현재 상태를 질의query하기 위해, 해당 디바이스가 현재 터치 모드에 있는지 여부를 알 수 있게 해 주는 isInTouchMode()를 호출할 수 있다.

Handling Focus

The framework will handle routine focus movement in response to user input. This includes changing the focus as Views are removed or hidden, or as new Views become available. Views indicate their willingness to take focus through the isFocusable() method. To change whether a View can take focus, call setFocusable(). When in touch mode, you may query whether a View allows focus with isFocusableInTouchMode(). You can change this with setFocusableInTouchMode().

프레임워크는 사용자 입력에 반응하여 일상적인 포커스 움직임을 처리할 것이다. 이것은 뷰가 제거되거나 숨겨질 때 또는 새로운 뷰가 존재할 때, 포커스를 변경하는 것을 포함한다. 뷰는 isFocusable() 메쏘드를 통해 포커스를 가지고자 하는 의향이 있는가를 표현한다. 뷰가 포커스를 가질 수 있는지 없는지를 변경시키기 위해서 setFocusable()을 호출한다. 터치 모드일 때, 여러분은 isFocusableInTouchMode()를 사용해서 뷰가 포커스를 허용하는 지 여부를 질의query할 수 있다. 여러분은 setFocusableInTouchMode()를 가지고 이것을 바꿀 수 있다.

Focus movement is based on an algorithm which finds the nearest neighbor in a given direction. In rare cases, the default algorithm may not match the intended behavior of the developer. In these situations, you can provide explicit overrides with the following XML attributes in the layout file: nextFocusDown, nextFocusLeft, nextFocusRight, and nextFocusUp. Add one of these attributes to the View from which the focus is leaving. Define the value of the attribute to be the id of the View to which focus should be given. For example:

포커스 이동은 주어진 방향에서 가장 가깝게 인접한 것을 찾는 알고리즘에 기반한다. 특이한 경우, 디폴트 알고리즘은 개발자가 의도했던 동작과 일치하지 않을 수 있다. 이런 상황에서, 여러분은 레이아웃 파일 안에서 nextFocusDown, nextFocusLeft, nextFocusRight, nextFocusUp과 같은 XML 애트리뷰트를 사용해서 명시적인 오버라이드를 제공할 수 있다. 포커스가 떠나게 되는 뷰에 이러한 애트리뷰트 중 하나를 추가하라. 그 애트리뷰트의 값은 포커스가 건네져야 하는 뷰의 id가 되도록 정의하라. 예를 들어 다음과 같다.

<LinearLayout
    android:orientation="vertical"
    ... >
  <Button android:id="@+id/top"
          android:nextFocusUp="@+id/bottom"
          ... />
  <Button android:id="@+id/bottom"
          android:nextFocusDown="@+id/top"
          ... />
</LinearLayout>

Ordinarily, in this vertical layout, navigating up from the first Button would not go anywhere, nor would navigating down from the second Button. Now that the top Button has defined the bottom one as the nextFocusUp (and vice versa), the navigation focus will cycle from top-to-bottom and bottom-to-top.

보통 위와 같은 버티컬vertical 레이아웃에서는, 첫 번째 버튼으로부터 위로 움직여서는 어디로도 갈 수 없고, 두 번째 버튼으로부터 아래로 움직여서도 어디로도 갈 수 없다. 이제 최상위 버튼은 nextFocusUp으로 아래쪽 버튼을 정의했고 그 반대도 마찬가지이기 때문에, 네비게이션 포커스는 위로부터 아래로top-to-bottom 그리고 아래로부터 위로bottom-to-top 사이클cycle을 돌 것이다.

If you'd like to declare a View as focusable in your UI (when it is traditionally not), add the android:focusable XML attribute to the View, in your layout declaration. Set the value true. You can also declare a View as focusable while in Touch Mode with android:focusableInTouchMode.

만약 UI에서 (전통적으로는 포커스가 되지 않지만) 뷰를 포커스 가능한 것으로 선언하고 싶다면 여러분의 레이아웃 선언에 android:focusable XML 애트리뷰트를 뷰에 추가하라. 그리고 값을 참true로 설정하라. 여러분은 또한 android:focusableIn TouchMode를 사용해서 터치모드 동안에도 뷰를 포커스 가능한 것으로 선언할 수 있다.

To request a particular View to take focus, call requestFocus().

특정 뷰가 포커스를 가지도록 요청하기 위해서는, requestFocus()를 호출하라.

To listen for focus events (be notified when a View receives or looses focus), use onFocusChange(), as discussed in the Event Listeners section, above.

(뷰가 포커스를 얻거나 놓을 때 통보되는) 포커스 이벤트를 청취할려면, 위의 이벤트 리스너 섹션에서 설명된 것과 같이 onFocusChange()를 사용하라.

↑ Go to top

← Back to User Interface