| page.title=입력 이벤트 |
| parent.title=사용자 인터페이스 |
| parent.link=index.html |
| @jd:body |
| |
| <div id="qv-wrapper"> |
| <div id="qv"> |
| <h2>이 문서의 내용</h2> |
| <ol> |
| <li><a href="#EventListeners">이벤트 수신기</a></li> |
| <li><a href="#EventHandlers">이벤트 처리기</a></li> |
| <li><a href="#TouchMode">터치 모드</a></li> |
| <li><a href="#HandlingFocus">초점 처리하기</a></li> |
| </ol> |
| |
| </div> |
| </div> |
| |
| <p>Android에는 사용자와 애플리케이션의 상호 작용으로부터 이벤트를 가로채는 방법이 여러 가지 있습니다. |
| 사용자 인터페이스 내의 이벤트가 관련된 경우, 이러한 방식은 이벤트를 사용자가 상호 작용하는 |
| 특정 보기 객체로부터 캡처하는 것입니다. 이에 필요한 수단은 보기 클래스가 제공합니다.</p> |
| |
| <p>레이아웃을 작성하는 데 사용하게 되는 여러 가지 보기 클래스 안을 보면 UI 이벤트에 유용해 보이는 공개 콜백 |
| 메서드가 여러 개 있는 것이 눈에 띕니다. 이러한 메서드는 해당 객체에서 각각의 작업이 발생할 때 Android 프레임워크가 |
| 호출하는 것입니다. 예를 들어 보기(예: 버튼)를 하나 터치하면 |
| 해당 객체에서 <code>onTouchEvent()</code> 메서드가 호출됩니다. 그러나 이것을 가로채려면 클래스를 확장하고 |
| 메서드를 재정의해야 합니다. 다만 그런 이벤트를 처리하기 위해 모든 보기 객체를 |
| 다 확장하는 것은 타당성이 없습니다. 이 때문에 보기 클래스에 |
| 일련의 중첩된 인터페이스가 있고 거기에 훨씬 쉽게 정의할 수 있는 콜백에 있습니다. 이와 같은 |
| 인터페이스를 일명 <a href="#EventListeners">이벤트 수신기</a>라고 하는데, 이것이 UI와 사용자 상호 작용을 캡처하는 데 아주 적합합니다.</p> |
| |
| <p>사용자 상호 작용을 수신 대기하는 데에는 이벤트 수신기를 사용하는 것이 좀 더 보편적이지만, 사용자 지정 |
| 구성 요소를 구축하기 위해 보기 클래스를 확장하고자 하는 상황이 올 수도 있습니다. |
| 어쩌면 {@link android.widget.Button} |
| 클래스를 확장하여 무언가 더 복잡한 것을 만들고자 할 수도 있습니다. 이런 경우, 클래스에 대한 기본 이벤트 행동을 클래스 |
| <a href="#EventHandlers">이벤트 처리기</a>를 사용하여 정의할 수 있습니다.</p> |
| |
| |
| <h2 id="EventListeners">이벤트 수신기</h2> |
| |
| <p>이벤트 수신기란 {@link android.view.View} 클래스 내에 있는 일종의 인터페이스로, 이 안에 하나의 |
| 콜백 메서드가 들어있습니다. 이러한 메서드는 수신기가 등록된 보기가 UI 안의 항목과 사용자의 상호 작용으로 인하여 트리거되었을 때 |
| Android 프레임워크가 호출하는 것입니다.</p> |
| |
| <p>이벤트 수신기 인터페이스에 포함된 콜백 메서드는 다음과 같습니다.</p> |
| |
| <dl> |
| <dt><code>onClick()</code></dt> |
| <dd>{@link android.view.View.OnClickListener}에서 온 것입니다. |
| 이것이 호출되는 것은 사용자가 항목을 터치하거나 |
| (터치 모드에 있을 때), 탐색 키 또는 트랙볼을 사용하여 해당 항목에 초점을 맞추고 있으면서 |
| 적절한 "엔터" 키를 누르거나 트랙볼을 꾹 누를 때입니다.</dd> |
| <dt><code>onLongClick()</code></dt> |
| <dd>{@link android.view.View.OnLongClickListener}에서 온 것입니다. |
| 이것이 호출되는 것은 사용자가 항목을 길게 누르거나(터치 모드에 있을 때), |
| 탐색 키 또는 트랙볼을 사용하여 해당 항목에 초점을 맞추고 있으면서 |
| 적절한 "엔터" 키를 누르거나 트랙볼을 꾹 누를 때입니다(일 초간).</dd> |
| <dt><code>onFocusChange()</code></dt> |
| <dd>{@link android.view.View.OnFocusChangeListener}에서 온 것입니다. |
| 이것이 호출되는 것은 사용자가 탐색 키 또는 트랙볼을 사용하여 항목 쪽으로 이동하거나 항목에서 멀어질 때입니다.</dd> |
| <dt><code>onKey()</code></dt> |
| <dd>{@link android.view.View.OnKeyListener}에서 온 것입니다. |
| 이것이 호출되는 것은 사용자가 항목에 초점을 맞추고 있으면서 기기에 있는 하드웨어 키를 누르거나 키에서 손을 떼는 경우입니다.</dd> |
| <dt><code>onTouch()</code></dt> |
| <dd>{@link android.view.View.OnTouchListener}에서 온 것입니다. |
| 이것이 호출되는 것은 사용자가 터치 이벤트로서의 자격을 만족하는 작업을 수행하는 경우로, 여기에 |
| 누르기, 손 떼기와 화면에서 이루어지는 모든 움직임 동작(항목의 경계 내에서)이 포함됩니다.</dd> |
| <dt><code>onCreateContextMenu()</code></dt> |
| <dd>{@link android.view.View.OnCreateContextMenuListener}에서 온 것입니다. |
| 이것을 호출하는 것은 컨텍스트 메뉴가 구축되는 중일 때입니다(정체된 "롱 클릭"의 결과로). |
| <a href="{@docRoot}guide/topics/ui/menus.html#context-menu">메뉴</a> |
| 개발자 가이드에 있는 컨텍스트 메뉴 관련 논의를 참조하십시오.</dd> |
| </dl> |
| |
| <p>이러한 메서드는 각자의 인터페이스 안에 거주하는 유일한 주민입니다. 이러한 메서드 중 하나를 |
| 정의하고 이벤트를 처리하려면 액티비티 내의 중첩된 인터페이스를 구현하거나 익명의 클래스로 정의하면 됩니다. |
| 그런 다음 구현의 인스턴스 하나를 |
| 각각의 <code>View.set...Listener()</code> 메서드에 전달하십시오 (예: |
| <code>{@link android.view.View#setOnClickListener(View.OnClickListener) setOnClickListener()}</code>를 |
| 호출한 다음 이를 {@link android.view.View.OnClickListener OnClickListener}의 구현에 전달합니다).</p> |
| |
| <p>아래의 예시는 버튼에 대하여 온-클릭 수신기를 등록하는 방법을 나타낸 것입니다. </p> |
| |
| <pre> |
| // 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); |
| ... |
| } |
| </pre> |
| |
| <p>OnClickListener를 액티비티의 일부로 구현하는 것이 더 편리할 수도 있습니다. |
| 이렇게 하면 클래스 부하와 객체 할당이 추가되는 것을 피할 수 있습니다. 예:</p> |
| <pre> |
| 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 |
| } |
| ... |
| } |
| </pre> |
| |
| <p>위의 예시에서 <code>onClick()</code> 콜백에는 |
| 반환 값이 없지만 다른 이벤트 수신기 메서드 중에는 부울 값을 반환해야만 하는 것도 있다는 점을 유의하십시오. 그 이유는 이벤트에 따라 |
| 다릅니다. 이런 필수 사항이 적용되는 몇몇 메서드의 경우, 이유는 다음과 같습니다.</p> |
| <ul> |
| <li><code>{@link android.view.View.OnLongClickListener#onLongClick(View) onLongClick()}</code> - |
| 이것은 부울 값을 반환하여 이벤트를 완전히 사용하였으며 더 이상 이를 담지 않아도 되는지 여부를 나타냅니다. |
| 다시 말해, <em>참</em>을 반환하면 이벤트를 처리했으며 여기에서 중단해야 한다는 것을 의미하며 |
| <em>거짓</em>을 반환하면 이벤트가 아직 미처리 상태이며/거나 이 이벤트를 다른 |
| 온-클릭 수신기로 계속 진행해야 할지 나타내는 것입니다.</li> |
| <li><code>{@link android.view.View.OnKeyListener#onKey(View,int,KeyEvent) onKey()}</code> - |
| 이것은 부울 값을 반환하여 이벤트를 완전히 사용하였으며 더 이상 이를 담지 않아도 되는지 여부를 나타냅니다. |
| 다시 말해, <em>참</em>을 반환하면 이벤트를 처리했으며 여기에서 중단해야 한다는 것을 의미하며 |
| <em>거짓</em>을 반환하면 이벤트가 아직 미처리 상태이며/거나 이 이벤트를 다른 |
| 온-키 수신기로 계속 진행해야 할지 나타내는 것입니다.</li> |
| <li><code>{@link android.view.View.OnTouchListener#onTouch(View,MotionEvent) onTouch()}</code> - |
| 이것은 부울 값을 반환하여 수신기가 이 이벤트를 사용하는지 아닌지를 나타냅니다. 여기서 중요한 점은 |
| 이 이벤트에는 서로 연달아 발생하는 여러 개의 작업이 있을 수 있다는 것입니다. 그러므로 '아래로' 작업 이벤트를 수신했을 때 <em>거짓</em>을 반환하면, |
| 해당 이벤트를 사용하지 않았으며 이 이벤트로부터 이어지는 이후의 작업에 |
| 흥미가 없음을 나타내는 것이 됩니다. 따라서 이 이벤트 내의 다른 모든 작업에 대해 |
| 호출되지 않습니다(예: 손가락 동작 또는 최종적인 '위로' 작업 이벤트 등).</li> |
| </ul> |
| |
| <p>하드웨어 키 이벤트는 항상 현재 초점의 중심에 있는 보기로 전달된다는 점을 명심하십시오. 이들은 보기 계층의 맨 위에서 시작하여 |
| 아래 방향으로 발송되어 적절한 목적지에 도달할 때까지 계속합니다. 보기(또는 보기의 하위)에 |
| 현재 초점이 맞춰져 있으면, 이벤트가 <code>{@link android.view.View#dispatchKeyEvent(KeyEvent) |
| dispatchKeyEvent()}</code> 메서드를 통과하여 이동하는 것을 확인할 수 있습니다. 보기를 통해 키 이벤트를 캡처하는 대신, 액티비티 내부의 모든 이벤트를 <code>{@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()}</code>및 |
| |
| <code>{@link android.app.Activity#onKeyUp(int,KeyEvent) onKeyUp()}</code>을 사용하여 수신할 수도 있습니다.</p> |
| |
| <p>또한, 애플리케이션에 대한 텍스트 입력의 경우 대다수의 기기에는 소프트웨어 입력 메서드만 있다는 사실을 |
| 명심하십시오. 그러한 메서드는 반드시 키 기반이 아니어도 됩니다. 음성 입력, 손글씨 등을 사용하는 것도 있습니다. 입력 |
| 메서드가 키보드 같은 인터페이스를 표시하더라도 일반적으로 |
| <code>{@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()}</code> 이벤트군을 트리거하지는 <strong>않습니다</strong>. 특정 키 누름을 |
| 제어해야만 하는 UI는 절대 구축하면 안 됩니다. 이렇게 하면 애플리케이션이 하드웨어 키보드가 있는 |
| 기기에만 한정됩니다. 특히, 사용자가 리턴 키를 누르면 입력의 유효성을 검사하는 데 이와 같은 메서드에 |
| 의존해서는 안 됩니다. 대신, {@link android.view.inputmethod.EditorInfo#IME_ACTION_DONE}과 같은 작업을 사용하여 애플리케이션이 반응할 것으로 기대되는 방식에 해당되는 |
| 입력 메서드를 신호하여 의미 있는 방식으로 UI를 변경할 수 있게 하는 것이 좋습니다. 소프트웨어 입력 메서드가 |
| 어떻게 작동할지 임의로 추정하지 마시고, 이미 서식 지정된 텍스트를 애플리케이션에 제공해줄 것이라 믿으면 됩니다.</p> |
| |
| <p class="note"><strong>참고:</strong> Androids는 우선 이벤트 처리기부터 호출하고, 그 다음에 클래스 정의로부터 가져온 |
| 적절한 기본 처리기를 두 번째로 호출합니다. 따라서, 이와 같은 이벤트 수신기에서 <em>참</em>을 반환하면 이벤트가 |
| 다른 이벤트 수신기로 전파되는 것을 중지시킬 뿐만 아니라 보기에 있는 |
| 기본 이벤트 처리기로의 콜백도 차단하게 됩니다. 따라서 <em>참</em>을 반환하는 경우 해당 이벤트를 종료하고 싶은 것인지 확신해야 합니다.</p> |
| |
| |
| <h2 id="EventHandlers">이벤트 처리기</h2> |
| |
| <p>보기에서 사용자 지정 구성 요소를 구축하는 경우, 기본 이벤트 처리기로 사용될 콜백 메서드를 |
| 여러 개 정의할 수 있게 됩니다. |
| <a href="{@docRoot}guide/topics/ui/custom-components.html">사용자 지정 |
| 구성 요소</a>에 대한 문서를 보면 이벤트 처리에 사용되는 몇 가지 보편적인 콜백을 확인할 수 있습니다. |
| 다음은 그 몇 가지 예입니다.</p> |
| <ul> |
| <li><code>{@link android.view.View#onKeyDown}</code> - 새로운 키 이벤트가 발생하면 호출합니다.</li> |
| <li><code>{@link android.view.View#onKeyUp}</code> - 새로운 키 '위로' 이벤트가 발생하면 호출합니다.</li> |
| <li><code>{@link android.view.View#onTrackballEvent}</code> - 트랙볼 동작 이벤트가 발생하면 호출합니다.</li> |
| <li><code>{@link android.view.View#onTouchEvent}</code> - 터치 스크린 동작 이벤트가 발생하면 호출합니다.</li> |
| <li><code>{@link android.view.View#onFocusChanged}</code> - 보기가 초점을 취하거나 이를 잃으면 호출합니다.</li> |
| </ul> |
| <p>개발자 여러분이 알아두어야 하는 다른 메서드가 몇 가지 더 있습니다. 이들은 보기 클래스의 일부분이 아니지만, |
| 이벤트를 처리할 수 있는 방식에 직접적으로 영향을 미칠 수 있는 것들입니다. 그러니, 레이아웃 안에서 좀 더 복잡한 이벤트를 관리하는 경우, |
| 이와 같은 다른 메서드도 고려하십시오.</p> |
| <ul> |
| <li><code>{@link android.app.Activity#dispatchTouchEvent(MotionEvent) |
| Activity.dispatchTouchEvent(MotionEvent)}</code> - 이것을 사용하면 {@link |
| android.app.Activity}로 하여금 모든 터치 이벤트가 창으로 발송되기 전에 이들을 가로채도록 할 수 있습니다.</li> |
| <li><code>{@link android.view.ViewGroup#onInterceptTouchEvent(MotionEvent) |
| ViewGroup.onInterceptTouchEvent(MotionEvent)}</code> - 이것을 사용하면 {@link |
| android.view.ViewGroup}으로 하여금 이벤트가 하위 보기로 발송되는 것을 지켜보도록 할 수 있습니다.</li> |
| <li><code>{@link android.view.ViewParent#requestDisallowInterceptTouchEvent(boolean) |
| ViewParent.requestDisallowInterceptTouchEvent(boolean)}</code> - 이것을 |
| 호출하는 것은 상위 보기에 <code>{@link |
| android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)}</code>가 있는 터치 이벤트를 가로채면 안 된다고 나타낼 때입니다.</li> |
| </ul> |
| |
| <h2 id="TouchMode">터치 모드</h2> |
| <p> |
| 사용자가 방향 키 또는 트랙볼을 사용하여 사용자 인터페이스를 탐색하고 있는 경우, |
| 조치 가능한 항목(예: 버튼)에 초점을 맞춰 어느 것이 입력을 허용할지 사용자가 |
| 볼 수 있도록 해야 합니다. 하지만 기기에 터치 기능이 있고 사용자가 |
| 인터페이스를 터치하여 인터페이스와의 상호 작용을 시작하는 경우라면, 더 이상 항목을 강조 표시하거나 |
| 특정 보기에 초점을 맞추지 않아도 됩니다. 따라서 "터치 모드"라고 불리는 상호 작용에 대한 |
| 모드가 따로 있습니다. |
| </p> |
| <p> |
| 터치 기능이 있는 기기의 경우, 사용자가 화면을 터치하면 기기가 터치 모드에 |
| 진입하게 됩니다. 이 시점부터는 |
| {@link android.view.View#isFocusableInTouchMode}가 참인 보기에만 초점을 맞출 수 있습니다. 예를 들어 텍스트 편집 위젯이 이에 해당됩니다. |
| 버튼처럼 터치할 수 있는 다른 보기의 경우 터치해도 주의를 끌 수 없으며 이를 누르면 그저 |
| 온-클릭 수신기를 실행시키기만 합니다. |
| </p> |
| <p> |
| 사용자가 방향 키를 누르거나 트랙볼로 스크롤 동작을 할 때마다 기기가 |
| 터치 모드를 종료하고 초점을 맞출 보기를 찾습니다. 이제 사용자는 사용자 인터페이스와 |
| 상호 작용을 재개해도 되며, 화면을 터치하지 않아도 됩니다. |
| </p> |
| <p> |
| 터치 모드 상태는 시스템 전체를 통틀어 유지됩니다(모든 창과 액티비티 포함). |
| 현재 상태를 쿼리하려면 |
| {@link android.view.View#isInTouchMode}를 호출하여 기기가 현재 터치 모드에 있는지 확인하면 됩니다. |
| </p> |
| |
| |
| <h2 id="HandlingFocus">초점 처리하기</h2> |
| |
| <p>프레임워크가 사용자 입력에 응답하여 일상적인 초점 이동을 처리합니다. |
| 여기에는 보기가 제거되거나 숨겨지는 것, 또는 새 보기를 사용할 수 있게 됨에 따라 |
| 초점을 변경하는 것이 포함됩니다. 보기는 초점을 취하고자 하는 의향을 |
| <code>{@link android.view.View#isFocusable()}</code> 메서드를 통해 나타냅니다. 보기가 초점을 취할 수 있는지 여부를 변경하려면 |
| <code>{@link android.view.View#setFocusable(boolean) setFocusable()}</code>을 호출합니다. 터치 모드에 있는 경우, |
| 어느 보기가 <code>{@link android.view.View#isFocusableInTouchMode()}</code>로 초점을 취하는 것을 허용하는지 여부를 쿼리할 수 있습니다. |
| 이것은 <code>{@link android.view.View#setFocusableInTouchMode(boolean) setFocusableInTouchMode()}</code>로 변경하면 됩니다. |
| </p> |
| |
| <p>초점 이동은 주어진 방향에서 가장 가까운 이웃을 찾아내는 알고리즘을 기반으로 |
| 합니다. 드문 일이지만 기본 알고리즘이 개발자가 의도한 행동과 일치하지 않는 |
| 경우도 있습니다. 이러한 상황이라면, 레이아웃 파일에서 다음과 같은 XML 속성을 |
| 사용하여 명시적 재정의를 제공하면 됩니다. |
| <var>nextFocusDown</var>, <var>nextFocusLeft</var>, <var>nextFocusRight</var>, 및 |
| <var>nextFocusUp</var>입니다. 이와 같은 속성 중 한 가지를 초점이 <em>떠나고</em> 있는 보기에 |
| 추가합니다. 속성의 값을 초점을 |
| <em>맞춰야 할</em> 보기의 ID가 되도록 정의합니다. 예:</p> |
| <pre> |
| <LinearLayout |
| android:orientation="vertical" |
| ... > |
| <Button android:id="@+id/top" |
| android:nextFocusUp="@+id/bottom" |
| ... /> |
| <Button android:id="@+id/bottom" |
| android:nextFocusDown="@+id/top" |
| ... /> |
| </LinearLayout> |
| </pre> |
| |
| <p>보통은 이런 수직 레이아웃에서 첫 버튼부터 위로 이동하면 아무 데도 갈 수 없고, |
| 두 번째 버튼에서 아래로 이동해도 마찬가지입니다. 이제 맨 위 버튼이 맨 아래 버튼을 다음과 같이 |
| 정의했습니다. <var>nextFocusUp</var> (반대쪽도 마찬가지) 따라서 이동 초점은 위에서 아래로 갔다가 |
| 아래에서 위로 순환하게 됩니다.</p> |
| |
| <p>보기를 UI에서 초점을 맞출 수 있는 것으로 선언하고자 하는 경우(일반적으로는 그렇지 않음), |
| 보기에 레이아웃 선언에서 <code>android:focusable</code> XML 속성을 추가합니다. |
| 이 값을 <var>참</var>으로 설정합니다. 터치 모드에 있을 때에도 보기를 초점을 맞출 수 있는 것으로 |
| 선언할 수 있습니다. <code>android:focusableInTouchMode</code>를 사용하면 됩니다.</p> |
| <p>특정 보기에 초점을 맞추기를 요청하려면, <code>{@link android.view.View#requestFocus()}</code>를 호출하십시오.</p> |
| <p>초점 이벤트를 수신 대기하려면(어떤 보기에 초점이 맞춰지거나 이를 잃는 경우 알림을 받으려면), |
| <code>{@link android.view.View.OnFocusChangeListener#onFocusChange(View,boolean) onFocusChange()}</code>를 사용하면 됩니다. |
| 이는 위의 <a href="#EventListeners">이벤트 수신기</a> 섹션에서 이야기한 바와 같습니다.</p> |
| |
| |
| |
| <!-- |
| <h2 is="EventCycle">Event Cycle</h2> |
| <p>The basic cycle of a View is as follows:</p> |
| <ol> |
| <li>An event comes in and is dispatched to the appropriate View. The View |
| handles the event and notifies any listeners.</li> |
| <li>If, in the course of processing the event, the View's bounds may need |
| to be changed, the View will call {@link android.view.View#requestLayout()}.</li> |
| <li>Similarly, if in the course of processing the event the View's appearance |
| may need to be changed, the View will call {@link android.view.View#invalidate()}.</li> |
| <li>If either {@link android.view.View#requestLayout()} or {@link android.view.View#invalidate()} were called, |
| the framework will take care of measuring, laying out, and drawing the tree |
| as appropriate.</li> |
| </ol> |
| |
| <p class="note"><strong>Note:</strong> The entire View tree is single threaded. You must always be on |
| the UI thread when calling any method on any View. |
| If you are doing work on other threads and want to update the state of a View |
| from that thread, you should use a {@link android.os.Handler}. |
| </p> |
| --> |