284 lines
16 KiB
Plaintext
284 lines
16 KiB
Plaintext
page.title=Handling UI Events
|
|
parent.title=User Interface
|
|
parent.link=index.html
|
|
@jd:body
|
|
|
|
<div id="qv-wrapper">
|
|
<div id="qv">
|
|
<h2>In this document</h2>
|
|
<ol>
|
|
<li><a href="#EventListeners">Event Listeners</a></li>
|
|
<li><a href="#EventHandlers">Event Handlers</a></li>
|
|
<li><a href="#TouchMode">Touch Mode</a></li>
|
|
<li><a href="#HandlingFocus">Handling Focus</a></li>
|
|
</ol>
|
|
|
|
<h2>Related tutorials</h2>
|
|
<ol>
|
|
<li><a href="{@docRoot}resources/tutorials/views/hello-formstuff.html">Form Stuff</a></li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
|
|
<p>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.</p>
|
|
|
|
<p>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 <code>onTouchEvent()</code> 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 <a href="#EventListeners">event listeners</a>, are your ticket to capturing the user interaction with your UI.</p>
|
|
|
|
<p>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 {@link android.widget.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 <a href="#EventHandlers">event handlers</a>.</p>
|
|
|
|
|
|
<h2 id="EventListeners">Event Listeners</h2>
|
|
|
|
<p>An event listener is an interface in the {@link android.view.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.</p>
|
|
|
|
<p>Included in the event listener interfaces are the following callback methods:</p>
|
|
|
|
<dl>
|
|
<dt><code>onClick()</code></dt>
|
|
<dd>From {@link android.view.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.</dd>
|
|
<dt><code>onLongClick()</code></dt>
|
|
<dd>From {@link android.view.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).</dd>
|
|
<dt><code>onFocusChange()</code></dt>
|
|
<dd>From {@link android.view.View.OnFocusChangeListener}.
|
|
This is called when the user navigates onto or away from the item, using the navigation-keys or trackball.</dd>
|
|
<dt><code>onKey()</code></dt>
|
|
<dd>From {@link android.view.View.OnKeyListener}.
|
|
This is called when the user is focused on the item and presses or releases a key on the device.</dd>
|
|
<dt><code>onTouch()</code></dt>
|
|
<dd>From {@link android.view.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).</dd>
|
|
<dt><code>onCreateContextMenu()</code></dt>
|
|
<dd>From {@link android.view.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 <a href="{@docRoot}guide/topics/ui/menus.html#context-menu">Creating Menus</a> for more information.</dd>
|
|
</dl>
|
|
|
|
<p>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 <code>View.set...Listener()</code> method. (E.g., call
|
|
<code>{@link android.view.View#setOnClickListener(View.OnClickListener) setOnClickListener()}</code>
|
|
and pass it your implementation of the {@link android.view.View.OnClickListener OnClickListener}.)</p>
|
|
|
|
<p>The example below shows how to register an on-click listener for a Button. </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>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:</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>Notice that the <code>onClick()</code> 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:</p>
|
|
<ul>
|
|
<li><code>{@link android.view.View.OnLongClickListener#onLongClick(View) onLongClick()}</code> -
|
|
This returns a boolean to indicate whether you have consumed the event and it should not be carried further.
|
|
That is, return <em>true</em> to indicate that you have handled the event and it should stop here;
|
|
return <em>false</em> if you have not handled it and/or the event should continue to any other
|
|
on-click listeners.</li>
|
|
<li><code>{@link android.view.View.OnKeyListener#onKey(View,int,KeyEvent) onKey()}</code> -
|
|
This returns a boolean to indicate whether you have consumed the event and it should not be carried further.
|
|
That is, return <em>true</em> to indicate that you have handled the event and it should stop here;
|
|
return <em>false</em> if you have not handled it and/or the event should continue to any other
|
|
on-key listeners.</li>
|
|
<li><code>{@link android.view.View.OnTouchListener#onTouch(View,MotionEvent) onTouch()}</code> -
|
|
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 <em>false</em> 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 finger gesture, or the eventual up action event.</li>
|
|
</ul>
|
|
|
|
<p>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 <code>{@link android.view.View#dispatchKeyEvent(KeyEvent)
|
|
dispatchKeyEvent()}</code> method. As an alternative to capturing key events through your View, you can also receive
|
|
all of the events inside your Activity with <code>{@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()}</code>
|
|
and <code>{@link android.app.Activity#onKeyUp(int,KeyEvent) onKeyUp()}</code>.</p>
|
|
|
|
<p class="note"><strong>Note:</strong> Android will call event handlers first and then the appropriate default
|
|
handlers from the class definition second. As such, returning <em>true</em> 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 <em>true</em>.</p>
|
|
|
|
|
|
<h2 id="EventHandlers">Event Handlers</h2>
|
|
|
|
<p>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 <a href="{@docRoot}guide/topics/ui/custom-components.html">Building Custom Components</a>,
|
|
you'll learn see some of the common callbacks used for event handling, including:</p>
|
|
<ul>
|
|
<li><code>{@link android.view.View#onKeyDown}</code> - Called when a new key event occurs.</li>
|
|
<li><code>{@link android.view.View#onKeyUp}</code> - Called when a key up event occurs.</li>
|
|
<li><code>{@link android.view.View#onTrackballEvent}</code> - Called when a trackball motion event occurs.</li>
|
|
<li><code>{@link android.view.View#onTouchEvent}</code> - Called when a touch screen motion event occurs.</li>
|
|
<li><code>{@link android.view.View#onFocusChanged}</code> - Called when the view gains or loses focus.</li>
|
|
</ul>
|
|
<p>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:</p>
|
|
<ul>
|
|
<li><code>{@link android.app.Activity#dispatchTouchEvent(MotionEvent)
|
|
Activity.dispatchTouchEvent(MotionEvent)}</code> - This allows your {@link
|
|
android.app.Activity} to intercept all touch events before they are dispatched to the window.</li>
|
|
<li><code>{@link android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)
|
|
ViewGroup.onInterceptTouchEvent(MotionEvent)}</code> - This allows a {@link
|
|
android.view.ViewGroup} to watch events as they are dispatched to child Views.</li>
|
|
<li><code>{@link android.view.ViewParent#requestDisallowInterceptTouchEvent(boolean)
|
|
ViewParent.requestDisallowInterceptTouchEvent(boolean)}</code> - Call this
|
|
upon a parent View to indicate that it should not intercept touch events with <code>{@link
|
|
android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)}</code>.</li>
|
|
</ul>
|
|
|
|
<h2 id="TouchMode">Touch Mode</h2>
|
|
<p>
|
|
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."
|
|
</p>
|
|
<p>
|
|
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
|
|
{@link android.view.View#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.
|
|
</p>
|
|
<p>
|
|
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.
|
|
</p>
|
|
<p>
|
|
The touch mode state is maintained throughout the entire system (all windows and activities).
|
|
To query the current state, you can call
|
|
{@link android.view.View#isInTouchMode} to see whether the device is currently in touch mode.
|
|
</p>
|
|
|
|
|
|
<h2 id="HandlingFocus">Handling Focus</h2>
|
|
|
|
<p>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 <code>{@link android.view.View#isFocusable()}</code> method. To change whether a View can take
|
|
focus, call <code>{@link android.view.View#setFocusable(boolean) setFocusable()}</code>. When in touch mode,
|
|
you may query whether a View allows focus with <code>{@link android.view.View#isFocusableInTouchMode()}</code>.
|
|
You can change this with <code>{@link android.view.View#setFocusableInTouchMode(boolean) setFocusableInTouchMode()}</code>.
|
|
</p>
|
|
|
|
<p>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:
|
|
<var>nextFocusDown</var>, <var>nextFocusLeft</var>, <var>nextFocusRight</var>, and
|
|
<var>nextFocusUp</var>. Add one of these attributes to the View <em>from</em> which
|
|
the focus is leaving. Define the value of the attribute to be the id of the View
|
|
<em>to</em> which focus should be given. For example:</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>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 <var>nextFocusUp</var> (and vice versa), the navigation focus will
|
|
cycle from top-to-bottom and bottom-to-top.</p>
|
|
|
|
<p>If you'd like to declare a View as focusable in your UI (when it is traditionally not),
|
|
add the <code>android:focusable</code> XML attribute to the View, in your layout declaration.
|
|
Set the value <var>true</var>. You can also declare a View
|
|
as focusable while in Touch Mode with <code>android:focusableInTouchMode</code>.</p>
|
|
<p>To request a particular View to take focus, call <code>{@link android.view.View#requestFocus()}</code>.</p>
|
|
<p>To listen for focus events (be notified when a View receives or looses focus), use
|
|
<code>{@link android.view.View.OnFocusChangeListener#onFocusChange(View,boolean) onFocusChange()}</code>,
|
|
as discussed in the <a href="#EventListeners">Event Listeners</a> section, above.</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>
|
|
-->
|