ui-events.jd revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
1page.title=Handling UI Events 2parent.title=User Interface 3parent.link=index.html 4@jd:body 5 6<div id="qv-wrapper"> 7<div id="qv"> 8 <h2>In this document</h2> 9 <ol> 10 <li><a href="#EventListeners">Event Listeners</a></li> 11 <li><a href="#EventHandlers">Event Handlers</a></li> 12 <li><a href="#TouchMode">Touch Mode</a></li> 13 <li><a href="#HandlingFocus">Handling Focus</a></li> 14 </ol> 15 16 <h2>See also</h2> 17 <ol> 18 <li><a href="{@docRoot}guide/tutorials/views/hello-formstuff.html">Hello Form Stuff tutorial</a></li> 19 </ol> 20</div> 21</div> 22 23<p>On Android, there's more than one way to intercept the events from a user's interaction with your application. 24When considering events within your user interface, the approach is to capture the events from 25the specific View object that the user interacts with. The View class provides the means to do so.</p> 26 27<p>Within the various View classes that you'll use to compose your layout, you may notice several public callback 28methods that look useful for UI events. These methods are called by the Android framework when the 29respective action occurs on that object. For instance, when a View (such as a Button) is touched, 30the <code>onTouchEvent()</code> method is called on that object. However, in order to intercept this, you must extend 31the class and override the method. Obviously, extending every View object 32you want to use (just to handle an event) would be obsurd. This is why the View class also contains 33a collection of nested interfaces with callbacks that you can much more easily define. These interfaces, 34called <a href="#EventListeners">event listeners</a>, are your ticket to capturing the user interaction with your UI.</p> 35 36<p>While you will more commonly use the event listeners to listen for user interaction, there may 37come a time when you do want to extend a View class, in order to build a custom component. 38Perhaps you want to extend the {@link android.widget.Button} 39class to make something more fancy. In this case, you'll be able to define the default event behaviors for your 40class using the class <a href="#EventHandlers">event handlers</a>.</p> 41 42 43<h2 id="EventListeners">Event Listeners</h2> 44 45<p>An event listener is an interface in the {@link android.view.View} class that contains a single 46callback method. These methods will be called by the Android framework when the View to which the listener has 47been registered is triggered by user interaction with the item in the UI.</p> 48 49<p>Included in the event listener interfaces are the following callback methods:</p> 50 51<dl> 52 <dt><code>onClick()</code></dt> 53 <dd>From {@link android.view.View.OnClickListener}. 54 This is called when the user either touches the item 55 (when in touch mode), or focuses upon the item with the navigation-keys or trackball and 56 presses the suitable "enter" key or presses down on the trackball.</dd> 57 <dt><code>onLongClick()</code></dt> 58 <dd>From {@link android.view.View.OnLongClickListener}. 59 This is called when the user either touches and holds the item (when in touch mode), or 60 focuses upon the item with the navigation-keys or trackball and 61 presses and holds the suitable "enter" key or presses and holds down on the trackball (for one second).</dd> 62 <dt><code>onFocusChange()</code></dt> 63 <dd>From {@link android.view.View.OnFocusChangeListener}. 64 This is called when the user navigates onto or away from the item, using the navigation-keys or trackball.</dd> 65 <dt><code>onKey()</code></dt> 66 <dd>From {@link android.view.View.OnKeyListener}. 67 This is called when the user is focused on the item and presses or releases a key on the device.</dd> 68 <dt><code>onTouch()</code></dt> 69 <dd>From {@link android.view.View.OnTouchListener}. 70 This is called when the user performs an action qualified as a touch event, including a press, a release, 71 or any movement gesture on the screen (within the bounds of the item).</dd> 72 <dt><code>onCreateContextMenu()</code></dt> 73 <dd>From {@link android.view.View.OnCreateContextMenuListener}. 74 This is called when a Context Menu is being built (as the result of a sustained "long click"). See the discussion 75 on context menus in <a href="{@docRoot}guide/topics/ui/menus.html#context-menu">Creating Menus</a> for more information.</dd> 76</dl> 77 78<p>These methods are the sole inhabitants of their respective interface. To define one of these methods 79and handle your events, implement the nested interface in your Activity or define it as an anonymous class. 80Then, pass an instance of your implementation 81to the respective <code>View.set...Listener()</code> method. (E.g., call 82<code>{@link android.view.View#setOnClickListener(View.OnClickListener) setOnClickListener()}</code> 83and pass it your implementation of the {@link android.view.View.OnClickListener OnClickListener}.)</p> 84 85<p>The example below shows how to register an on-click listener for a Button. </p> 86 87<pre> 88// Create an anonymous implementation of OnClickListener 89private OnClickListener mCorkyListener = new OnClickListener() { 90 public void onClick(View v) { 91 // do something when the button is clicked 92 } 93}; 94 95protected void onCreate(Bundle savedValues) { 96 ... 97 // Capture our button from layout 98 Button button = (Button)findViewById(R.id.corky); 99 // Register the onClick listener with the implementation above 100 button.setOnClickListener(mCorkyListener); 101 ... 102} 103</pre> 104 105<p>You may also find it more conventient to implement OnClickListener as a part of your Activity. 106This will avoid the extra class load and object allocation. For example:</p> 107<pre> 108public class ExampleActivity extends Activity implements OnClickListener { 109 protected void onCreate(Bundle savedValues) { 110 ... 111 Button button = (Button)findViewById(R.id.corky); 112 button.setOnClickListener(this); 113 } 114 115 // Implement the OnClickListener callback 116 public void onClick(View v) { 117 // do something when the button is clicked 118 } 119 ... 120} 121</pre> 122 123<p>Notice that the <code>onClick()</code> callback in the above example has 124no return value, but some other event listener methods must return a boolean. The reason 125depends on the event. For the few that do, here's why:</p> 126<ul> 127 <li><code>{@link android.view.View.OnLongClickListener#onLongClick(View) onLongClick()}</code> - 128 This returns a boolean to indicate whether you have consumed the event and it should not be carried further. 129 That is, return <em>true</em> to indicate that you have handled the event and it should stop here; 130 return <em>false</em> if you have not handled it and/or the event should continue to any other 131 on-click listeners.</li> 132 <li><code>{@link android.view.View.OnKeyListener#onKey(View,int,KeyEvent) onKey()}</code> - 133 This returns a boolean to indicate whether you have consumed the event and it should not be carried further. 134 That is, return <em>true</em> to indicate that you have handled the event and it should stop here; 135 return <em>false</em> if you have not handled it and/or the event should continue to any other 136 on-key listeners.</li> 137 <li><code>{@link android.view.View.OnTouchListener#onTouch(View,MotionEvent) onTouch()}</code> - 138 This returns a boolean to indicate whether your listener consumes this event. The important thing is that 139 this event can have multiple actions that follow each other. So, if you return <em>false</em> when the 140 down action event is received, you indicate that you have not consumed the event and are also 141 not interested in subsequent actions from this event. Thus, you will not be called for any other actions 142 within the event, such as a fingure gesture, or the eventual up action event.</li> 143</ul> 144 145<p>Remember that key events are always delivered to the View currently in focus. They are dispatched starting from the top 146of the View hierarchy, and then down, until they reach the appropriate destination. If your View (or a child of your View) 147currently has focus, then you can see the event travel through the <code>{@link android.view.View#dispatchKeyEvent(KeyEvent) 148dispatchKeyEvent()}</code> method. As an alternative to capturing key events through your View, you can also receive 149all of the events inside your Activity with <code>{@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()}</code> 150and <code>{@link android.app.Activity#onKeyUp(int,KeyEvent) onKeyUp()}</code>.</p> 151 152<p class="note"><strong>Note:</strong> Android will call event handlers first and then the appropriate default 153handlers from the class definition second. As such, returning <em>true</em> from these event listeners will stop 154the propagation of the event to other event listeners and will also block the callback to the 155default event handler in the View. So be certain that you want to terminate the event when you return <em>true</em>.</p> 156 157 158<h2 id="EventHandlers">Event Handlers</h2> 159 160<p>If you're building a custom component from View, then you'll be able to define several callback methods 161used as default event handlers. 162In the document on <a href="{@docRoot}guide/topics/ui/custom-components.html">Building Custom Components</a>, 163you'll learn see some of the common callbacks used for event handling, including:</p> 164<ul> 165 <li><code>{@link android.view.View#onKeyDown}</code> - Called when a new key event occurs.</li> 166 <li><code>{@link android.view.View#onKeyUp}</code> - Called when a key up event occurs.</li> 167 <li><code>{@link android.view.View#onTrackballEvent}</code> - Called when a trackball motion event occurs.</li> 168 <li><code>{@link android.view.View#onTouchEvent}</code> - Called when a touch screen motion event occurs.</li> 169 <li><code>{@link android.view.View#onFocusChanged}</code> - Called when the view gains or loses focus.</li> 170</ul> 171<p>There are some other methods that you should be awere of, which are not part of the View class, 172but can directly impact the way you're able to handle events. So, when managing more complex events inside 173a layout, consider these other methods:</p> 174<ul> 175 <li><code>{@link android.app.Activity#dispatchTouchEvent(MotionEvent) 176 Activity.dispatchTouchEvent(MotionEvent)}</code> - This allows your {@link 177 android.app.Activity} to intercept all touch events before they are dispatched to the window.</li> 178 <li><code>{@link android.view.ViewGroup#onInterceptTouchEvent(MotionEvent) 179 ViewGroup.onInterceptTouchEvent(MotionEvent)}</code> - This allows a {@link 180 android.view.ViewGroup} to watch events as they are dispatched to child Views.</li> 181 <li><code>{@link android.view.ViewParent#requestDisallowInterceptTouchEvent(boolean) 182 ViewParent.requestDisallowInterceptTouchEvent(boolean)}</code> - Call this 183 upon a parent View to indicate that it should not intercept touch events with <code>{@link 184 android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)}</code>.</li> 185</ul> 186 187<h2 id="TouchMode">Touch Mode</h2> 188<p> 189When a user is navigating a user interface with directional keys or a trackball, it is 190necessary to give focus to actionable items (like buttons) so the user can see 191what will accept input. If the device has touch capabilities, however, and the user 192begins interacting with the interface by touching it, then it is no longer necessary to 193highlight items, or give focus to a particular View. Thus, there is a mode 194for interaction named "touch mode." 195</p> 196<p> 197For a touch-capable device, once the user touches the screen, the device 198will enter touch mode. From this point onward, only Views for which 199{@link android.view.View#isFocusableInTouchMode} is true will be focusable, such as text editing widgets. 200Other Views that are touchable, like buttons, will not take focus when touched; they will 201simply fire their on-click listeners when pressed. 202</p> 203<p> 204Any time a user hits a directional key or scrolls with a trackball, the device will 205exit touch mode, and find a view to take focus. Now, the user may resume interacting 206with the user interface without touching the screen. 207</p> 208<p> 209The touch mode state is maintained throughout the entire system (all windows and activities). 210To query the current state, you can call 211{@link android.view.View#isInTouchMode} to see whether the device is currently in touch mode. 212</p> 213 214 215<h2 id="HandlingFocus">Handling Focus</h2> 216 217<p>The framework will handle routine focus movement in response to user input. 218This includes changing the focus as Views are removed or hidden, or as new 219Views become available. Views indicate their willingness to take focus 220through the <code>{@link android.view.View#isFocusable()}</code> method. To change whether a View can take 221focus, call <code>{@link android.view.View#setFocusable(boolean) setFocusable()}</code>. When in touch mode, 222you may query whether a View allows focus with <code>{@link android.view.View#isFocusableInTouchMode()}</code>. 223You can change this with <code>{@link android.view.View#setFocusableInTouchMode(boolean) setFocusableInTouchMode()}</code>. 224</p> 225 226<p>Focus movement is based on an algorithm which finds the nearest neighbor in a 227given direction. In rare cases, the default algorithm may not match the 228intended behavior of the developer. In these situations, you can provide 229explicit overrides with the following XML attributes in the layout file: 230<var>nextFocusDown</var>, <var>nextFocusLeft</var>, <var>nextFocusRight</var>, and 231<var>nextFocusUp</var>. Add one of these attributes to the View <em>from</em> which 232the focus is leaving. Define the value of the attribute to be the id of the View 233<em>to</em> which focus should be given. For example:</p> 234<pre> 235<LinearLayout 236 android:orientation="vertical" 237 ... > 238 <Button android:id="@+id/top" 239 android:nextFocusUp="@+id/bottom" 240 ... /> 241 <Button android:id="@+id/bottom" 242 android:nextFocusDown="@+id/top" 243 ... /> 244</LinearLayout> 245</pre> 246 247<p>Ordinarily, in this vertical layout, navigating up from the first Button would not go 248anywhere, nor would navigating down from the second Button. Now that the top Button has 249defined the bottom one as the <var>nextFocusUp</var> (and vice versa), the navigation focus will 250cycle from top-to-bottom and bottom-to-top.</p> 251 252<p>If you'd like to declare a View as focusable in your UI (when it is traditionally not), 253add the <code>android:focusable</code> XML attribute to the View, in your layout declaration. 254Set the value <var>true</var>. You can also declare a View 255as focusable while in Touch Mode with <code>android:focusableInTouchMode</code>.</p> 256<p>To request a particular View to take focus, call <code>{@link android.view.View#requestFocus()}</code>.</p> 257<p>To listen for focus events (be notified when a View receives or looses focus), use 258<code>{@link android.view.View.OnFocusChangeListener#onFocusChange(View,boolean) onFocusChange()}</code>, 259as discussed in the <a href="#EventListeners">Event Listeners</a> section, above.</p> 260 261 262 263<!-- 264<h2 is="EventCycle">Event Cycle</h2> 265 <p>The basic cycle of a View is as follows:</p> 266 <ol> 267 <li>An event comes in and is dispatched to the appropriate View. The View 268 handles the event and notifies any listeners.</li> 269 <li>If, in the course of processing the event, the View's bounds may need 270 to be changed, the View will call {@link android.view.View#requestLayout()}.</li> 271 <li>Similarly, if in the course of processing the event the View's appearance 272 may need to be changed, the View will call {@link android.view.View#invalidate()}.</li> 273 <li>If either {@link android.view.View#requestLayout()} or {@link android.view.View#invalidate()} were called, 274 the framework will take care of measuring, laying out, and drawing the tree 275 as appropriate.</li> 276 </ol> 277 278 <p class="note"><strong>Note:</strong> The entire View tree is single threaded. You must always be on 279 the UI thread when calling any method on any View. 280 If you are doing work on other threads and want to update the state of a View 281 from that thread, you should use a {@link android.os.Handler}. 282 </p> 283--> 284