View.java revision 52f0a6495277469bd7ede29ef89bc34cb2aa8a85
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import com.android.internal.R;
20import com.android.internal.view.menu.MenuBuilder;
21
22import android.content.Context;
23import android.content.res.Resources;
24import android.content.res.TypedArray;
25import android.graphics.Bitmap;
26import android.graphics.Canvas;
27import android.graphics.Interpolator;
28import android.graphics.LinearGradient;
29import android.graphics.Matrix;
30import android.graphics.Paint;
31import android.graphics.PixelFormat;
32import android.graphics.Point;
33import android.graphics.PorterDuff;
34import android.graphics.PorterDuffXfermode;
35import android.graphics.Rect;
36import android.graphics.Region;
37import android.graphics.Shader;
38import android.graphics.drawable.ColorDrawable;
39import android.graphics.drawable.Drawable;
40import android.os.Handler;
41import android.os.IBinder;
42import android.os.Message;
43import android.os.Parcel;
44import android.os.Parcelable;
45import android.os.RemoteException;
46import android.os.SystemClock;
47import android.os.SystemProperties;
48import android.util.AttributeSet;
49import android.util.Config;
50import android.util.EventLog;
51import android.util.Log;
52import android.util.Pool;
53import android.util.Poolable;
54import android.util.PoolableManager;
55import android.util.Pools;
56import android.util.SparseArray;
57import android.view.ContextMenu.ContextMenuInfo;
58import android.view.accessibility.AccessibilityEvent;
59import android.view.accessibility.AccessibilityEventSource;
60import android.view.accessibility.AccessibilityManager;
61import android.view.animation.Animation;
62import android.view.animation.AnimationUtils;
63import android.view.inputmethod.EditorInfo;
64import android.view.inputmethod.InputConnection;
65import android.view.inputmethod.InputMethodManager;
66import android.widget.ScrollBarDrawable;
67
68import java.lang.ref.SoftReference;
69import java.lang.reflect.InvocationTargetException;
70import java.lang.reflect.Method;
71import java.util.ArrayList;
72import java.util.Arrays;
73import java.util.WeakHashMap;
74
75/**
76 * <p>
77 * This class represents the basic building block for user interface components. A View
78 * occupies a rectangular area on the screen and is responsible for drawing and
79 * event handling. View is the base class for <em>widgets</em>, which are
80 * used to create interactive UI components (buttons, text fields, etc.). The
81 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
82 * are invisible containers that hold other Views (or other ViewGroups) and define
83 * their layout properties.
84 * </p>
85 *
86 * <div class="special">
87 * <p>For an introduction to using this class to develop your
88 * application's user interface, read the Developer Guide documentation on
89 * <strong><a href="{@docRoot}guide/topics/ui/index.html">User Interface</a></strong>. Special topics
90 * include:
91 * <br/><a href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout</a>
92 * <br/><a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a>
93 * <br/><a href="{@docRoot}guide/topics/ui/layout-objects.html">Common Layout Objects</a>
94 * <br/><a href="{@docRoot}guide/topics/ui/binding.html">Binding to Data with AdapterView</a>
95 * <br/><a href="{@docRoot}guide/topics/ui/ui-events.html">Handling UI Events</a>
96 * <br/><a href="{@docRoot}guide/topics/ui/themes.html">Applying Styles and Themes</a>
97 * <br/><a href="{@docRoot}guide/topics/ui/custom-components.html">Building Custom Components</a>
98 * <br/><a href="{@docRoot}guide/topics/ui/how-android-draws.html">How Android Draws Views</a>.
99 * </p>
100 * </div>
101 *
102 * <a name="Using"></a>
103 * <h3>Using Views</h3>
104 * <p>
105 * All of the views in a window are arranged in a single tree. You can add views
106 * either from code or by specifying a tree of views in one or more XML layout
107 * files. There are many specialized subclasses of views that act as controls or
108 * are capable of displaying text, images, or other content.
109 * </p>
110 * <p>
111 * Once you have created a tree of views, there are typically a few types of
112 * common operations you may wish to perform:
113 * <ul>
114 * <li><strong>Set properties:</strong> for example setting the text of a
115 * {@link android.widget.TextView}. The available properties and the methods
116 * that set them will vary among the different subclasses of views. Note that
117 * properties that are known at build time can be set in the XML layout
118 * files.</li>
119 * <li><strong>Set focus:</strong> The framework will handled moving focus in
120 * response to user input. To force focus to a specific view, call
121 * {@link #requestFocus}.</li>
122 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
123 * that will be notified when something interesting happens to the view. For
124 * example, all views will let you set a listener to be notified when the view
125 * gains or loses focus. You can register such a listener using
126 * {@link #setOnFocusChangeListener}. Other view subclasses offer more
127 * specialized listeners. For example, a Button exposes a listener to notify
128 * clients when the button is clicked.</li>
129 * <li><strong>Set visibility:</strong> You can hide or show views using
130 * {@link #setVisibility}.</li>
131 * </ul>
132 * </p>
133 * <p><em>
134 * Note: The Android framework is responsible for measuring, laying out and
135 * drawing views. You should not call methods that perform these actions on
136 * views yourself unless you are actually implementing a
137 * {@link android.view.ViewGroup}.
138 * </em></p>
139 *
140 * <a name="Lifecycle"></a>
141 * <h3>Implementing a Custom View</h3>
142 *
143 * <p>
144 * To implement a custom view, you will usually begin by providing overrides for
145 * some of the standard methods that the framework calls on all views. You do
146 * not need to override all of these methods. In fact, you can start by just
147 * overriding {@link #onDraw(android.graphics.Canvas)}.
148 * <table border="2" width="85%" align="center" cellpadding="5">
149 *     <thead>
150 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
151 *     </thead>
152 *
153 *     <tbody>
154 *     <tr>
155 *         <td rowspan="2">Creation</td>
156 *         <td>Constructors</td>
157 *         <td>There is a form of the constructor that are called when the view
158 *         is created from code and a form that is called when the view is
159 *         inflated from a layout file. The second form should parse and apply
160 *         any attributes defined in the layout file.
161 *         </td>
162 *     </tr>
163 *     <tr>
164 *         <td><code>{@link #onFinishInflate()}</code></td>
165 *         <td>Called after a view and all of its children has been inflated
166 *         from XML.</td>
167 *     </tr>
168 *
169 *     <tr>
170 *         <td rowspan="3">Layout</td>
171 *         <td><code>{@link #onMeasure}</code></td>
172 *         <td>Called to determine the size requirements for this view and all
173 *         of its children.
174 *         </td>
175 *     </tr>
176 *     <tr>
177 *         <td><code>{@link #onLayout}</code></td>
178 *         <td>Called when this view should assign a size and position to all
179 *         of its children.
180 *         </td>
181 *     </tr>
182 *     <tr>
183 *         <td><code>{@link #onSizeChanged}</code></td>
184 *         <td>Called when the size of this view has changed.
185 *         </td>
186 *     </tr>
187 *
188 *     <tr>
189 *         <td>Drawing</td>
190 *         <td><code>{@link #onDraw}</code></td>
191 *         <td>Called when the view should render its content.
192 *         </td>
193 *     </tr>
194 *
195 *     <tr>
196 *         <td rowspan="4">Event processing</td>
197 *         <td><code>{@link #onKeyDown}</code></td>
198 *         <td>Called when a new key event occurs.
199 *         </td>
200 *     </tr>
201 *     <tr>
202 *         <td><code>{@link #onKeyUp}</code></td>
203 *         <td>Called when a key up event occurs.
204 *         </td>
205 *     </tr>
206 *     <tr>
207 *         <td><code>{@link #onTrackballEvent}</code></td>
208 *         <td>Called when a trackball motion event occurs.
209 *         </td>
210 *     </tr>
211 *     <tr>
212 *         <td><code>{@link #onTouchEvent}</code></td>
213 *         <td>Called when a touch screen motion event occurs.
214 *         </td>
215 *     </tr>
216 *
217 *     <tr>
218 *         <td rowspan="2">Focus</td>
219 *         <td><code>{@link #onFocusChanged}</code></td>
220 *         <td>Called when the view gains or loses focus.
221 *         </td>
222 *     </tr>
223 *
224 *     <tr>
225 *         <td><code>{@link #onWindowFocusChanged}</code></td>
226 *         <td>Called when the window containing the view gains or loses focus.
227 *         </td>
228 *     </tr>
229 *
230 *     <tr>
231 *         <td rowspan="3">Attaching</td>
232 *         <td><code>{@link #onAttachedToWindow()}</code></td>
233 *         <td>Called when the view is attached to a window.
234 *         </td>
235 *     </tr>
236 *
237 *     <tr>
238 *         <td><code>{@link #onDetachedFromWindow}</code></td>
239 *         <td>Called when the view is detached from its window.
240 *         </td>
241 *     </tr>
242 *
243 *     <tr>
244 *         <td><code>{@link #onWindowVisibilityChanged}</code></td>
245 *         <td>Called when the visibility of the window containing the view
246 *         has changed.
247 *         </td>
248 *     </tr>
249 *     </tbody>
250 *
251 * </table>
252 * </p>
253 *
254 * <a name="IDs"></a>
255 * <h3>IDs</h3>
256 * Views may have an integer id associated with them. These ids are typically
257 * assigned in the layout XML files, and are used to find specific views within
258 * the view tree. A common pattern is to:
259 * <ul>
260 * <li>Define a Button in the layout file and assign it a unique ID.
261 * <pre>
262 * &lt;Button id="@+id/my_button"
263 *     android:layout_width="wrap_content"
264 *     android:layout_height="wrap_content"
265 *     android:text="@string/my_button_text"/&gt;
266 * </pre></li>
267 * <li>From the onCreate method of an Activity, find the Button
268 * <pre class="prettyprint">
269 *      Button myButton = (Button) findViewById(R.id.my_button);
270 * </pre></li>
271 * </ul>
272 * <p>
273 * View IDs need not be unique throughout the tree, but it is good practice to
274 * ensure that they are at least unique within the part of the tree you are
275 * searching.
276 * </p>
277 *
278 * <a name="Position"></a>
279 * <h3>Position</h3>
280 * <p>
281 * The geometry of a view is that of a rectangle. A view has a location,
282 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
283 * two dimensions, expressed as a width and a height. The unit for location
284 * and dimensions is the pixel.
285 * </p>
286 *
287 * <p>
288 * It is possible to retrieve the location of a view by invoking the methods
289 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
290 * coordinate of the rectangle representing the view. The latter returns the
291 * top, or Y, coordinate of the rectangle representing the view. These methods
292 * both return the location of the view relative to its parent. For instance,
293 * when getLeft() returns 20, that means the view is located 20 pixels to the
294 * right of the left edge of its direct parent.
295 * </p>
296 *
297 * <p>
298 * In addition, several convenience methods are offered to avoid unnecessary
299 * computations, namely {@link #getRight()} and {@link #getBottom()}.
300 * These methods return the coordinates of the right and bottom edges of the
301 * rectangle representing the view. For instance, calling {@link #getRight()}
302 * is similar to the following computation: <code>getLeft() + getWidth()</code>
303 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
304 * </p>
305 *
306 * <a name="SizePaddingMargins"></a>
307 * <h3>Size, padding and margins</h3>
308 * <p>
309 * The size of a view is expressed with a width and a height. A view actually
310 * possess two pairs of width and height values.
311 * </p>
312 *
313 * <p>
314 * The first pair is known as <em>measured width</em> and
315 * <em>measured height</em>. These dimensions define how big a view wants to be
316 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
317 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
318 * and {@link #getMeasuredHeight()}.
319 * </p>
320 *
321 * <p>
322 * The second pair is simply known as <em>width</em> and <em>height</em>, or
323 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
324 * dimensions define the actual size of the view on screen, at drawing time and
325 * after layout. These values may, but do not have to, be different from the
326 * measured width and height. The width and height can be obtained by calling
327 * {@link #getWidth()} and {@link #getHeight()}.
328 * </p>
329 *
330 * <p>
331 * To measure its dimensions, a view takes into account its padding. The padding
332 * is expressed in pixels for the left, top, right and bottom parts of the view.
333 * Padding can be used to offset the content of the view by a specific amount of
334 * pixels. For instance, a left padding of 2 will push the view's content by
335 * 2 pixels to the right of the left edge. Padding can be set using the
336 * {@link #setPadding(int, int, int, int)} method and queried by calling
337 * {@link #getPaddingLeft()}, {@link #getPaddingTop()},
338 * {@link #getPaddingRight()} and {@link #getPaddingBottom()}.
339 * </p>
340 *
341 * <p>
342 * Even though a view can define a padding, it does not provide any support for
343 * margins. However, view groups provide such a support. Refer to
344 * {@link android.view.ViewGroup} and
345 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
346 * </p>
347 *
348 * <a name="Layout"></a>
349 * <h3>Layout</h3>
350 * <p>
351 * Layout is a two pass process: a measure pass and a layout pass. The measuring
352 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
353 * of the view tree. Each view pushes dimension specifications down the tree
354 * during the recursion. At the end of the measure pass, every view has stored
355 * its measurements. The second pass happens in
356 * {@link #layout(int,int,int,int)} and is also top-down. During
357 * this pass each parent is responsible for positioning all of its children
358 * using the sizes computed in the measure pass.
359 * </p>
360 *
361 * <p>
362 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
363 * {@link #getMeasuredHeight()} values must be set, along with those for all of
364 * that view's descendants. A view's measured width and measured height values
365 * must respect the constraints imposed by the view's parents. This guarantees
366 * that at the end of the measure pass, all parents accept all of their
367 * children's measurements. A parent view may call measure() more than once on
368 * its children. For example, the parent may measure each child once with
369 * unspecified dimensions to find out how big they want to be, then call
370 * measure() on them again with actual numbers if the sum of all the children's
371 * unconstrained sizes is too big or too small.
372 * </p>
373 *
374 * <p>
375 * The measure pass uses two classes to communicate dimensions. The
376 * {@link MeasureSpec} class is used by views to tell their parents how they
377 * want to be measured and positioned. The base LayoutParams class just
378 * describes how big the view wants to be for both width and height. For each
379 * dimension, it can specify one of:
380 * <ul>
381 * <li> an exact number
382 * <li>FILL_PARENT, which means the view wants to be as big as its parent
383 * (minus padding)
384 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
385 * enclose its content (plus padding).
386 * </ul>
387 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
388 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
389 * an X and Y value.
390 * </p>
391 *
392 * <p>
393 * MeasureSpecs are used to push requirements down the tree from parent to
394 * child. A MeasureSpec can be in one of three modes:
395 * <ul>
396 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
397 * of a child view. For example, a LinearLayout may call measure() on its child
398 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
399 * tall the child view wants to be given a width of 240 pixels.
400 * <li>EXACTLY: This is used by the parent to impose an exact size on the
401 * child. The child must use this size, and guarantee that all of its
402 * descendants will fit within this size.
403 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
404 * child. The child must gurantee that it and all of its descendants will fit
405 * within this size.
406 * </ul>
407 * </p>
408 *
409 * <p>
410 * To intiate a layout, call {@link #requestLayout}. This method is typically
411 * called by a view on itself when it believes that is can no longer fit within
412 * its current bounds.
413 * </p>
414 *
415 * <a name="Drawing"></a>
416 * <h3>Drawing</h3>
417 * <p>
418 * Drawing is handled by walking the tree and rendering each view that
419 * intersects the the invalid region. Because the tree is traversed in-order,
420 * this means that parents will draw before (i.e., behind) their children, with
421 * siblings drawn in the order they appear in the tree.
422 * If you set a background drawable for a View, then the View will draw it for you
423 * before calling back to its <code>onDraw()</code> method.
424 * </p>
425 *
426 * <p>
427 * Note that the framework will not draw views that are not in the invalid region.
428 * </p>
429 *
430 * <p>
431 * To force a view to draw, call {@link #invalidate()}.
432 * </p>
433 *
434 * <a name="EventHandlingThreading"></a>
435 * <h3>Event Handling and Threading</h3>
436 * <p>
437 * The basic cycle of a view is as follows:
438 * <ol>
439 * <li>An event comes in and is dispatched to the appropriate view. The view
440 * handles the event and notifies any listeners.</li>
441 * <li>If in the course of processing the event, the view's bounds may need
442 * to be changed, the view will call {@link #requestLayout()}.</li>
443 * <li>Similarly, if in the course of processing the event the view's appearance
444 * may need to be changed, the view will call {@link #invalidate()}.</li>
445 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
446 * the framework will take care of measuring, laying out, and drawing the tree
447 * as appropriate.</li>
448 * </ol>
449 * </p>
450 *
451 * <p><em>Note: The entire view tree is single threaded. You must always be on
452 * the UI thread when calling any method on any view.</em>
453 * If you are doing work on other threads and want to update the state of a view
454 * from that thread, you should use a {@link Handler}.
455 * </p>
456 *
457 * <a name="FocusHandling"></a>
458 * <h3>Focus Handling</h3>
459 * <p>
460 * The framework will handle routine focus movement in response to user input.
461 * This includes changing the focus as views are removed or hidden, or as new
462 * views become available. Views indicate their willingness to take focus
463 * through the {@link #isFocusable} method. To change whether a view can take
464 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
465 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
466 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
467 * </p>
468 * <p>
469 * Focus movement is based on an algorithm which finds the nearest neighbor in a
470 * given direction. In rare cases, the default algorithm may not match the
471 * intended behavior of the developer. In these situations, you can provide
472 * explicit overrides by using these XML attributes in the layout file:
473 * <pre>
474 * nextFocusDown
475 * nextFocusLeft
476 * nextFocusRight
477 * nextFocusUp
478 * </pre>
479 * </p>
480 *
481 *
482 * <p>
483 * To get a particular view to take focus, call {@link #requestFocus()}.
484 * </p>
485 *
486 * <a name="TouchMode"></a>
487 * <h3>Touch Mode</h3>
488 * <p>
489 * When a user is navigating a user interface via directional keys such as a D-pad, it is
490 * necessary to give focus to actionable items such as buttons so the user can see
491 * what will take input.  If the device has touch capabilities, however, and the user
492 * begins interacting with the interface by touching it, it is no longer necessary to
493 * always highlight, or give focus to, a particular view.  This motivates a mode
494 * for interaction named 'touch mode'.
495 * </p>
496 * <p>
497 * For a touch capable device, once the user touches the screen, the device
498 * will enter touch mode.  From this point onward, only views for which
499 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
500 * Other views that are touchable, like buttons, will not take focus when touched; they will
501 * only fire the on click listeners.
502 * </p>
503 * <p>
504 * Any time a user hits a directional key, such as a D-pad direction, the view device will
505 * exit touch mode, and find a view to take focus, so that the user may resume interacting
506 * with the user interface without touching the screen again.
507 * </p>
508 * <p>
509 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
510 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
511 * </p>
512 *
513 * <a name="Scrolling"></a>
514 * <h3>Scrolling</h3>
515 * <p>
516 * The framework provides basic support for views that wish to internally
517 * scroll their content. This includes keeping track of the X and Y scroll
518 * offset as well as mechanisms for drawing scrollbars. See
519 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
520 * {@link #awakenScrollBars()} for more details.
521 * </p>
522 *
523 * <a name="Tags"></a>
524 * <h3>Tags</h3>
525 * <p>
526 * Unlike IDs, tags are not used to identify views. Tags are essentially an
527 * extra piece of information that can be associated with a view. They are most
528 * often used as a convenience to store data related to views in the views
529 * themselves rather than by putting them in a separate structure.
530 * </p>
531 *
532 * <a name="Animation"></a>
533 * <h3>Animation</h3>
534 * <p>
535 * You can attach an {@link Animation} object to a view using
536 * {@link #setAnimation(Animation)} or
537 * {@link #startAnimation(Animation)}. The animation can alter the scale,
538 * rotation, translation and alpha of a view over time. If the animation is
539 * attached to a view that has children, the animation will affect the entire
540 * subtree rooted by that node. When an animation is started, the framework will
541 * take care of redrawing the appropriate views until the animation completes.
542 * </p>
543 *
544 * @attr ref android.R.styleable#View_background
545 * @attr ref android.R.styleable#View_clickable
546 * @attr ref android.R.styleable#View_contentDescription
547 * @attr ref android.R.styleable#View_drawingCacheQuality
548 * @attr ref android.R.styleable#View_duplicateParentState
549 * @attr ref android.R.styleable#View_id
550 * @attr ref android.R.styleable#View_fadingEdge
551 * @attr ref android.R.styleable#View_fadingEdgeLength
552 * @attr ref android.R.styleable#View_fitsSystemWindows
553 * @attr ref android.R.styleable#View_isScrollContainer
554 * @attr ref android.R.styleable#View_focusable
555 * @attr ref android.R.styleable#View_focusableInTouchMode
556 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
557 * @attr ref android.R.styleable#View_keepScreenOn
558 * @attr ref android.R.styleable#View_longClickable
559 * @attr ref android.R.styleable#View_minHeight
560 * @attr ref android.R.styleable#View_minWidth
561 * @attr ref android.R.styleable#View_nextFocusDown
562 * @attr ref android.R.styleable#View_nextFocusLeft
563 * @attr ref android.R.styleable#View_nextFocusRight
564 * @attr ref android.R.styleable#View_nextFocusUp
565 * @attr ref android.R.styleable#View_onClick
566 * @attr ref android.R.styleable#View_padding
567 * @attr ref android.R.styleable#View_paddingBottom
568 * @attr ref android.R.styleable#View_paddingLeft
569 * @attr ref android.R.styleable#View_paddingRight
570 * @attr ref android.R.styleable#View_paddingTop
571 * @attr ref android.R.styleable#View_saveEnabled
572 * @attr ref android.R.styleable#View_scrollX
573 * @attr ref android.R.styleable#View_scrollY
574 * @attr ref android.R.styleable#View_scrollbarSize
575 * @attr ref android.R.styleable#View_scrollbarStyle
576 * @attr ref android.R.styleable#View_scrollbars
577 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
578 * @attr ref android.R.styleable#View_scrollbarFadeDuration
579 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
580 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
581 * @attr ref android.R.styleable#View_scrollbarThumbVertical
582 * @attr ref android.R.styleable#View_scrollbarTrackVertical
583 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
584 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
585 * @attr ref android.R.styleable#View_soundEffectsEnabled
586 * @attr ref android.R.styleable#View_tag
587 * @attr ref android.R.styleable#View_visibility
588 *
589 * @see android.view.ViewGroup
590 */
591public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {
592    private static final boolean DBG = false;
593
594    /**
595     * The logging tag used by this class with android.util.Log.
596     */
597    protected static final String VIEW_LOG_TAG = "View";
598
599    /**
600     * Used to mark a View that has no ID.
601     */
602    public static final int NO_ID = -1;
603
604    /**
605     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
606     * calling setFlags.
607     */
608    private static final int NOT_FOCUSABLE = 0x00000000;
609
610    /**
611     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
612     * setFlags.
613     */
614    private static final int FOCUSABLE = 0x00000001;
615
616    /**
617     * Mask for use with setFlags indicating bits used for focus.
618     */
619    private static final int FOCUSABLE_MASK = 0x00000001;
620
621    /**
622     * This view will adjust its padding to fit sytem windows (e.g. status bar)
623     */
624    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
625
626    /**
627     * This view is visible.  Use with {@link #setVisibility}.
628     */
629    public static final int VISIBLE = 0x00000000;
630
631    /**
632     * This view is invisible, but it still takes up space for layout purposes.
633     * Use with {@link #setVisibility}.
634     */
635    public static final int INVISIBLE = 0x00000004;
636
637    /**
638     * This view is invisible, and it doesn't take any space for layout
639     * purposes. Use with {@link #setVisibility}.
640     */
641    public static final int GONE = 0x00000008;
642
643    /**
644     * Mask for use with setFlags indicating bits used for visibility.
645     * {@hide}
646     */
647    static final int VISIBILITY_MASK = 0x0000000C;
648
649    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
650
651    /**
652     * This view is enabled. Intrepretation varies by subclass.
653     * Use with ENABLED_MASK when calling setFlags.
654     * {@hide}
655     */
656    static final int ENABLED = 0x00000000;
657
658    /**
659     * This view is disabled. Intrepretation varies by subclass.
660     * Use with ENABLED_MASK when calling setFlags.
661     * {@hide}
662     */
663    static final int DISABLED = 0x00000020;
664
665   /**
666    * Mask for use with setFlags indicating bits used for indicating whether
667    * this view is enabled
668    * {@hide}
669    */
670    static final int ENABLED_MASK = 0x00000020;
671
672    /**
673     * This view won't draw. {@link #onDraw} won't be called and further
674     * optimizations
675     * will be performed. It is okay to have this flag set and a background.
676     * Use with DRAW_MASK when calling setFlags.
677     * {@hide}
678     */
679    static final int WILL_NOT_DRAW = 0x00000080;
680
681    /**
682     * Mask for use with setFlags indicating bits used for indicating whether
683     * this view is will draw
684     * {@hide}
685     */
686    static final int DRAW_MASK = 0x00000080;
687
688    /**
689     * <p>This view doesn't show scrollbars.</p>
690     * {@hide}
691     */
692    static final int SCROLLBARS_NONE = 0x00000000;
693
694    /**
695     * <p>This view shows horizontal scrollbars.</p>
696     * {@hide}
697     */
698    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
699
700    /**
701     * <p>This view shows vertical scrollbars.</p>
702     * {@hide}
703     */
704    static final int SCROLLBARS_VERTICAL = 0x00000200;
705
706    /**
707     * <p>Mask for use with setFlags indicating bits used for indicating which
708     * scrollbars are enabled.</p>
709     * {@hide}
710     */
711    static final int SCROLLBARS_MASK = 0x00000300;
712
713    // note 0x00000400 and 0x00000800 are now available for next flags...
714
715    /**
716     * <p>This view doesn't show fading edges.</p>
717     * {@hide}
718     */
719    static final int FADING_EDGE_NONE = 0x00000000;
720
721    /**
722     * <p>This view shows horizontal fading edges.</p>
723     * {@hide}
724     */
725    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
726
727    /**
728     * <p>This view shows vertical fading edges.</p>
729     * {@hide}
730     */
731    static final int FADING_EDGE_VERTICAL = 0x00002000;
732
733    /**
734     * <p>Mask for use with setFlags indicating bits used for indicating which
735     * fading edges are enabled.</p>
736     * {@hide}
737     */
738    static final int FADING_EDGE_MASK = 0x00003000;
739
740    /**
741     * <p>Indicates this view can be clicked. When clickable, a View reacts
742     * to clicks by notifying the OnClickListener.<p>
743     * {@hide}
744     */
745    static final int CLICKABLE = 0x00004000;
746
747    /**
748     * <p>Indicates this view is caching its drawing into a bitmap.</p>
749     * {@hide}
750     */
751    static final int DRAWING_CACHE_ENABLED = 0x00008000;
752
753    /**
754     * <p>Indicates that no icicle should be saved for this view.<p>
755     * {@hide}
756     */
757    static final int SAVE_DISABLED = 0x000010000;
758
759    /**
760     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
761     * property.</p>
762     * {@hide}
763     */
764    static final int SAVE_DISABLED_MASK = 0x000010000;
765
766    /**
767     * <p>Indicates that no drawing cache should ever be created for this view.<p>
768     * {@hide}
769     */
770    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
771
772    /**
773     * <p>Indicates this view can take / keep focus when int touch mode.</p>
774     * {@hide}
775     */
776    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
777
778    /**
779     * <p>Enables low quality mode for the drawing cache.</p>
780     */
781    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
782
783    /**
784     * <p>Enables high quality mode for the drawing cache.</p>
785     */
786    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
787
788    /**
789     * <p>Enables automatic quality mode for the drawing cache.</p>
790     */
791    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
792
793    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
794            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
795    };
796
797    /**
798     * <p>Mask for use with setFlags indicating bits used for the cache
799     * quality property.</p>
800     * {@hide}
801     */
802    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
803
804    /**
805     * <p>
806     * Indicates this view can be long clicked. When long clickable, a View
807     * reacts to long clicks by notifying the OnLongClickListener or showing a
808     * context menu.
809     * </p>
810     * {@hide}
811     */
812    static final int LONG_CLICKABLE = 0x00200000;
813
814    /**
815     * <p>Indicates that this view gets its drawable states from its direct parent
816     * and ignores its original internal states.</p>
817     *
818     * @hide
819     */
820    static final int DUPLICATE_PARENT_STATE = 0x00400000;
821
822    /**
823     * The scrollbar style to display the scrollbars inside the content area,
824     * without increasing the padding. The scrollbars will be overlaid with
825     * translucency on the view's content.
826     */
827    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
828
829    /**
830     * The scrollbar style to display the scrollbars inside the padded area,
831     * increasing the padding of the view. The scrollbars will not overlap the
832     * content area of the view.
833     */
834    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
835
836    /**
837     * The scrollbar style to display the scrollbars at the edge of the view,
838     * without increasing the padding. The scrollbars will be overlaid with
839     * translucency.
840     */
841    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
842
843    /**
844     * The scrollbar style to display the scrollbars at the edge of the view,
845     * increasing the padding of the view. The scrollbars will only overlap the
846     * background, if any.
847     */
848    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
849
850    /**
851     * Mask to check if the scrollbar style is overlay or inset.
852     * {@hide}
853     */
854    static final int SCROLLBARS_INSET_MASK = 0x01000000;
855
856    /**
857     * Mask to check if the scrollbar style is inside or outside.
858     * {@hide}
859     */
860    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
861
862    /**
863     * Mask for scrollbar style.
864     * {@hide}
865     */
866    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
867
868    /**
869     * View flag indicating that the screen should remain on while the
870     * window containing this view is visible to the user.  This effectively
871     * takes care of automatically setting the WindowManager's
872     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
873     */
874    public static final int KEEP_SCREEN_ON = 0x04000000;
875
876    /**
877     * View flag indicating whether this view should have sound effects enabled
878     * for events such as clicking and touching.
879     */
880    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
881
882    /**
883     * View flag indicating whether this view should have haptic feedback
884     * enabled for events such as long presses.
885     */
886    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
887
888    /**
889     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
890     * should add all focusable Views regardless if they are focusable in touch mode.
891     */
892    public static final int FOCUSABLES_ALL = 0x00000000;
893
894    /**
895     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
896     * should add only Views focusable in touch mode.
897     */
898    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
899
900    /**
901     * Use with {@link #focusSearch}. Move focus to the previous selectable
902     * item.
903     */
904    public static final int FOCUS_BACKWARD = 0x00000001;
905
906    /**
907     * Use with {@link #focusSearch}. Move focus to the next selectable
908     * item.
909     */
910    public static final int FOCUS_FORWARD = 0x00000002;
911
912    /**
913     * Use with {@link #focusSearch}. Move focus to the left.
914     */
915    public static final int FOCUS_LEFT = 0x00000011;
916
917    /**
918     * Use with {@link #focusSearch}. Move focus up.
919     */
920    public static final int FOCUS_UP = 0x00000021;
921
922    /**
923     * Use with {@link #focusSearch}. Move focus to the right.
924     */
925    public static final int FOCUS_RIGHT = 0x00000042;
926
927    /**
928     * Use with {@link #focusSearch}. Move focus down.
929     */
930    public static final int FOCUS_DOWN = 0x00000082;
931
932    /**
933     * Base View state sets
934     */
935    // Singles
936    /**
937     * Indicates the view has no states set. States are used with
938     * {@link android.graphics.drawable.Drawable} to change the drawing of the
939     * view depending on its state.
940     *
941     * @see android.graphics.drawable.Drawable
942     * @see #getDrawableState()
943     */
944    protected static final int[] EMPTY_STATE_SET = {};
945    /**
946     * Indicates the view is enabled. States are used with
947     * {@link android.graphics.drawable.Drawable} to change the drawing of the
948     * view depending on its state.
949     *
950     * @see android.graphics.drawable.Drawable
951     * @see #getDrawableState()
952     */
953    protected static final int[] ENABLED_STATE_SET = {R.attr.state_enabled};
954    /**
955     * Indicates the view is focused. States are used with
956     * {@link android.graphics.drawable.Drawable} to change the drawing of the
957     * view depending on its state.
958     *
959     * @see android.graphics.drawable.Drawable
960     * @see #getDrawableState()
961     */
962    protected static final int[] FOCUSED_STATE_SET = {R.attr.state_focused};
963    /**
964     * Indicates the view is selected. States are used with
965     * {@link android.graphics.drawable.Drawable} to change the drawing of the
966     * view depending on its state.
967     *
968     * @see android.graphics.drawable.Drawable
969     * @see #getDrawableState()
970     */
971    protected static final int[] SELECTED_STATE_SET = {R.attr.state_selected};
972    /**
973     * Indicates the view is pressed. States are used with
974     * {@link android.graphics.drawable.Drawable} to change the drawing of the
975     * view depending on its state.
976     *
977     * @see android.graphics.drawable.Drawable
978     * @see #getDrawableState()
979     * @hide
980     */
981    protected static final int[] PRESSED_STATE_SET = {R.attr.state_pressed};
982    /**
983     * Indicates the view's window has focus. States are used with
984     * {@link android.graphics.drawable.Drawable} to change the drawing of the
985     * view depending on its state.
986     *
987     * @see android.graphics.drawable.Drawable
988     * @see #getDrawableState()
989     */
990    protected static final int[] WINDOW_FOCUSED_STATE_SET =
991            {R.attr.state_window_focused};
992    // Doubles
993    /**
994     * Indicates the view is enabled and has the focus.
995     *
996     * @see #ENABLED_STATE_SET
997     * @see #FOCUSED_STATE_SET
998     */
999    protected static final int[] ENABLED_FOCUSED_STATE_SET =
1000            stateSetUnion(ENABLED_STATE_SET, FOCUSED_STATE_SET);
1001    /**
1002     * Indicates the view is enabled and selected.
1003     *
1004     * @see #ENABLED_STATE_SET
1005     * @see #SELECTED_STATE_SET
1006     */
1007    protected static final int[] ENABLED_SELECTED_STATE_SET =
1008            stateSetUnion(ENABLED_STATE_SET, SELECTED_STATE_SET);
1009    /**
1010     * Indicates the view is enabled and that its window has focus.
1011     *
1012     * @see #ENABLED_STATE_SET
1013     * @see #WINDOW_FOCUSED_STATE_SET
1014     */
1015    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET =
1016            stateSetUnion(ENABLED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1017    /**
1018     * Indicates the view is focused and selected.
1019     *
1020     * @see #FOCUSED_STATE_SET
1021     * @see #SELECTED_STATE_SET
1022     */
1023    protected static final int[] FOCUSED_SELECTED_STATE_SET =
1024            stateSetUnion(FOCUSED_STATE_SET, SELECTED_STATE_SET);
1025    /**
1026     * Indicates the view has the focus and that its window has the focus.
1027     *
1028     * @see #FOCUSED_STATE_SET
1029     * @see #WINDOW_FOCUSED_STATE_SET
1030     */
1031    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET =
1032            stateSetUnion(FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1033    /**
1034     * Indicates the view is selected and that its window has the focus.
1035     *
1036     * @see #SELECTED_STATE_SET
1037     * @see #WINDOW_FOCUSED_STATE_SET
1038     */
1039    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET =
1040            stateSetUnion(SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1041    // Triples
1042    /**
1043     * Indicates the view is enabled, focused and selected.
1044     *
1045     * @see #ENABLED_STATE_SET
1046     * @see #FOCUSED_STATE_SET
1047     * @see #SELECTED_STATE_SET
1048     */
1049    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET =
1050            stateSetUnion(ENABLED_FOCUSED_STATE_SET, SELECTED_STATE_SET);
1051    /**
1052     * Indicates the view is enabled, focused and its window has the focus.
1053     *
1054     * @see #ENABLED_STATE_SET
1055     * @see #FOCUSED_STATE_SET
1056     * @see #WINDOW_FOCUSED_STATE_SET
1057     */
1058    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET =
1059            stateSetUnion(ENABLED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1060    /**
1061     * Indicates the view is enabled, selected and its window has the focus.
1062     *
1063     * @see #ENABLED_STATE_SET
1064     * @see #SELECTED_STATE_SET
1065     * @see #WINDOW_FOCUSED_STATE_SET
1066     */
1067    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET =
1068            stateSetUnion(ENABLED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1069    /**
1070     * Indicates the view is focused, selected and its window has the focus.
1071     *
1072     * @see #FOCUSED_STATE_SET
1073     * @see #SELECTED_STATE_SET
1074     * @see #WINDOW_FOCUSED_STATE_SET
1075     */
1076    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET =
1077            stateSetUnion(FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1078    /**
1079     * Indicates the view is enabled, focused, selected and its window
1080     * has the focus.
1081     *
1082     * @see #ENABLED_STATE_SET
1083     * @see #FOCUSED_STATE_SET
1084     * @see #SELECTED_STATE_SET
1085     * @see #WINDOW_FOCUSED_STATE_SET
1086     */
1087    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET =
1088            stateSetUnion(ENABLED_FOCUSED_SELECTED_STATE_SET,
1089                          WINDOW_FOCUSED_STATE_SET);
1090
1091    /**
1092     * Indicates the view is pressed and its window has the focus.
1093     *
1094     * @see #PRESSED_STATE_SET
1095     * @see #WINDOW_FOCUSED_STATE_SET
1096     */
1097    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET =
1098            stateSetUnion(PRESSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1099
1100    /**
1101     * Indicates the view is pressed and selected.
1102     *
1103     * @see #PRESSED_STATE_SET
1104     * @see #SELECTED_STATE_SET
1105     */
1106    protected static final int[] PRESSED_SELECTED_STATE_SET =
1107            stateSetUnion(PRESSED_STATE_SET, SELECTED_STATE_SET);
1108
1109    /**
1110     * Indicates the view is pressed, selected and its window has the focus.
1111     *
1112     * @see #PRESSED_STATE_SET
1113     * @see #SELECTED_STATE_SET
1114     * @see #WINDOW_FOCUSED_STATE_SET
1115     */
1116    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET =
1117            stateSetUnion(PRESSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1118
1119    /**
1120     * Indicates the view is pressed and focused.
1121     *
1122     * @see #PRESSED_STATE_SET
1123     * @see #FOCUSED_STATE_SET
1124     */
1125    protected static final int[] PRESSED_FOCUSED_STATE_SET =
1126            stateSetUnion(PRESSED_STATE_SET, FOCUSED_STATE_SET);
1127
1128    /**
1129     * Indicates the view is pressed, focused and its window has the focus.
1130     *
1131     * @see #PRESSED_STATE_SET
1132     * @see #FOCUSED_STATE_SET
1133     * @see #WINDOW_FOCUSED_STATE_SET
1134     */
1135    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET =
1136            stateSetUnion(PRESSED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1137
1138    /**
1139     * Indicates the view is pressed, focused and selected.
1140     *
1141     * @see #PRESSED_STATE_SET
1142     * @see #SELECTED_STATE_SET
1143     * @see #FOCUSED_STATE_SET
1144     */
1145    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET =
1146            stateSetUnion(PRESSED_FOCUSED_STATE_SET, SELECTED_STATE_SET);
1147
1148    /**
1149     * Indicates the view is pressed, focused, selected and its window has the focus.
1150     *
1151     * @see #PRESSED_STATE_SET
1152     * @see #FOCUSED_STATE_SET
1153     * @see #SELECTED_STATE_SET
1154     * @see #WINDOW_FOCUSED_STATE_SET
1155     */
1156    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET =
1157            stateSetUnion(PRESSED_FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1158
1159    /**
1160     * Indicates the view is pressed and enabled.
1161     *
1162     * @see #PRESSED_STATE_SET
1163     * @see #ENABLED_STATE_SET
1164     */
1165    protected static final int[] PRESSED_ENABLED_STATE_SET =
1166            stateSetUnion(PRESSED_STATE_SET, ENABLED_STATE_SET);
1167
1168    /**
1169     * Indicates the view is pressed, enabled and its window has the focus.
1170     *
1171     * @see #PRESSED_STATE_SET
1172     * @see #ENABLED_STATE_SET
1173     * @see #WINDOW_FOCUSED_STATE_SET
1174     */
1175    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET =
1176            stateSetUnion(PRESSED_ENABLED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1177
1178    /**
1179     * Indicates the view is pressed, enabled and selected.
1180     *
1181     * @see #PRESSED_STATE_SET
1182     * @see #ENABLED_STATE_SET
1183     * @see #SELECTED_STATE_SET
1184     */
1185    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET =
1186            stateSetUnion(PRESSED_ENABLED_STATE_SET, SELECTED_STATE_SET);
1187
1188    /**
1189     * Indicates the view is pressed, enabled, selected and its window has the
1190     * focus.
1191     *
1192     * @see #PRESSED_STATE_SET
1193     * @see #ENABLED_STATE_SET
1194     * @see #SELECTED_STATE_SET
1195     * @see #WINDOW_FOCUSED_STATE_SET
1196     */
1197    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET =
1198            stateSetUnion(PRESSED_ENABLED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1199
1200    /**
1201     * Indicates the view is pressed, enabled and focused.
1202     *
1203     * @see #PRESSED_STATE_SET
1204     * @see #ENABLED_STATE_SET
1205     * @see #FOCUSED_STATE_SET
1206     */
1207    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET =
1208            stateSetUnion(PRESSED_ENABLED_STATE_SET, FOCUSED_STATE_SET);
1209
1210    /**
1211     * Indicates the view is pressed, enabled, focused and its window has the
1212     * focus.
1213     *
1214     * @see #PRESSED_STATE_SET
1215     * @see #ENABLED_STATE_SET
1216     * @see #FOCUSED_STATE_SET
1217     * @see #WINDOW_FOCUSED_STATE_SET
1218     */
1219    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET =
1220            stateSetUnion(PRESSED_ENABLED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1221
1222    /**
1223     * Indicates the view is pressed, enabled, focused and selected.
1224     *
1225     * @see #PRESSED_STATE_SET
1226     * @see #ENABLED_STATE_SET
1227     * @see #SELECTED_STATE_SET
1228     * @see #FOCUSED_STATE_SET
1229     */
1230    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET =
1231            stateSetUnion(PRESSED_ENABLED_FOCUSED_STATE_SET, SELECTED_STATE_SET);
1232
1233    /**
1234     * Indicates the view is pressed, enabled, focused, selected and its window
1235     * has the focus.
1236     *
1237     * @see #PRESSED_STATE_SET
1238     * @see #ENABLED_STATE_SET
1239     * @see #SELECTED_STATE_SET
1240     * @see #FOCUSED_STATE_SET
1241     * @see #WINDOW_FOCUSED_STATE_SET
1242     */
1243    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET =
1244            stateSetUnion(PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1245
1246    /**
1247     * The order here is very important to {@link #getDrawableState()}
1248     */
1249    private static final int[][] VIEW_STATE_SETS = {
1250        EMPTY_STATE_SET,                                           // 0 0 0 0 0
1251        WINDOW_FOCUSED_STATE_SET,                                  // 0 0 0 0 1
1252        SELECTED_STATE_SET,                                        // 0 0 0 1 0
1253        SELECTED_WINDOW_FOCUSED_STATE_SET,                         // 0 0 0 1 1
1254        FOCUSED_STATE_SET,                                         // 0 0 1 0 0
1255        FOCUSED_WINDOW_FOCUSED_STATE_SET,                          // 0 0 1 0 1
1256        FOCUSED_SELECTED_STATE_SET,                                // 0 0 1 1 0
1257        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET,                 // 0 0 1 1 1
1258        ENABLED_STATE_SET,                                         // 0 1 0 0 0
1259        ENABLED_WINDOW_FOCUSED_STATE_SET,                          // 0 1 0 0 1
1260        ENABLED_SELECTED_STATE_SET,                                // 0 1 0 1 0
1261        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET,                 // 0 1 0 1 1
1262        ENABLED_FOCUSED_STATE_SET,                                 // 0 1 1 0 0
1263        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET,                  // 0 1 1 0 1
1264        ENABLED_FOCUSED_SELECTED_STATE_SET,                        // 0 1 1 1 0
1265        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET,         // 0 1 1 1 1
1266        PRESSED_STATE_SET,                                         // 1 0 0 0 0
1267        PRESSED_WINDOW_FOCUSED_STATE_SET,                          // 1 0 0 0 1
1268        PRESSED_SELECTED_STATE_SET,                                // 1 0 0 1 0
1269        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET,                 // 1 0 0 1 1
1270        PRESSED_FOCUSED_STATE_SET,                                 // 1 0 1 0 0
1271        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET,                  // 1 0 1 0 1
1272        PRESSED_FOCUSED_SELECTED_STATE_SET,                        // 1 0 1 1 0
1273        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET,         // 1 0 1 1 1
1274        PRESSED_ENABLED_STATE_SET,                                 // 1 1 0 0 0
1275        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET,                  // 1 1 0 0 1
1276        PRESSED_ENABLED_SELECTED_STATE_SET,                        // 1 1 0 1 0
1277        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET,         // 1 1 0 1 1
1278        PRESSED_ENABLED_FOCUSED_STATE_SET,                         // 1 1 1 0 0
1279        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET,          // 1 1 1 0 1
1280        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET,                // 1 1 1 1 0
1281        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 1 1 1 1 1
1282    };
1283
1284    /**
1285     * Used by views that contain lists of items. This state indicates that
1286     * the view is showing the last item.
1287     * @hide
1288     */
1289    protected static final int[] LAST_STATE_SET = {R.attr.state_last};
1290    /**
1291     * Used by views that contain lists of items. This state indicates that
1292     * the view is showing the first item.
1293     * @hide
1294     */
1295    protected static final int[] FIRST_STATE_SET = {R.attr.state_first};
1296    /**
1297     * Used by views that contain lists of items. This state indicates that
1298     * the view is showing the middle item.
1299     * @hide
1300     */
1301    protected static final int[] MIDDLE_STATE_SET = {R.attr.state_middle};
1302    /**
1303     * Used by views that contain lists of items. This state indicates that
1304     * the view is showing only one item.
1305     * @hide
1306     */
1307    protected static final int[] SINGLE_STATE_SET = {R.attr.state_single};
1308    /**
1309     * Used by views that contain lists of items. This state indicates that
1310     * the view is pressed and showing the last item.
1311     * @hide
1312     */
1313    protected static final int[] PRESSED_LAST_STATE_SET = {R.attr.state_last, R.attr.state_pressed};
1314    /**
1315     * Used by views that contain lists of items. This state indicates that
1316     * the view is pressed and showing the first item.
1317     * @hide
1318     */
1319    protected static final int[] PRESSED_FIRST_STATE_SET = {R.attr.state_first, R.attr.state_pressed};
1320    /**
1321     * Used by views that contain lists of items. This state indicates that
1322     * the view is pressed and showing the middle item.
1323     * @hide
1324     */
1325    protected static final int[] PRESSED_MIDDLE_STATE_SET = {R.attr.state_middle, R.attr.state_pressed};
1326    /**
1327     * Used by views that contain lists of items. This state indicates that
1328     * the view is pressed and showing only one item.
1329     * @hide
1330     */
1331    protected static final int[] PRESSED_SINGLE_STATE_SET = {R.attr.state_single, R.attr.state_pressed};
1332
1333    /**
1334     * Temporary Rect currently for use in setBackground().  This will probably
1335     * be extended in the future to hold our own class with more than just
1336     * a Rect. :)
1337     */
1338    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1339
1340    /**
1341     * Map used to store views' tags.
1342     */
1343    private static WeakHashMap<View, SparseArray<Object>> sTags;
1344
1345    /**
1346     * Lock used to access sTags.
1347     */
1348    private static final Object sTagsLock = new Object();
1349
1350    /**
1351     * The animation currently associated with this view.
1352     * @hide
1353     */
1354    protected Animation mCurrentAnimation = null;
1355
1356    /**
1357     * Width as measured during measure pass.
1358     * {@hide}
1359     */
1360    @ViewDebug.ExportedProperty
1361    protected int mMeasuredWidth;
1362
1363    /**
1364     * Height as measured during measure pass.
1365     * {@hide}
1366     */
1367    @ViewDebug.ExportedProperty
1368    protected int mMeasuredHeight;
1369
1370    /**
1371     * The view's identifier.
1372     * {@hide}
1373     *
1374     * @see #setId(int)
1375     * @see #getId()
1376     */
1377    @ViewDebug.ExportedProperty(resolveId = true)
1378    int mID = NO_ID;
1379
1380    /**
1381     * The view's tag.
1382     * {@hide}
1383     *
1384     * @see #setTag(Object)
1385     * @see #getTag()
1386     */
1387    protected Object mTag;
1388
1389    // for mPrivateFlags:
1390    /** {@hide} */
1391    static final int WANTS_FOCUS                    = 0x00000001;
1392    /** {@hide} */
1393    static final int FOCUSED                        = 0x00000002;
1394    /** {@hide} */
1395    static final int SELECTED                       = 0x00000004;
1396    /** {@hide} */
1397    static final int IS_ROOT_NAMESPACE              = 0x00000008;
1398    /** {@hide} */
1399    static final int HAS_BOUNDS                     = 0x00000010;
1400    /** {@hide} */
1401    static final int DRAWN                          = 0x00000020;
1402    /**
1403     * When this flag is set, this view is running an animation on behalf of its
1404     * children and should therefore not cancel invalidate requests, even if they
1405     * lie outside of this view's bounds.
1406     *
1407     * {@hide}
1408     */
1409    static final int DRAW_ANIMATION                 = 0x00000040;
1410    /** {@hide} */
1411    static final int SKIP_DRAW                      = 0x00000080;
1412    /** {@hide} */
1413    static final int ONLY_DRAWS_BACKGROUND          = 0x00000100;
1414    /** {@hide} */
1415    static final int REQUEST_TRANSPARENT_REGIONS    = 0x00000200;
1416    /** {@hide} */
1417    static final int DRAWABLE_STATE_DIRTY           = 0x00000400;
1418    /** {@hide} */
1419    static final int MEASURED_DIMENSION_SET         = 0x00000800;
1420    /** {@hide} */
1421    static final int FORCE_LAYOUT                   = 0x00001000;
1422
1423    private static final int LAYOUT_REQUIRED        = 0x00002000;
1424
1425    private static final int PRESSED                = 0x00004000;
1426
1427    /** {@hide} */
1428    static final int DRAWING_CACHE_VALID            = 0x00008000;
1429    /**
1430     * Flag used to indicate that this view should be drawn once more (and only once
1431     * more) after its animation has completed.
1432     * {@hide}
1433     */
1434    static final int ANIMATION_STARTED              = 0x00010000;
1435
1436    private static final int SAVE_STATE_CALLED      = 0x00020000;
1437
1438    /**
1439     * Indicates that the View returned true when onSetAlpha() was called and that
1440     * the alpha must be restored.
1441     * {@hide}
1442     */
1443    static final int ALPHA_SET                      = 0x00040000;
1444
1445    /**
1446     * Set by {@link #setScrollContainer(boolean)}.
1447     */
1448    static final int SCROLL_CONTAINER               = 0x00080000;
1449
1450    /**
1451     * Set by {@link #setScrollContainer(boolean)}.
1452     */
1453    static final int SCROLL_CONTAINER_ADDED         = 0x00100000;
1454
1455    /**
1456     * View flag indicating whether this view was invalidated (fully or partially.)
1457     *
1458     * @hide
1459     */
1460    static final int DIRTY                          = 0x00200000;
1461
1462    /**
1463     * View flag indicating whether this view was invalidated by an opaque
1464     * invalidate request.
1465     *
1466     * @hide
1467     */
1468    static final int DIRTY_OPAQUE                   = 0x00400000;
1469
1470    /**
1471     * Mask for {@link #DIRTY} and {@link #DIRTY_OPAQUE}.
1472     *
1473     * @hide
1474     */
1475    static final int DIRTY_MASK                     = 0x00600000;
1476
1477    /**
1478     * Indicates whether the background is opaque.
1479     *
1480     * @hide
1481     */
1482    static final int OPAQUE_BACKGROUND              = 0x00800000;
1483
1484    /**
1485     * Indicates whether the scrollbars are opaque.
1486     *
1487     * @hide
1488     */
1489    static final int OPAQUE_SCROLLBARS              = 0x01000000;
1490
1491    /**
1492     * Indicates whether the view is opaque.
1493     *
1494     * @hide
1495     */
1496    static final int OPAQUE_MASK                    = 0x01800000;
1497
1498    /**
1499     * The parent this view is attached to.
1500     * {@hide}
1501     *
1502     * @see #getParent()
1503     */
1504    protected ViewParent mParent;
1505
1506    /**
1507     * {@hide}
1508     */
1509    AttachInfo mAttachInfo;
1510
1511    /**
1512     * {@hide}
1513     */
1514    @ViewDebug.ExportedProperty(flagMapping = {
1515        @ViewDebug.FlagToString(mask = FORCE_LAYOUT, equals = FORCE_LAYOUT,
1516                name = "FORCE_LAYOUT"),
1517        @ViewDebug.FlagToString(mask = LAYOUT_REQUIRED, equals = LAYOUT_REQUIRED,
1518                name = "LAYOUT_REQUIRED"),
1519        @ViewDebug.FlagToString(mask = DRAWING_CACHE_VALID, equals = DRAWING_CACHE_VALID,
1520            name = "DRAWING_CACHE_INVALID", outputIf = false),
1521        @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "DRAWN", outputIf = true),
1522        @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "NOT_DRAWN", outputIf = false),
1523        @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
1524        @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY, name = "DIRTY")
1525    })
1526    int mPrivateFlags;
1527
1528    /**
1529     * Count of how many windows this view has been attached to.
1530     */
1531    int mWindowAttachCount;
1532
1533    /**
1534     * The layout parameters associated with this view and used by the parent
1535     * {@link android.view.ViewGroup} to determine how this view should be
1536     * laid out.
1537     * {@hide}
1538     */
1539    protected ViewGroup.LayoutParams mLayoutParams;
1540
1541    /**
1542     * The view flags hold various views states.
1543     * {@hide}
1544     */
1545    @ViewDebug.ExportedProperty
1546    int mViewFlags;
1547
1548    /**
1549     * The distance in pixels from the left edge of this view's parent
1550     * to the left edge of this view.
1551     * {@hide}
1552     */
1553    @ViewDebug.ExportedProperty
1554    protected int mLeft;
1555    /**
1556     * The distance in pixels from the left edge of this view's parent
1557     * to the right edge of this view.
1558     * {@hide}
1559     */
1560    @ViewDebug.ExportedProperty
1561    protected int mRight;
1562    /**
1563     * The distance in pixels from the top edge of this view's parent
1564     * to the top edge of this view.
1565     * {@hide}
1566     */
1567    @ViewDebug.ExportedProperty
1568    protected int mTop;
1569    /**
1570     * The distance in pixels from the top edge of this view's parent
1571     * to the bottom edge of this view.
1572     * {@hide}
1573     */
1574    @ViewDebug.ExportedProperty
1575    protected int mBottom;
1576
1577    /**
1578     * The offset, in pixels, by which the content of this view is scrolled
1579     * horizontally.
1580     * {@hide}
1581     */
1582    @ViewDebug.ExportedProperty
1583    protected int mScrollX;
1584    /**
1585     * The offset, in pixels, by which the content of this view is scrolled
1586     * vertically.
1587     * {@hide}
1588     */
1589    @ViewDebug.ExportedProperty
1590    protected int mScrollY;
1591
1592    /**
1593     * The left padding in pixels, that is the distance in pixels between the
1594     * left edge of this view and the left edge of its content.
1595     * {@hide}
1596     */
1597    @ViewDebug.ExportedProperty
1598    protected int mPaddingLeft;
1599    /**
1600     * The right padding in pixels, that is the distance in pixels between the
1601     * right edge of this view and the right edge of its content.
1602     * {@hide}
1603     */
1604    @ViewDebug.ExportedProperty
1605    protected int mPaddingRight;
1606    /**
1607     * The top padding in pixels, that is the distance in pixels between the
1608     * top edge of this view and the top edge of its content.
1609     * {@hide}
1610     */
1611    @ViewDebug.ExportedProperty
1612    protected int mPaddingTop;
1613    /**
1614     * The bottom padding in pixels, that is the distance in pixels between the
1615     * bottom edge of this view and the bottom edge of its content.
1616     * {@hide}
1617     */
1618    @ViewDebug.ExportedProperty
1619    protected int mPaddingBottom;
1620
1621    /**
1622     * Briefly describes the view and is primarily used for accessibility support.
1623     */
1624    private CharSequence mContentDescription;
1625
1626    /**
1627     * Cache the paddingRight set by the user to append to the scrollbar's size.
1628     */
1629    @ViewDebug.ExportedProperty
1630    int mUserPaddingRight;
1631
1632    /**
1633     * Cache the paddingBottom set by the user to append to the scrollbar's size.
1634     */
1635    @ViewDebug.ExportedProperty
1636    int mUserPaddingBottom;
1637
1638    /**
1639     * @hide
1640     */
1641    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
1642    /**
1643     * @hide
1644     */
1645    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
1646
1647    private Resources mResources = null;
1648
1649    private Drawable mBGDrawable;
1650
1651    private int mBackgroundResource;
1652    private boolean mBackgroundSizeChanged;
1653
1654    /**
1655     * Listener used to dispatch focus change events.
1656     * This field should be made private, so it is hidden from the SDK.
1657     * {@hide}
1658     */
1659    protected OnFocusChangeListener mOnFocusChangeListener;
1660
1661    /**
1662     * Listener used to dispatch click events.
1663     * This field should be made private, so it is hidden from the SDK.
1664     * {@hide}
1665     */
1666    protected OnClickListener mOnClickListener;
1667
1668    /**
1669     * Listener used to dispatch long click events.
1670     * This field should be made private, so it is hidden from the SDK.
1671     * {@hide}
1672     */
1673    protected OnLongClickListener mOnLongClickListener;
1674
1675    /**
1676     * Listener used to build the context menu.
1677     * This field should be made private, so it is hidden from the SDK.
1678     * {@hide}
1679     */
1680    protected OnCreateContextMenuListener mOnCreateContextMenuListener;
1681
1682    private OnKeyListener mOnKeyListener;
1683
1684    private OnTouchListener mOnTouchListener;
1685
1686    /**
1687     * The application environment this view lives in.
1688     * This field should be made private, so it is hidden from the SDK.
1689     * {@hide}
1690     */
1691    protected Context mContext;
1692
1693    private ScrollabilityCache mScrollCache;
1694
1695    private int[] mDrawableState = null;
1696
1697    private SoftReference<Bitmap> mDrawingCache;
1698    private SoftReference<Bitmap> mUnscaledDrawingCache;
1699
1700    /**
1701     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
1702     * the user may specify which view to go to next.
1703     */
1704    private int mNextFocusLeftId = View.NO_ID;
1705
1706    /**
1707     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
1708     * the user may specify which view to go to next.
1709     */
1710    private int mNextFocusRightId = View.NO_ID;
1711
1712    /**
1713     * When this view has focus and the next focus is {@link #FOCUS_UP},
1714     * the user may specify which view to go to next.
1715     */
1716    private int mNextFocusUpId = View.NO_ID;
1717
1718    /**
1719     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
1720     * the user may specify which view to go to next.
1721     */
1722    private int mNextFocusDownId = View.NO_ID;
1723
1724    private CheckForLongPress mPendingCheckForLongPress;
1725    private UnsetPressedState mUnsetPressedState;
1726
1727    /**
1728     * Whether the long press's action has been invoked.  The tap's action is invoked on the
1729     * up event while a long press is invoked as soon as the long press duration is reached, so
1730     * a long press could be performed before the tap is checked, in which case the tap's action
1731     * should not be invoked.
1732     */
1733    private boolean mHasPerformedLongPress;
1734
1735    /**
1736     * The minimum height of the view. We'll try our best to have the height
1737     * of this view to at least this amount.
1738     */
1739    @ViewDebug.ExportedProperty
1740    private int mMinHeight;
1741
1742    /**
1743     * The minimum width of the view. We'll try our best to have the width
1744     * of this view to at least this amount.
1745     */
1746    @ViewDebug.ExportedProperty
1747    private int mMinWidth;
1748
1749    /**
1750     * The delegate to handle touch events that are physically in this view
1751     * but should be handled by another view.
1752     */
1753    private TouchDelegate mTouchDelegate = null;
1754
1755    /**
1756     * Solid color to use as a background when creating the drawing cache. Enables
1757     * the cache to use 16 bit bitmaps instead of 32 bit.
1758     */
1759    private int mDrawingCacheBackgroundColor = 0;
1760
1761    /**
1762     * Special tree observer used when mAttachInfo is null.
1763     */
1764    private ViewTreeObserver mFloatingTreeObserver;
1765
1766    // Used for debug only
1767    static long sInstanceCount = 0;
1768
1769    /**
1770     * Simple constructor to use when creating a view from code.
1771     *
1772     * @param context The Context the view is running in, through which it can
1773     *        access the current theme, resources, etc.
1774     */
1775    public View(Context context) {
1776        mContext = context;
1777        mResources = context != null ? context.getResources() : null;
1778        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
1779        ++sInstanceCount;
1780    }
1781
1782    /**
1783     * Constructor that is called when inflating a view from XML. This is called
1784     * when a view is being constructed from an XML file, supplying attributes
1785     * that were specified in the XML file. This version uses a default style of
1786     * 0, so the only attribute values applied are those in the Context's Theme
1787     * and the given AttributeSet.
1788     *
1789     * <p>
1790     * The method onFinishInflate() will be called after all children have been
1791     * added.
1792     *
1793     * @param context The Context the view is running in, through which it can
1794     *        access the current theme, resources, etc.
1795     * @param attrs The attributes of the XML tag that is inflating the view.
1796     * @see #View(Context, AttributeSet, int)
1797     */
1798    public View(Context context, AttributeSet attrs) {
1799        this(context, attrs, 0);
1800    }
1801
1802    /**
1803     * Perform inflation from XML and apply a class-specific base style. This
1804     * constructor of View allows subclasses to use their own base style when
1805     * they are inflating. For example, a Button class's constructor would call
1806     * this version of the super class constructor and supply
1807     * <code>R.attr.buttonStyle</code> for <var>defStyle</var>; this allows
1808     * the theme's button style to modify all of the base view attributes (in
1809     * particular its background) as well as the Button class's attributes.
1810     *
1811     * @param context The Context the view is running in, through which it can
1812     *        access the current theme, resources, etc.
1813     * @param attrs The attributes of the XML tag that is inflating the view.
1814     * @param defStyle The default style to apply to this view. If 0, no style
1815     *        will be applied (beyond what is included in the theme). This may
1816     *        either be an attribute resource, whose value will be retrieved
1817     *        from the current theme, or an explicit style resource.
1818     * @see #View(Context, AttributeSet)
1819     */
1820    public View(Context context, AttributeSet attrs, int defStyle) {
1821        this(context);
1822
1823        TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View,
1824                defStyle, 0);
1825
1826        Drawable background = null;
1827
1828        int leftPadding = -1;
1829        int topPadding = -1;
1830        int rightPadding = -1;
1831        int bottomPadding = -1;
1832
1833        int padding = -1;
1834
1835        int viewFlagValues = 0;
1836        int viewFlagMasks = 0;
1837
1838        boolean setScrollContainer = false;
1839
1840        int x = 0;
1841        int y = 0;
1842
1843        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
1844
1845        final int N = a.getIndexCount();
1846        for (int i = 0; i < N; i++) {
1847            int attr = a.getIndex(i);
1848            switch (attr) {
1849                case com.android.internal.R.styleable.View_background:
1850                    background = a.getDrawable(attr);
1851                    break;
1852                case com.android.internal.R.styleable.View_padding:
1853                    padding = a.getDimensionPixelSize(attr, -1);
1854                    break;
1855                 case com.android.internal.R.styleable.View_paddingLeft:
1856                    leftPadding = a.getDimensionPixelSize(attr, -1);
1857                    break;
1858                case com.android.internal.R.styleable.View_paddingTop:
1859                    topPadding = a.getDimensionPixelSize(attr, -1);
1860                    break;
1861                case com.android.internal.R.styleable.View_paddingRight:
1862                    rightPadding = a.getDimensionPixelSize(attr, -1);
1863                    break;
1864                case com.android.internal.R.styleable.View_paddingBottom:
1865                    bottomPadding = a.getDimensionPixelSize(attr, -1);
1866                    break;
1867                case com.android.internal.R.styleable.View_scrollX:
1868                    x = a.getDimensionPixelOffset(attr, 0);
1869                    break;
1870                case com.android.internal.R.styleable.View_scrollY:
1871                    y = a.getDimensionPixelOffset(attr, 0);
1872                    break;
1873                case com.android.internal.R.styleable.View_id:
1874                    mID = a.getResourceId(attr, NO_ID);
1875                    break;
1876                case com.android.internal.R.styleable.View_tag:
1877                    mTag = a.getText(attr);
1878                    break;
1879                case com.android.internal.R.styleable.View_fitsSystemWindows:
1880                    if (a.getBoolean(attr, false)) {
1881                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
1882                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
1883                    }
1884                    break;
1885                case com.android.internal.R.styleable.View_focusable:
1886                    if (a.getBoolean(attr, false)) {
1887                        viewFlagValues |= FOCUSABLE;
1888                        viewFlagMasks |= FOCUSABLE_MASK;
1889                    }
1890                    break;
1891                case com.android.internal.R.styleable.View_focusableInTouchMode:
1892                    if (a.getBoolean(attr, false)) {
1893                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
1894                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
1895                    }
1896                    break;
1897                case com.android.internal.R.styleable.View_clickable:
1898                    if (a.getBoolean(attr, false)) {
1899                        viewFlagValues |= CLICKABLE;
1900                        viewFlagMasks |= CLICKABLE;
1901                    }
1902                    break;
1903                case com.android.internal.R.styleable.View_longClickable:
1904                    if (a.getBoolean(attr, false)) {
1905                        viewFlagValues |= LONG_CLICKABLE;
1906                        viewFlagMasks |= LONG_CLICKABLE;
1907                    }
1908                    break;
1909                case com.android.internal.R.styleable.View_saveEnabled:
1910                    if (!a.getBoolean(attr, true)) {
1911                        viewFlagValues |= SAVE_DISABLED;
1912                        viewFlagMasks |= SAVE_DISABLED_MASK;
1913                    }
1914                    break;
1915                case com.android.internal.R.styleable.View_duplicateParentState:
1916                    if (a.getBoolean(attr, false)) {
1917                        viewFlagValues |= DUPLICATE_PARENT_STATE;
1918                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
1919                    }
1920                    break;
1921                case com.android.internal.R.styleable.View_visibility:
1922                    final int visibility = a.getInt(attr, 0);
1923                    if (visibility != 0) {
1924                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
1925                        viewFlagMasks |= VISIBILITY_MASK;
1926                    }
1927                    break;
1928                case com.android.internal.R.styleable.View_drawingCacheQuality:
1929                    final int cacheQuality = a.getInt(attr, 0);
1930                    if (cacheQuality != 0) {
1931                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
1932                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
1933                    }
1934                    break;
1935                case com.android.internal.R.styleable.View_contentDescription:
1936                    mContentDescription = a.getString(attr);
1937                    break;
1938                case com.android.internal.R.styleable.View_soundEffectsEnabled:
1939                    if (!a.getBoolean(attr, true)) {
1940                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
1941                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
1942                    }
1943                    break;
1944                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
1945                    if (!a.getBoolean(attr, true)) {
1946                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
1947                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
1948                    }
1949                    break;
1950                case R.styleable.View_scrollbars:
1951                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
1952                    if (scrollbars != SCROLLBARS_NONE) {
1953                        viewFlagValues |= scrollbars;
1954                        viewFlagMasks |= SCROLLBARS_MASK;
1955                        initializeScrollbars(a);
1956                    }
1957                    break;
1958                case R.styleable.View_fadingEdge:
1959                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
1960                    if (fadingEdge != FADING_EDGE_NONE) {
1961                        viewFlagValues |= fadingEdge;
1962                        viewFlagMasks |= FADING_EDGE_MASK;
1963                        initializeFadingEdge(a);
1964                    }
1965                    break;
1966                case R.styleable.View_scrollbarStyle:
1967                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
1968                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
1969                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
1970                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
1971                    }
1972                    break;
1973                case R.styleable.View_isScrollContainer:
1974                    setScrollContainer = true;
1975                    if (a.getBoolean(attr, false)) {
1976                        setScrollContainer(true);
1977                    }
1978                    break;
1979                case com.android.internal.R.styleable.View_keepScreenOn:
1980                    if (a.getBoolean(attr, false)) {
1981                        viewFlagValues |= KEEP_SCREEN_ON;
1982                        viewFlagMasks |= KEEP_SCREEN_ON;
1983                    }
1984                    break;
1985                case R.styleable.View_nextFocusLeft:
1986                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
1987                    break;
1988                case R.styleable.View_nextFocusRight:
1989                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
1990                    break;
1991                case R.styleable.View_nextFocusUp:
1992                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
1993                    break;
1994                case R.styleable.View_nextFocusDown:
1995                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
1996                    break;
1997                case R.styleable.View_minWidth:
1998                    mMinWidth = a.getDimensionPixelSize(attr, 0);
1999                    break;
2000                case R.styleable.View_minHeight:
2001                    mMinHeight = a.getDimensionPixelSize(attr, 0);
2002                    break;
2003                case R.styleable.View_onClick:
2004                    if (context.isRestricted()) {
2005                        throw new IllegalStateException("The android:onClick attribute cannot "
2006                                + "be used within a restricted context");
2007                    }
2008
2009                    final String handlerName = a.getString(attr);
2010                    if (handlerName != null) {
2011                        setOnClickListener(new OnClickListener() {
2012                            private Method mHandler;
2013
2014                            public void onClick(View v) {
2015                                if (mHandler == null) {
2016                                    try {
2017                                        mHandler = getContext().getClass().getMethod(handlerName,
2018                                                View.class);
2019                                    } catch (NoSuchMethodException e) {
2020                                        throw new IllegalStateException("Could not find a method " +
2021                                                handlerName + "(View) in the activity", e);
2022                                    }
2023                                }
2024
2025                                try {
2026                                    mHandler.invoke(getContext(), View.this);
2027                                } catch (IllegalAccessException e) {
2028                                    throw new IllegalStateException("Could not execute non "
2029                                            + "public method of the activity", e);
2030                                } catch (InvocationTargetException e) {
2031                                    throw new IllegalStateException("Could not execute "
2032                                            + "method of the activity", e);
2033                                }
2034                            }
2035                        });
2036                    }
2037                    break;
2038            }
2039        }
2040
2041        if (background != null) {
2042            setBackgroundDrawable(background);
2043        }
2044
2045        if (padding >= 0) {
2046            leftPadding = padding;
2047            topPadding = padding;
2048            rightPadding = padding;
2049            bottomPadding = padding;
2050        }
2051
2052        // If the user specified the padding (either with android:padding or
2053        // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
2054        // use the default padding or the padding from the background drawable
2055        // (stored at this point in mPadding*)
2056        setPadding(leftPadding >= 0 ? leftPadding : mPaddingLeft,
2057                topPadding >= 0 ? topPadding : mPaddingTop,
2058                rightPadding >= 0 ? rightPadding : mPaddingRight,
2059                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
2060
2061        if (viewFlagMasks != 0) {
2062            setFlags(viewFlagValues, viewFlagMasks);
2063        }
2064
2065        // Needs to be called after mViewFlags is set
2066        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
2067            recomputePadding();
2068        }
2069
2070        if (x != 0 || y != 0) {
2071            scrollTo(x, y);
2072        }
2073
2074        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
2075            setScrollContainer(true);
2076        }
2077
2078        computeOpaqueFlags();
2079
2080        a.recycle();
2081    }
2082
2083    /**
2084     * Non-public constructor for use in testing
2085     */
2086    View() {
2087    }
2088
2089    @Override
2090    protected void finalize() throws Throwable {
2091        super.finalize();
2092        --sInstanceCount;
2093    }
2094
2095    /**
2096     * <p>
2097     * Initializes the fading edges from a given set of styled attributes. This
2098     * method should be called by subclasses that need fading edges and when an
2099     * instance of these subclasses is created programmatically rather than
2100     * being inflated from XML. This method is automatically called when the XML
2101     * is inflated.
2102     * </p>
2103     *
2104     * @param a the styled attributes set to initialize the fading edges from
2105     */
2106    protected void initializeFadingEdge(TypedArray a) {
2107        initScrollCache();
2108
2109        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
2110                R.styleable.View_fadingEdgeLength,
2111                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
2112    }
2113
2114    /**
2115     * Returns the size of the vertical faded edges used to indicate that more
2116     * content in this view is visible.
2117     *
2118     * @return The size in pixels of the vertical faded edge or 0 if vertical
2119     *         faded edges are not enabled for this view.
2120     * @attr ref android.R.styleable#View_fadingEdgeLength
2121     */
2122    public int getVerticalFadingEdgeLength() {
2123        if (isVerticalFadingEdgeEnabled()) {
2124            ScrollabilityCache cache = mScrollCache;
2125            if (cache != null) {
2126                return cache.fadingEdgeLength;
2127            }
2128        }
2129        return 0;
2130    }
2131
2132    /**
2133     * Set the size of the faded edge used to indicate that more content in this
2134     * view is available.  Will not change whether the fading edge is enabled; use
2135     * {@link #setVerticalFadingEdgeEnabled} or {@link #setHorizontalFadingEdgeEnabled}
2136     * to enable the fading edge for the vertical or horizontal fading edges.
2137     *
2138     * @param length The size in pixels of the faded edge used to indicate that more
2139     *        content in this view is visible.
2140     */
2141    public void setFadingEdgeLength(int length) {
2142        initScrollCache();
2143        mScrollCache.fadingEdgeLength = length;
2144    }
2145
2146    /**
2147     * Returns the size of the horizontal faded edges used to indicate that more
2148     * content in this view is visible.
2149     *
2150     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
2151     *         faded edges are not enabled for this view.
2152     * @attr ref android.R.styleable#View_fadingEdgeLength
2153     */
2154    public int getHorizontalFadingEdgeLength() {
2155        if (isHorizontalFadingEdgeEnabled()) {
2156            ScrollabilityCache cache = mScrollCache;
2157            if (cache != null) {
2158                return cache.fadingEdgeLength;
2159            }
2160        }
2161        return 0;
2162    }
2163
2164    /**
2165     * Returns the width of the vertical scrollbar.
2166     *
2167     * @return The width in pixels of the vertical scrollbar or 0 if there
2168     *         is no vertical scrollbar.
2169     */
2170    public int getVerticalScrollbarWidth() {
2171        ScrollabilityCache cache = mScrollCache;
2172        if (cache != null) {
2173            ScrollBarDrawable scrollBar = cache.scrollBar;
2174            if (scrollBar != null) {
2175                int size = scrollBar.getSize(true);
2176                if (size <= 0) {
2177                    size = cache.scrollBarSize;
2178                }
2179                return size;
2180            }
2181            return 0;
2182        }
2183        return 0;
2184    }
2185
2186    /**
2187     * Returns the height of the horizontal scrollbar.
2188     *
2189     * @return The height in pixels of the horizontal scrollbar or 0 if
2190     *         there is no horizontal scrollbar.
2191     */
2192    protected int getHorizontalScrollbarHeight() {
2193        ScrollabilityCache cache = mScrollCache;
2194        if (cache != null) {
2195            ScrollBarDrawable scrollBar = cache.scrollBar;
2196            if (scrollBar != null) {
2197                int size = scrollBar.getSize(false);
2198                if (size <= 0) {
2199                    size = cache.scrollBarSize;
2200                }
2201                return size;
2202            }
2203            return 0;
2204        }
2205        return 0;
2206    }
2207
2208    /**
2209     * <p>
2210     * Initializes the scrollbars from a given set of styled attributes. This
2211     * method should be called by subclasses that need scrollbars and when an
2212     * instance of these subclasses is created programmatically rather than
2213     * being inflated from XML. This method is automatically called when the XML
2214     * is inflated.
2215     * </p>
2216     *
2217     * @param a the styled attributes set to initialize the scrollbars from
2218     */
2219    protected void initializeScrollbars(TypedArray a) {
2220        initScrollCache();
2221
2222        final ScrollabilityCache scrollabilityCache = mScrollCache;
2223
2224        if (scrollabilityCache.scrollBar == null) {
2225            scrollabilityCache.scrollBar = new ScrollBarDrawable();
2226        }
2227
2228        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, false);
2229
2230        if (!fadeScrollbars) {
2231            scrollabilityCache.state = ScrollabilityCache.ON;
2232        }
2233        scrollabilityCache.fadeScrollBars = fadeScrollbars;
2234
2235
2236        scrollabilityCache.scrollBarFadeDuration = a.getInt(
2237                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
2238                        .getScrollBarFadeDuration());
2239        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
2240                R.styleable.View_scrollbarDefaultDelayBeforeFade,
2241                ViewConfiguration.getScrollDefaultDelay());
2242
2243
2244        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
2245                com.android.internal.R.styleable.View_scrollbarSize,
2246                ViewConfiguration.get(mContext).getScaledScrollBarSize());
2247
2248        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
2249        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
2250
2251        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
2252        if (thumb != null) {
2253            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
2254        }
2255
2256        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
2257                false);
2258        if (alwaysDraw) {
2259            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
2260        }
2261
2262        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
2263        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
2264
2265        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
2266        if (thumb != null) {
2267            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
2268        }
2269
2270        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
2271                false);
2272        if (alwaysDraw) {
2273            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
2274        }
2275
2276        // Re-apply user/background padding so that scrollbar(s) get added
2277        recomputePadding();
2278    }
2279
2280    /**
2281     * <p>
2282     * Initalizes the scrollability cache if necessary.
2283     * </p>
2284     */
2285    private void initScrollCache() {
2286        if (mScrollCache == null) {
2287            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
2288        }
2289    }
2290
2291    /**
2292     * Register a callback to be invoked when focus of this view changed.
2293     *
2294     * @param l The callback that will run.
2295     */
2296    public void setOnFocusChangeListener(OnFocusChangeListener l) {
2297        mOnFocusChangeListener = l;
2298    }
2299
2300    /**
2301     * Returns the focus-change callback registered for this view.
2302     *
2303     * @return The callback, or null if one is not registered.
2304     */
2305    public OnFocusChangeListener getOnFocusChangeListener() {
2306        return mOnFocusChangeListener;
2307    }
2308
2309    /**
2310     * Register a callback to be invoked when this view is clicked. If this view is not
2311     * clickable, it becomes clickable.
2312     *
2313     * @param l The callback that will run
2314     *
2315     * @see #setClickable(boolean)
2316     */
2317    public void setOnClickListener(OnClickListener l) {
2318        if (!isClickable()) {
2319            setClickable(true);
2320        }
2321        mOnClickListener = l;
2322    }
2323
2324    /**
2325     * Register a callback to be invoked when this view is clicked and held. If this view is not
2326     * long clickable, it becomes long clickable.
2327     *
2328     * @param l The callback that will run
2329     *
2330     * @see #setLongClickable(boolean)
2331     */
2332    public void setOnLongClickListener(OnLongClickListener l) {
2333        if (!isLongClickable()) {
2334            setLongClickable(true);
2335        }
2336        mOnLongClickListener = l;
2337    }
2338
2339    /**
2340     * Register a callback to be invoked when the context menu for this view is
2341     * being built. If this view is not long clickable, it becomes long clickable.
2342     *
2343     * @param l The callback that will run
2344     *
2345     */
2346    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
2347        if (!isLongClickable()) {
2348            setLongClickable(true);
2349        }
2350        mOnCreateContextMenuListener = l;
2351    }
2352
2353    /**
2354     * Call this view's OnClickListener, if it is defined.
2355     *
2356     * @return True there was an assigned OnClickListener that was called, false
2357     *         otherwise is returned.
2358     */
2359    public boolean performClick() {
2360        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
2361
2362        if (mOnClickListener != null) {
2363            playSoundEffect(SoundEffectConstants.CLICK);
2364            mOnClickListener.onClick(this);
2365            return true;
2366        }
2367
2368        return false;
2369    }
2370
2371    /**
2372     * Call this view's OnLongClickListener, if it is defined. Invokes the context menu
2373     * if the OnLongClickListener did not consume the event.
2374     *
2375     * @return True there was an assigned OnLongClickListener that was called, false
2376     *         otherwise is returned.
2377     */
2378    public boolean performLongClick() {
2379        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
2380
2381        boolean handled = false;
2382        if (mOnLongClickListener != null) {
2383            handled = mOnLongClickListener.onLongClick(View.this);
2384        }
2385        if (!handled) {
2386            handled = showContextMenu();
2387        }
2388        if (handled) {
2389            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
2390        }
2391        return handled;
2392    }
2393
2394    /**
2395     * Bring up the context menu for this view.
2396     *
2397     * @return Whether a context menu was displayed.
2398     */
2399    public boolean showContextMenu() {
2400        return getParent().showContextMenuForChild(this);
2401    }
2402
2403    /**
2404     * Register a callback to be invoked when a key is pressed in this view.
2405     * @param l the key listener to attach to this view
2406     */
2407    public void setOnKeyListener(OnKeyListener l) {
2408        mOnKeyListener = l;
2409    }
2410
2411    /**
2412     * Register a callback to be invoked when a touch event is sent to this view.
2413     * @param l the touch listener to attach to this view
2414     */
2415    public void setOnTouchListener(OnTouchListener l) {
2416        mOnTouchListener = l;
2417    }
2418
2419    /**
2420     * Give this view focus. This will cause {@link #onFocusChanged} to be called.
2421     *
2422     * Note: this does not check whether this {@link View} should get focus, it just
2423     * gives it focus no matter what.  It should only be called internally by framework
2424     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
2425     *
2426     * @param direction values are View.FOCUS_UP, View.FOCUS_DOWN,
2427     *        View.FOCUS_LEFT or View.FOCUS_RIGHT. This is the direction which
2428     *        focus moved when requestFocus() is called. It may not always
2429     *        apply, in which case use the default View.FOCUS_DOWN.
2430     * @param previouslyFocusedRect The rectangle of the view that had focus
2431     *        prior in this View's coordinate system.
2432     */
2433    void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) {
2434        if (DBG) {
2435            System.out.println(this + " requestFocus()");
2436        }
2437
2438        if ((mPrivateFlags & FOCUSED) == 0) {
2439            mPrivateFlags |= FOCUSED;
2440
2441            if (mParent != null) {
2442                mParent.requestChildFocus(this, this);
2443            }
2444
2445            onFocusChanged(true, direction, previouslyFocusedRect);
2446            refreshDrawableState();
2447        }
2448    }
2449
2450    /**
2451     * Request that a rectangle of this view be visible on the screen,
2452     * scrolling if necessary just enough.
2453     *
2454     * <p>A View should call this if it maintains some notion of which part
2455     * of its content is interesting.  For example, a text editing view
2456     * should call this when its cursor moves.
2457     *
2458     * @param rectangle The rectangle.
2459     * @return Whether any parent scrolled.
2460     */
2461    public boolean requestRectangleOnScreen(Rect rectangle) {
2462        return requestRectangleOnScreen(rectangle, false);
2463    }
2464
2465    /**
2466     * Request that a rectangle of this view be visible on the screen,
2467     * scrolling if necessary just enough.
2468     *
2469     * <p>A View should call this if it maintains some notion of which part
2470     * of its content is interesting.  For example, a text editing view
2471     * should call this when its cursor moves.
2472     *
2473     * <p>When <code>immediate</code> is set to true, scrolling will not be
2474     * animated.
2475     *
2476     * @param rectangle The rectangle.
2477     * @param immediate True to forbid animated scrolling, false otherwise
2478     * @return Whether any parent scrolled.
2479     */
2480    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
2481        View child = this;
2482        ViewParent parent = mParent;
2483        boolean scrolled = false;
2484        while (parent != null) {
2485            scrolled |= parent.requestChildRectangleOnScreen(child,
2486                    rectangle, immediate);
2487
2488            // offset rect so next call has the rectangle in the
2489            // coordinate system of its direct child.
2490            rectangle.offset(child.getLeft(), child.getTop());
2491            rectangle.offset(-child.getScrollX(), -child.getScrollY());
2492
2493            if (!(parent instanceof View)) {
2494                break;
2495            }
2496
2497            child = (View) parent;
2498            parent = child.getParent();
2499        }
2500        return scrolled;
2501    }
2502
2503    /**
2504     * Called when this view wants to give up focus. This will cause
2505     * {@link #onFocusChanged} to be called.
2506     */
2507    public void clearFocus() {
2508        if (DBG) {
2509            System.out.println(this + " clearFocus()");
2510        }
2511
2512        if ((mPrivateFlags & FOCUSED) != 0) {
2513            mPrivateFlags &= ~FOCUSED;
2514
2515            if (mParent != null) {
2516                mParent.clearChildFocus(this);
2517            }
2518
2519            onFocusChanged(false, 0, null);
2520            refreshDrawableState();
2521        }
2522    }
2523
2524    /**
2525     * Called to clear the focus of a view that is about to be removed.
2526     * Doesn't call clearChildFocus, which prevents this view from taking
2527     * focus again before it has been removed from the parent
2528     */
2529    void clearFocusForRemoval() {
2530        if ((mPrivateFlags & FOCUSED) != 0) {
2531            mPrivateFlags &= ~FOCUSED;
2532
2533            onFocusChanged(false, 0, null);
2534            refreshDrawableState();
2535        }
2536    }
2537
2538    /**
2539     * Called internally by the view system when a new view is getting focus.
2540     * This is what clears the old focus.
2541     */
2542    void unFocus() {
2543        if (DBG) {
2544            System.out.println(this + " unFocus()");
2545        }
2546
2547        if ((mPrivateFlags & FOCUSED) != 0) {
2548            mPrivateFlags &= ~FOCUSED;
2549
2550            onFocusChanged(false, 0, null);
2551            refreshDrawableState();
2552        }
2553    }
2554
2555    /**
2556     * Returns true if this view has focus iteself, or is the ancestor of the
2557     * view that has focus.
2558     *
2559     * @return True if this view has or contains focus, false otherwise.
2560     */
2561    @ViewDebug.ExportedProperty
2562    public boolean hasFocus() {
2563        return (mPrivateFlags & FOCUSED) != 0;
2564    }
2565
2566    /**
2567     * Returns true if this view is focusable or if it contains a reachable View
2568     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
2569     * is a View whose parents do not block descendants focus.
2570     *
2571     * Only {@link #VISIBLE} views are considered focusable.
2572     *
2573     * @return True if the view is focusable or if the view contains a focusable
2574     *         View, false otherwise.
2575     *
2576     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
2577     */
2578    public boolean hasFocusable() {
2579        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
2580    }
2581
2582    /**
2583     * Called by the view system when the focus state of this view changes.
2584     * When the focus change event is caused by directional navigation, direction
2585     * and previouslyFocusedRect provide insight into where the focus is coming from.
2586     * When overriding, be sure to call up through to the super class so that
2587     * the standard focus handling will occur.
2588     *
2589     * @param gainFocus True if the View has focus; false otherwise.
2590     * @param direction The direction focus has moved when requestFocus()
2591     *                  is called to give this view focus. Values are
2592     *                  View.FOCUS_UP, View.FOCUS_DOWN, View.FOCUS_LEFT or
2593     *                  View.FOCUS_RIGHT. It may not always apply, in which
2594     *                  case use the default.
2595     * @param previouslyFocusedRect The rectangle, in this view's coordinate
2596     *        system, of the previously focused view.  If applicable, this will be
2597     *        passed in as finer grained information about where the focus is coming
2598     *        from (in addition to direction).  Will be <code>null</code> otherwise.
2599     */
2600    protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
2601        if (gainFocus) {
2602            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
2603        }
2604
2605        InputMethodManager imm = InputMethodManager.peekInstance();
2606        if (!gainFocus) {
2607            if (isPressed()) {
2608                setPressed(false);
2609            }
2610            if (imm != null && mAttachInfo != null
2611                    && mAttachInfo.mHasWindowFocus) {
2612                imm.focusOut(this);
2613            }
2614            onFocusLost();
2615        } else if (imm != null && mAttachInfo != null
2616                && mAttachInfo.mHasWindowFocus) {
2617            imm.focusIn(this);
2618        }
2619
2620        invalidate();
2621        if (mOnFocusChangeListener != null) {
2622            mOnFocusChangeListener.onFocusChange(this, gainFocus);
2623        }
2624
2625        if (mAttachInfo != null) {
2626            mAttachInfo.mKeyDispatchState.reset(this);
2627        }
2628    }
2629
2630    /**
2631     * {@inheritDoc}
2632     */
2633    public void sendAccessibilityEvent(int eventType) {
2634        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
2635            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
2636        }
2637    }
2638
2639    /**
2640     * {@inheritDoc}
2641     */
2642    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
2643        event.setClassName(getClass().getName());
2644        event.setPackageName(getContext().getPackageName());
2645        event.setEnabled(isEnabled());
2646        event.setContentDescription(mContentDescription);
2647
2648        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED && mAttachInfo != null) {
2649            ArrayList<View> focusablesTempList = mAttachInfo.mFocusablesTempList;
2650            getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
2651            event.setItemCount(focusablesTempList.size());
2652            event.setCurrentItemIndex(focusablesTempList.indexOf(this));
2653            focusablesTempList.clear();
2654        }
2655
2656        dispatchPopulateAccessibilityEvent(event);
2657
2658        AccessibilityManager.getInstance(mContext).sendAccessibilityEvent(event);
2659    }
2660
2661    /**
2662     * Dispatches an {@link AccessibilityEvent} to the {@link View} children
2663     * to be populated.
2664     *
2665     * @param event The event.
2666     *
2667     * @return True if the event population was completed.
2668     */
2669    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
2670        return false;
2671    }
2672
2673    /**
2674     * Gets the {@link View} description. It briefly describes the view and is
2675     * primarily used for accessibility support. Set this property to enable
2676     * better accessibility support for your application. This is especially
2677     * true for views that do not have textual representation (For example,
2678     * ImageButton).
2679     *
2680     * @return The content descriptiopn.
2681     *
2682     * @attr ref android.R.styleable#View_contentDescription
2683     */
2684    public CharSequence getContentDescription() {
2685        return mContentDescription;
2686    }
2687
2688    /**
2689     * Sets the {@link View} description. It briefly describes the view and is
2690     * primarily used for accessibility support. Set this property to enable
2691     * better accessibility support for your application. This is especially
2692     * true for views that do not have textual representation (For example,
2693     * ImageButton).
2694     *
2695     * @param contentDescription The content description.
2696     *
2697     * @attr ref android.R.styleable#View_contentDescription
2698     */
2699    public void setContentDescription(CharSequence contentDescription) {
2700        mContentDescription = contentDescription;
2701    }
2702
2703    /**
2704     * Invoked whenever this view loses focus, either by losing window focus or by losing
2705     * focus within its window. This method can be used to clear any state tied to the
2706     * focus. For instance, if a button is held pressed with the trackball and the window
2707     * loses focus, this method can be used to cancel the press.
2708     *
2709     * Subclasses of View overriding this method should always call super.onFocusLost().
2710     *
2711     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
2712     * @see #onWindowFocusChanged(boolean)
2713     *
2714     * @hide pending API council approval
2715     */
2716    protected void onFocusLost() {
2717        resetPressedState();
2718    }
2719
2720    private void resetPressedState() {
2721        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
2722            return;
2723        }
2724
2725        if (isPressed()) {
2726            setPressed(false);
2727
2728            if (!mHasPerformedLongPress) {
2729                if (mPendingCheckForLongPress != null) {
2730                    removeCallbacks(mPendingCheckForLongPress);
2731                }
2732            }
2733        }
2734    }
2735
2736    /**
2737     * Returns true if this view has focus
2738     *
2739     * @return True if this view has focus, false otherwise.
2740     */
2741    @ViewDebug.ExportedProperty
2742    public boolean isFocused() {
2743        return (mPrivateFlags & FOCUSED) != 0;
2744    }
2745
2746    /**
2747     * Find the view in the hierarchy rooted at this view that currently has
2748     * focus.
2749     *
2750     * @return The view that currently has focus, or null if no focused view can
2751     *         be found.
2752     */
2753    public View findFocus() {
2754        return (mPrivateFlags & FOCUSED) != 0 ? this : null;
2755    }
2756
2757    /**
2758     * Change whether this view is one of the set of scrollable containers in
2759     * its window.  This will be used to determine whether the window can
2760     * resize or must pan when a soft input area is open -- scrollable
2761     * containers allow the window to use resize mode since the container
2762     * will appropriately shrink.
2763     */
2764    public void setScrollContainer(boolean isScrollContainer) {
2765        if (isScrollContainer) {
2766            if (mAttachInfo != null && (mPrivateFlags&SCROLL_CONTAINER_ADDED) == 0) {
2767                mAttachInfo.mScrollContainers.add(this);
2768                mPrivateFlags |= SCROLL_CONTAINER_ADDED;
2769            }
2770            mPrivateFlags |= SCROLL_CONTAINER;
2771        } else {
2772            if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) {
2773                mAttachInfo.mScrollContainers.remove(this);
2774            }
2775            mPrivateFlags &= ~(SCROLL_CONTAINER|SCROLL_CONTAINER_ADDED);
2776        }
2777    }
2778
2779    /**
2780     * Returns the quality of the drawing cache.
2781     *
2782     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
2783     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
2784     *
2785     * @see #setDrawingCacheQuality(int)
2786     * @see #setDrawingCacheEnabled(boolean)
2787     * @see #isDrawingCacheEnabled()
2788     *
2789     * @attr ref android.R.styleable#View_drawingCacheQuality
2790     */
2791    public int getDrawingCacheQuality() {
2792        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
2793    }
2794
2795    /**
2796     * Set the drawing cache quality of this view. This value is used only when the
2797     * drawing cache is enabled
2798     *
2799     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
2800     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
2801     *
2802     * @see #getDrawingCacheQuality()
2803     * @see #setDrawingCacheEnabled(boolean)
2804     * @see #isDrawingCacheEnabled()
2805     *
2806     * @attr ref android.R.styleable#View_drawingCacheQuality
2807     */
2808    public void setDrawingCacheQuality(int quality) {
2809        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
2810    }
2811
2812    /**
2813     * Returns whether the screen should remain on, corresponding to the current
2814     * value of {@link #KEEP_SCREEN_ON}.
2815     *
2816     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
2817     *
2818     * @see #setKeepScreenOn(boolean)
2819     *
2820     * @attr ref android.R.styleable#View_keepScreenOn
2821     */
2822    public boolean getKeepScreenOn() {
2823        return (mViewFlags & KEEP_SCREEN_ON) != 0;
2824    }
2825
2826    /**
2827     * Controls whether the screen should remain on, modifying the
2828     * value of {@link #KEEP_SCREEN_ON}.
2829     *
2830     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
2831     *
2832     * @see #getKeepScreenOn()
2833     *
2834     * @attr ref android.R.styleable#View_keepScreenOn
2835     */
2836    public void setKeepScreenOn(boolean keepScreenOn) {
2837        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
2838    }
2839
2840    /**
2841     * @return The user specified next focus ID.
2842     *
2843     * @attr ref android.R.styleable#View_nextFocusLeft
2844     */
2845    public int getNextFocusLeftId() {
2846        return mNextFocusLeftId;
2847    }
2848
2849    /**
2850     * Set the id of the view to use for the next focus
2851     *
2852     * @param nextFocusLeftId
2853     *
2854     * @attr ref android.R.styleable#View_nextFocusLeft
2855     */
2856    public void setNextFocusLeftId(int nextFocusLeftId) {
2857        mNextFocusLeftId = nextFocusLeftId;
2858    }
2859
2860    /**
2861     * @return The user specified next focus ID.
2862     *
2863     * @attr ref android.R.styleable#View_nextFocusRight
2864     */
2865    public int getNextFocusRightId() {
2866        return mNextFocusRightId;
2867    }
2868
2869    /**
2870     * Set the id of the view to use for the next focus
2871     *
2872     * @param nextFocusRightId
2873     *
2874     * @attr ref android.R.styleable#View_nextFocusRight
2875     */
2876    public void setNextFocusRightId(int nextFocusRightId) {
2877        mNextFocusRightId = nextFocusRightId;
2878    }
2879
2880    /**
2881     * @return The user specified next focus ID.
2882     *
2883     * @attr ref android.R.styleable#View_nextFocusUp
2884     */
2885    public int getNextFocusUpId() {
2886        return mNextFocusUpId;
2887    }
2888
2889    /**
2890     * Set the id of the view to use for the next focus
2891     *
2892     * @param nextFocusUpId
2893     *
2894     * @attr ref android.R.styleable#View_nextFocusUp
2895     */
2896    public void setNextFocusUpId(int nextFocusUpId) {
2897        mNextFocusUpId = nextFocusUpId;
2898    }
2899
2900    /**
2901     * @return The user specified next focus ID.
2902     *
2903     * @attr ref android.R.styleable#View_nextFocusDown
2904     */
2905    public int getNextFocusDownId() {
2906        return mNextFocusDownId;
2907    }
2908
2909    /**
2910     * Set the id of the view to use for the next focus
2911     *
2912     * @param nextFocusDownId
2913     *
2914     * @attr ref android.R.styleable#View_nextFocusDown
2915     */
2916    public void setNextFocusDownId(int nextFocusDownId) {
2917        mNextFocusDownId = nextFocusDownId;
2918    }
2919
2920    /**
2921     * Returns the visibility of this view and all of its ancestors
2922     *
2923     * @return True if this view and all of its ancestors are {@link #VISIBLE}
2924     */
2925    public boolean isShown() {
2926        View current = this;
2927        //noinspection ConstantConditions
2928        do {
2929            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
2930                return false;
2931            }
2932            ViewParent parent = current.mParent;
2933            if (parent == null) {
2934                return false; // We are not attached to the view root
2935            }
2936            if (!(parent instanceof View)) {
2937                return true;
2938            }
2939            current = (View) parent;
2940        } while (current != null);
2941
2942        return false;
2943    }
2944
2945    /**
2946     * Apply the insets for system windows to this view, if the FITS_SYSTEM_WINDOWS flag
2947     * is set
2948     *
2949     * @param insets Insets for system windows
2950     *
2951     * @return True if this view applied the insets, false otherwise
2952     */
2953    protected boolean fitSystemWindows(Rect insets) {
2954        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
2955            mPaddingLeft = insets.left;
2956            mPaddingTop = insets.top;
2957            mPaddingRight = insets.right;
2958            mPaddingBottom = insets.bottom;
2959            requestLayout();
2960            return true;
2961        }
2962        return false;
2963    }
2964
2965    /**
2966     * Returns the visibility status for this view.
2967     *
2968     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
2969     * @attr ref android.R.styleable#View_visibility
2970     */
2971    @ViewDebug.ExportedProperty(mapping = {
2972        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
2973        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
2974        @ViewDebug.IntToString(from = GONE,      to = "GONE")
2975    })
2976    public int getVisibility() {
2977        return mViewFlags & VISIBILITY_MASK;
2978    }
2979
2980    /**
2981     * Set the enabled state of this view.
2982     *
2983     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
2984     * @attr ref android.R.styleable#View_visibility
2985     */
2986    @RemotableViewMethod
2987    public void setVisibility(int visibility) {
2988        setFlags(visibility, VISIBILITY_MASK);
2989        if (mBGDrawable != null) mBGDrawable.setVisible(visibility == VISIBLE, false);
2990    }
2991
2992    /**
2993     * Returns the enabled status for this view. The interpretation of the
2994     * enabled state varies by subclass.
2995     *
2996     * @return True if this view is enabled, false otherwise.
2997     */
2998    @ViewDebug.ExportedProperty
2999    public boolean isEnabled() {
3000        return (mViewFlags & ENABLED_MASK) == ENABLED;
3001    }
3002
3003    /**
3004     * Set the enabled state of this view. The interpretation of the enabled
3005     * state varies by subclass.
3006     *
3007     * @param enabled True if this view is enabled, false otherwise.
3008     */
3009    public void setEnabled(boolean enabled) {
3010        if (enabled == isEnabled()) return;
3011
3012        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
3013
3014        /*
3015         * The View most likely has to change its appearance, so refresh
3016         * the drawable state.
3017         */
3018        refreshDrawableState();
3019
3020        // Invalidate too, since the default behavior for views is to be
3021        // be drawn at 50% alpha rather than to change the drawable.
3022        invalidate();
3023    }
3024
3025    /**
3026     * Set whether this view can receive the focus.
3027     *
3028     * Setting this to false will also ensure that this view is not focusable
3029     * in touch mode.
3030     *
3031     * @param focusable If true, this view can receive the focus.
3032     *
3033     * @see #setFocusableInTouchMode(boolean)
3034     * @attr ref android.R.styleable#View_focusable
3035     */
3036    public void setFocusable(boolean focusable) {
3037        if (!focusable) {
3038            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
3039        }
3040        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
3041    }
3042
3043    /**
3044     * Set whether this view can receive focus while in touch mode.
3045     *
3046     * Setting this to true will also ensure that this view is focusable.
3047     *
3048     * @param focusableInTouchMode If true, this view can receive the focus while
3049     *   in touch mode.
3050     *
3051     * @see #setFocusable(boolean)
3052     * @attr ref android.R.styleable#View_focusableInTouchMode
3053     */
3054    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
3055        // Focusable in touch mode should always be set before the focusable flag
3056        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
3057        // which, in touch mode, will not successfully request focus on this view
3058        // because the focusable in touch mode flag is not set
3059        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
3060        if (focusableInTouchMode) {
3061            setFlags(FOCUSABLE, FOCUSABLE_MASK);
3062        }
3063    }
3064
3065    /**
3066     * Set whether this view should have sound effects enabled for events such as
3067     * clicking and touching.
3068     *
3069     * <p>You may wish to disable sound effects for a view if you already play sounds,
3070     * for instance, a dial key that plays dtmf tones.
3071     *
3072     * @param soundEffectsEnabled whether sound effects are enabled for this view.
3073     * @see #isSoundEffectsEnabled()
3074     * @see #playSoundEffect(int)
3075     * @attr ref android.R.styleable#View_soundEffectsEnabled
3076     */
3077    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
3078        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
3079    }
3080
3081    /**
3082     * @return whether this view should have sound effects enabled for events such as
3083     *     clicking and touching.
3084     *
3085     * @see #setSoundEffectsEnabled(boolean)
3086     * @see #playSoundEffect(int)
3087     * @attr ref android.R.styleable#View_soundEffectsEnabled
3088     */
3089    @ViewDebug.ExportedProperty
3090    public boolean isSoundEffectsEnabled() {
3091        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
3092    }
3093
3094    /**
3095     * Set whether this view should have haptic feedback for events such as
3096     * long presses.
3097     *
3098     * <p>You may wish to disable haptic feedback if your view already controls
3099     * its own haptic feedback.
3100     *
3101     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
3102     * @see #isHapticFeedbackEnabled()
3103     * @see #performHapticFeedback(int)
3104     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
3105     */
3106    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
3107        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
3108    }
3109
3110    /**
3111     * @return whether this view should have haptic feedback enabled for events
3112     * long presses.
3113     *
3114     * @see #setHapticFeedbackEnabled(boolean)
3115     * @see #performHapticFeedback(int)
3116     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
3117     */
3118    @ViewDebug.ExportedProperty
3119    public boolean isHapticFeedbackEnabled() {
3120        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
3121    }
3122
3123    /**
3124     * If this view doesn't do any drawing on its own, set this flag to
3125     * allow further optimizations. By default, this flag is not set on
3126     * View, but could be set on some View subclasses such as ViewGroup.
3127     *
3128     * Typically, if you override {@link #onDraw} you should clear this flag.
3129     *
3130     * @param willNotDraw whether or not this View draw on its own
3131     */
3132    public void setWillNotDraw(boolean willNotDraw) {
3133        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
3134    }
3135
3136    /**
3137     * Returns whether or not this View draws on its own.
3138     *
3139     * @return true if this view has nothing to draw, false otherwise
3140     */
3141    @ViewDebug.ExportedProperty
3142    public boolean willNotDraw() {
3143        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
3144    }
3145
3146    /**
3147     * When a View's drawing cache is enabled, drawing is redirected to an
3148     * offscreen bitmap. Some views, like an ImageView, must be able to
3149     * bypass this mechanism if they already draw a single bitmap, to avoid
3150     * unnecessary usage of the memory.
3151     *
3152     * @param willNotCacheDrawing true if this view does not cache its
3153     *        drawing, false otherwise
3154     */
3155    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
3156        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
3157    }
3158
3159    /**
3160     * Returns whether or not this View can cache its drawing or not.
3161     *
3162     * @return true if this view does not cache its drawing, false otherwise
3163     */
3164    @ViewDebug.ExportedProperty
3165    public boolean willNotCacheDrawing() {
3166        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
3167    }
3168
3169    /**
3170     * Indicates whether this view reacts to click events or not.
3171     *
3172     * @return true if the view is clickable, false otherwise
3173     *
3174     * @see #setClickable(boolean)
3175     * @attr ref android.R.styleable#View_clickable
3176     */
3177    @ViewDebug.ExportedProperty
3178    public boolean isClickable() {
3179        return (mViewFlags & CLICKABLE) == CLICKABLE;
3180    }
3181
3182    /**
3183     * Enables or disables click events for this view. When a view
3184     * is clickable it will change its state to "pressed" on every click.
3185     * Subclasses should set the view clickable to visually react to
3186     * user's clicks.
3187     *
3188     * @param clickable true to make the view clickable, false otherwise
3189     *
3190     * @see #isClickable()
3191     * @attr ref android.R.styleable#View_clickable
3192     */
3193    public void setClickable(boolean clickable) {
3194        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
3195    }
3196
3197    /**
3198     * Indicates whether this view reacts to long click events or not.
3199     *
3200     * @return true if the view is long clickable, false otherwise
3201     *
3202     * @see #setLongClickable(boolean)
3203     * @attr ref android.R.styleable#View_longClickable
3204     */
3205    public boolean isLongClickable() {
3206        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
3207    }
3208
3209    /**
3210     * Enables or disables long click events for this view. When a view is long
3211     * clickable it reacts to the user holding down the button for a longer
3212     * duration than a tap. This event can either launch the listener or a
3213     * context menu.
3214     *
3215     * @param longClickable true to make the view long clickable, false otherwise
3216     * @see #isLongClickable()
3217     * @attr ref android.R.styleable#View_longClickable
3218     */
3219    public void setLongClickable(boolean longClickable) {
3220        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
3221    }
3222
3223    /**
3224     * Sets the pressed that for this view.
3225     *
3226     * @see #isClickable()
3227     * @see #setClickable(boolean)
3228     *
3229     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
3230     *        the View's internal state from a previously set "pressed" state.
3231     */
3232    public void setPressed(boolean pressed) {
3233        if (pressed) {
3234            mPrivateFlags |= PRESSED;
3235        } else {
3236            mPrivateFlags &= ~PRESSED;
3237        }
3238        refreshDrawableState();
3239        dispatchSetPressed(pressed);
3240    }
3241
3242    /**
3243     * Dispatch setPressed to all of this View's children.
3244     *
3245     * @see #setPressed(boolean)
3246     *
3247     * @param pressed The new pressed state
3248     */
3249    protected void dispatchSetPressed(boolean pressed) {
3250    }
3251
3252    /**
3253     * Indicates whether the view is currently in pressed state. Unless
3254     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
3255     * the pressed state.
3256     *
3257     * @see #setPressed
3258     * @see #isClickable()
3259     * @see #setClickable(boolean)
3260     *
3261     * @return true if the view is currently pressed, false otherwise
3262     */
3263    public boolean isPressed() {
3264        return (mPrivateFlags & PRESSED) == PRESSED;
3265    }
3266
3267    /**
3268     * Indicates whether this view will save its state (that is,
3269     * whether its {@link #onSaveInstanceState} method will be called).
3270     *
3271     * @return Returns true if the view state saving is enabled, else false.
3272     *
3273     * @see #setSaveEnabled(boolean)
3274     * @attr ref android.R.styleable#View_saveEnabled
3275     */
3276    public boolean isSaveEnabled() {
3277        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
3278    }
3279
3280    /**
3281     * Controls whether the saving of this view's state is
3282     * enabled (that is, whether its {@link #onSaveInstanceState} method
3283     * will be called).  Note that even if freezing is enabled, the
3284     * view still must have an id assigned to it (via {@link #setId setId()})
3285     * for its state to be saved.  This flag can only disable the
3286     * saving of this view; any child views may still have their state saved.
3287     *
3288     * @param enabled Set to false to <em>disable</em> state saving, or true
3289     * (the default) to allow it.
3290     *
3291     * @see #isSaveEnabled()
3292     * @see #setId(int)
3293     * @see #onSaveInstanceState()
3294     * @attr ref android.R.styleable#View_saveEnabled
3295     */
3296    public void setSaveEnabled(boolean enabled) {
3297        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
3298    }
3299
3300
3301    /**
3302     * Returns whether this View is able to take focus.
3303     *
3304     * @return True if this view can take focus, or false otherwise.
3305     * @attr ref android.R.styleable#View_focusable
3306     */
3307    @ViewDebug.ExportedProperty
3308    public final boolean isFocusable() {
3309        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
3310    }
3311
3312    /**
3313     * When a view is focusable, it may not want to take focus when in touch mode.
3314     * For example, a button would like focus when the user is navigating via a D-pad
3315     * so that the user can click on it, but once the user starts touching the screen,
3316     * the button shouldn't take focus
3317     * @return Whether the view is focusable in touch mode.
3318     * @attr ref android.R.styleable#View_focusableInTouchMode
3319     */
3320    @ViewDebug.ExportedProperty
3321    public final boolean isFocusableInTouchMode() {
3322        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
3323    }
3324
3325    /**
3326     * Find the nearest view in the specified direction that can take focus.
3327     * This does not actually give focus to that view.
3328     *
3329     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
3330     *
3331     * @return The nearest focusable in the specified direction, or null if none
3332     *         can be found.
3333     */
3334    public View focusSearch(int direction) {
3335        if (mParent != null) {
3336            return mParent.focusSearch(this, direction);
3337        } else {
3338            return null;
3339        }
3340    }
3341
3342    /**
3343     * This method is the last chance for the focused view and its ancestors to
3344     * respond to an arrow key. This is called when the focused view did not
3345     * consume the key internally, nor could the view system find a new view in
3346     * the requested direction to give focus to.
3347     *
3348     * @param focused The currently focused view.
3349     * @param direction The direction focus wants to move. One of FOCUS_UP,
3350     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
3351     * @return True if the this view consumed this unhandled move.
3352     */
3353    public boolean dispatchUnhandledMove(View focused, int direction) {
3354        return false;
3355    }
3356
3357    /**
3358     * If a user manually specified the next view id for a particular direction,
3359     * use the root to look up the view.  Once a view is found, it is cached
3360     * for future lookups.
3361     * @param root The root view of the hierarchy containing this view.
3362     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
3363     * @return The user specified next view, or null if there is none.
3364     */
3365    View findUserSetNextFocus(View root, int direction) {
3366        switch (direction) {
3367            case FOCUS_LEFT:
3368                if (mNextFocusLeftId == View.NO_ID) return null;
3369                return findViewShouldExist(root, mNextFocusLeftId);
3370            case FOCUS_RIGHT:
3371                if (mNextFocusRightId == View.NO_ID) return null;
3372                return findViewShouldExist(root, mNextFocusRightId);
3373            case FOCUS_UP:
3374                if (mNextFocusUpId == View.NO_ID) return null;
3375                return findViewShouldExist(root, mNextFocusUpId);
3376            case FOCUS_DOWN:
3377                if (mNextFocusDownId == View.NO_ID) return null;
3378                return findViewShouldExist(root, mNextFocusDownId);
3379        }
3380        return null;
3381    }
3382
3383    private static View findViewShouldExist(View root, int childViewId) {
3384        View result = root.findViewById(childViewId);
3385        if (result == null) {
3386            Log.w(VIEW_LOG_TAG, "couldn't find next focus view specified "
3387                    + "by user for id " + childViewId);
3388        }
3389        return result;
3390    }
3391
3392    /**
3393     * Find and return all focusable views that are descendants of this view,
3394     * possibly including this view if it is focusable itself.
3395     *
3396     * @param direction The direction of the focus
3397     * @return A list of focusable views
3398     */
3399    public ArrayList<View> getFocusables(int direction) {
3400        ArrayList<View> result = new ArrayList<View>(24);
3401        addFocusables(result, direction);
3402        return result;
3403    }
3404
3405    /**
3406     * Add any focusable views that are descendants of this view (possibly
3407     * including this view if it is focusable itself) to views.  If we are in touch mode,
3408     * only add views that are also focusable in touch mode.
3409     *
3410     * @param views Focusable views found so far
3411     * @param direction The direction of the focus
3412     */
3413    public void addFocusables(ArrayList<View> views, int direction) {
3414        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
3415    }
3416
3417    /**
3418     * Adds any focusable views that are descendants of this view (possibly
3419     * including this view if it is focusable itself) to views. This method
3420     * adds all focusable views regardless if we are in touch mode or
3421     * only views focusable in touch mode if we are in touch mode depending on
3422     * the focusable mode paramater.
3423     *
3424     * @param views Focusable views found so far or null if all we are interested is
3425     *        the number of focusables.
3426     * @param direction The direction of the focus.
3427     * @param focusableMode The type of focusables to be added.
3428     *
3429     * @see #FOCUSABLES_ALL
3430     * @see #FOCUSABLES_TOUCH_MODE
3431     */
3432    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
3433        if (!isFocusable()) {
3434            return;
3435        }
3436
3437        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE &&
3438                isInTouchMode() && !isFocusableInTouchMode()) {
3439            return;
3440        }
3441
3442        if (views != null) {
3443            views.add(this);
3444        }
3445    }
3446
3447    /**
3448     * Find and return all touchable views that are descendants of this view,
3449     * possibly including this view if it is touchable itself.
3450     *
3451     * @return A list of touchable views
3452     */
3453    public ArrayList<View> getTouchables() {
3454        ArrayList<View> result = new ArrayList<View>();
3455        addTouchables(result);
3456        return result;
3457    }
3458
3459    /**
3460     * Add any touchable views that are descendants of this view (possibly
3461     * including this view if it is touchable itself) to views.
3462     *
3463     * @param views Touchable views found so far
3464     */
3465    public void addTouchables(ArrayList<View> views) {
3466        final int viewFlags = mViewFlags;
3467
3468        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
3469                && (viewFlags & ENABLED_MASK) == ENABLED) {
3470            views.add(this);
3471        }
3472    }
3473
3474    /**
3475     * Call this to try to give focus to a specific view or to one of its
3476     * descendants.
3477     *
3478     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns false),
3479     * or if it is focusable and it is not focusable in touch mode ({@link #isFocusableInTouchMode})
3480     * while the device is in touch mode.
3481     *
3482     * See also {@link #focusSearch}, which is what you call to say that you
3483     * have focus, and you want your parent to look for the next one.
3484     *
3485     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
3486     * {@link #FOCUS_DOWN} and <code>null</code>.
3487     *
3488     * @return Whether this view or one of its descendants actually took focus.
3489     */
3490    public final boolean requestFocus() {
3491        return requestFocus(View.FOCUS_DOWN);
3492    }
3493
3494
3495    /**
3496     * Call this to try to give focus to a specific view or to one of its
3497     * descendants and give it a hint about what direction focus is heading.
3498     *
3499     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns false),
3500     * or if it is focusable and it is not focusable in touch mode ({@link #isFocusableInTouchMode})
3501     * while the device is in touch mode.
3502     *
3503     * See also {@link #focusSearch}, which is what you call to say that you
3504     * have focus, and you want your parent to look for the next one.
3505     *
3506     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
3507     * <code>null</code> set for the previously focused rectangle.
3508     *
3509     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
3510     * @return Whether this view or one of its descendants actually took focus.
3511     */
3512    public final boolean requestFocus(int direction) {
3513        return requestFocus(direction, null);
3514    }
3515
3516    /**
3517     * Call this to try to give focus to a specific view or to one of its descendants
3518     * and give it hints about the direction and a specific rectangle that the focus
3519     * is coming from.  The rectangle can help give larger views a finer grained hint
3520     * about where focus is coming from, and therefore, where to show selection, or
3521     * forward focus change internally.
3522     *
3523     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns false),
3524     * or if it is focusable and it is not focusable in touch mode ({@link #isFocusableInTouchMode})
3525     * while the device is in touch mode.
3526     *
3527     * A View will not take focus if it is not visible.
3528     *
3529     * A View will not take focus if one of its parents has {@link android.view.ViewGroup#getDescendantFocusability()}
3530     * equal to {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
3531     *
3532     * See also {@link #focusSearch}, which is what you call to say that you
3533     * have focus, and you want your parent to look for the next one.
3534     *
3535     * You may wish to override this method if your custom {@link View} has an internal
3536     * {@link View} that it wishes to forward the request to.
3537     *
3538     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
3539     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
3540     *        to give a finer grained hint about where focus is coming from.  May be null
3541     *        if there is no hint.
3542     * @return Whether this view or one of its descendants actually took focus.
3543     */
3544    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
3545        // need to be focusable
3546        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
3547                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
3548            return false;
3549        }
3550
3551        // need to be focusable in touch mode if in touch mode
3552        if (isInTouchMode() &&
3553                (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
3554            return false;
3555        }
3556
3557        // need to not have any parents blocking us
3558        if (hasAncestorThatBlocksDescendantFocus()) {
3559            return false;
3560        }
3561
3562        handleFocusGainInternal(direction, previouslyFocusedRect);
3563        return true;
3564    }
3565
3566    /**
3567     * Call this to try to give focus to a specific view or to one of its descendants. This is a
3568     * special variant of {@link #requestFocus() } that will allow views that are not focuable in
3569     * touch mode to request focus when they are touched.
3570     *
3571     * @return Whether this view or one of its descendants actually took focus.
3572     *
3573     * @see #isInTouchMode()
3574     *
3575     */
3576    public final boolean requestFocusFromTouch() {
3577        // Leave touch mode if we need to
3578        if (isInTouchMode()) {
3579            View root = getRootView();
3580            if (root != null) {
3581               ViewRoot viewRoot = (ViewRoot)root.getParent();
3582               if (viewRoot != null) {
3583                   viewRoot.ensureTouchMode(false);
3584               }
3585            }
3586        }
3587        return requestFocus(View.FOCUS_DOWN);
3588    }
3589
3590    /**
3591     * @return Whether any ancestor of this view blocks descendant focus.
3592     */
3593    private boolean hasAncestorThatBlocksDescendantFocus() {
3594        ViewParent ancestor = mParent;
3595        while (ancestor instanceof ViewGroup) {
3596            final ViewGroup vgAncestor = (ViewGroup) ancestor;
3597            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) {
3598                return true;
3599            } else {
3600                ancestor = vgAncestor.getParent();
3601            }
3602        }
3603        return false;
3604    }
3605
3606    /**
3607     * This is called when a container is going to temporarily detach a child
3608     * that currently has focus, with
3609     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
3610     * It will either be followed by {@link #onFinishTemporaryDetach()} or
3611     * {@link #onDetachedFromWindow()} when the container is done.  Generally
3612     * this is currently only done ListView for a view with focus.
3613     */
3614    public void onStartTemporaryDetach() {
3615    }
3616
3617    /**
3618     * Called after {@link #onStartTemporaryDetach} when the container is done
3619     * changing the view.
3620     */
3621    public void onFinishTemporaryDetach() {
3622    }
3623
3624    /**
3625     * capture information of this view for later analysis: developement only
3626     * check dynamic switch to make sure we only dump view
3627     * when ViewDebug.SYSTEM_PROPERTY_CAPTURE_VIEW) is set
3628     */
3629    private static void captureViewInfo(String subTag, View v) {
3630        if (v == null || SystemProperties.getInt(ViewDebug.SYSTEM_PROPERTY_CAPTURE_VIEW, 0) == 0) {
3631            return;
3632        }
3633        ViewDebug.dumpCapturedView(subTag, v);
3634    }
3635
3636    /**
3637     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
3638     * for this view's window.  Returns null if the view is not currently attached
3639     * to the window.  Normally you will not need to use this directly, but
3640     * just use the standard high-level event callbacks like {@link #onKeyDown}.
3641     */
3642    public KeyEvent.DispatcherState getKeyDispatcherState() {
3643        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
3644    }
3645
3646    /**
3647     * Dispatch a key event before it is processed by any input method
3648     * associated with the view hierarchy.  This can be used to intercept
3649     * key events in special situations before the IME consumes them; a
3650     * typical example would be handling the BACK key to update the application's
3651     * UI instead of allowing the IME to see it and close itself.
3652     *
3653     * @param event The key event to be dispatched.
3654     * @return True if the event was handled, false otherwise.
3655     */
3656    public boolean dispatchKeyEventPreIme(KeyEvent event) {
3657        return onKeyPreIme(event.getKeyCode(), event);
3658    }
3659
3660    /**
3661     * Dispatch a key event to the next view on the focus path. This path runs
3662     * from the top of the view tree down to the currently focused view. If this
3663     * view has focus, it will dispatch to itself. Otherwise it will dispatch
3664     * the next node down the focus path. This method also fires any key
3665     * listeners.
3666     *
3667     * @param event The key event to be dispatched.
3668     * @return True if the event was handled, false otherwise.
3669     */
3670    public boolean dispatchKeyEvent(KeyEvent event) {
3671        // If any attached key listener a first crack at the event.
3672        //noinspection SimplifiableIfStatement
3673
3674        if (android.util.Config.LOGV) {
3675            captureViewInfo("captureViewKeyEvent", this);
3676        }
3677
3678        if (mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
3679                && mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
3680            return true;
3681        }
3682
3683        return event.dispatch(this, mAttachInfo != null
3684                ? mAttachInfo.mKeyDispatchState : null, this);
3685    }
3686
3687    /**
3688     * Dispatches a key shortcut event.
3689     *
3690     * @param event The key event to be dispatched.
3691     * @return True if the event was handled by the view, false otherwise.
3692     */
3693    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
3694        return onKeyShortcut(event.getKeyCode(), event);
3695    }
3696
3697    /**
3698     * Pass the touch screen motion event down to the target view, or this
3699     * view if it is the target.
3700     *
3701     * @param event The motion event to be dispatched.
3702     * @return True if the event was handled by the view, false otherwise.
3703     */
3704    public boolean dispatchTouchEvent(MotionEvent event) {
3705        if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
3706                mOnTouchListener.onTouch(this, event)) {
3707            return true;
3708        }
3709        return onTouchEvent(event);
3710    }
3711
3712    /**
3713     * Pass a trackball motion event down to the focused view.
3714     *
3715     * @param event The motion event to be dispatched.
3716     * @return True if the event was handled by the view, false otherwise.
3717     */
3718    public boolean dispatchTrackballEvent(MotionEvent event) {
3719        //Log.i("view", "view=" + this + ", " + event.toString());
3720        return onTrackballEvent(event);
3721    }
3722
3723    /**
3724     * Called when the window containing this view gains or loses window focus.
3725     * ViewGroups should override to route to their children.
3726     *
3727     * @param hasFocus True if the window containing this view now has focus,
3728     *        false otherwise.
3729     */
3730    public void dispatchWindowFocusChanged(boolean hasFocus) {
3731        onWindowFocusChanged(hasFocus);
3732    }
3733
3734    /**
3735     * Called when the window containing this view gains or loses focus.  Note
3736     * that this is separate from view focus: to receive key events, both
3737     * your view and its window must have focus.  If a window is displayed
3738     * on top of yours that takes input focus, then your own window will lose
3739     * focus but the view focus will remain unchanged.
3740     *
3741     * @param hasWindowFocus True if the window containing this view now has
3742     *        focus, false otherwise.
3743     */
3744    public void onWindowFocusChanged(boolean hasWindowFocus) {
3745        InputMethodManager imm = InputMethodManager.peekInstance();
3746        if (!hasWindowFocus) {
3747            if (isPressed()) {
3748                setPressed(false);
3749            }
3750            if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
3751                imm.focusOut(this);
3752            }
3753            if (mPendingCheckForLongPress != null) {
3754                removeCallbacks(mPendingCheckForLongPress);
3755            }
3756            onFocusLost();
3757        } else if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
3758            imm.focusIn(this);
3759        }
3760        refreshDrawableState();
3761    }
3762
3763    /**
3764     * Returns true if this view is in a window that currently has window focus.
3765     * Note that this is not the same as the view itself having focus.
3766     *
3767     * @return True if this view is in a window that currently has window focus.
3768     */
3769    public boolean hasWindowFocus() {
3770        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
3771    }
3772
3773    /**
3774     * Dispatch a window visibility change down the view hierarchy.
3775     * ViewGroups should override to route to their children.
3776     *
3777     * @param visibility The new visibility of the window.
3778     *
3779     * @see #onWindowVisibilityChanged
3780     */
3781    public void dispatchWindowVisibilityChanged(int visibility) {
3782        onWindowVisibilityChanged(visibility);
3783    }
3784
3785    /**
3786     * Called when the window containing has change its visibility
3787     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
3788     * that this tells you whether or not your window is being made visible
3789     * to the window manager; this does <em>not</em> tell you whether or not
3790     * your window is obscured by other windows on the screen, even if it
3791     * is itself visible.
3792     *
3793     * @param visibility The new visibility of the window.
3794     */
3795    protected void onWindowVisibilityChanged(int visibility) {
3796    }
3797
3798    /**
3799     * Returns the current visibility of the window this view is attached to
3800     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
3801     *
3802     * @return Returns the current visibility of the view's window.
3803     */
3804    public int getWindowVisibility() {
3805        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
3806    }
3807
3808    /**
3809     * Retrieve the overall visible display size in which the window this view is
3810     * attached to has been positioned in.  This takes into account screen
3811     * decorations above the window, for both cases where the window itself
3812     * is being position inside of them or the window is being placed under
3813     * then and covered insets are used for the window to position its content
3814     * inside.  In effect, this tells you the available area where content can
3815     * be placed and remain visible to users.
3816     *
3817     * <p>This function requires an IPC back to the window manager to retrieve
3818     * the requested information, so should not be used in performance critical
3819     * code like drawing.
3820     *
3821     * @param outRect Filled in with the visible display frame.  If the view
3822     * is not attached to a window, this is simply the raw display size.
3823     */
3824    public void getWindowVisibleDisplayFrame(Rect outRect) {
3825        if (mAttachInfo != null) {
3826            try {
3827                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
3828            } catch (RemoteException e) {
3829                return;
3830            }
3831            // XXX This is really broken, and probably all needs to be done
3832            // in the window manager, and we need to know more about whether
3833            // we want the area behind or in front of the IME.
3834            final Rect insets = mAttachInfo.mVisibleInsets;
3835            outRect.left += insets.left;
3836            outRect.top += insets.top;
3837            outRect.right -= insets.right;
3838            outRect.bottom -= insets.bottom;
3839            return;
3840        }
3841        Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
3842        outRect.set(0, 0, d.getWidth(), d.getHeight());
3843    }
3844
3845    /**
3846     * Private function to aggregate all per-view attributes in to the view
3847     * root.
3848     */
3849    void dispatchCollectViewAttributes(int visibility) {
3850        performCollectViewAttributes(visibility);
3851    }
3852
3853    void performCollectViewAttributes(int visibility) {
3854        //noinspection PointlessBitwiseExpression
3855        if (((visibility | mViewFlags) & (VISIBILITY_MASK | KEEP_SCREEN_ON))
3856                == (VISIBLE | KEEP_SCREEN_ON)) {
3857            mAttachInfo.mKeepScreenOn = true;
3858        }
3859    }
3860
3861    void needGlobalAttributesUpdate(boolean force) {
3862        AttachInfo ai = mAttachInfo;
3863        if (ai != null) {
3864            if (ai.mKeepScreenOn || force) {
3865                ai.mRecomputeGlobalAttributes = true;
3866            }
3867        }
3868    }
3869
3870    /**
3871     * Returns whether the device is currently in touch mode.  Touch mode is entered
3872     * once the user begins interacting with the device by touch, and affects various
3873     * things like whether focus is always visible to the user.
3874     *
3875     * @return Whether the device is in touch mode.
3876     */
3877    @ViewDebug.ExportedProperty
3878    public boolean isInTouchMode() {
3879        if (mAttachInfo != null) {
3880            return mAttachInfo.mInTouchMode;
3881        } else {
3882            return ViewRoot.isInTouchMode();
3883        }
3884    }
3885
3886    /**
3887     * Returns the context the view is running in, through which it can
3888     * access the current theme, resources, etc.
3889     *
3890     * @return The view's Context.
3891     */
3892    @ViewDebug.CapturedViewProperty
3893    public final Context getContext() {
3894        return mContext;
3895    }
3896
3897    /**
3898     * Handle a key event before it is processed by any input method
3899     * associated with the view hierarchy.  This can be used to intercept
3900     * key events in special situations before the IME consumes them; a
3901     * typical example would be handling the BACK key to update the application's
3902     * UI instead of allowing the IME to see it and close itself.
3903     *
3904     * @param keyCode The value in event.getKeyCode().
3905     * @param event Description of the key event.
3906     * @return If you handled the event, return true. If you want to allow the
3907     *         event to be handled by the next receiver, return false.
3908     */
3909    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
3910        return false;
3911    }
3912
3913    /**
3914     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
3915     * KeyEvent.Callback.onKeyMultiple()}: perform press of the view
3916     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
3917     * is released, if the view is enabled and clickable.
3918     *
3919     * @param keyCode A key code that represents the button pressed, from
3920     *                {@link android.view.KeyEvent}.
3921     * @param event   The KeyEvent object that defines the button action.
3922     */
3923    public boolean onKeyDown(int keyCode, KeyEvent event) {
3924        boolean result = false;
3925
3926        switch (keyCode) {
3927            case KeyEvent.KEYCODE_DPAD_CENTER:
3928            case KeyEvent.KEYCODE_ENTER: {
3929                if ((mViewFlags & ENABLED_MASK) == DISABLED) {
3930                    return true;
3931                }
3932                // Long clickable items don't necessarily have to be clickable
3933                if (((mViewFlags & CLICKABLE) == CLICKABLE ||
3934                        (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
3935                        (event.getRepeatCount() == 0)) {
3936                    setPressed(true);
3937                    if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
3938                        postCheckForLongClick();
3939                    }
3940                    return true;
3941                }
3942                break;
3943            }
3944        }
3945        return result;
3946    }
3947
3948    /**
3949     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
3950     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
3951     * the event).
3952     */
3953    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
3954        return false;
3955    }
3956
3957    /**
3958     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
3959     * KeyEvent.Callback.onKeyMultiple()}: perform clicking of the view
3960     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
3961     * {@link KeyEvent#KEYCODE_ENTER} is released.
3962     *
3963     * @param keyCode A key code that represents the button pressed, from
3964     *                {@link android.view.KeyEvent}.
3965     * @param event   The KeyEvent object that defines the button action.
3966     */
3967    public boolean onKeyUp(int keyCode, KeyEvent event) {
3968        boolean result = false;
3969
3970        switch (keyCode) {
3971            case KeyEvent.KEYCODE_DPAD_CENTER:
3972            case KeyEvent.KEYCODE_ENTER: {
3973                if ((mViewFlags & ENABLED_MASK) == DISABLED) {
3974                    return true;
3975                }
3976                if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
3977                    setPressed(false);
3978
3979                    if (!mHasPerformedLongPress) {
3980                        // This is a tap, so remove the longpress check
3981                        if (mPendingCheckForLongPress != null) {
3982                            removeCallbacks(mPendingCheckForLongPress);
3983                        }
3984
3985                        result = performClick();
3986                    }
3987                }
3988                break;
3989            }
3990        }
3991        return result;
3992    }
3993
3994    /**
3995     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
3996     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
3997     * the event).
3998     *
3999     * @param keyCode     A key code that represents the button pressed, from
4000     *                    {@link android.view.KeyEvent}.
4001     * @param repeatCount The number of times the action was made.
4002     * @param event       The KeyEvent object that defines the button action.
4003     */
4004    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
4005        return false;
4006    }
4007
4008    /**
4009     * Called when an unhandled key shortcut event occurs.
4010     *
4011     * @param keyCode The value in event.getKeyCode().
4012     * @param event Description of the key event.
4013     * @return If you handled the event, return true. If you want to allow the
4014     *         event to be handled by the next receiver, return false.
4015     */
4016    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
4017        return false;
4018    }
4019
4020    /**
4021     * Check whether the called view is a text editor, in which case it
4022     * would make sense to automatically display a soft input window for
4023     * it.  Subclasses should override this if they implement
4024     * {@link #onCreateInputConnection(EditorInfo)} to return true if
4025     * a call on that method would return a non-null InputConnection, and
4026     * they are really a first-class editor that the user would normally
4027     * start typing on when the go into a window containing your view.
4028     *
4029     * <p>The default implementation always returns false.  This does
4030     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
4031     * will not be called or the user can not otherwise perform edits on your
4032     * view; it is just a hint to the system that this is not the primary
4033     * purpose of this view.
4034     *
4035     * @return Returns true if this view is a text editor, else false.
4036     */
4037    public boolean onCheckIsTextEditor() {
4038        return false;
4039    }
4040
4041    /**
4042     * Create a new InputConnection for an InputMethod to interact
4043     * with the view.  The default implementation returns null, since it doesn't
4044     * support input methods.  You can override this to implement such support.
4045     * This is only needed for views that take focus and text input.
4046     *
4047     * <p>When implementing this, you probably also want to implement
4048     * {@link #onCheckIsTextEditor()} to indicate you will return a
4049     * non-null InputConnection.
4050     *
4051     * @param outAttrs Fill in with attribute information about the connection.
4052     */
4053    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
4054        return null;
4055    }
4056
4057    /**
4058     * Called by the {@link android.view.inputmethod.InputMethodManager}
4059     * when a view who is not the current
4060     * input connection target is trying to make a call on the manager.  The
4061     * default implementation returns false; you can override this to return
4062     * true for certain views if you are performing InputConnection proxying
4063     * to them.
4064     * @param view The View that is making the InputMethodManager call.
4065     * @return Return true to allow the call, false to reject.
4066     */
4067    public boolean checkInputConnectionProxy(View view) {
4068        return false;
4069    }
4070
4071    /**
4072     * Show the context menu for this view. It is not safe to hold on to the
4073     * menu after returning from this method.
4074     *
4075     * @param menu The context menu to populate
4076     */
4077    public void createContextMenu(ContextMenu menu) {
4078        ContextMenuInfo menuInfo = getContextMenuInfo();
4079
4080        // Sets the current menu info so all items added to menu will have
4081        // my extra info set.
4082        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
4083
4084        onCreateContextMenu(menu);
4085        if (mOnCreateContextMenuListener != null) {
4086            mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
4087        }
4088
4089        // Clear the extra information so subsequent items that aren't mine don't
4090        // have my extra info.
4091        ((MenuBuilder)menu).setCurrentMenuInfo(null);
4092
4093        if (mParent != null) {
4094            mParent.createContextMenu(menu);
4095        }
4096    }
4097
4098    /**
4099     * Views should implement this if they have extra information to associate
4100     * with the context menu. The return result is supplied as a parameter to
4101     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
4102     * callback.
4103     *
4104     * @return Extra information about the item for which the context menu
4105     *         should be shown. This information will vary across different
4106     *         subclasses of View.
4107     */
4108    protected ContextMenuInfo getContextMenuInfo() {
4109        return null;
4110    }
4111
4112    /**
4113     * Views should implement this if the view itself is going to add items to
4114     * the context menu.
4115     *
4116     * @param menu the context menu to populate
4117     */
4118    protected void onCreateContextMenu(ContextMenu menu) {
4119    }
4120
4121    /**
4122     * Implement this method to handle trackball motion events.  The
4123     * <em>relative</em> movement of the trackball since the last event
4124     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
4125     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
4126     * that a movement of 1 corresponds to the user pressing one DPAD key (so
4127     * they will often be fractional values, representing the more fine-grained
4128     * movement information available from a trackball).
4129     *
4130     * @param event The motion event.
4131     * @return True if the event was handled, false otherwise.
4132     */
4133    public boolean onTrackballEvent(MotionEvent event) {
4134        return false;
4135    }
4136
4137    /**
4138     * Implement this method to handle touch screen motion events.
4139     *
4140     * @param event The motion event.
4141     * @return True if the event was handled, false otherwise.
4142     */
4143    public boolean onTouchEvent(MotionEvent event) {
4144        final int viewFlags = mViewFlags;
4145
4146        if ((viewFlags & ENABLED_MASK) == DISABLED) {
4147            // A disabled view that is clickable still consumes the touch
4148            // events, it just doesn't respond to them.
4149            return (((viewFlags & CLICKABLE) == CLICKABLE ||
4150                    (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
4151        }
4152
4153        if (mTouchDelegate != null) {
4154            if (mTouchDelegate.onTouchEvent(event)) {
4155                return true;
4156            }
4157        }
4158
4159        if (((viewFlags & CLICKABLE) == CLICKABLE ||
4160                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
4161            switch (event.getAction()) {
4162                case MotionEvent.ACTION_UP:
4163                    if ((mPrivateFlags & PRESSED) != 0) {
4164                        // take focus if we don't have it already and we should in
4165                        // touch mode.
4166                        boolean focusTaken = false;
4167                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
4168                            focusTaken = requestFocus();
4169                        }
4170
4171                        if (!mHasPerformedLongPress) {
4172                            // This is a tap, so remove the longpress check
4173                            if (mPendingCheckForLongPress != null) {
4174                                removeCallbacks(mPendingCheckForLongPress);
4175                            }
4176
4177                            // Only perform take click actions if we were in the pressed state
4178                            if (!focusTaken) {
4179                                performClick();
4180                            }
4181                        }
4182
4183                        if (mUnsetPressedState == null) {
4184                            mUnsetPressedState = new UnsetPressedState();
4185                        }
4186
4187                        if (!post(mUnsetPressedState)) {
4188                            // If the post failed, unpress right now
4189                            mUnsetPressedState.run();
4190                        }
4191                    }
4192                    break;
4193
4194                case MotionEvent.ACTION_DOWN:
4195                    mPrivateFlags |= PRESSED;
4196                    refreshDrawableState();
4197                    if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
4198                        postCheckForLongClick();
4199                    }
4200                    break;
4201
4202                case MotionEvent.ACTION_CANCEL:
4203                    mPrivateFlags &= ~PRESSED;
4204                    refreshDrawableState();
4205                    break;
4206
4207                case MotionEvent.ACTION_MOVE:
4208                    final int x = (int) event.getX();
4209                    final int y = (int) event.getY();
4210
4211                    // Be lenient about moving outside of buttons
4212                    int slop = ViewConfiguration.get(mContext).getScaledTouchSlop();
4213                    if ((x < 0 - slop) || (x >= getWidth() + slop) ||
4214                            (y < 0 - slop) || (y >= getHeight() + slop)) {
4215                        // Outside button
4216                        if ((mPrivateFlags & PRESSED) != 0) {
4217                            // Remove any future long press checks
4218                            if (mPendingCheckForLongPress != null) {
4219                                removeCallbacks(mPendingCheckForLongPress);
4220                            }
4221
4222                            // Need to switch from pressed to not pressed
4223                            mPrivateFlags &= ~PRESSED;
4224                            refreshDrawableState();
4225                        }
4226                    } else {
4227                        // Inside button
4228                        if ((mPrivateFlags & PRESSED) == 0) {
4229                            // Need to switch from not pressed to pressed
4230                            mPrivateFlags |= PRESSED;
4231                            refreshDrawableState();
4232                        }
4233                    }
4234                    break;
4235            }
4236            return true;
4237        }
4238
4239        return false;
4240    }
4241
4242    /**
4243     * Cancels a pending long press.  Your subclass can use this if you
4244     * want the context menu to come up if the user presses and holds
4245     * at the same place, but you don't want it to come up if they press
4246     * and then move around enough to cause scrolling.
4247     */
4248    public void cancelLongPress() {
4249        if (mPendingCheckForLongPress != null) {
4250            removeCallbacks(mPendingCheckForLongPress);
4251        }
4252    }
4253
4254    /**
4255     * Sets the TouchDelegate for this View.
4256     */
4257    public void setTouchDelegate(TouchDelegate delegate) {
4258        mTouchDelegate = delegate;
4259    }
4260
4261    /**
4262     * Gets the TouchDelegate for this View.
4263     */
4264    public TouchDelegate getTouchDelegate() {
4265        return mTouchDelegate;
4266    }
4267
4268    /**
4269     * Set flags controlling behavior of this view.
4270     *
4271     * @param flags Constant indicating the value which should be set
4272     * @param mask Constant indicating the bit range that should be changed
4273     */
4274    void setFlags(int flags, int mask) {
4275        int old = mViewFlags;
4276        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
4277
4278        int changed = mViewFlags ^ old;
4279        if (changed == 0) {
4280            return;
4281        }
4282        int privateFlags = mPrivateFlags;
4283
4284        /* Check if the FOCUSABLE bit has changed */
4285        if (((changed & FOCUSABLE_MASK) != 0) &&
4286                ((privateFlags & HAS_BOUNDS) !=0)) {
4287            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
4288                    && ((privateFlags & FOCUSED) != 0)) {
4289                /* Give up focus if we are no longer focusable */
4290                clearFocus();
4291            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
4292                    && ((privateFlags & FOCUSED) == 0)) {
4293                /*
4294                 * Tell the view system that we are now available to take focus
4295                 * if no one else already has it.
4296                 */
4297                if (mParent != null) mParent.focusableViewAvailable(this);
4298            }
4299        }
4300
4301        if ((flags & VISIBILITY_MASK) == VISIBLE) {
4302            if ((changed & VISIBILITY_MASK) != 0) {
4303                /*
4304                 * If this view is becoming visible, set the DRAWN flag so that
4305                 * the next invalidate() will not be skipped.
4306                 */
4307                mPrivateFlags |= DRAWN;
4308
4309                needGlobalAttributesUpdate(true);
4310
4311                // a view becoming visible is worth notifying the parent
4312                // about in case nothing has focus.  even if this specific view
4313                // isn't focusable, it may contain something that is, so let
4314                // the root view try to give this focus if nothing else does.
4315                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
4316                    mParent.focusableViewAvailable(this);
4317                }
4318            }
4319        }
4320
4321        /* Check if the GONE bit has changed */
4322        if ((changed & GONE) != 0) {
4323            needGlobalAttributesUpdate(false);
4324            requestLayout();
4325            invalidate();
4326
4327            if (((mViewFlags & VISIBILITY_MASK) == GONE) && hasFocus()) {
4328                clearFocus();
4329            }
4330            if (mAttachInfo != null) {
4331                mAttachInfo.mViewVisibilityChanged = true;
4332            }
4333        }
4334
4335        /* Check if the VISIBLE bit has changed */
4336        if ((changed & INVISIBLE) != 0) {
4337            needGlobalAttributesUpdate(false);
4338            invalidate();
4339
4340            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) {
4341                // root view becoming invisible shouldn't clear focus
4342                if (getRootView() != this) {
4343                    clearFocus();
4344                }
4345            }
4346            if (mAttachInfo != null) {
4347                mAttachInfo.mViewVisibilityChanged = true;
4348            }
4349        }
4350
4351        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
4352            destroyDrawingCache();
4353        }
4354
4355        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
4356            destroyDrawingCache();
4357            mPrivateFlags &= ~DRAWING_CACHE_VALID;
4358        }
4359
4360        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
4361            destroyDrawingCache();
4362            mPrivateFlags &= ~DRAWING_CACHE_VALID;
4363        }
4364
4365        if ((changed & DRAW_MASK) != 0) {
4366            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
4367                if (mBGDrawable != null) {
4368                    mPrivateFlags &= ~SKIP_DRAW;
4369                    mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
4370                } else {
4371                    mPrivateFlags |= SKIP_DRAW;
4372                }
4373            } else {
4374                mPrivateFlags &= ~SKIP_DRAW;
4375            }
4376            requestLayout();
4377            invalidate();
4378        }
4379
4380        if ((changed & KEEP_SCREEN_ON) != 0) {
4381            if (mParent != null) {
4382                mParent.recomputeViewAttributes(this);
4383            }
4384        }
4385    }
4386
4387    /**
4388     * Change the view's z order in the tree, so it's on top of other sibling
4389     * views
4390     */
4391    public void bringToFront() {
4392        if (mParent != null) {
4393            mParent.bringChildToFront(this);
4394        }
4395    }
4396
4397    /**
4398     * This is called in response to an internal scroll in this view (i.e., the
4399     * view scrolled its own contents). This is typically as a result of
4400     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
4401     * called.
4402     *
4403     * @param l Current horizontal scroll origin.
4404     * @param t Current vertical scroll origin.
4405     * @param oldl Previous horizontal scroll origin.
4406     * @param oldt Previous vertical scroll origin.
4407     */
4408    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
4409        mBackgroundSizeChanged = true;
4410
4411        final AttachInfo ai = mAttachInfo;
4412        if (ai != null) {
4413            ai.mViewScrollChanged = true;
4414        }
4415    }
4416
4417    /**
4418     * This is called during layout when the size of this view has changed. If
4419     * you were just added to the view hierarchy, you're called with the old
4420     * values of 0.
4421     *
4422     * @param w Current width of this view.
4423     * @param h Current height of this view.
4424     * @param oldw Old width of this view.
4425     * @param oldh Old height of this view.
4426     */
4427    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
4428    }
4429
4430    /**
4431     * Called by draw to draw the child views. This may be overridden
4432     * by derived classes to gain control just before its children are drawn
4433     * (but after its own view has been drawn).
4434     * @param canvas the canvas on which to draw the view
4435     */
4436    protected void dispatchDraw(Canvas canvas) {
4437    }
4438
4439    /**
4440     * Gets the parent of this view. Note that the parent is a
4441     * ViewParent and not necessarily a View.
4442     *
4443     * @return Parent of this view.
4444     */
4445    public final ViewParent getParent() {
4446        return mParent;
4447    }
4448
4449    /**
4450     * Return the scrolled left position of this view. This is the left edge of
4451     * the displayed part of your view. You do not need to draw any pixels
4452     * farther left, since those are outside of the frame of your view on
4453     * screen.
4454     *
4455     * @return The left edge of the displayed part of your view, in pixels.
4456     */
4457    public final int getScrollX() {
4458        return mScrollX;
4459    }
4460
4461    /**
4462     * Return the scrolled top position of this view. This is the top edge of
4463     * the displayed part of your view. You do not need to draw any pixels above
4464     * it, since those are outside of the frame of your view on screen.
4465     *
4466     * @return The top edge of the displayed part of your view, in pixels.
4467     */
4468    public final int getScrollY() {
4469        return mScrollY;
4470    }
4471
4472    /**
4473     * Return the width of the your view.
4474     *
4475     * @return The width of your view, in pixels.
4476     */
4477    @ViewDebug.ExportedProperty
4478    public final int getWidth() {
4479        return mRight - mLeft;
4480    }
4481
4482    /**
4483     * Return the height of your view.
4484     *
4485     * @return The height of your view, in pixels.
4486     */
4487    @ViewDebug.ExportedProperty
4488    public final int getHeight() {
4489        return mBottom - mTop;
4490    }
4491
4492    /**
4493     * Return the visible drawing bounds of your view. Fills in the output
4494     * rectangle with the values from getScrollX(), getScrollY(),
4495     * getWidth(), and getHeight().
4496     *
4497     * @param outRect The (scrolled) drawing bounds of the view.
4498     */
4499    public void getDrawingRect(Rect outRect) {
4500        outRect.left = mScrollX;
4501        outRect.top = mScrollY;
4502        outRect.right = mScrollX + (mRight - mLeft);
4503        outRect.bottom = mScrollY + (mBottom - mTop);
4504    }
4505
4506    /**
4507     * The width of this view as measured in the most recent call to measure().
4508     * This should be used during measurement and layout calculations only. Use
4509     * {@link #getWidth()} to see how wide a view is after layout.
4510     *
4511     * @return The measured width of this view.
4512     */
4513    public final int getMeasuredWidth() {
4514        return mMeasuredWidth;
4515    }
4516
4517    /**
4518     * The height of this view as measured in the most recent call to measure().
4519     * This should be used during measurement and layout calculations only. Use
4520     * {@link #getHeight()} to see how tall a view is after layout.
4521     *
4522     * @return The measured height of this view.
4523     */
4524    public final int getMeasuredHeight() {
4525        return mMeasuredHeight;
4526    }
4527
4528    /**
4529     * Top position of this view relative to its parent.
4530     *
4531     * @return The top of this view, in pixels.
4532     */
4533    @ViewDebug.CapturedViewProperty
4534    public final int getTop() {
4535        return mTop;
4536    }
4537
4538    /**
4539     * Bottom position of this view relative to its parent.
4540     *
4541     * @return The bottom of this view, in pixels.
4542     */
4543    @ViewDebug.CapturedViewProperty
4544    public final int getBottom() {
4545        return mBottom;
4546    }
4547
4548    /**
4549     * Left position of this view relative to its parent.
4550     *
4551     * @return The left edge of this view, in pixels.
4552     */
4553    @ViewDebug.CapturedViewProperty
4554    public final int getLeft() {
4555        return mLeft;
4556    }
4557
4558    /**
4559     * Right position of this view relative to its parent.
4560     *
4561     * @return The right edge of this view, in pixels.
4562     */
4563    @ViewDebug.CapturedViewProperty
4564    public final int getRight() {
4565        return mRight;
4566    }
4567
4568    /**
4569     * Hit rectangle in parent's coordinates
4570     *
4571     * @param outRect The hit rectangle of the view.
4572     */
4573    public void getHitRect(Rect outRect) {
4574        outRect.set(mLeft, mTop, mRight, mBottom);
4575    }
4576
4577    /**
4578     * When a view has focus and the user navigates away from it, the next view is searched for
4579     * starting from the rectangle filled in by this method.
4580     *
4581     * By default, the rectange is the {@link #getDrawingRect})of the view.  However, if your
4582     * view maintains some idea of internal selection, such as a cursor, or a selected row
4583     * or column, you should override this method and fill in a more specific rectangle.
4584     *
4585     * @param r The rectangle to fill in, in this view's coordinates.
4586     */
4587    public void getFocusedRect(Rect r) {
4588        getDrawingRect(r);
4589    }
4590
4591    /**
4592     * If some part of this view is not clipped by any of its parents, then
4593     * return that area in r in global (root) coordinates. To convert r to local
4594     * coordinates, offset it by -globalOffset (e.g. r.offset(-globalOffset.x,
4595     * -globalOffset.y)) If the view is completely clipped or translated out,
4596     * return false.
4597     *
4598     * @param r If true is returned, r holds the global coordinates of the
4599     *        visible portion of this view.
4600     * @param globalOffset If true is returned, globalOffset holds the dx,dy
4601     *        between this view and its root. globalOffet may be null.
4602     * @return true if r is non-empty (i.e. part of the view is visible at the
4603     *         root level.
4604     */
4605    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
4606        int width = mRight - mLeft;
4607        int height = mBottom - mTop;
4608        if (width > 0 && height > 0) {
4609            r.set(0, 0, width, height);
4610            if (globalOffset != null) {
4611                globalOffset.set(-mScrollX, -mScrollY);
4612            }
4613            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
4614        }
4615        return false;
4616    }
4617
4618    public final boolean getGlobalVisibleRect(Rect r) {
4619        return getGlobalVisibleRect(r, null);
4620    }
4621
4622    public final boolean getLocalVisibleRect(Rect r) {
4623        Point offset = new Point();
4624        if (getGlobalVisibleRect(r, offset)) {
4625            r.offset(-offset.x, -offset.y); // make r local
4626            return true;
4627        }
4628        return false;
4629    }
4630
4631    /**
4632     * Offset this view's vertical location by the specified number of pixels.
4633     *
4634     * @param offset the number of pixels to offset the view by
4635     */
4636    public void offsetTopAndBottom(int offset) {
4637        mTop += offset;
4638        mBottom += offset;
4639    }
4640
4641    /**
4642     * Offset this view's horizontal location by the specified amount of pixels.
4643     *
4644     * @param offset the numer of pixels to offset the view by
4645     */
4646    public void offsetLeftAndRight(int offset) {
4647        mLeft += offset;
4648        mRight += offset;
4649    }
4650
4651    /**
4652     * Get the LayoutParams associated with this view. All views should have
4653     * layout parameters. These supply parameters to the <i>parent</i> of this
4654     * view specifying how it should be arranged. There are many subclasses of
4655     * ViewGroup.LayoutParams, and these correspond to the different subclasses
4656     * of ViewGroup that are responsible for arranging their children.
4657     * @return The LayoutParams associated with this view
4658     */
4659    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
4660    public ViewGroup.LayoutParams getLayoutParams() {
4661        return mLayoutParams;
4662    }
4663
4664    /**
4665     * Set the layout parameters associated with this view. These supply
4666     * parameters to the <i>parent</i> of this view specifying how it should be
4667     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
4668     * correspond to the different subclasses of ViewGroup that are responsible
4669     * for arranging their children.
4670     *
4671     * @param params the layout parameters for this view
4672     */
4673    public void setLayoutParams(ViewGroup.LayoutParams params) {
4674        if (params == null) {
4675            throw new NullPointerException("params == null");
4676        }
4677        mLayoutParams = params;
4678        requestLayout();
4679    }
4680
4681    /**
4682     * Set the scrolled position of your view. This will cause a call to
4683     * {@link #onScrollChanged(int, int, int, int)} and the view will be
4684     * invalidated.
4685     * @param x the x position to scroll to
4686     * @param y the y position to scroll to
4687     */
4688    public void scrollTo(int x, int y) {
4689        if (mScrollX != x || mScrollY != y) {
4690            int oldX = mScrollX;
4691            int oldY = mScrollY;
4692            mScrollX = x;
4693            mScrollY = y;
4694            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
4695            if (!awakenScrollBars()) {
4696                invalidate();
4697            }
4698        }
4699    }
4700
4701    /**
4702     * Move the scrolled position of your view. This will cause a call to
4703     * {@link #onScrollChanged(int, int, int, int)} and the view will be
4704     * invalidated.
4705     * @param x the amount of pixels to scroll by horizontally
4706     * @param y the amount of pixels to scroll by vertically
4707     */
4708    public void scrollBy(int x, int y) {
4709        scrollTo(mScrollX + x, mScrollY + y);
4710    }
4711
4712    /**
4713     * <p>Trigger the scrollbars to draw. When invoked this method starts an
4714     * animation to fade the scrollbars out after a default delay. If a subclass
4715     * provides animated scrolling, the start delay should equal the duration
4716     * of the scrolling animation.</p>
4717     *
4718     * <p>The animation starts only if at least one of the scrollbars is
4719     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
4720     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
4721     * this method returns true, and false otherwise. If the animation is
4722     * started, this method calls {@link #invalidate()}; in that case the
4723     * caller should not call {@link #invalidate()}.</p>
4724     *
4725     * <p>This method should be invoked every time a subclass directly updates
4726     * the scroll parameters.</p>
4727     *
4728     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
4729     * and {@link #scrollTo(int, int)}.</p>
4730     *
4731     * @return true if the animation is played, false otherwise
4732     *
4733     * @see #awakenScrollBars(int)
4734     * @see #scrollBy(int, int)
4735     * @see #scrollTo(int, int)
4736     * @see #isHorizontalScrollBarEnabled()
4737     * @see #isVerticalScrollBarEnabled()
4738     * @see #setHorizontalScrollBarEnabled(boolean)
4739     * @see #setVerticalScrollBarEnabled(boolean)
4740     */
4741    protected boolean awakenScrollBars() {
4742        return mScrollCache != null &&
4743                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade);
4744    }
4745
4746    /**
4747     * <p>
4748     * Trigger the scrollbars to draw. When invoked this method starts an
4749     * animation to fade the scrollbars out after a fixed delay. If a subclass
4750     * provides animated scrolling, the start delay should equal the duration of
4751     * the scrolling animation.
4752     * </p>
4753     *
4754     * <p>
4755     * The animation starts only if at least one of the scrollbars is enabled,
4756     * as specified by {@link #isHorizontalScrollBarEnabled()} and
4757     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
4758     * this method returns true, and false otherwise. If the animation is
4759     * started, this method calls {@link #invalidate()}; in that case the caller
4760     * should not call {@link #invalidate()}.
4761     * </p>
4762     *
4763     * <p>
4764     * This method should be invoked everytime a subclass directly updates the
4765     * scroll parameters.
4766     * </p>
4767     *
4768     * @param startDelay the delay, in milliseconds, after which the animation
4769     *        should start; when the delay is 0, the animation starts
4770     *        immediately
4771     * @return true if the animation is played, false otherwise
4772     *
4773     * @see #scrollBy(int, int)
4774     * @see #scrollTo(int, int)
4775     * @see #isHorizontalScrollBarEnabled()
4776     * @see #isVerticalScrollBarEnabled()
4777     * @see #setHorizontalScrollBarEnabled(boolean)
4778     * @see #setVerticalScrollBarEnabled(boolean)
4779     */
4780    protected boolean awakenScrollBars(int startDelay) {
4781        final ScrollabilityCache scrollCache = mScrollCache;
4782
4783        if (scrollCache == null || !scrollCache.fadeScrollBars) {
4784            return false;
4785        }
4786
4787        if (scrollCache.scrollBar == null) {
4788            scrollCache.scrollBar = new ScrollBarDrawable();
4789        }
4790
4791        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
4792
4793            // Invalidate to show the scrollbars
4794            invalidate();
4795
4796            if (scrollCache.state == ScrollabilityCache.OFF) {
4797                // FIXME: this is copied from WindowManagerService.
4798                // We should get this value from the system when it
4799                // is possible to do so.
4800                final int KEY_REPEAT_FIRST_DELAY = 750;
4801                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
4802            }
4803
4804            // Tell mScrollCache when we should start fading. This may
4805            // extend the fade start time if one was already scheduled
4806            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
4807            scrollCache.fadeStartTime = fadeStartTime;
4808            scrollCache.state = ScrollabilityCache.ON;
4809
4810            // Schedule our fader to run, unscheduling any old ones first
4811            if (mAttachInfo != null) {
4812                mAttachInfo.mHandler.removeCallbacks(scrollCache);
4813                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
4814            }
4815
4816            return true;
4817        }
4818
4819        return false;
4820    }
4821
4822    /**
4823     * Mark the the area defined by dirty as needing to be drawn. If the view is
4824     * visible, {@link #onDraw} will be called at some point in the future.
4825     * This must be called from a UI thread. To call from a non-UI thread, call
4826     * {@link #postInvalidate()}.
4827     *
4828     * WARNING: This method is destructive to dirty.
4829     * @param dirty the rectangle representing the bounds of the dirty region
4830     */
4831    public void invalidate(Rect dirty) {
4832        if (ViewDebug.TRACE_HIERARCHY) {
4833            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
4834        }
4835
4836        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) {
4837            mPrivateFlags &= ~DRAWING_CACHE_VALID;
4838            final ViewParent p = mParent;
4839            final AttachInfo ai = mAttachInfo;
4840            if (p != null && ai != null) {
4841                final int scrollX = mScrollX;
4842                final int scrollY = mScrollY;
4843                final Rect r = ai.mTmpInvalRect;
4844                r.set(dirty.left - scrollX, dirty.top - scrollY,
4845                        dirty.right - scrollX, dirty.bottom - scrollY);
4846                mParent.invalidateChild(this, r);
4847            }
4848        }
4849    }
4850
4851    /**
4852     * Mark the the area defined by the rect (l,t,r,b) as needing to be drawn.
4853     * The coordinates of the dirty rect are relative to the view.
4854     * If the view is visible, {@link #onDraw} will be called at some point
4855     * in the future. This must be called from a UI thread. To call
4856     * from a non-UI thread, call {@link #postInvalidate()}.
4857     * @param l the left position of the dirty region
4858     * @param t the top position of the dirty region
4859     * @param r the right position of the dirty region
4860     * @param b the bottom position of the dirty region
4861     */
4862    public void invalidate(int l, int t, int r, int b) {
4863        if (ViewDebug.TRACE_HIERARCHY) {
4864            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
4865        }
4866
4867        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) {
4868            mPrivateFlags &= ~DRAWING_CACHE_VALID;
4869            final ViewParent p = mParent;
4870            final AttachInfo ai = mAttachInfo;
4871            if (p != null && ai != null && l < r && t < b) {
4872                final int scrollX = mScrollX;
4873                final int scrollY = mScrollY;
4874                final Rect tmpr = ai.mTmpInvalRect;
4875                tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY);
4876                p.invalidateChild(this, tmpr);
4877            }
4878        }
4879    }
4880
4881    /**
4882     * Invalidate the whole view. If the view is visible, {@link #onDraw} will
4883     * be called at some point in the future. This must be called from a
4884     * UI thread. To call from a non-UI thread, call {@link #postInvalidate()}.
4885     */
4886    public void invalidate() {
4887        if (ViewDebug.TRACE_HIERARCHY) {
4888            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
4889        }
4890
4891        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) {
4892            mPrivateFlags &= ~DRAWN & ~DRAWING_CACHE_VALID;
4893            final ViewParent p = mParent;
4894            final AttachInfo ai = mAttachInfo;
4895            if (p != null && ai != null) {
4896                final Rect r = ai.mTmpInvalRect;
4897                r.set(0, 0, mRight - mLeft, mBottom - mTop);
4898                // Don't call invalidate -- we don't want to internally scroll
4899                // our own bounds
4900                p.invalidateChild(this, r);
4901            }
4902        }
4903    }
4904
4905    /**
4906     * Indicates whether this View is opaque. An opaque View guarantees that it will
4907     * draw all the pixels overlapping its bounds using a fully opaque color.
4908     *
4909     * Subclasses of View should override this method whenever possible to indicate
4910     * whether an instance is opaque. Opaque Views are treated in a special way by
4911     * the View hierarchy, possibly allowing it to perform optimizations during
4912     * invalidate/draw passes.
4913     *
4914     * @return True if this View is guaranteed to be fully opaque, false otherwise.
4915     *
4916     * @hide Pending API council approval
4917     */
4918    @ViewDebug.ExportedProperty
4919    public boolean isOpaque() {
4920        return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK;
4921    }
4922
4923    private void computeOpaqueFlags() {
4924        // Opaque if:
4925        //   - Has a background
4926        //   - Background is opaque
4927        //   - Doesn't have scrollbars or scrollbars are inside overlay
4928
4929        if (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE) {
4930            mPrivateFlags |= OPAQUE_BACKGROUND;
4931        } else {
4932            mPrivateFlags &= ~OPAQUE_BACKGROUND;
4933        }
4934
4935        final int flags = mViewFlags;
4936        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
4937                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) {
4938            mPrivateFlags |= OPAQUE_SCROLLBARS;
4939        } else {
4940            mPrivateFlags &= ~OPAQUE_SCROLLBARS;
4941        }
4942    }
4943
4944    /**
4945     * @hide
4946     */
4947    protected boolean hasOpaqueScrollbars() {
4948        return (mPrivateFlags & OPAQUE_SCROLLBARS) == OPAQUE_SCROLLBARS;
4949    }
4950
4951    /**
4952     * @return A handler associated with the thread running the View. This
4953     * handler can be used to pump events in the UI events queue.
4954     */
4955    public Handler getHandler() {
4956        if (mAttachInfo != null) {
4957            return mAttachInfo.mHandler;
4958        }
4959        return null;
4960    }
4961
4962    /**
4963     * Causes the Runnable to be added to the message queue.
4964     * The runnable will be run on the user interface thread.
4965     *
4966     * @param action The Runnable that will be executed.
4967     *
4968     * @return Returns true if the Runnable was successfully placed in to the
4969     *         message queue.  Returns false on failure, usually because the
4970     *         looper processing the message queue is exiting.
4971     */
4972    public boolean post(Runnable action) {
4973        Handler handler;
4974        if (mAttachInfo != null) {
4975            handler = mAttachInfo.mHandler;
4976        } else {
4977            // Assume that post will succeed later
4978            ViewRoot.getRunQueue().post(action);
4979            return true;
4980        }
4981
4982        return handler.post(action);
4983    }
4984
4985    /**
4986     * Causes the Runnable to be added to the message queue, to be run
4987     * after the specified amount of time elapses.
4988     * The runnable will be run on the user interface thread.
4989     *
4990     * @param action The Runnable that will be executed.
4991     * @param delayMillis The delay (in milliseconds) until the Runnable
4992     *        will be executed.
4993     *
4994     * @return true if the Runnable was successfully placed in to the
4995     *         message queue.  Returns false on failure, usually because the
4996     *         looper processing the message queue is exiting.  Note that a
4997     *         result of true does not mean the Runnable will be processed --
4998     *         if the looper is quit before the delivery time of the message
4999     *         occurs then the message will be dropped.
5000     */
5001    public boolean postDelayed(Runnable action, long delayMillis) {
5002        Handler handler;
5003        if (mAttachInfo != null) {
5004            handler = mAttachInfo.mHandler;
5005        } else {
5006            // Assume that post will succeed later
5007            ViewRoot.getRunQueue().postDelayed(action, delayMillis);
5008            return true;
5009        }
5010
5011        return handler.postDelayed(action, delayMillis);
5012    }
5013
5014    /**
5015     * Removes the specified Runnable from the message queue.
5016     *
5017     * @param action The Runnable to remove from the message handling queue
5018     *
5019     * @return true if this view could ask the Handler to remove the Runnable,
5020     *         false otherwise. When the returned value is true, the Runnable
5021     *         may or may not have been actually removed from the message queue
5022     *         (for instance, if the Runnable was not in the queue already.)
5023     */
5024    public boolean removeCallbacks(Runnable action) {
5025        Handler handler;
5026        if (mAttachInfo != null) {
5027            handler = mAttachInfo.mHandler;
5028        } else {
5029            // Assume that post will succeed later
5030            ViewRoot.getRunQueue().removeCallbacks(action);
5031            return true;
5032        }
5033
5034        handler.removeCallbacks(action);
5035        return true;
5036    }
5037
5038    /**
5039     * Cause an invalidate to happen on a subsequent cycle through the event loop.
5040     * Use this to invalidate the View from a non-UI thread.
5041     *
5042     * @see #invalidate()
5043     */
5044    public void postInvalidate() {
5045        postInvalidateDelayed(0);
5046    }
5047
5048    /**
5049     * Cause an invalidate of the specified area to happen on a subsequent cycle
5050     * through the event loop. Use this to invalidate the View from a non-UI thread.
5051     *
5052     * @param left The left coordinate of the rectangle to invalidate.
5053     * @param top The top coordinate of the rectangle to invalidate.
5054     * @param right The right coordinate of the rectangle to invalidate.
5055     * @param bottom The bottom coordinate of the rectangle to invalidate.
5056     *
5057     * @see #invalidate(int, int, int, int)
5058     * @see #invalidate(Rect)
5059     */
5060    public void postInvalidate(int left, int top, int right, int bottom) {
5061        postInvalidateDelayed(0, left, top, right, bottom);
5062    }
5063
5064    /**
5065     * Cause an invalidate to happen on a subsequent cycle through the event
5066     * loop. Waits for the specified amount of time.
5067     *
5068     * @param delayMilliseconds the duration in milliseconds to delay the
5069     *         invalidation by
5070     */
5071    public void postInvalidateDelayed(long delayMilliseconds) {
5072        // We try only with the AttachInfo because there's no point in invalidating
5073        // if we are not attached to our window
5074        if (mAttachInfo != null) {
5075            Message msg = Message.obtain();
5076            msg.what = AttachInfo.INVALIDATE_MSG;
5077            msg.obj = this;
5078            mAttachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
5079        }
5080    }
5081
5082    /**
5083     * Cause an invalidate of the specified area to happen on a subsequent cycle
5084     * through the event loop. Waits for the specified amount of time.
5085     *
5086     * @param delayMilliseconds the duration in milliseconds to delay the
5087     *         invalidation by
5088     * @param left The left coordinate of the rectangle to invalidate.
5089     * @param top The top coordinate of the rectangle to invalidate.
5090     * @param right The right coordinate of the rectangle to invalidate.
5091     * @param bottom The bottom coordinate of the rectangle to invalidate.
5092     */
5093    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
5094            int right, int bottom) {
5095
5096        // We try only with the AttachInfo because there's no point in invalidating
5097        // if we are not attached to our window
5098        if (mAttachInfo != null) {
5099            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
5100            info.target = this;
5101            info.left = left;
5102            info.top = top;
5103            info.right = right;
5104            info.bottom = bottom;
5105
5106            final Message msg = Message.obtain();
5107            msg.what = AttachInfo.INVALIDATE_RECT_MSG;
5108            msg.obj = info;
5109            mAttachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
5110        }
5111    }
5112
5113    /**
5114     * Called by a parent to request that a child update its values for mScrollX
5115     * and mScrollY if necessary. This will typically be done if the child is
5116     * animating a scroll using a {@link android.widget.Scroller Scroller}
5117     * object.
5118     */
5119    public void computeScroll() {
5120    }
5121
5122    /**
5123     * <p>Indicate whether the horizontal edges are faded when the view is
5124     * scrolled horizontally.</p>
5125     *
5126     * @return true if the horizontal edges should are faded on scroll, false
5127     *         otherwise
5128     *
5129     * @see #setHorizontalFadingEdgeEnabled(boolean)
5130     * @attr ref android.R.styleable#View_fadingEdge
5131     */
5132    public boolean isHorizontalFadingEdgeEnabled() {
5133        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
5134    }
5135
5136    /**
5137     * <p>Define whether the horizontal edges should be faded when this view
5138     * is scrolled horizontally.</p>
5139     *
5140     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
5141     *                                    be faded when the view is scrolled
5142     *                                    horizontally
5143     *
5144     * @see #isHorizontalFadingEdgeEnabled()
5145     * @attr ref android.R.styleable#View_fadingEdge
5146     */
5147    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
5148        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
5149            if (horizontalFadingEdgeEnabled) {
5150                initScrollCache();
5151            }
5152
5153            mViewFlags ^= FADING_EDGE_HORIZONTAL;
5154        }
5155    }
5156
5157    /**
5158     * <p>Indicate whether the vertical edges are faded when the view is
5159     * scrolled horizontally.</p>
5160     *
5161     * @return true if the vertical edges should are faded on scroll, false
5162     *         otherwise
5163     *
5164     * @see #setVerticalFadingEdgeEnabled(boolean)
5165     * @attr ref android.R.styleable#View_fadingEdge
5166     */
5167    public boolean isVerticalFadingEdgeEnabled() {
5168        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
5169    }
5170
5171    /**
5172     * <p>Define whether the vertical edges should be faded when this view
5173     * is scrolled vertically.</p>
5174     *
5175     * @param verticalFadingEdgeEnabled true if the vertical edges should
5176     *                                  be faded when the view is scrolled
5177     *                                  vertically
5178     *
5179     * @see #isVerticalFadingEdgeEnabled()
5180     * @attr ref android.R.styleable#View_fadingEdge
5181     */
5182    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
5183        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
5184            if (verticalFadingEdgeEnabled) {
5185                initScrollCache();
5186            }
5187
5188            mViewFlags ^= FADING_EDGE_VERTICAL;
5189        }
5190    }
5191
5192    /**
5193     * Returns the strength, or intensity, of the top faded edge. The strength is
5194     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
5195     * returns 0.0 or 1.0 but no value in between.
5196     *
5197     * Subclasses should override this method to provide a smoother fade transition
5198     * when scrolling occurs.
5199     *
5200     * @return the intensity of the top fade as a float between 0.0f and 1.0f
5201     */
5202    protected float getTopFadingEdgeStrength() {
5203        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
5204    }
5205
5206    /**
5207     * Returns the strength, or intensity, of the bottom faded edge. The strength is
5208     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
5209     * returns 0.0 or 1.0 but no value in between.
5210     *
5211     * Subclasses should override this method to provide a smoother fade transition
5212     * when scrolling occurs.
5213     *
5214     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
5215     */
5216    protected float getBottomFadingEdgeStrength() {
5217        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
5218                computeVerticalScrollRange() ? 1.0f : 0.0f;
5219    }
5220
5221    /**
5222     * Returns the strength, or intensity, of the left faded edge. The strength is
5223     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
5224     * returns 0.0 or 1.0 but no value in between.
5225     *
5226     * Subclasses should override this method to provide a smoother fade transition
5227     * when scrolling occurs.
5228     *
5229     * @return the intensity of the left fade as a float between 0.0f and 1.0f
5230     */
5231    protected float getLeftFadingEdgeStrength() {
5232        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
5233    }
5234
5235    /**
5236     * Returns the strength, or intensity, of the right faded edge. The strength is
5237     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
5238     * returns 0.0 or 1.0 but no value in between.
5239     *
5240     * Subclasses should override this method to provide a smoother fade transition
5241     * when scrolling occurs.
5242     *
5243     * @return the intensity of the right fade as a float between 0.0f and 1.0f
5244     */
5245    protected float getRightFadingEdgeStrength() {
5246        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
5247                computeHorizontalScrollRange() ? 1.0f : 0.0f;
5248    }
5249
5250    /**
5251     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
5252     * scrollbar is not drawn by default.</p>
5253     *
5254     * @return true if the horizontal scrollbar should be painted, false
5255     *         otherwise
5256     *
5257     * @see #setHorizontalScrollBarEnabled(boolean)
5258     */
5259    public boolean isHorizontalScrollBarEnabled() {
5260        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
5261    }
5262
5263    /**
5264     * <p>Define whether the horizontal scrollbar should be drawn or not. The
5265     * scrollbar is not drawn by default.</p>
5266     *
5267     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
5268     *                                   be painted
5269     *
5270     * @see #isHorizontalScrollBarEnabled()
5271     */
5272    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
5273        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
5274            mViewFlags ^= SCROLLBARS_HORIZONTAL;
5275            computeOpaqueFlags();
5276            recomputePadding();
5277        }
5278    }
5279
5280    /**
5281     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
5282     * scrollbar is not drawn by default.</p>
5283     *
5284     * @return true if the vertical scrollbar should be painted, false
5285     *         otherwise
5286     *
5287     * @see #setVerticalScrollBarEnabled(boolean)
5288     */
5289    public boolean isVerticalScrollBarEnabled() {
5290        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
5291    }
5292
5293    /**
5294     * <p>Define whether the vertical scrollbar should be drawn or not. The
5295     * scrollbar is not drawn by default.</p>
5296     *
5297     * @param verticalScrollBarEnabled true if the vertical scrollbar should
5298     *                                 be painted
5299     *
5300     * @see #isVerticalScrollBarEnabled()
5301     */
5302    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
5303        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
5304            mViewFlags ^= SCROLLBARS_VERTICAL;
5305            computeOpaqueFlags();
5306            recomputePadding();
5307        }
5308    }
5309
5310    private void recomputePadding() {
5311        setPadding(mPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
5312    }
5313
5314    /**
5315     * Define whether scrollbars will fade when the view is not scrolling.
5316     *
5317     * @param fadeScrollbars wheter to enable fading
5318     *
5319     */
5320    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
5321        initScrollCache();
5322        final ScrollabilityCache scrollabilityCache = mScrollCache;
5323        scrollabilityCache.fadeScrollBars = fadeScrollbars;
5324        if (fadeScrollbars) {
5325            scrollabilityCache.state = ScrollabilityCache.OFF;
5326        } else {
5327            scrollabilityCache.state = ScrollabilityCache.ON;
5328        }
5329    }
5330
5331    /**
5332     *
5333     * Returns true if scrollbars will fade when this view is not scrolling
5334     *
5335     * @return true if scrollbar fading is enabled
5336     */
5337    public boolean isScrollbarFadingEnabled() {
5338        return mScrollCache != null && mScrollCache.fadeScrollBars;
5339    }
5340
5341    /**
5342     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
5343     * inset. When inset, they add to the padding of the view. And the scrollbars
5344     * can be drawn inside the padding area or on the edge of the view. For example,
5345     * if a view has a background drawable and you want to draw the scrollbars
5346     * inside the padding specified by the drawable, you can use
5347     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
5348     * appear at the edge of the view, ignoring the padding, then you can use
5349     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
5350     * @param style the style of the scrollbars. Should be one of
5351     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
5352     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
5353     * @see #SCROLLBARS_INSIDE_OVERLAY
5354     * @see #SCROLLBARS_INSIDE_INSET
5355     * @see #SCROLLBARS_OUTSIDE_OVERLAY
5356     * @see #SCROLLBARS_OUTSIDE_INSET
5357     */
5358    public void setScrollBarStyle(int style) {
5359        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
5360            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
5361            computeOpaqueFlags();
5362            recomputePadding();
5363        }
5364    }
5365
5366    /**
5367     * <p>Returns the current scrollbar style.</p>
5368     * @return the current scrollbar style
5369     * @see #SCROLLBARS_INSIDE_OVERLAY
5370     * @see #SCROLLBARS_INSIDE_INSET
5371     * @see #SCROLLBARS_OUTSIDE_OVERLAY
5372     * @see #SCROLLBARS_OUTSIDE_INSET
5373     */
5374    public int getScrollBarStyle() {
5375        return mViewFlags & SCROLLBARS_STYLE_MASK;
5376    }
5377
5378    /**
5379     * <p>Compute the horizontal range that the horizontal scrollbar
5380     * represents.</p>
5381     *
5382     * <p>The range is expressed in arbitrary units that must be the same as the
5383     * units used by {@link #computeHorizontalScrollExtent()} and
5384     * {@link #computeHorizontalScrollOffset()}.</p>
5385     *
5386     * <p>The default range is the drawing width of this view.</p>
5387     *
5388     * @return the total horizontal range represented by the horizontal
5389     *         scrollbar
5390     *
5391     * @see #computeHorizontalScrollExtent()
5392     * @see #computeHorizontalScrollOffset()
5393     * @see android.widget.ScrollBarDrawable
5394     */
5395    protected int computeHorizontalScrollRange() {
5396        return getWidth();
5397    }
5398
5399    /**
5400     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
5401     * within the horizontal range. This value is used to compute the position
5402     * of the thumb within the scrollbar's track.</p>
5403     *
5404     * <p>The range is expressed in arbitrary units that must be the same as the
5405     * units used by {@link #computeHorizontalScrollRange()} and
5406     * {@link #computeHorizontalScrollExtent()}.</p>
5407     *
5408     * <p>The default offset is the scroll offset of this view.</p>
5409     *
5410     * @return the horizontal offset of the scrollbar's thumb
5411     *
5412     * @see #computeHorizontalScrollRange()
5413     * @see #computeHorizontalScrollExtent()
5414     * @see android.widget.ScrollBarDrawable
5415     */
5416    protected int computeHorizontalScrollOffset() {
5417        return mScrollX;
5418    }
5419
5420    /**
5421     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
5422     * within the horizontal range. This value is used to compute the length
5423     * of the thumb within the scrollbar's track.</p>
5424     *
5425     * <p>The range is expressed in arbitrary units that must be the same as the
5426     * units used by {@link #computeHorizontalScrollRange()} and
5427     * {@link #computeHorizontalScrollOffset()}.</p>
5428     *
5429     * <p>The default extent is the drawing width of this view.</p>
5430     *
5431     * @return the horizontal extent of the scrollbar's thumb
5432     *
5433     * @see #computeHorizontalScrollRange()
5434     * @see #computeHorizontalScrollOffset()
5435     * @see android.widget.ScrollBarDrawable
5436     */
5437    protected int computeHorizontalScrollExtent() {
5438        return getWidth();
5439    }
5440
5441    /**
5442     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
5443     *
5444     * <p>The range is expressed in arbitrary units that must be the same as the
5445     * units used by {@link #computeVerticalScrollExtent()} and
5446     * {@link #computeVerticalScrollOffset()}.</p>
5447     *
5448     * @return the total vertical range represented by the vertical scrollbar
5449     *
5450     * <p>The default range is the drawing height of this view.</p>
5451     *
5452     * @see #computeVerticalScrollExtent()
5453     * @see #computeVerticalScrollOffset()
5454     * @see android.widget.ScrollBarDrawable
5455     */
5456    protected int computeVerticalScrollRange() {
5457        return getHeight();
5458    }
5459
5460    /**
5461     * <p>Compute the vertical offset of the vertical scrollbar's thumb
5462     * within the horizontal range. This value is used to compute the position
5463     * of the thumb within the scrollbar's track.</p>
5464     *
5465     * <p>The range is expressed in arbitrary units that must be the same as the
5466     * units used by {@link #computeVerticalScrollRange()} and
5467     * {@link #computeVerticalScrollExtent()}.</p>
5468     *
5469     * <p>The default offset is the scroll offset of this view.</p>
5470     *
5471     * @return the vertical offset of the scrollbar's thumb
5472     *
5473     * @see #computeVerticalScrollRange()
5474     * @see #computeVerticalScrollExtent()
5475     * @see android.widget.ScrollBarDrawable
5476     */
5477    protected int computeVerticalScrollOffset() {
5478        return mScrollY;
5479    }
5480
5481    /**
5482     * <p>Compute the vertical extent of the horizontal scrollbar's thumb
5483     * within the vertical range. This value is used to compute the length
5484     * of the thumb within the scrollbar's track.</p>
5485     *
5486     * <p>The range is expressed in arbitrary units that must be the same as the
5487     * units used by {@link #computeHorizontalScrollRange()} and
5488     * {@link #computeVerticalScrollOffset()}.</p>
5489     *
5490     * <p>The default extent is the drawing height of this view.</p>
5491     *
5492     * @return the vertical extent of the scrollbar's thumb
5493     *
5494     * @see #computeVerticalScrollRange()
5495     * @see #computeVerticalScrollOffset()
5496     * @see android.widget.ScrollBarDrawable
5497     */
5498    protected int computeVerticalScrollExtent() {
5499        return getHeight();
5500    }
5501
5502    /**
5503     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
5504     * scrollbars are painted only if they have been awakened first.</p>
5505     *
5506     * @param canvas the canvas on which to draw the scrollbars
5507     *
5508     * @see #awakenScrollBars(int)
5509     */
5510    private void onDrawScrollBars(Canvas canvas) {
5511        // scrollbars are drawn only when the animation is running
5512        final ScrollabilityCache cache = mScrollCache;
5513        if (cache != null) {
5514
5515            int state = cache.state;
5516
5517            if (state == ScrollabilityCache.OFF) {
5518                return;
5519            }
5520
5521            boolean invalidate = false;
5522
5523            if (state == ScrollabilityCache.FADING) {
5524                // We're fading -- get our fade interpolation
5525                if (cache.interpolatorValues == null) {
5526                    cache.interpolatorValues = new float[1];
5527                }
5528
5529                float[] values = cache.interpolatorValues;
5530
5531                // Stops the animation if we're done
5532                if (cache.scrollBarInterpolator.timeToValues(values) ==
5533                        Interpolator.Result.FREEZE_END) {
5534                    cache.state = ScrollabilityCache.OFF;
5535                } else {
5536                    cache.scrollBar.setAlpha(Math.round(values[0]));
5537                }
5538
5539                // This will make the scroll bars inval themselves after
5540                // drawing. We only want this when we're fading so that
5541                // we prevent excessive redraws
5542                invalidate = true;
5543            } else {
5544                // We're just on -- but we may have been fading before so
5545                // reset alpha
5546                cache.scrollBar.setAlpha(255);
5547            }
5548
5549
5550            final int viewFlags = mViewFlags;
5551
5552            final boolean drawHorizontalScrollBar =
5553                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
5554            final boolean drawVerticalScrollBar =
5555                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
5556                && !isVerticalScrollBarHidden();
5557
5558            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
5559                final int width = mRight - mLeft;
5560                final int height = mBottom - mTop;
5561
5562                final ScrollBarDrawable scrollBar = cache.scrollBar;
5563                int size = scrollBar.getSize(false);
5564                if (size <= 0) {
5565                    size = cache.scrollBarSize;
5566                }
5567
5568                final int scrollX = mScrollX;
5569                final int scrollY = mScrollY;
5570                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
5571
5572                int left, top, right, bottom;
5573
5574                if (drawHorizontalScrollBar) {
5575                    scrollBar.setParameters(computeHorizontalScrollRange(),
5576                                            computeHorizontalScrollOffset(),
5577                                            computeHorizontalScrollExtent(), false);
5578                    final int verticalScrollBarGap = drawVerticalScrollBar ?
5579                            getVerticalScrollbarWidth() : 0;
5580                    top = scrollY + height - size - (mUserPaddingBottom & inside);
5581                    left = scrollX + (mPaddingLeft & inside);
5582                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
5583                    bottom = top + size;
5584                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
5585                    if (invalidate) {
5586                        invalidate(left, top, right, bottom);
5587                    }
5588                }
5589
5590                if (drawVerticalScrollBar) {
5591                    scrollBar.setParameters(computeVerticalScrollRange(),
5592                                            computeVerticalScrollOffset(),
5593                                            computeVerticalScrollExtent(), true);
5594                    // TODO: Deal with RTL languages to position scrollbar on left
5595                    left = scrollX + width - size - (mUserPaddingRight & inside);
5596                    top = scrollY + (mPaddingTop & inside);
5597                    right = left + size;
5598                    bottom = scrollY + height - (mUserPaddingBottom & inside);
5599                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
5600                    if (invalidate) {
5601                        invalidate(left, top, right, bottom);
5602                    }
5603                }
5604            }
5605        }
5606    }
5607
5608    /**
5609     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
5610     * FastScroller is visible.
5611     * @return whether to temporarily hide the vertical scrollbar
5612     * @hide
5613     */
5614    protected boolean isVerticalScrollBarHidden() {
5615        return false;
5616    }
5617
5618    /**
5619     * <p>Draw the horizontal scrollbar if
5620     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
5621     *
5622     * @param canvas the canvas on which to draw the scrollbar
5623     * @param scrollBar the scrollbar's drawable
5624     *
5625     * @see #isHorizontalScrollBarEnabled()
5626     * @see #computeHorizontalScrollRange()
5627     * @see #computeHorizontalScrollExtent()
5628     * @see #computeHorizontalScrollOffset()
5629     * @see android.widget.ScrollBarDrawable
5630     * @hide
5631     */
5632    protected void onDrawHorizontalScrollBar(Canvas canvas,
5633                                             Drawable scrollBar,
5634                                             int l, int t, int r, int b) {
5635        scrollBar.setBounds(l, t, r, b);
5636        scrollBar.draw(canvas);
5637    }
5638
5639    /**
5640     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
5641     * returns true.</p>
5642     *
5643     * @param canvas the canvas on which to draw the scrollbar
5644     * @param scrollBar the scrollbar's drawable
5645     *
5646     * @see #isVerticalScrollBarEnabled()
5647     * @see #computeVerticalScrollRange()
5648     * @see #computeVerticalScrollExtent()
5649     * @see #computeVerticalScrollOffset()
5650     * @see android.widget.ScrollBarDrawable
5651     * @hide
5652     */
5653    protected void onDrawVerticalScrollBar(Canvas canvas,
5654                                           Drawable scrollBar,
5655                                           int l, int t, int r, int b) {
5656        scrollBar.setBounds(l, t, r, b);
5657        scrollBar.draw(canvas);
5658    }
5659
5660    /**
5661     * Implement this to do your drawing.
5662     *
5663     * @param canvas the canvas on which the background will be drawn
5664     */
5665    protected void onDraw(Canvas canvas) {
5666    }
5667
5668    /*
5669     * Caller is responsible for calling requestLayout if necessary.
5670     * (This allows addViewInLayout to not request a new layout.)
5671     */
5672    void assignParent(ViewParent parent) {
5673        if (mParent == null) {
5674            mParent = parent;
5675        } else if (parent == null) {
5676            mParent = null;
5677        } else {
5678            throw new RuntimeException("view " + this + " being added, but"
5679                    + " it already has a parent");
5680        }
5681    }
5682
5683    /**
5684     * This is called when the view is attached to a window.  At this point it
5685     * has a Surface and will start drawing.  Note that this function is
5686     * guaranteed to be called before {@link #onDraw}, however it may be called
5687     * any time before the first onDraw -- including before or after
5688     * {@link #onMeasure}.
5689     *
5690     * @see #onDetachedFromWindow()
5691     */
5692    protected void onAttachedToWindow() {
5693        if ((mPrivateFlags & REQUEST_TRANSPARENT_REGIONS) != 0) {
5694            mParent.requestTransparentRegion(this);
5695        }
5696    }
5697
5698    /**
5699     * This is called when the view is detached from a window.  At this point it
5700     * no longer has a surface for drawing.
5701     *
5702     * @see #onAttachedToWindow()
5703     */
5704    protected void onDetachedFromWindow() {
5705        if (mPendingCheckForLongPress != null) {
5706            removeCallbacks(mPendingCheckForLongPress);
5707        }
5708        destroyDrawingCache();
5709    }
5710
5711    /**
5712     * @return The number of times this view has been attached to a window
5713     */
5714    protected int getWindowAttachCount() {
5715        return mWindowAttachCount;
5716    }
5717
5718    /**
5719     * Retrieve a unique token identifying the window this view is attached to.
5720     * @return Return the window's token for use in
5721     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
5722     */
5723    public IBinder getWindowToken() {
5724        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
5725    }
5726
5727    /**
5728     * Retrieve a unique token identifying the top-level "real" window of
5729     * the window that this view is attached to.  That is, this is like
5730     * {@link #getWindowToken}, except if the window this view in is a panel
5731     * window (attached to another containing window), then the token of
5732     * the containing window is returned instead.
5733     *
5734     * @return Returns the associated window token, either
5735     * {@link #getWindowToken()} or the containing window's token.
5736     */
5737    public IBinder getApplicationWindowToken() {
5738        AttachInfo ai = mAttachInfo;
5739        if (ai != null) {
5740            IBinder appWindowToken = ai.mPanelParentWindowToken;
5741            if (appWindowToken == null) {
5742                appWindowToken = ai.mWindowToken;
5743            }
5744            return appWindowToken;
5745        }
5746        return null;
5747    }
5748
5749    /**
5750     * Retrieve private session object this view hierarchy is using to
5751     * communicate with the window manager.
5752     * @return the session object to communicate with the window manager
5753     */
5754    /*package*/ IWindowSession getWindowSession() {
5755        return mAttachInfo != null ? mAttachInfo.mSession : null;
5756    }
5757
5758    /**
5759     * @param info the {@link android.view.View.AttachInfo} to associated with
5760     *        this view
5761     */
5762    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
5763        //System.out.println("Attached! " + this);
5764        mAttachInfo = info;
5765        mWindowAttachCount++;
5766        if (mFloatingTreeObserver != null) {
5767            info.mTreeObserver.merge(mFloatingTreeObserver);
5768            mFloatingTreeObserver = null;
5769        }
5770        if ((mPrivateFlags&SCROLL_CONTAINER) != 0) {
5771            mAttachInfo.mScrollContainers.add(this);
5772            mPrivateFlags |= SCROLL_CONTAINER_ADDED;
5773        }
5774        performCollectViewAttributes(visibility);
5775        onAttachedToWindow();
5776        int vis = info.mWindowVisibility;
5777        if (vis != GONE) {
5778            onWindowVisibilityChanged(vis);
5779        }
5780    }
5781
5782    void dispatchDetachedFromWindow() {
5783        //System.out.println("Detached! " + this);
5784        AttachInfo info = mAttachInfo;
5785        if (info != null) {
5786            int vis = info.mWindowVisibility;
5787            if (vis != GONE) {
5788                onWindowVisibilityChanged(GONE);
5789            }
5790        }
5791
5792        onDetachedFromWindow();
5793        if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) {
5794            mAttachInfo.mScrollContainers.remove(this);
5795            mPrivateFlags &= ~SCROLL_CONTAINER_ADDED;
5796        }
5797        mAttachInfo = null;
5798    }
5799
5800    /**
5801     * Store this view hierarchy's frozen state into the given container.
5802     *
5803     * @param container The SparseArray in which to save the view's state.
5804     *
5805     * @see #restoreHierarchyState
5806     * @see #dispatchSaveInstanceState
5807     * @see #onSaveInstanceState
5808     */
5809    public void saveHierarchyState(SparseArray<Parcelable> container) {
5810        dispatchSaveInstanceState(container);
5811    }
5812
5813    /**
5814     * Called by {@link #saveHierarchyState} to store the state for this view and its children.
5815     * May be overridden to modify how freezing happens to a view's children; for example, some
5816     * views may want to not store state for their children.
5817     *
5818     * @param container The SparseArray in which to save the view's state.
5819     *
5820     * @see #dispatchRestoreInstanceState
5821     * @see #saveHierarchyState
5822     * @see #onSaveInstanceState
5823     */
5824    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
5825        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
5826            mPrivateFlags &= ~SAVE_STATE_CALLED;
5827            Parcelable state = onSaveInstanceState();
5828            if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
5829                throw new IllegalStateException(
5830                        "Derived class did not call super.onSaveInstanceState()");
5831            }
5832            if (state != null) {
5833                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
5834                // + ": " + state);
5835                container.put(mID, state);
5836            }
5837        }
5838    }
5839
5840    /**
5841     * Hook allowing a view to generate a representation of its internal state
5842     * that can later be used to create a new instance with that same state.
5843     * This state should only contain information that is not persistent or can
5844     * not be reconstructed later. For example, you will never store your
5845     * current position on screen because that will be computed again when a
5846     * new instance of the view is placed in its view hierarchy.
5847     * <p>
5848     * Some examples of things you may store here: the current cursor position
5849     * in a text view (but usually not the text itself since that is stored in a
5850     * content provider or other persistent storage), the currently selected
5851     * item in a list view.
5852     *
5853     * @return Returns a Parcelable object containing the view's current dynamic
5854     *         state, or null if there is nothing interesting to save. The
5855     *         default implementation returns null.
5856     * @see #onRestoreInstanceState
5857     * @see #saveHierarchyState
5858     * @see #dispatchSaveInstanceState
5859     * @see #setSaveEnabled(boolean)
5860     */
5861    protected Parcelable onSaveInstanceState() {
5862        mPrivateFlags |= SAVE_STATE_CALLED;
5863        return BaseSavedState.EMPTY_STATE;
5864    }
5865
5866    /**
5867     * Restore this view hierarchy's frozen state from the given container.
5868     *
5869     * @param container The SparseArray which holds previously frozen states.
5870     *
5871     * @see #saveHierarchyState
5872     * @see #dispatchRestoreInstanceState
5873     * @see #onRestoreInstanceState
5874     */
5875    public void restoreHierarchyState(SparseArray<Parcelable> container) {
5876        dispatchRestoreInstanceState(container);
5877    }
5878
5879    /**
5880     * Called by {@link #restoreHierarchyState} to retrieve the state for this view and its
5881     * children. May be overridden to modify how restoreing happens to a view's children; for
5882     * example, some views may want to not store state for their children.
5883     *
5884     * @param container The SparseArray which holds previously saved state.
5885     *
5886     * @see #dispatchSaveInstanceState
5887     * @see #restoreHierarchyState
5888     * @see #onRestoreInstanceState
5889     */
5890    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
5891        if (mID != NO_ID) {
5892            Parcelable state = container.get(mID);
5893            if (state != null) {
5894                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
5895                // + ": " + state);
5896                mPrivateFlags &= ~SAVE_STATE_CALLED;
5897                onRestoreInstanceState(state);
5898                if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
5899                    throw new IllegalStateException(
5900                            "Derived class did not call super.onRestoreInstanceState()");
5901                }
5902            }
5903        }
5904    }
5905
5906    /**
5907     * Hook allowing a view to re-apply a representation of its internal state that had previously
5908     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
5909     * null state.
5910     *
5911     * @param state The frozen state that had previously been returned by
5912     *        {@link #onSaveInstanceState}.
5913     *
5914     * @see #onSaveInstanceState
5915     * @see #restoreHierarchyState
5916     * @see #dispatchRestoreInstanceState
5917     */
5918    protected void onRestoreInstanceState(Parcelable state) {
5919        mPrivateFlags |= SAVE_STATE_CALLED;
5920        if (state != BaseSavedState.EMPTY_STATE && state != null) {
5921            throw new IllegalArgumentException("Wrong state class -- expecting View State");
5922        }
5923    }
5924
5925    /**
5926     * <p>Return the time at which the drawing of the view hierarchy started.</p>
5927     *
5928     * @return the drawing start time in milliseconds
5929     */
5930    public long getDrawingTime() {
5931        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
5932    }
5933
5934    /**
5935     * <p>Enables or disables the duplication of the parent's state into this view. When
5936     * duplication is enabled, this view gets its drawable state from its parent rather
5937     * than from its own internal properties.</p>
5938     *
5939     * <p>Note: in the current implementation, setting this property to true after the
5940     * view was added to a ViewGroup might have no effect at all. This property should
5941     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
5942     *
5943     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
5944     * property is enabled, an exception will be thrown.</p>
5945     *
5946     * @param enabled True to enable duplication of the parent's drawable state, false
5947     *                to disable it.
5948     *
5949     * @see #getDrawableState()
5950     * @see #isDuplicateParentStateEnabled()
5951     */
5952    public void setDuplicateParentStateEnabled(boolean enabled) {
5953        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
5954    }
5955
5956    /**
5957     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
5958     *
5959     * @return True if this view's drawable state is duplicated from the parent,
5960     *         false otherwise
5961     *
5962     * @see #getDrawableState()
5963     * @see #setDuplicateParentStateEnabled(boolean)
5964     */
5965    public boolean isDuplicateParentStateEnabled() {
5966        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
5967    }
5968
5969    /**
5970     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
5971     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
5972     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
5973     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
5974     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
5975     * null.</p>
5976     *
5977     * @param enabled true to enable the drawing cache, false otherwise
5978     *
5979     * @see #isDrawingCacheEnabled()
5980     * @see #getDrawingCache()
5981     * @see #buildDrawingCache()
5982     */
5983    public void setDrawingCacheEnabled(boolean enabled) {
5984        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
5985    }
5986
5987    /**
5988     * <p>Indicates whether the drawing cache is enabled for this view.</p>
5989     *
5990     * @return true if the drawing cache is enabled
5991     *
5992     * @see #setDrawingCacheEnabled(boolean)
5993     * @see #getDrawingCache()
5994     */
5995    @ViewDebug.ExportedProperty
5996    public boolean isDrawingCacheEnabled() {
5997        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
5998    }
5999
6000    /**
6001     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
6002     *
6003     * @return A non-scaled bitmap representing this view or null if cache is disabled.
6004     *
6005     * @see #getDrawingCache(boolean)
6006     */
6007    public Bitmap getDrawingCache() {
6008        return getDrawingCache(false);
6009    }
6010
6011    /**
6012     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
6013     * is null when caching is disabled. If caching is enabled and the cache is not ready,
6014     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
6015     * draw from the cache when the cache is enabled. To benefit from the cache, you must
6016     * request the drawing cache by calling this method and draw it on screen if the
6017     * returned bitmap is not null.</p>
6018     *
6019     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
6020     * this method will create a bitmap of the same size as this view. Because this bitmap
6021     * will be drawn scaled by the parent ViewGroup, the result on screen might show
6022     * scaling artifacts. To avoid such artifacts, you should call this method by setting
6023     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
6024     * size than the view. This implies that your application must be able to handle this
6025     * size.</p>
6026     *
6027     * @param autoScale Indicates whether the generated bitmap should be scaled based on
6028     *        the current density of the screen when the application is in compatibility
6029     *        mode.
6030     *
6031     * @return A bitmap representing this view or null if cache is disabled.
6032     *
6033     * @see #setDrawingCacheEnabled(boolean)
6034     * @see #isDrawingCacheEnabled()
6035     * @see #buildDrawingCache(boolean)
6036     * @see #destroyDrawingCache()
6037     */
6038    public Bitmap getDrawingCache(boolean autoScale) {
6039        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
6040            return null;
6041        }
6042        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
6043            buildDrawingCache(autoScale);
6044        }
6045        return autoScale ? (mDrawingCache == null ? null : mDrawingCache.get()) :
6046                (mUnscaledDrawingCache == null ? null : mUnscaledDrawingCache.get());
6047    }
6048
6049    /**
6050     * <p>Frees the resources used by the drawing cache. If you call
6051     * {@link #buildDrawingCache()} manually without calling
6052     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
6053     * should cleanup the cache with this method afterwards.</p>
6054     *
6055     * @see #setDrawingCacheEnabled(boolean)
6056     * @see #buildDrawingCache()
6057     * @see #getDrawingCache()
6058     */
6059    public void destroyDrawingCache() {
6060        if (mDrawingCache != null) {
6061            final Bitmap bitmap = mDrawingCache.get();
6062            if (bitmap != null) bitmap.recycle();
6063            mDrawingCache = null;
6064        }
6065        if (mUnscaledDrawingCache != null) {
6066            final Bitmap bitmap = mUnscaledDrawingCache.get();
6067            if (bitmap != null) bitmap.recycle();
6068            mUnscaledDrawingCache = null;
6069        }
6070    }
6071
6072    /**
6073     * Setting a solid background color for the drawing cache's bitmaps will improve
6074     * perfromance and memory usage. Note, though that this should only be used if this
6075     * view will always be drawn on top of a solid color.
6076     *
6077     * @param color The background color to use for the drawing cache's bitmap
6078     *
6079     * @see #setDrawingCacheEnabled(boolean)
6080     * @see #buildDrawingCache()
6081     * @see #getDrawingCache()
6082     */
6083    public void setDrawingCacheBackgroundColor(int color) {
6084        mDrawingCacheBackgroundColor = color;
6085    }
6086
6087    /**
6088     * @see #setDrawingCacheBackgroundColor(int)
6089     *
6090     * @return The background color to used for the drawing cache's bitmap
6091     */
6092    public int getDrawingCacheBackgroundColor() {
6093        return mDrawingCacheBackgroundColor;
6094    }
6095
6096    /**
6097     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
6098     *
6099     * @see #buildDrawingCache(boolean)
6100     */
6101    public void buildDrawingCache() {
6102        buildDrawingCache(false);
6103    }
6104
6105    /**
6106     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
6107     *
6108     * <p>If you call {@link #buildDrawingCache()} manually without calling
6109     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
6110     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
6111     *
6112     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
6113     * this method will create a bitmap of the same size as this view. Because this bitmap
6114     * will be drawn scaled by the parent ViewGroup, the result on screen might show
6115     * scaling artifacts. To avoid such artifacts, you should call this method by setting
6116     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
6117     * size than the view. This implies that your application must be able to handle this
6118     * size.</p>
6119     *
6120     * @see #getDrawingCache()
6121     * @see #destroyDrawingCache()
6122     */
6123    public void buildDrawingCache(boolean autoScale) {
6124        if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || (autoScale ?
6125                (mDrawingCache == null || mDrawingCache.get() == null) :
6126                (mUnscaledDrawingCache == null || mUnscaledDrawingCache.get() == null))) {
6127
6128            if (ViewDebug.TRACE_HIERARCHY) {
6129                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.BUILD_CACHE);
6130            }
6131            if (Config.DEBUG && ViewDebug.profileDrawing) {
6132                EventLog.writeEvent(60002, hashCode());
6133            }
6134
6135            int width = mRight - mLeft;
6136            int height = mBottom - mTop;
6137
6138            final AttachInfo attachInfo = mAttachInfo;
6139            final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
6140
6141            if (autoScale && scalingRequired) {
6142                width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
6143                height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
6144            }
6145
6146            final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
6147            final boolean opaque = drawingCacheBackgroundColor != 0 ||
6148                (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE);
6149
6150            if (width <= 0 || height <= 0 ||
6151                    (width * height * (opaque ? 2 : 4) > // Projected bitmap size in bytes
6152                            ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) {
6153                destroyDrawingCache();
6154                return;
6155            }
6156
6157            boolean clear = true;
6158            Bitmap bitmap = autoScale ? (mDrawingCache == null ? null : mDrawingCache.get()) :
6159                    (mUnscaledDrawingCache == null ? null : mUnscaledDrawingCache.get());
6160
6161            if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
6162
6163                Bitmap.Config quality;
6164                if (!opaque) {
6165                    switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
6166                        case DRAWING_CACHE_QUALITY_AUTO:
6167                            quality = Bitmap.Config.ARGB_8888;
6168                            break;
6169                        case DRAWING_CACHE_QUALITY_LOW:
6170                            quality = Bitmap.Config.ARGB_4444;
6171                            break;
6172                        case DRAWING_CACHE_QUALITY_HIGH:
6173                            quality = Bitmap.Config.ARGB_8888;
6174                            break;
6175                        default:
6176                            quality = Bitmap.Config.ARGB_8888;
6177                            break;
6178                    }
6179                } else {
6180                    quality = Bitmap.Config.RGB_565;
6181                }
6182
6183                // Try to cleanup memory
6184                if (bitmap != null) bitmap.recycle();
6185
6186                try {
6187                    bitmap = Bitmap.createBitmap(width, height, quality);
6188                    bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
6189                    if (autoScale) {
6190                        mDrawingCache = new SoftReference<Bitmap>(bitmap);
6191                    } else {
6192                        mUnscaledDrawingCache = new SoftReference<Bitmap>(bitmap);
6193                    }
6194                } catch (OutOfMemoryError e) {
6195                    // If there is not enough memory to create the bitmap cache, just
6196                    // ignore the issue as bitmap caches are not required to draw the
6197                    // view hierarchy
6198                    if (autoScale) {
6199                        mDrawingCache = null;
6200                    } else {
6201                        mUnscaledDrawingCache = null;
6202                    }
6203                    return;
6204                }
6205
6206                clear = drawingCacheBackgroundColor != 0;
6207            }
6208
6209            Canvas canvas;
6210            if (attachInfo != null) {
6211                canvas = attachInfo.mCanvas;
6212                if (canvas == null) {
6213                    canvas = new Canvas();
6214                }
6215                canvas.setBitmap(bitmap);
6216                // Temporarily clobber the cached Canvas in case one of our children
6217                // is also using a drawing cache. Without this, the children would
6218                // steal the canvas by attaching their own bitmap to it and bad, bad
6219                // thing would happen (invisible views, corrupted drawings, etc.)
6220                attachInfo.mCanvas = null;
6221            } else {
6222                // This case should hopefully never or seldom happen
6223                canvas = new Canvas(bitmap);
6224            }
6225
6226            if (clear) {
6227                bitmap.eraseColor(drawingCacheBackgroundColor);
6228            }
6229
6230            computeScroll();
6231            final int restoreCount = canvas.save();
6232
6233            if (autoScale && scalingRequired) {
6234                final float scale = attachInfo.mApplicationScale;
6235                canvas.scale(scale, scale);
6236            }
6237
6238            canvas.translate(-mScrollX, -mScrollY);
6239
6240            mPrivateFlags |= DRAWN;
6241
6242            // Fast path for layouts with no backgrounds
6243            if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
6244                if (ViewDebug.TRACE_HIERARCHY) {
6245                    ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
6246                }
6247                mPrivateFlags &= ~DIRTY_MASK;
6248                dispatchDraw(canvas);
6249            } else {
6250                draw(canvas);
6251            }
6252
6253            canvas.restoreToCount(restoreCount);
6254
6255            if (attachInfo != null) {
6256                // Restore the cached Canvas for our siblings
6257                attachInfo.mCanvas = canvas;
6258            }
6259            mPrivateFlags |= DRAWING_CACHE_VALID;
6260        }
6261    }
6262
6263    /**
6264     * Create a snapshot of the view into a bitmap.  We should probably make
6265     * some form of this public, but should think about the API.
6266     */
6267    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor) {
6268        int width = mRight - mLeft;
6269        int height = mBottom - mTop;
6270
6271        final AttachInfo attachInfo = mAttachInfo;
6272        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
6273        width = (int) ((width * scale) + 0.5f);
6274        height = (int) ((height * scale) + 0.5f);
6275
6276        Bitmap bitmap = Bitmap.createBitmap(width > 0 ? width : 1, height > 0 ? height : 1, quality);
6277        if (bitmap == null) {
6278            throw new OutOfMemoryError();
6279        }
6280
6281        bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
6282
6283        Canvas canvas;
6284        if (attachInfo != null) {
6285            canvas = attachInfo.mCanvas;
6286            if (canvas == null) {
6287                canvas = new Canvas();
6288            }
6289            canvas.setBitmap(bitmap);
6290            // Temporarily clobber the cached Canvas in case one of our children
6291            // is also using a drawing cache. Without this, the children would
6292            // steal the canvas by attaching their own bitmap to it and bad, bad
6293            // things would happen (invisible views, corrupted drawings, etc.)
6294            attachInfo.mCanvas = null;
6295        } else {
6296            // This case should hopefully never or seldom happen
6297            canvas = new Canvas(bitmap);
6298        }
6299
6300        if ((backgroundColor & 0xff000000) != 0) {
6301            bitmap.eraseColor(backgroundColor);
6302        }
6303
6304        computeScroll();
6305        final int restoreCount = canvas.save();
6306        canvas.scale(scale, scale);
6307        canvas.translate(-mScrollX, -mScrollY);
6308
6309        // Temporarily remove the dirty mask
6310        int flags = mPrivateFlags;
6311        mPrivateFlags &= ~DIRTY_MASK;
6312
6313        // Fast path for layouts with no backgrounds
6314        if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
6315            dispatchDraw(canvas);
6316        } else {
6317            draw(canvas);
6318        }
6319
6320        mPrivateFlags = flags;
6321
6322        canvas.restoreToCount(restoreCount);
6323
6324        if (attachInfo != null) {
6325            // Restore the cached Canvas for our siblings
6326            attachInfo.mCanvas = canvas;
6327        }
6328
6329        return bitmap;
6330    }
6331
6332    /**
6333     * Indicates whether this View is currently in edit mode. A View is usually
6334     * in edit mode when displayed within a developer tool. For instance, if
6335     * this View is being drawn by a visual user interface builder, this method
6336     * should return true.
6337     *
6338     * Subclasses should check the return value of this method to provide
6339     * different behaviors if their normal behavior might interfere with the
6340     * host environment. For instance: the class spawns a thread in its
6341     * constructor, the drawing code relies on device-specific features, etc.
6342     *
6343     * This method is usually checked in the drawing code of custom widgets.
6344     *
6345     * @return True if this View is in edit mode, false otherwise.
6346     */
6347    public boolean isInEditMode() {
6348        return false;
6349    }
6350
6351    /**
6352     * If the View draws content inside its padding and enables fading edges,
6353     * it needs to support padding offsets. Padding offsets are added to the
6354     * fading edges to extend the length of the fade so that it covers pixels
6355     * drawn inside the padding.
6356     *
6357     * Subclasses of this class should override this method if they need
6358     * to draw content inside the padding.
6359     *
6360     * @return True if padding offset must be applied, false otherwise.
6361     *
6362     * @see #getLeftPaddingOffset()
6363     * @see #getRightPaddingOffset()
6364     * @see #getTopPaddingOffset()
6365     * @see #getBottomPaddingOffset()
6366     *
6367     * @since CURRENT
6368     */
6369    protected boolean isPaddingOffsetRequired() {
6370        return false;
6371    }
6372
6373    /**
6374     * Amount by which to extend the left fading region. Called only when
6375     * {@link #isPaddingOffsetRequired()} returns true.
6376     *
6377     * @return The left padding offset in pixels.
6378     *
6379     * @see #isPaddingOffsetRequired()
6380     *
6381     * @since CURRENT
6382     */
6383    protected int getLeftPaddingOffset() {
6384        return 0;
6385    }
6386
6387    /**
6388     * Amount by which to extend the right fading region. Called only when
6389     * {@link #isPaddingOffsetRequired()} returns true.
6390     *
6391     * @return The right padding offset in pixels.
6392     *
6393     * @see #isPaddingOffsetRequired()
6394     *
6395     * @since CURRENT
6396     */
6397    protected int getRightPaddingOffset() {
6398        return 0;
6399    }
6400
6401    /**
6402     * Amount by which to extend the top fading region. Called only when
6403     * {@link #isPaddingOffsetRequired()} returns true.
6404     *
6405     * @return The top padding offset in pixels.
6406     *
6407     * @see #isPaddingOffsetRequired()
6408     *
6409     * @since CURRENT
6410     */
6411    protected int getTopPaddingOffset() {
6412        return 0;
6413    }
6414
6415    /**
6416     * Amount by which to extend the bottom fading region. Called only when
6417     * {@link #isPaddingOffsetRequired()} returns true.
6418     *
6419     * @return The bottom padding offset in pixels.
6420     *
6421     * @see #isPaddingOffsetRequired()
6422     *
6423     * @since CURRENT
6424     */
6425    protected int getBottomPaddingOffset() {
6426        return 0;
6427    }
6428
6429    /**
6430     * Manually render this view (and all of its children) to the given Canvas.
6431     * The view must have already done a full layout before this function is
6432     * called.  When implementing a view, do not override this method; instead,
6433     * you should implement {@link #onDraw}.
6434     *
6435     * @param canvas The Canvas to which the View is rendered.
6436     */
6437    public void draw(Canvas canvas) {
6438        if (ViewDebug.TRACE_HIERARCHY) {
6439            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
6440        }
6441
6442        final int privateFlags = mPrivateFlags;
6443        final boolean dirtyOpaque = (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE &&
6444                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
6445        mPrivateFlags = (privateFlags & ~DIRTY_MASK) | DRAWN;
6446
6447        /*
6448         * Draw traversal performs several drawing steps which must be executed
6449         * in the appropriate order:
6450         *
6451         *      1. Draw the background
6452         *      2. If necessary, save the canvas' layers to prepare for fading
6453         *      3. Draw view's content
6454         *      4. Draw children
6455         *      5. If necessary, draw the fading edges and restore layers
6456         *      6. Draw decorations (scrollbars for instance)
6457         */
6458
6459        // Step 1, draw the background, if needed
6460        int saveCount;
6461
6462        if (!dirtyOpaque) {
6463            final Drawable background = mBGDrawable;
6464            if (background != null) {
6465                final int scrollX = mScrollX;
6466                final int scrollY = mScrollY;
6467
6468                if (mBackgroundSizeChanged) {
6469                    background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
6470                    mBackgroundSizeChanged = false;
6471                }
6472
6473                if ((scrollX | scrollY) == 0) {
6474                    background.draw(canvas);
6475                } else {
6476                    canvas.translate(scrollX, scrollY);
6477                    background.draw(canvas);
6478                    canvas.translate(-scrollX, -scrollY);
6479                }
6480            }
6481        }
6482
6483        // skip step 2 & 5 if possible (common case)
6484        final int viewFlags = mViewFlags;
6485        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
6486        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
6487        if (!verticalEdges && !horizontalEdges) {
6488            // Step 3, draw the content
6489            if (!dirtyOpaque) onDraw(canvas);
6490
6491            // Step 4, draw the children
6492            dispatchDraw(canvas);
6493
6494            // Step 6, draw decorations (scrollbars)
6495            onDrawScrollBars(canvas);
6496
6497            // we're done...
6498            return;
6499        }
6500
6501        /*
6502         * Here we do the full fledged routine...
6503         * (this is an uncommon case where speed matters less,
6504         * this is why we repeat some of the tests that have been
6505         * done above)
6506         */
6507
6508        boolean drawTop = false;
6509        boolean drawBottom = false;
6510        boolean drawLeft = false;
6511        boolean drawRight = false;
6512
6513        float topFadeStrength = 0.0f;
6514        float bottomFadeStrength = 0.0f;
6515        float leftFadeStrength = 0.0f;
6516        float rightFadeStrength = 0.0f;
6517
6518        // Step 2, save the canvas' layers
6519        int paddingLeft = mPaddingLeft;
6520        int paddingTop = mPaddingTop;
6521
6522        final boolean offsetRequired = isPaddingOffsetRequired();
6523        if (offsetRequired) {
6524            paddingLeft += getLeftPaddingOffset();
6525            paddingTop += getTopPaddingOffset();
6526        }
6527
6528        int left = mScrollX + paddingLeft;
6529        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
6530        int top = mScrollY + paddingTop;
6531        int bottom = top + mBottom - mTop - mPaddingBottom - paddingTop;
6532
6533        if (offsetRequired) {
6534            right += getRightPaddingOffset();
6535            bottom += getBottomPaddingOffset();
6536        }
6537
6538        final ScrollabilityCache scrollabilityCache = mScrollCache;
6539        int length = scrollabilityCache.fadingEdgeLength;
6540
6541        // clip the fade length if top and bottom fades overlap
6542        // overlapping fades produce odd-looking artifacts
6543        if (verticalEdges && (top + length > bottom - length)) {
6544            length = (bottom - top) / 2;
6545        }
6546
6547        // also clip horizontal fades if necessary
6548        if (horizontalEdges && (left + length > right - length)) {
6549            length = (right - left) / 2;
6550        }
6551
6552        if (verticalEdges) {
6553            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
6554            drawTop = topFadeStrength >= 0.0f;
6555            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
6556            drawBottom = bottomFadeStrength >= 0.0f;
6557        }
6558
6559        if (horizontalEdges) {
6560            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
6561            drawLeft = leftFadeStrength >= 0.0f;
6562            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
6563            drawRight = rightFadeStrength >= 0.0f;
6564        }
6565
6566        saveCount = canvas.getSaveCount();
6567
6568        int solidColor = getSolidColor();
6569        if (solidColor == 0) {
6570            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
6571
6572            if (drawTop) {
6573                canvas.saveLayer(left, top, right, top + length, null, flags);
6574            }
6575
6576            if (drawBottom) {
6577                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
6578            }
6579
6580            if (drawLeft) {
6581                canvas.saveLayer(left, top, left + length, bottom, null, flags);
6582            }
6583
6584            if (drawRight) {
6585                canvas.saveLayer(right - length, top, right, bottom, null, flags);
6586            }
6587        } else {
6588            scrollabilityCache.setFadeColor(solidColor);
6589        }
6590
6591        // Step 3, draw the content
6592        if (!dirtyOpaque) onDraw(canvas);
6593
6594        // Step 4, draw the children
6595        dispatchDraw(canvas);
6596
6597        // Step 5, draw the fade effect and restore layers
6598        final Paint p = scrollabilityCache.paint;
6599        final Matrix matrix = scrollabilityCache.matrix;
6600        final Shader fade = scrollabilityCache.shader;
6601        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
6602
6603        if (drawTop) {
6604            matrix.setScale(1, fadeHeight * topFadeStrength);
6605            matrix.postTranslate(left, top);
6606            fade.setLocalMatrix(matrix);
6607            canvas.drawRect(left, top, right, top + length, p);
6608        }
6609
6610        if (drawBottom) {
6611            matrix.setScale(1, fadeHeight * bottomFadeStrength);
6612            matrix.postRotate(180);
6613            matrix.postTranslate(left, bottom);
6614            fade.setLocalMatrix(matrix);
6615            canvas.drawRect(left, bottom - length, right, bottom, p);
6616        }
6617
6618        if (drawLeft) {
6619            matrix.setScale(1, fadeHeight * leftFadeStrength);
6620            matrix.postRotate(-90);
6621            matrix.postTranslate(left, top);
6622            fade.setLocalMatrix(matrix);
6623            canvas.drawRect(left, top, left + length, bottom, p);
6624        }
6625
6626        if (drawRight) {
6627            matrix.setScale(1, fadeHeight * rightFadeStrength);
6628            matrix.postRotate(90);
6629            matrix.postTranslate(right, top);
6630            fade.setLocalMatrix(matrix);
6631            canvas.drawRect(right - length, top, right, bottom, p);
6632        }
6633
6634        canvas.restoreToCount(saveCount);
6635
6636        // Step 6, draw decorations (scrollbars)
6637        onDrawScrollBars(canvas);
6638    }
6639
6640    /**
6641     * Override this if your view is known to always be drawn on top of a solid color background,
6642     * and needs to draw fading edges. Returning a non-zero color enables the view system to
6643     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
6644     * should be set to 0xFF.
6645     *
6646     * @see #setVerticalFadingEdgeEnabled
6647     * @see #setHorizontalFadingEdgeEnabled
6648     *
6649     * @return The known solid color background for this view, or 0 if the color may vary
6650     */
6651    public int getSolidColor() {
6652        return 0;
6653    }
6654
6655    /**
6656     * Build a human readable string representation of the specified view flags.
6657     *
6658     * @param flags the view flags to convert to a string
6659     * @return a String representing the supplied flags
6660     */
6661    private static String printFlags(int flags) {
6662        String output = "";
6663        int numFlags = 0;
6664        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
6665            output += "TAKES_FOCUS";
6666            numFlags++;
6667        }
6668
6669        switch (flags & VISIBILITY_MASK) {
6670        case INVISIBLE:
6671            if (numFlags > 0) {
6672                output += " ";
6673            }
6674            output += "INVISIBLE";
6675            // USELESS HERE numFlags++;
6676            break;
6677        case GONE:
6678            if (numFlags > 0) {
6679                output += " ";
6680            }
6681            output += "GONE";
6682            // USELESS HERE numFlags++;
6683            break;
6684        default:
6685            break;
6686        }
6687        return output;
6688    }
6689
6690    /**
6691     * Build a human readable string representation of the specified private
6692     * view flags.
6693     *
6694     * @param privateFlags the private view flags to convert to a string
6695     * @return a String representing the supplied flags
6696     */
6697    private static String printPrivateFlags(int privateFlags) {
6698        String output = "";
6699        int numFlags = 0;
6700
6701        if ((privateFlags & WANTS_FOCUS) == WANTS_FOCUS) {
6702            output += "WANTS_FOCUS";
6703            numFlags++;
6704        }
6705
6706        if ((privateFlags & FOCUSED) == FOCUSED) {
6707            if (numFlags > 0) {
6708                output += " ";
6709            }
6710            output += "FOCUSED";
6711            numFlags++;
6712        }
6713
6714        if ((privateFlags & SELECTED) == SELECTED) {
6715            if (numFlags > 0) {
6716                output += " ";
6717            }
6718            output += "SELECTED";
6719            numFlags++;
6720        }
6721
6722        if ((privateFlags & IS_ROOT_NAMESPACE) == IS_ROOT_NAMESPACE) {
6723            if (numFlags > 0) {
6724                output += " ";
6725            }
6726            output += "IS_ROOT_NAMESPACE";
6727            numFlags++;
6728        }
6729
6730        if ((privateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
6731            if (numFlags > 0) {
6732                output += " ";
6733            }
6734            output += "HAS_BOUNDS";
6735            numFlags++;
6736        }
6737
6738        if ((privateFlags & DRAWN) == DRAWN) {
6739            if (numFlags > 0) {
6740                output += " ";
6741            }
6742            output += "DRAWN";
6743            // USELESS HERE numFlags++;
6744        }
6745        return output;
6746    }
6747
6748    /**
6749     * <p>Indicates whether or not this view's layout will be requested during
6750     * the next hierarchy layout pass.</p>
6751     *
6752     * @return true if the layout will be forced during next layout pass
6753     */
6754    public boolean isLayoutRequested() {
6755        return (mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT;
6756    }
6757
6758    /**
6759     * Assign a size and position to a view and all of its
6760     * descendants
6761     *
6762     * <p>This is the second phase of the layout mechanism.
6763     * (The first is measuring). In this phase, each parent calls
6764     * layout on all of its children to position them.
6765     * This is typically done using the child measurements
6766     * that were stored in the measure pass().
6767     *
6768     * Derived classes with children should override
6769     * onLayout. In that method, they should
6770     * call layout on each of their their children.
6771     *
6772     * @param l Left position, relative to parent
6773     * @param t Top position, relative to parent
6774     * @param r Right position, relative to parent
6775     * @param b Bottom position, relative to parent
6776     */
6777    public final void layout(int l, int t, int r, int b) {
6778        boolean changed = setFrame(l, t, r, b);
6779        if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) {
6780            if (ViewDebug.TRACE_HIERARCHY) {
6781                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_LAYOUT);
6782            }
6783
6784            onLayout(changed, l, t, r, b);
6785            mPrivateFlags &= ~LAYOUT_REQUIRED;
6786        }
6787        mPrivateFlags &= ~FORCE_LAYOUT;
6788    }
6789
6790    /**
6791     * Called from layout when this view should
6792     * assign a size and position to each of its children.
6793     *
6794     * Derived classes with children should override
6795     * this method and call layout on each of
6796     * their their children.
6797     * @param changed This is a new size or position for this view
6798     * @param left Left position, relative to parent
6799     * @param top Top position, relative to parent
6800     * @param right Right position, relative to parent
6801     * @param bottom Bottom position, relative to parent
6802     */
6803    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
6804    }
6805
6806    /**
6807     * Assign a size and position to this view.
6808     *
6809     * This is called from layout.
6810     *
6811     * @param left Left position, relative to parent
6812     * @param top Top position, relative to parent
6813     * @param right Right position, relative to parent
6814     * @param bottom Bottom position, relative to parent
6815     * @return true if the new size and position are different than the
6816     *         previous ones
6817     * {@hide}
6818     */
6819    protected boolean setFrame(int left, int top, int right, int bottom) {
6820        boolean changed = false;
6821
6822        if (DBG) {
6823            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
6824                    + right + "," + bottom + ")");
6825        }
6826
6827        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
6828            changed = true;
6829
6830            // Remember our drawn bit
6831            int drawn = mPrivateFlags & DRAWN;
6832
6833            // Invalidate our old position
6834            invalidate();
6835
6836
6837            int oldWidth = mRight - mLeft;
6838            int oldHeight = mBottom - mTop;
6839
6840            mLeft = left;
6841            mTop = top;
6842            mRight = right;
6843            mBottom = bottom;
6844
6845            mPrivateFlags |= HAS_BOUNDS;
6846
6847            int newWidth = right - left;
6848            int newHeight = bottom - top;
6849
6850            if (newWidth != oldWidth || newHeight != oldHeight) {
6851                onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
6852            }
6853
6854            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
6855                // If we are visible, force the DRAWN bit to on so that
6856                // this invalidate will go through (at least to our parent).
6857                // This is because someone may have invalidated this view
6858                // before this call to setFrame came in, therby clearing
6859                // the DRAWN bit.
6860                mPrivateFlags |= DRAWN;
6861                invalidate();
6862            }
6863
6864            // Reset drawn bit to original value (invalidate turns it off)
6865            mPrivateFlags |= drawn;
6866
6867            mBackgroundSizeChanged = true;
6868        }
6869        return changed;
6870    }
6871
6872    /**
6873     * Finalize inflating a view from XML.  This is called as the last phase
6874     * of inflation, after all child views have been added.
6875     *
6876     * <p>Even if the subclass overrides onFinishInflate, they should always be
6877     * sure to call the super method, so that we get called.
6878     */
6879    protected void onFinishInflate() {
6880    }
6881
6882    /**
6883     * Returns the resources associated with this view.
6884     *
6885     * @return Resources object.
6886     */
6887    public Resources getResources() {
6888        return mResources;
6889    }
6890
6891    /**
6892     * Invalidates the specified Drawable.
6893     *
6894     * @param drawable the drawable to invalidate
6895     */
6896    public void invalidateDrawable(Drawable drawable) {
6897        if (verifyDrawable(drawable)) {
6898            final Rect dirty = drawable.getBounds();
6899            final int scrollX = mScrollX;
6900            final int scrollY = mScrollY;
6901
6902            invalidate(dirty.left + scrollX, dirty.top + scrollY,
6903                    dirty.right + scrollX, dirty.bottom + scrollY);
6904        }
6905    }
6906
6907    /**
6908     * Schedules an action on a drawable to occur at a specified time.
6909     *
6910     * @param who the recipient of the action
6911     * @param what the action to run on the drawable
6912     * @param when the time at which the action must occur. Uses the
6913     *        {@link SystemClock#uptimeMillis} timebase.
6914     */
6915    public void scheduleDrawable(Drawable who, Runnable what, long when) {
6916        if (verifyDrawable(who) && what != null && mAttachInfo != null) {
6917            mAttachInfo.mHandler.postAtTime(what, who, when);
6918        }
6919    }
6920
6921    /**
6922     * Cancels a scheduled action on a drawable.
6923     *
6924     * @param who the recipient of the action
6925     * @param what the action to cancel
6926     */
6927    public void unscheduleDrawable(Drawable who, Runnable what) {
6928        if (verifyDrawable(who) && what != null && mAttachInfo != null) {
6929            mAttachInfo.mHandler.removeCallbacks(what, who);
6930        }
6931    }
6932
6933    /**
6934     * Unschedule any events associated with the given Drawable.  This can be
6935     * used when selecting a new Drawable into a view, so that the previous
6936     * one is completely unscheduled.
6937     *
6938     * @param who The Drawable to unschedule.
6939     *
6940     * @see #drawableStateChanged
6941     */
6942    public void unscheduleDrawable(Drawable who) {
6943        if (mAttachInfo != null) {
6944            mAttachInfo.mHandler.removeCallbacksAndMessages(who);
6945        }
6946    }
6947
6948    /**
6949     * If your view subclass is displaying its own Drawable objects, it should
6950     * override this function and return true for any Drawable it is
6951     * displaying.  This allows animations for those drawables to be
6952     * scheduled.
6953     *
6954     * <p>Be sure to call through to the super class when overriding this
6955     * function.
6956     *
6957     * @param who The Drawable to verify.  Return true if it is one you are
6958     *            displaying, else return the result of calling through to the
6959     *            super class.
6960     *
6961     * @return boolean If true than the Drawable is being displayed in the
6962     *         view; else false and it is not allowed to animate.
6963     *
6964     * @see #unscheduleDrawable
6965     * @see #drawableStateChanged
6966     */
6967    protected boolean verifyDrawable(Drawable who) {
6968        return who == mBGDrawable;
6969    }
6970
6971    /**
6972     * This function is called whenever the state of the view changes in such
6973     * a way that it impacts the state of drawables being shown.
6974     *
6975     * <p>Be sure to call through to the superclass when overriding this
6976     * function.
6977     *
6978     * @see Drawable#setState
6979     */
6980    protected void drawableStateChanged() {
6981        Drawable d = mBGDrawable;
6982        if (d != null && d.isStateful()) {
6983            d.setState(getDrawableState());
6984        }
6985    }
6986
6987    /**
6988     * Call this to force a view to update its drawable state. This will cause
6989     * drawableStateChanged to be called on this view. Views that are interested
6990     * in the new state should call getDrawableState.
6991     *
6992     * @see #drawableStateChanged
6993     * @see #getDrawableState
6994     */
6995    public void refreshDrawableState() {
6996        mPrivateFlags |= DRAWABLE_STATE_DIRTY;
6997        drawableStateChanged();
6998
6999        ViewParent parent = mParent;
7000        if (parent != null) {
7001            parent.childDrawableStateChanged(this);
7002        }
7003    }
7004
7005    /**
7006     * Return an array of resource IDs of the drawable states representing the
7007     * current state of the view.
7008     *
7009     * @return The current drawable state
7010     *
7011     * @see Drawable#setState
7012     * @see #drawableStateChanged
7013     * @see #onCreateDrawableState
7014     */
7015    public final int[] getDrawableState() {
7016        if ((mDrawableState != null) && ((mPrivateFlags & DRAWABLE_STATE_DIRTY) == 0)) {
7017            return mDrawableState;
7018        } else {
7019            mDrawableState = onCreateDrawableState(0);
7020            mPrivateFlags &= ~DRAWABLE_STATE_DIRTY;
7021            return mDrawableState;
7022        }
7023    }
7024
7025    /**
7026     * Generate the new {@link android.graphics.drawable.Drawable} state for
7027     * this view. This is called by the view
7028     * system when the cached Drawable state is determined to be invalid.  To
7029     * retrieve the current state, you should use {@link #getDrawableState}.
7030     *
7031     * @param extraSpace if non-zero, this is the number of extra entries you
7032     * would like in the returned array in which you can place your own
7033     * states.
7034     *
7035     * @return Returns an array holding the current {@link Drawable} state of
7036     * the view.
7037     *
7038     * @see #mergeDrawableStates
7039     */
7040    protected int[] onCreateDrawableState(int extraSpace) {
7041        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
7042                mParent instanceof View) {
7043            return ((View) mParent).onCreateDrawableState(extraSpace);
7044        }
7045
7046        int[] drawableState;
7047
7048        int privateFlags = mPrivateFlags;
7049
7050        int viewStateIndex = (((privateFlags & PRESSED) != 0) ? 1 : 0);
7051
7052        viewStateIndex = (viewStateIndex << 1)
7053                + (((mViewFlags & ENABLED_MASK) == ENABLED) ? 1 : 0);
7054
7055        viewStateIndex = (viewStateIndex << 1) + (isFocused() ? 1 : 0);
7056
7057        viewStateIndex = (viewStateIndex << 1)
7058                + (((privateFlags & SELECTED) != 0) ? 1 : 0);
7059
7060        final boolean hasWindowFocus = hasWindowFocus();
7061        viewStateIndex = (viewStateIndex << 1) + (hasWindowFocus ? 1 : 0);
7062
7063        drawableState = VIEW_STATE_SETS[viewStateIndex];
7064
7065        //noinspection ConstantIfStatement
7066        if (false) {
7067            Log.i("View", "drawableStateIndex=" + viewStateIndex);
7068            Log.i("View", toString()
7069                    + " pressed=" + ((privateFlags & PRESSED) != 0)
7070                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
7071                    + " fo=" + hasFocus()
7072                    + " sl=" + ((privateFlags & SELECTED) != 0)
7073                    + " wf=" + hasWindowFocus
7074                    + ": " + Arrays.toString(drawableState));
7075        }
7076
7077        if (extraSpace == 0) {
7078            return drawableState;
7079        }
7080
7081        final int[] fullState;
7082        if (drawableState != null) {
7083            fullState = new int[drawableState.length + extraSpace];
7084            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
7085        } else {
7086            fullState = new int[extraSpace];
7087        }
7088
7089        return fullState;
7090    }
7091
7092    /**
7093     * Merge your own state values in <var>additionalState</var> into the base
7094     * state values <var>baseState</var> that were returned by
7095     * {@link #onCreateDrawableState}.
7096     *
7097     * @param baseState The base state values returned by
7098     * {@link #onCreateDrawableState}, which will be modified to also hold your
7099     * own additional state values.
7100     *
7101     * @param additionalState The additional state values you would like
7102     * added to <var>baseState</var>; this array is not modified.
7103     *
7104     * @return As a convenience, the <var>baseState</var> array you originally
7105     * passed into the function is returned.
7106     *
7107     * @see #onCreateDrawableState
7108     */
7109    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
7110        final int N = baseState.length;
7111        int i = N - 1;
7112        while (i >= 0 && baseState[i] == 0) {
7113            i--;
7114        }
7115        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
7116        return baseState;
7117    }
7118
7119    /**
7120     * Sets the background color for this view.
7121     * @param color the color of the background
7122     */
7123    public void setBackgroundColor(int color) {
7124        setBackgroundDrawable(new ColorDrawable(color));
7125    }
7126
7127    /**
7128     * Set the background to a given resource. The resource should refer to
7129     * a Drawable object or 0 to remove the background.
7130     * @param resid The identifier of the resource.
7131     * @attr ref android.R.styleable#View_background
7132     */
7133    public void setBackgroundResource(int resid) {
7134        if (resid != 0 && resid == mBackgroundResource) {
7135            return;
7136        }
7137
7138        Drawable d= null;
7139        if (resid != 0) {
7140            d = mResources.getDrawable(resid);
7141        }
7142        setBackgroundDrawable(d);
7143
7144        mBackgroundResource = resid;
7145    }
7146
7147    /**
7148     * Set the background to a given Drawable, or remove the background. If the
7149     * background has padding, this View's padding is set to the background's
7150     * padding. However, when a background is removed, this View's padding isn't
7151     * touched. If setting the padding is desired, please use
7152     * {@link #setPadding(int, int, int, int)}.
7153     *
7154     * @param d The Drawable to use as the background, or null to remove the
7155     *        background
7156     */
7157    public void setBackgroundDrawable(Drawable d) {
7158        boolean requestLayout = false;
7159
7160        mBackgroundResource = 0;
7161
7162        /*
7163         * Regardless of whether we're setting a new background or not, we want
7164         * to clear the previous drawable.
7165         */
7166        if (mBGDrawable != null) {
7167            mBGDrawable.setCallback(null);
7168            unscheduleDrawable(mBGDrawable);
7169        }
7170
7171        if (d != null) {
7172            Rect padding = sThreadLocal.get();
7173            if (padding == null) {
7174                padding = new Rect();
7175                sThreadLocal.set(padding);
7176            }
7177            if (d.getPadding(padding)) {
7178                setPadding(padding.left, padding.top, padding.right, padding.bottom);
7179            }
7180
7181            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
7182            // if it has a different minimum size, we should layout again
7183            if (mBGDrawable == null || mBGDrawable.getMinimumHeight() != d.getMinimumHeight() ||
7184                    mBGDrawable.getMinimumWidth() != d.getMinimumWidth()) {
7185                requestLayout = true;
7186            }
7187
7188            d.setCallback(this);
7189            if (d.isStateful()) {
7190                d.setState(getDrawableState());
7191            }
7192            d.setVisible(getVisibility() == VISIBLE, false);
7193            mBGDrawable = d;
7194
7195            if ((mPrivateFlags & SKIP_DRAW) != 0) {
7196                mPrivateFlags &= ~SKIP_DRAW;
7197                mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
7198                requestLayout = true;
7199            }
7200        } else {
7201            /* Remove the background */
7202            mBGDrawable = null;
7203
7204            if ((mPrivateFlags & ONLY_DRAWS_BACKGROUND) != 0) {
7205                /*
7206                 * This view ONLY drew the background before and we're removing
7207                 * the background, so now it won't draw anything
7208                 * (hence we SKIP_DRAW)
7209                 */
7210                mPrivateFlags &= ~ONLY_DRAWS_BACKGROUND;
7211                mPrivateFlags |= SKIP_DRAW;
7212            }
7213
7214            /*
7215             * When the background is set, we try to apply its padding to this
7216             * View. When the background is removed, we don't touch this View's
7217             * padding. This is noted in the Javadocs. Hence, we don't need to
7218             * requestLayout(), the invalidate() below is sufficient.
7219             */
7220
7221            // The old background's minimum size could have affected this
7222            // View's layout, so let's requestLayout
7223            requestLayout = true;
7224        }
7225
7226        computeOpaqueFlags();
7227
7228        if (requestLayout) {
7229            requestLayout();
7230        }
7231
7232        mBackgroundSizeChanged = true;
7233        invalidate();
7234    }
7235
7236    /**
7237     * Gets the background drawable
7238     * @return The drawable used as the background for this view, if any.
7239     */
7240    public Drawable getBackground() {
7241        return mBGDrawable;
7242    }
7243
7244    /**
7245     * Sets the padding. The view may add on the space required to display
7246     * the scrollbars, depending on the style and visibility of the scrollbars.
7247     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
7248     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
7249     * from the values set in this call.
7250     *
7251     * @attr ref android.R.styleable#View_padding
7252     * @attr ref android.R.styleable#View_paddingBottom
7253     * @attr ref android.R.styleable#View_paddingLeft
7254     * @attr ref android.R.styleable#View_paddingRight
7255     * @attr ref android.R.styleable#View_paddingTop
7256     * @param left the left padding in pixels
7257     * @param top the top padding in pixels
7258     * @param right the right padding in pixels
7259     * @param bottom the bottom padding in pixels
7260     */
7261    public void setPadding(int left, int top, int right, int bottom) {
7262        boolean changed = false;
7263
7264        mUserPaddingRight = right;
7265        mUserPaddingBottom = bottom;
7266
7267        final int viewFlags = mViewFlags;
7268
7269        // Common case is there are no scroll bars.
7270        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
7271            // TODO: Deal with RTL languages to adjust left padding instead of right.
7272            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
7273                right += (viewFlags & SCROLLBARS_INSET_MASK) == 0
7274                        ? 0 : getVerticalScrollbarWidth();
7275            }
7276            if ((viewFlags & SCROLLBARS_HORIZONTAL) == 0) {
7277                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
7278                        ? 0 : getHorizontalScrollbarHeight();
7279            }
7280        }
7281
7282        if (mPaddingLeft != left) {
7283            changed = true;
7284            mPaddingLeft = left;
7285        }
7286        if (mPaddingTop != top) {
7287            changed = true;
7288            mPaddingTop = top;
7289        }
7290        if (mPaddingRight != right) {
7291            changed = true;
7292            mPaddingRight = right;
7293        }
7294        if (mPaddingBottom != bottom) {
7295            changed = true;
7296            mPaddingBottom = bottom;
7297        }
7298
7299        if (changed) {
7300            requestLayout();
7301        }
7302    }
7303
7304    /**
7305     * Returns the top padding of this view.
7306     *
7307     * @return the top padding in pixels
7308     */
7309    public int getPaddingTop() {
7310        return mPaddingTop;
7311    }
7312
7313    /**
7314     * Returns the bottom padding of this view. If there are inset and enabled
7315     * scrollbars, this value may include the space required to display the
7316     * scrollbars as well.
7317     *
7318     * @return the bottom padding in pixels
7319     */
7320    public int getPaddingBottom() {
7321        return mPaddingBottom;
7322    }
7323
7324    /**
7325     * Returns the left padding of this view. If there are inset and enabled
7326     * scrollbars, this value may include the space required to display the
7327     * scrollbars as well.
7328     *
7329     * @return the left padding in pixels
7330     */
7331    public int getPaddingLeft() {
7332        return mPaddingLeft;
7333    }
7334
7335    /**
7336     * Returns the right padding of this view. If there are inset and enabled
7337     * scrollbars, this value may include the space required to display the
7338     * scrollbars as well.
7339     *
7340     * @return the right padding in pixels
7341     */
7342    public int getPaddingRight() {
7343        return mPaddingRight;
7344    }
7345
7346    /**
7347     * Changes the selection state of this view. A view can be selected or not.
7348     * Note that selection is not the same as focus. Views are typically
7349     * selected in the context of an AdapterView like ListView or GridView;
7350     * the selected view is the view that is highlighted.
7351     *
7352     * @param selected true if the view must be selected, false otherwise
7353     */
7354    public void setSelected(boolean selected) {
7355        if (((mPrivateFlags & SELECTED) != 0) != selected) {
7356            mPrivateFlags = (mPrivateFlags & ~SELECTED) | (selected ? SELECTED : 0);
7357            if (!selected) resetPressedState();
7358            invalidate();
7359            refreshDrawableState();
7360            dispatchSetSelected(selected);
7361        }
7362    }
7363
7364    /**
7365     * Dispatch setSelected to all of this View's children.
7366     *
7367     * @see #setSelected(boolean)
7368     *
7369     * @param selected The new selected state
7370     */
7371    protected void dispatchSetSelected(boolean selected) {
7372    }
7373
7374    /**
7375     * Indicates the selection state of this view.
7376     *
7377     * @return true if the view is selected, false otherwise
7378     */
7379    @ViewDebug.ExportedProperty
7380    public boolean isSelected() {
7381        return (mPrivateFlags & SELECTED) != 0;
7382    }
7383
7384    /**
7385     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
7386     * observer can be used to get notifications when global events, like
7387     * layout, happen.
7388     *
7389     * The returned ViewTreeObserver observer is not guaranteed to remain
7390     * valid for the lifetime of this View. If the caller of this method keeps
7391     * a long-lived reference to ViewTreeObserver, it should always check for
7392     * the return value of {@link ViewTreeObserver#isAlive()}.
7393     *
7394     * @return The ViewTreeObserver for this view's hierarchy.
7395     */
7396    public ViewTreeObserver getViewTreeObserver() {
7397        if (mAttachInfo != null) {
7398            return mAttachInfo.mTreeObserver;
7399        }
7400        if (mFloatingTreeObserver == null) {
7401            mFloatingTreeObserver = new ViewTreeObserver();
7402        }
7403        return mFloatingTreeObserver;
7404    }
7405
7406    /**
7407     * <p>Finds the topmost view in the current view hierarchy.</p>
7408     *
7409     * @return the topmost view containing this view
7410     */
7411    public View getRootView() {
7412        if (mAttachInfo != null) {
7413            final View v = mAttachInfo.mRootView;
7414            if (v != null) {
7415                return v;
7416            }
7417        }
7418
7419        View parent = this;
7420
7421        while (parent.mParent != null && parent.mParent instanceof View) {
7422            parent = (View) parent.mParent;
7423        }
7424
7425        return parent;
7426    }
7427
7428    /**
7429     * <p>Computes the coordinates of this view on the screen. The argument
7430     * must be an array of two integers. After the method returns, the array
7431     * contains the x and y location in that order.</p>
7432     *
7433     * @param location an array of two integers in which to hold the coordinates
7434     */
7435    public void getLocationOnScreen(int[] location) {
7436        getLocationInWindow(location);
7437
7438        final AttachInfo info = mAttachInfo;
7439        if (info != null) {
7440            location[0] += info.mWindowLeft;
7441            location[1] += info.mWindowTop;
7442        }
7443    }
7444
7445    /**
7446     * <p>Computes the coordinates of this view in its window. The argument
7447     * must be an array of two integers. After the method returns, the array
7448     * contains the x and y location in that order.</p>
7449     *
7450     * @param location an array of two integers in which to hold the coordinates
7451     */
7452    public void getLocationInWindow(int[] location) {
7453        if (location == null || location.length < 2) {
7454            throw new IllegalArgumentException("location must be an array of "
7455                    + "two integers");
7456        }
7457
7458        location[0] = mLeft;
7459        location[1] = mTop;
7460
7461        ViewParent viewParent = mParent;
7462        while (viewParent instanceof View) {
7463            final View view = (View)viewParent;
7464            location[0] += view.mLeft - view.mScrollX;
7465            location[1] += view.mTop - view.mScrollY;
7466            viewParent = view.mParent;
7467        }
7468
7469        if (viewParent instanceof ViewRoot) {
7470            // *cough*
7471            final ViewRoot vr = (ViewRoot)viewParent;
7472            location[1] -= vr.mCurScrollY;
7473        }
7474    }
7475
7476    /**
7477     * {@hide}
7478     * @param id the id of the view to be found
7479     * @return the view of the specified id, null if cannot be found
7480     */
7481    protected View findViewTraversal(int id) {
7482        if (id == mID) {
7483            return this;
7484        }
7485        return null;
7486    }
7487
7488    /**
7489     * {@hide}
7490     * @param tag the tag of the view to be found
7491     * @return the view of specified tag, null if cannot be found
7492     */
7493    protected View findViewWithTagTraversal(Object tag) {
7494        if (tag != null && tag.equals(mTag)) {
7495            return this;
7496        }
7497        return null;
7498    }
7499
7500    /**
7501     * Look for a child view with the given id.  If this view has the given
7502     * id, return this view.
7503     *
7504     * @param id The id to search for.
7505     * @return The view that has the given id in the hierarchy or null
7506     */
7507    public final View findViewById(int id) {
7508        if (id < 0) {
7509            return null;
7510        }
7511        return findViewTraversal(id);
7512    }
7513
7514    /**
7515     * Look for a child view with the given tag.  If this view has the given
7516     * tag, return this view.
7517     *
7518     * @param tag The tag to search for, using "tag.equals(getTag())".
7519     * @return The View that has the given tag in the hierarchy or null
7520     */
7521    public final View findViewWithTag(Object tag) {
7522        if (tag == null) {
7523            return null;
7524        }
7525        return findViewWithTagTraversal(tag);
7526    }
7527
7528    /**
7529     * Sets the identifier for this view. The identifier does not have to be
7530     * unique in this view's hierarchy. The identifier should be a positive
7531     * number.
7532     *
7533     * @see #NO_ID
7534     * @see #getId
7535     * @see #findViewById
7536     *
7537     * @param id a number used to identify the view
7538     *
7539     * @attr ref android.R.styleable#View_id
7540     */
7541    public void setId(int id) {
7542        mID = id;
7543    }
7544
7545    /**
7546     * {@hide}
7547     *
7548     * @param isRoot true if the view belongs to the root namespace, false
7549     *        otherwise
7550     */
7551    public void setIsRootNamespace(boolean isRoot) {
7552        if (isRoot) {
7553            mPrivateFlags |= IS_ROOT_NAMESPACE;
7554        } else {
7555            mPrivateFlags &= ~IS_ROOT_NAMESPACE;
7556        }
7557    }
7558
7559    /**
7560     * {@hide}
7561     *
7562     * @return true if the view belongs to the root namespace, false otherwise
7563     */
7564    public boolean isRootNamespace() {
7565        return (mPrivateFlags&IS_ROOT_NAMESPACE) != 0;
7566    }
7567
7568    /**
7569     * Returns this view's identifier.
7570     *
7571     * @return a positive integer used to identify the view or {@link #NO_ID}
7572     *         if the view has no ID
7573     *
7574     * @see #setId
7575     * @see #findViewById
7576     * @attr ref android.R.styleable#View_id
7577     */
7578    @ViewDebug.CapturedViewProperty
7579    public int getId() {
7580        return mID;
7581    }
7582
7583    /**
7584     * Returns this view's tag.
7585     *
7586     * @return the Object stored in this view as a tag
7587     *
7588     * @see #setTag(Object)
7589     * @see #getTag(int)
7590     */
7591    @ViewDebug.ExportedProperty
7592    public Object getTag() {
7593        return mTag;
7594    }
7595
7596    /**
7597     * Sets the tag associated with this view. A tag can be used to mark
7598     * a view in its hierarchy and does not have to be unique within the
7599     * hierarchy. Tags can also be used to store data within a view without
7600     * resorting to another data structure.
7601     *
7602     * @param tag an Object to tag the view with
7603     *
7604     * @see #getTag()
7605     * @see #setTag(int, Object)
7606     */
7607    public void setTag(final Object tag) {
7608        mTag = tag;
7609    }
7610
7611    /**
7612     * Returns the tag associated with this view and the specified key.
7613     *
7614     * @param key The key identifying the tag
7615     *
7616     * @return the Object stored in this view as a tag
7617     *
7618     * @see #setTag(int, Object)
7619     * @see #getTag()
7620     */
7621    public Object getTag(int key) {
7622        SparseArray<Object> tags = null;
7623        synchronized (sTagsLock) {
7624            if (sTags != null) {
7625                tags = sTags.get(this);
7626            }
7627        }
7628
7629        if (tags != null) return tags.get(key);
7630        return null;
7631    }
7632
7633    /**
7634     * Sets a tag associated with this view and a key. A tag can be used
7635     * to mark a view in its hierarchy and does not have to be unique within
7636     * the hierarchy. Tags can also be used to store data within a view
7637     * without resorting to another data structure.
7638     *
7639     * The specified key should be an id declared in the resources of the
7640     * application to ensure it is unique. Keys identified as belonging to
7641     * the Android framework or not associated with any package will cause
7642     * an {@link IllegalArgumentException} to be thrown.
7643     *
7644     * @param key The key identifying the tag
7645     * @param tag An Object to tag the view with
7646     *
7647     * @throws IllegalArgumentException If they specified key is not valid
7648     *
7649     * @see #setTag(Object)
7650     * @see #getTag(int)
7651     */
7652    public void setTag(int key, final Object tag) {
7653        // If the package id is 0x00 or 0x01, it's either an undefined package
7654        // or a framework id
7655        if ((key >>> 24) < 2) {
7656            throw new IllegalArgumentException("The key must be an application-specific "
7657                    + "resource id.");
7658        }
7659
7660        setTagInternal(this, key, tag);
7661    }
7662
7663    /**
7664     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
7665     * framework id.
7666     *
7667     * @hide
7668     */
7669    public void setTagInternal(int key, Object tag) {
7670        if ((key >>> 24) != 0x1) {
7671            throw new IllegalArgumentException("The key must be a framework-specific "
7672                    + "resource id.");
7673        }
7674
7675        setTagInternal(this, key, tag);
7676    }
7677
7678    private static void setTagInternal(View view, int key, Object tag) {
7679        SparseArray<Object> tags = null;
7680        synchronized (sTagsLock) {
7681            if (sTags == null) {
7682                sTags = new WeakHashMap<View, SparseArray<Object>>();
7683            } else {
7684                tags = sTags.get(view);
7685            }
7686        }
7687
7688        if (tags == null) {
7689            tags = new SparseArray<Object>(2);
7690            synchronized (sTagsLock) {
7691                sTags.put(view, tags);
7692            }
7693        }
7694
7695        tags.put(key, tag);
7696    }
7697
7698    /**
7699     * @param consistency The type of consistency. See ViewDebug for more information.
7700     *
7701     * @hide
7702     */
7703    protected boolean dispatchConsistencyCheck(int consistency) {
7704        return onConsistencyCheck(consistency);
7705    }
7706
7707    /**
7708     * Method that subclasses should implement to check their consistency. The type of
7709     * consistency check is indicated by the bit field passed as a parameter.
7710     *
7711     * @param consistency The type of consistency. See ViewDebug for more information.
7712     *
7713     * @throws IllegalStateException if the view is in an inconsistent state.
7714     *
7715     * @hide
7716     */
7717    protected boolean onConsistencyCheck(int consistency) {
7718        boolean result = true;
7719
7720        final boolean checkLayout = (consistency & ViewDebug.CONSISTENCY_LAYOUT) != 0;
7721        final boolean checkDrawing = (consistency & ViewDebug.CONSISTENCY_DRAWING) != 0;
7722
7723        if (checkLayout) {
7724            if (getParent() == null) {
7725                result = false;
7726                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
7727                        "View " + this + " does not have a parent.");
7728            }
7729
7730            if (mAttachInfo == null) {
7731                result = false;
7732                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
7733                        "View " + this + " is not attached to a window.");
7734            }
7735        }
7736
7737        if (checkDrawing) {
7738            // Do not check the DIRTY/DRAWN flags because views can call invalidate()
7739            // from their draw() method
7740
7741            if ((mPrivateFlags & DRAWN) != DRAWN &&
7742                    (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
7743                result = false;
7744                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
7745                        "View " + this + " was invalidated but its drawing cache is valid.");
7746            }
7747        }
7748
7749        return result;
7750    }
7751
7752    /**
7753     * Prints information about this view in the log output, with the tag
7754     * {@link #VIEW_LOG_TAG}.
7755     *
7756     * @hide
7757     */
7758    public void debug() {
7759        debug(0);
7760    }
7761
7762    /**
7763     * Prints information about this view in the log output, with the tag
7764     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
7765     * indentation defined by the <code>depth</code>.
7766     *
7767     * @param depth the indentation level
7768     *
7769     * @hide
7770     */
7771    protected void debug(int depth) {
7772        String output = debugIndent(depth - 1);
7773
7774        output += "+ " + this;
7775        int id = getId();
7776        if (id != -1) {
7777            output += " (id=" + id + ")";
7778        }
7779        Object tag = getTag();
7780        if (tag != null) {
7781            output += " (tag=" + tag + ")";
7782        }
7783        Log.d(VIEW_LOG_TAG, output);
7784
7785        if ((mPrivateFlags & FOCUSED) != 0) {
7786            output = debugIndent(depth) + " FOCUSED";
7787            Log.d(VIEW_LOG_TAG, output);
7788        }
7789
7790        output = debugIndent(depth);
7791        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
7792                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
7793                + "} ";
7794        Log.d(VIEW_LOG_TAG, output);
7795
7796        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
7797                || mPaddingBottom != 0) {
7798            output = debugIndent(depth);
7799            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
7800                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
7801            Log.d(VIEW_LOG_TAG, output);
7802        }
7803
7804        output = debugIndent(depth);
7805        output += "mMeasureWidth=" + mMeasuredWidth +
7806                " mMeasureHeight=" + mMeasuredHeight;
7807        Log.d(VIEW_LOG_TAG, output);
7808
7809        output = debugIndent(depth);
7810        if (mLayoutParams == null) {
7811            output += "BAD! no layout params";
7812        } else {
7813            output = mLayoutParams.debug(output);
7814        }
7815        Log.d(VIEW_LOG_TAG, output);
7816
7817        output = debugIndent(depth);
7818        output += "flags={";
7819        output += View.printFlags(mViewFlags);
7820        output += "}";
7821        Log.d(VIEW_LOG_TAG, output);
7822
7823        output = debugIndent(depth);
7824        output += "privateFlags={";
7825        output += View.printPrivateFlags(mPrivateFlags);
7826        output += "}";
7827        Log.d(VIEW_LOG_TAG, output);
7828    }
7829
7830    /**
7831     * Creates an string of whitespaces used for indentation.
7832     *
7833     * @param depth the indentation level
7834     * @return a String containing (depth * 2 + 3) * 2 white spaces
7835     *
7836     * @hide
7837     */
7838    protected static String debugIndent(int depth) {
7839        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
7840        for (int i = 0; i < (depth * 2) + 3; i++) {
7841            spaces.append(' ').append(' ');
7842        }
7843        return spaces.toString();
7844    }
7845
7846    /**
7847     * <p>Return the offset of the widget's text baseline from the widget's top
7848     * boundary. If this widget does not support baseline alignment, this
7849     * method returns -1. </p>
7850     *
7851     * @return the offset of the baseline within the widget's bounds or -1
7852     *         if baseline alignment is not supported
7853     */
7854    @ViewDebug.ExportedProperty
7855    public int getBaseline() {
7856        return -1;
7857    }
7858
7859    /**
7860     * Call this when something has changed which has invalidated the
7861     * layout of this view. This will schedule a layout pass of the view
7862     * tree.
7863     */
7864    public void requestLayout() {
7865        if (ViewDebug.TRACE_HIERARCHY) {
7866            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.REQUEST_LAYOUT);
7867        }
7868
7869        mPrivateFlags |= FORCE_LAYOUT;
7870
7871        if (mParent != null && !mParent.isLayoutRequested()) {
7872            mParent.requestLayout();
7873        }
7874    }
7875
7876    /**
7877     * Forces this view to be laid out during the next layout pass.
7878     * This method does not call requestLayout() or forceLayout()
7879     * on the parent.
7880     */
7881    public void forceLayout() {
7882        mPrivateFlags |= FORCE_LAYOUT;
7883    }
7884
7885    /**
7886     * <p>
7887     * This is called to find out how big a view should be. The parent
7888     * supplies constraint information in the width and height parameters.
7889     * </p>
7890     *
7891     * <p>
7892     * The actual mesurement work of a view is performed in
7893     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
7894     * {@link #onMeasure(int, int)} can and must be overriden by subclasses.
7895     * </p>
7896     *
7897     *
7898     * @param widthMeasureSpec Horizontal space requirements as imposed by the
7899     *        parent
7900     * @param heightMeasureSpec Vertical space requirements as imposed by the
7901     *        parent
7902     *
7903     * @see #onMeasure(int, int)
7904     */
7905    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
7906        if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||
7907                widthMeasureSpec != mOldWidthMeasureSpec ||
7908                heightMeasureSpec != mOldHeightMeasureSpec) {
7909
7910            // first clears the measured dimension flag
7911            mPrivateFlags &= ~MEASURED_DIMENSION_SET;
7912
7913            if (ViewDebug.TRACE_HIERARCHY) {
7914                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE);
7915            }
7916
7917            // measure ourselves, this should set the measured dimension flag back
7918            onMeasure(widthMeasureSpec, heightMeasureSpec);
7919
7920            // flag not set, setMeasuredDimension() was not invoked, we raise
7921            // an exception to warn the developer
7922            if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {
7923                throw new IllegalStateException("onMeasure() did not set the"
7924                        + " measured dimension by calling"
7925                        + " setMeasuredDimension()");
7926            }
7927
7928            mPrivateFlags |= LAYOUT_REQUIRED;
7929        }
7930
7931        mOldWidthMeasureSpec = widthMeasureSpec;
7932        mOldHeightMeasureSpec = heightMeasureSpec;
7933    }
7934
7935    /**
7936     * <p>
7937     * Measure the view and its content to determine the measured width and the
7938     * measured height. This method is invoked by {@link #measure(int, int)} and
7939     * should be overriden by subclasses to provide accurate and efficient
7940     * measurement of their contents.
7941     * </p>
7942     *
7943     * <p>
7944     * <strong>CONTRACT:</strong> When overriding this method, you
7945     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
7946     * measured width and height of this view. Failure to do so will trigger an
7947     * <code>IllegalStateException</code>, thrown by
7948     * {@link #measure(int, int)}. Calling the superclass'
7949     * {@link #onMeasure(int, int)} is a valid use.
7950     * </p>
7951     *
7952     * <p>
7953     * The base class implementation of measure defaults to the background size,
7954     * unless a larger size is allowed by the MeasureSpec. Subclasses should
7955     * override {@link #onMeasure(int, int)} to provide better measurements of
7956     * their content.
7957     * </p>
7958     *
7959     * <p>
7960     * If this method is overridden, it is the subclass's responsibility to make
7961     * sure the measured height and width are at least the view's minimum height
7962     * and width ({@link #getSuggestedMinimumHeight()} and
7963     * {@link #getSuggestedMinimumWidth()}).
7964     * </p>
7965     *
7966     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
7967     *                         The requirements are encoded with
7968     *                         {@link android.view.View.MeasureSpec}.
7969     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
7970     *                         The requirements are encoded with
7971     *                         {@link android.view.View.MeasureSpec}.
7972     *
7973     * @see #getMeasuredWidth()
7974     * @see #getMeasuredHeight()
7975     * @see #setMeasuredDimension(int, int)
7976     * @see #getSuggestedMinimumHeight()
7977     * @see #getSuggestedMinimumWidth()
7978     * @see android.view.View.MeasureSpec#getMode(int)
7979     * @see android.view.View.MeasureSpec#getSize(int)
7980     */
7981    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
7982        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
7983                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
7984    }
7985
7986    /**
7987     * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the
7988     * measured width and measured height. Failing to do so will trigger an
7989     * exception at measurement time.</p>
7990     *
7991     * @param measuredWidth the measured width of this view
7992     * @param measuredHeight the measured height of this view
7993     */
7994    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
7995        mMeasuredWidth = measuredWidth;
7996        mMeasuredHeight = measuredHeight;
7997
7998        mPrivateFlags |= MEASURED_DIMENSION_SET;
7999    }
8000
8001    /**
8002     * Utility to reconcile a desired size with constraints imposed by a MeasureSpec.
8003     * Will take the desired size, unless a different size is imposed by the constraints.
8004     *
8005     * @param size How big the view wants to be
8006     * @param measureSpec Constraints imposed by the parent
8007     * @return The size this view should be.
8008     */
8009    public static int resolveSize(int size, int measureSpec) {
8010        int result = size;
8011        int specMode = MeasureSpec.getMode(measureSpec);
8012        int specSize =  MeasureSpec.getSize(measureSpec);
8013        switch (specMode) {
8014        case MeasureSpec.UNSPECIFIED:
8015            result = size;
8016            break;
8017        case MeasureSpec.AT_MOST:
8018            result = Math.min(size, specSize);
8019            break;
8020        case MeasureSpec.EXACTLY:
8021            result = specSize;
8022            break;
8023        }
8024        return result;
8025    }
8026
8027    /**
8028     * Utility to return a default size. Uses the supplied size if the
8029     * MeasureSpec imposed no contraints. Will get larger if allowed
8030     * by the MeasureSpec.
8031     *
8032     * @param size Default size for this view
8033     * @param measureSpec Constraints imposed by the parent
8034     * @return The size this view should be.
8035     */
8036    public static int getDefaultSize(int size, int measureSpec) {
8037        int result = size;
8038        int specMode = MeasureSpec.getMode(measureSpec);
8039        int specSize =  MeasureSpec.getSize(measureSpec);
8040
8041        switch (specMode) {
8042        case MeasureSpec.UNSPECIFIED:
8043            result = size;
8044            break;
8045        case MeasureSpec.AT_MOST:
8046        case MeasureSpec.EXACTLY:
8047            result = specSize;
8048            break;
8049        }
8050        return result;
8051    }
8052
8053    /**
8054     * Returns the suggested minimum height that the view should use. This
8055     * returns the maximum of the view's minimum height
8056     * and the background's minimum height
8057     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
8058     * <p>
8059     * When being used in {@link #onMeasure(int, int)}, the caller should still
8060     * ensure the returned height is within the requirements of the parent.
8061     *
8062     * @return The suggested minimum height of the view.
8063     */
8064    protected int getSuggestedMinimumHeight() {
8065        int suggestedMinHeight = mMinHeight;
8066
8067        if (mBGDrawable != null) {
8068            final int bgMinHeight = mBGDrawable.getMinimumHeight();
8069            if (suggestedMinHeight < bgMinHeight) {
8070                suggestedMinHeight = bgMinHeight;
8071            }
8072        }
8073
8074        return suggestedMinHeight;
8075    }
8076
8077    /**
8078     * Returns the suggested minimum width that the view should use. This
8079     * returns the maximum of the view's minimum width)
8080     * and the background's minimum width
8081     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
8082     * <p>
8083     * When being used in {@link #onMeasure(int, int)}, the caller should still
8084     * ensure the returned width is within the requirements of the parent.
8085     *
8086     * @return The suggested minimum width of the view.
8087     */
8088    protected int getSuggestedMinimumWidth() {
8089        int suggestedMinWidth = mMinWidth;
8090
8091        if (mBGDrawable != null) {
8092            final int bgMinWidth = mBGDrawable.getMinimumWidth();
8093            if (suggestedMinWidth < bgMinWidth) {
8094                suggestedMinWidth = bgMinWidth;
8095            }
8096        }
8097
8098        return suggestedMinWidth;
8099    }
8100
8101    /**
8102     * Sets the minimum height of the view. It is not guaranteed the view will
8103     * be able to achieve this minimum height (for example, if its parent layout
8104     * constrains it with less available height).
8105     *
8106     * @param minHeight The minimum height the view will try to be.
8107     */
8108    public void setMinimumHeight(int minHeight) {
8109        mMinHeight = minHeight;
8110    }
8111
8112    /**
8113     * Sets the minimum width of the view. It is not guaranteed the view will
8114     * be able to achieve this minimum width (for example, if its parent layout
8115     * constrains it with less available width).
8116     *
8117     * @param minWidth The minimum width the view will try to be.
8118     */
8119    public void setMinimumWidth(int minWidth) {
8120        mMinWidth = minWidth;
8121    }
8122
8123    /**
8124     * Get the animation currently associated with this view.
8125     *
8126     * @return The animation that is currently playing or
8127     *         scheduled to play for this view.
8128     */
8129    public Animation getAnimation() {
8130        return mCurrentAnimation;
8131    }
8132
8133    /**
8134     * Start the specified animation now.
8135     *
8136     * @param animation the animation to start now
8137     */
8138    public void startAnimation(Animation animation) {
8139        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
8140        setAnimation(animation);
8141        invalidate();
8142    }
8143
8144    /**
8145     * Cancels any animations for this view.
8146     */
8147    public void clearAnimation() {
8148        mCurrentAnimation = null;
8149    }
8150
8151    /**
8152     * Sets the next animation to play for this view.
8153     * If you want the animation to play immediately, use
8154     * startAnimation. This method provides allows fine-grained
8155     * control over the start time and invalidation, but you
8156     * must make sure that 1) the animation has a start time set, and
8157     * 2) the view will be invalidated when the animation is supposed to
8158     * start.
8159     *
8160     * @param animation The next animation, or null.
8161     */
8162    public void setAnimation(Animation animation) {
8163        mCurrentAnimation = animation;
8164        if (animation != null) {
8165            animation.reset();
8166        }
8167    }
8168
8169    /**
8170     * Invoked by a parent ViewGroup to notify the start of the animation
8171     * currently associated with this view. If you override this method,
8172     * always call super.onAnimationStart();
8173     *
8174     * @see #setAnimation(android.view.animation.Animation)
8175     * @see #getAnimation()
8176     */
8177    protected void onAnimationStart() {
8178        mPrivateFlags |= ANIMATION_STARTED;
8179    }
8180
8181    /**
8182     * Invoked by a parent ViewGroup to notify the end of the animation
8183     * currently associated with this view. If you override this method,
8184     * always call super.onAnimationEnd();
8185     *
8186     * @see #setAnimation(android.view.animation.Animation)
8187     * @see #getAnimation()
8188     */
8189    protected void onAnimationEnd() {
8190        mPrivateFlags &= ~ANIMATION_STARTED;
8191    }
8192
8193    /**
8194     * Invoked if there is a Transform that involves alpha. Subclass that can
8195     * draw themselves with the specified alpha should return true, and then
8196     * respect that alpha when their onDraw() is called. If this returns false
8197     * then the view may be redirected to draw into an offscreen buffer to
8198     * fulfill the request, which will look fine, but may be slower than if the
8199     * subclass handles it internally. The default implementation returns false.
8200     *
8201     * @param alpha The alpha (0..255) to apply to the view's drawing
8202     * @return true if the view can draw with the specified alpha.
8203     */
8204    protected boolean onSetAlpha(int alpha) {
8205        return false;
8206    }
8207
8208    /**
8209     * This is used by the RootView to perform an optimization when
8210     * the view hierarchy contains one or several SurfaceView.
8211     * SurfaceView is always considered transparent, but its children are not,
8212     * therefore all View objects remove themselves from the global transparent
8213     * region (passed as a parameter to this function).
8214     *
8215     * @param region The transparent region for this ViewRoot (window).
8216     *
8217     * @return Returns true if the effective visibility of the view at this
8218     * point is opaque, regardless of the transparent region; returns false
8219     * if it is possible for underlying windows to be seen behind the view.
8220     *
8221     * {@hide}
8222     */
8223    public boolean gatherTransparentRegion(Region region) {
8224        final AttachInfo attachInfo = mAttachInfo;
8225        if (region != null && attachInfo != null) {
8226            final int pflags = mPrivateFlags;
8227            if ((pflags & SKIP_DRAW) == 0) {
8228                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
8229                // remove it from the transparent region.
8230                final int[] location = attachInfo.mTransparentLocation;
8231                getLocationInWindow(location);
8232                region.op(location[0], location[1], location[0] + mRight - mLeft,
8233                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
8234            } else if ((pflags & ONLY_DRAWS_BACKGROUND) != 0 && mBGDrawable != null) {
8235                // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
8236                // exists, so we remove the background drawable's non-transparent
8237                // parts from this transparent region.
8238                applyDrawableToTransparentRegion(mBGDrawable, region);
8239            }
8240        }
8241        return true;
8242    }
8243
8244    /**
8245     * Play a sound effect for this view.
8246     *
8247     * <p>The framework will play sound effects for some built in actions, such as
8248     * clicking, but you may wish to play these effects in your widget,
8249     * for instance, for internal navigation.
8250     *
8251     * <p>The sound effect will only be played if sound effects are enabled by the user, and
8252     * {@link #isSoundEffectsEnabled()} is true.
8253     *
8254     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
8255     */
8256    public void playSoundEffect(int soundConstant) {
8257        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
8258            return;
8259        }
8260        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
8261    }
8262
8263    /**
8264     * BZZZTT!!1!
8265     *
8266     * <p>Provide haptic feedback to the user for this view.
8267     *
8268     * <p>The framework will provide haptic feedback for some built in actions,
8269     * such as long presses, but you may wish to provide feedback for your
8270     * own widget.
8271     *
8272     * <p>The feedback will only be performed if
8273     * {@link #isHapticFeedbackEnabled()} is true.
8274     *
8275     * @param feedbackConstant One of the constants defined in
8276     * {@link HapticFeedbackConstants}
8277     */
8278    public boolean performHapticFeedback(int feedbackConstant) {
8279        return performHapticFeedback(feedbackConstant, 0);
8280    }
8281
8282    /**
8283     * BZZZTT!!1!
8284     *
8285     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
8286     *
8287     * @param feedbackConstant One of the constants defined in
8288     * {@link HapticFeedbackConstants}
8289     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
8290     */
8291    public boolean performHapticFeedback(int feedbackConstant, int flags) {
8292        if (mAttachInfo == null) {
8293            return false;
8294        }
8295        if ((flags&HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
8296                && !isHapticFeedbackEnabled()) {
8297            return false;
8298        }
8299        return mAttachInfo.mRootCallbacks.performHapticFeedback(
8300                feedbackConstant,
8301                (flags&HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
8302    }
8303
8304    /**
8305     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
8306     * it is ever exposed at all.
8307     */
8308    public void onCloseSystemDialogs(String reason) {
8309    }
8310
8311    /**
8312     * Given a Drawable whose bounds have been set to draw into this view,
8313     * update a Region being computed for {@link #gatherTransparentRegion} so
8314     * that any non-transparent parts of the Drawable are removed from the
8315     * given transparent region.
8316     *
8317     * @param dr The Drawable whose transparency is to be applied to the region.
8318     * @param region A Region holding the current transparency information,
8319     * where any parts of the region that are set are considered to be
8320     * transparent.  On return, this region will be modified to have the
8321     * transparency information reduced by the corresponding parts of the
8322     * Drawable that are not transparent.
8323     * {@hide}
8324     */
8325    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
8326        if (DBG) {
8327            Log.i("View", "Getting transparent region for: " + this);
8328        }
8329        final Region r = dr.getTransparentRegion();
8330        final Rect db = dr.getBounds();
8331        final AttachInfo attachInfo = mAttachInfo;
8332        if (r != null && attachInfo != null) {
8333            final int w = getRight()-getLeft();
8334            final int h = getBottom()-getTop();
8335            if (db.left > 0) {
8336                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
8337                r.op(0, 0, db.left, h, Region.Op.UNION);
8338            }
8339            if (db.right < w) {
8340                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
8341                r.op(db.right, 0, w, h, Region.Op.UNION);
8342            }
8343            if (db.top > 0) {
8344                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
8345                r.op(0, 0, w, db.top, Region.Op.UNION);
8346            }
8347            if (db.bottom < h) {
8348                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
8349                r.op(0, db.bottom, w, h, Region.Op.UNION);
8350            }
8351            final int[] location = attachInfo.mTransparentLocation;
8352            getLocationInWindow(location);
8353            r.translate(location[0], location[1]);
8354            region.op(r, Region.Op.INTERSECT);
8355        } else {
8356            region.op(db, Region.Op.DIFFERENCE);
8357        }
8358    }
8359
8360    private void postCheckForLongClick() {
8361        mHasPerformedLongPress = false;
8362
8363        if (mPendingCheckForLongPress == null) {
8364            mPendingCheckForLongPress = new CheckForLongPress();
8365        }
8366        mPendingCheckForLongPress.rememberWindowAttachCount();
8367        postDelayed(mPendingCheckForLongPress, ViewConfiguration.getLongPressTimeout());
8368    }
8369
8370    private static int[] stateSetUnion(final int[] stateSet1,
8371                                       final int[] stateSet2) {
8372        final int stateSet1Length = stateSet1.length;
8373        final int stateSet2Length = stateSet2.length;
8374        final int[] newSet = new int[stateSet1Length + stateSet2Length];
8375        int k = 0;
8376        int i = 0;
8377        int j = 0;
8378        // This is a merge of the two input state sets and assumes that the
8379        // input sets are sorted by the order imposed by ViewDrawableStates.
8380        for (int viewState : R.styleable.ViewDrawableStates) {
8381            if (i < stateSet1Length && stateSet1[i] == viewState) {
8382                newSet[k++] = viewState;
8383                i++;
8384            } else if (j < stateSet2Length && stateSet2[j] == viewState) {
8385                newSet[k++] = viewState;
8386                j++;
8387            }
8388            if (k > 1) {
8389                assert(newSet[k - 1] > newSet[k - 2]);
8390            }
8391        }
8392        return newSet;
8393    }
8394
8395    /**
8396     * Inflate a view from an XML resource.  This convenience method wraps the {@link
8397     * LayoutInflater} class, which provides a full range of options for view inflation.
8398     *
8399     * @param context The Context object for your activity or application.
8400     * @param resource The resource ID to inflate
8401     * @param root A view group that will be the parent.  Used to properly inflate the
8402     * layout_* parameters.
8403     * @see LayoutInflater
8404     */
8405    public static View inflate(Context context, int resource, ViewGroup root) {
8406        LayoutInflater factory = LayoutInflater.from(context);
8407        return factory.inflate(resource, root);
8408    }
8409
8410    /**
8411     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
8412     * Each MeasureSpec represents a requirement for either the width or the height.
8413     * A MeasureSpec is comprised of a size and a mode. There are three possible
8414     * modes:
8415     * <dl>
8416     * <dt>UNSPECIFIED</dt>
8417     * <dd>
8418     * The parent has not imposed any constraint on the child. It can be whatever size
8419     * it wants.
8420     * </dd>
8421     *
8422     * <dt>EXACTLY</dt>
8423     * <dd>
8424     * The parent has determined an exact size for the child. The child is going to be
8425     * given those bounds regardless of how big it wants to be.
8426     * </dd>
8427     *
8428     * <dt>AT_MOST</dt>
8429     * <dd>
8430     * The child can be as large as it wants up to the specified size.
8431     * </dd>
8432     * </dl>
8433     *
8434     * MeasureSpecs are implemented as ints to reduce object allocation. This class
8435     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
8436     */
8437    public static class MeasureSpec {
8438        private static final int MODE_SHIFT = 30;
8439        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
8440
8441        /**
8442         * Measure specification mode: The parent has not imposed any constraint
8443         * on the child. It can be whatever size it wants.
8444         */
8445        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
8446
8447        /**
8448         * Measure specification mode: The parent has determined an exact size
8449         * for the child. The child is going to be given those bounds regardless
8450         * of how big it wants to be.
8451         */
8452        public static final int EXACTLY     = 1 << MODE_SHIFT;
8453
8454        /**
8455         * Measure specification mode: The child can be as large as it wants up
8456         * to the specified size.
8457         */
8458        public static final int AT_MOST     = 2 << MODE_SHIFT;
8459
8460        /**
8461         * Creates a measure specification based on the supplied size and mode.
8462         *
8463         * The mode must always be one of the following:
8464         * <ul>
8465         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
8466         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
8467         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
8468         * </ul>
8469         *
8470         * @param size the size of the measure specification
8471         * @param mode the mode of the measure specification
8472         * @return the measure specification based on size and mode
8473         */
8474        public static int makeMeasureSpec(int size, int mode) {
8475            return size + mode;
8476        }
8477
8478        /**
8479         * Extracts the mode from the supplied measure specification.
8480         *
8481         * @param measureSpec the measure specification to extract the mode from
8482         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
8483         *         {@link android.view.View.MeasureSpec#AT_MOST} or
8484         *         {@link android.view.View.MeasureSpec#EXACTLY}
8485         */
8486        public static int getMode(int measureSpec) {
8487            return (measureSpec & MODE_MASK);
8488        }
8489
8490        /**
8491         * Extracts the size from the supplied measure specification.
8492         *
8493         * @param measureSpec the measure specification to extract the size from
8494         * @return the size in pixels defined in the supplied measure specification
8495         */
8496        public static int getSize(int measureSpec) {
8497            return (measureSpec & ~MODE_MASK);
8498        }
8499
8500        /**
8501         * Returns a String representation of the specified measure
8502         * specification.
8503         *
8504         * @param measureSpec the measure specification to convert to a String
8505         * @return a String with the following format: "MeasureSpec: MODE SIZE"
8506         */
8507        public static String toString(int measureSpec) {
8508            int mode = getMode(measureSpec);
8509            int size = getSize(measureSpec);
8510
8511            StringBuilder sb = new StringBuilder("MeasureSpec: ");
8512
8513            if (mode == UNSPECIFIED)
8514                sb.append("UNSPECIFIED ");
8515            else if (mode == EXACTLY)
8516                sb.append("EXACTLY ");
8517            else if (mode == AT_MOST)
8518                sb.append("AT_MOST ");
8519            else
8520                sb.append(mode).append(" ");
8521
8522            sb.append(size);
8523            return sb.toString();
8524        }
8525    }
8526
8527    class CheckForLongPress implements Runnable {
8528
8529        private int mOriginalWindowAttachCount;
8530
8531        public void run() {
8532            if (isPressed() && (mParent != null)
8533                    && mOriginalWindowAttachCount == mWindowAttachCount) {
8534                if (performLongClick()) {
8535                    mHasPerformedLongPress = true;
8536                }
8537            }
8538        }
8539
8540        public void rememberWindowAttachCount() {
8541            mOriginalWindowAttachCount = mWindowAttachCount;
8542        }
8543    }
8544
8545    /**
8546     * Interface definition for a callback to be invoked when a key event is
8547     * dispatched to this view. The callback will be invoked before the key
8548     * event is given to the view.
8549     */
8550    public interface OnKeyListener {
8551        /**
8552         * Called when a key is dispatched to a view. This allows listeners to
8553         * get a chance to respond before the target view.
8554         *
8555         * @param v The view the key has been dispatched to.
8556         * @param keyCode The code for the physical key that was pressed
8557         * @param event The KeyEvent object containing full information about
8558         *        the event.
8559         * @return True if the listener has consumed the event, false otherwise.
8560         */
8561        boolean onKey(View v, int keyCode, KeyEvent event);
8562    }
8563
8564    /**
8565     * Interface definition for a callback to be invoked when a touch event is
8566     * dispatched to this view. The callback will be invoked before the touch
8567     * event is given to the view.
8568     */
8569    public interface OnTouchListener {
8570        /**
8571         * Called when a touch event is dispatched to a view. This allows listeners to
8572         * get a chance to respond before the target view.
8573         *
8574         * @param v The view the touch event has been dispatched to.
8575         * @param event The MotionEvent object containing full information about
8576         *        the event.
8577         * @return True if the listener has consumed the event, false otherwise.
8578         */
8579        boolean onTouch(View v, MotionEvent event);
8580    }
8581
8582    /**
8583     * Interface definition for a callback to be invoked when a view has been clicked and held.
8584     */
8585    public interface OnLongClickListener {
8586        /**
8587         * Called when a view has been clicked and held.
8588         *
8589         * @param v The view that was clicked and held.
8590         *
8591         * return True if the callback consumed the long click, false otherwise
8592         */
8593        boolean onLongClick(View v);
8594    }
8595
8596    /**
8597     * Interface definition for a callback to be invoked when the focus state of
8598     * a view changed.
8599     */
8600    public interface OnFocusChangeListener {
8601        /**
8602         * Called when the focus state of a view has changed.
8603         *
8604         * @param v The view whose state has changed.
8605         * @param hasFocus The new focus state of v.
8606         */
8607        void onFocusChange(View v, boolean hasFocus);
8608    }
8609
8610    /**
8611     * Interface definition for a callback to be invoked when a view is clicked.
8612     */
8613    public interface OnClickListener {
8614        /**
8615         * Called when a view has been clicked.
8616         *
8617         * @param v The view that was clicked.
8618         */
8619        void onClick(View v);
8620    }
8621
8622    /**
8623     * Interface definition for a callback to be invoked when the context menu
8624     * for this view is being built.
8625     */
8626    public interface OnCreateContextMenuListener {
8627        /**
8628         * Called when the context menu for this view is being built. It is not
8629         * safe to hold onto the menu after this method returns.
8630         *
8631         * @param menu The context menu that is being built
8632         * @param v The view for which the context menu is being built
8633         * @param menuInfo Extra information about the item for which the
8634         *            context menu should be shown. This information will vary
8635         *            depending on the class of v.
8636         */
8637        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
8638    }
8639
8640    private final class UnsetPressedState implements Runnable {
8641        public void run() {
8642            setPressed(false);
8643        }
8644    }
8645
8646    /**
8647     * Base class for derived classes that want to save and restore their own
8648     * state in {@link android.view.View#onSaveInstanceState()}.
8649     */
8650    public static class BaseSavedState extends AbsSavedState {
8651        /**
8652         * Constructor used when reading from a parcel. Reads the state of the superclass.
8653         *
8654         * @param source
8655         */
8656        public BaseSavedState(Parcel source) {
8657            super(source);
8658        }
8659
8660        /**
8661         * Constructor called by derived classes when creating their SavedState objects
8662         *
8663         * @param superState The state of the superclass of this view
8664         */
8665        public BaseSavedState(Parcelable superState) {
8666            super(superState);
8667        }
8668
8669        public static final Parcelable.Creator<BaseSavedState> CREATOR =
8670                new Parcelable.Creator<BaseSavedState>() {
8671            public BaseSavedState createFromParcel(Parcel in) {
8672                return new BaseSavedState(in);
8673            }
8674
8675            public BaseSavedState[] newArray(int size) {
8676                return new BaseSavedState[size];
8677            }
8678        };
8679    }
8680
8681    /**
8682     * A set of information given to a view when it is attached to its parent
8683     * window.
8684     */
8685    static class AttachInfo {
8686        interface Callbacks {
8687            void playSoundEffect(int effectId);
8688            boolean performHapticFeedback(int effectId, boolean always);
8689        }
8690
8691        /**
8692         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
8693         * to a Handler. This class contains the target (View) to invalidate and
8694         * the coordinates of the dirty rectangle.
8695         *
8696         * For performance purposes, this class also implements a pool of up to
8697         * POOL_LIMIT objects that get reused. This reduces memory allocations
8698         * whenever possible.
8699         */
8700        static class InvalidateInfo implements Poolable<InvalidateInfo> {
8701            private static final int POOL_LIMIT = 10;
8702            private static final Pool<InvalidateInfo> sPool = Pools.synchronizedPool(
8703                    Pools.finitePool(new PoolableManager<InvalidateInfo>() {
8704                        public InvalidateInfo newInstance() {
8705                            return new InvalidateInfo();
8706                        }
8707
8708                        public void onAcquired(InvalidateInfo element) {
8709                        }
8710
8711                        public void onReleased(InvalidateInfo element) {
8712                        }
8713                    }, POOL_LIMIT)
8714            );
8715
8716            private InvalidateInfo mNext;
8717
8718            View target;
8719
8720            int left;
8721            int top;
8722            int right;
8723            int bottom;
8724
8725            public void setNextPoolable(InvalidateInfo element) {
8726                mNext = element;
8727            }
8728
8729            public InvalidateInfo getNextPoolable() {
8730                return mNext;
8731            }
8732
8733            static InvalidateInfo acquire() {
8734                return sPool.acquire();
8735            }
8736
8737            void release() {
8738                sPool.release(this);
8739            }
8740        }
8741
8742        final IWindowSession mSession;
8743
8744        final IWindow mWindow;
8745
8746        final IBinder mWindowToken;
8747
8748        final Callbacks mRootCallbacks;
8749
8750        /**
8751         * The top view of the hierarchy.
8752         */
8753        View mRootView;
8754
8755        IBinder mPanelParentWindowToken;
8756        Surface mSurface;
8757
8758        /**
8759         * Scale factor used by the compatibility mode
8760         */
8761        float mApplicationScale;
8762
8763        /**
8764         * Indicates whether the application is in compatibility mode
8765         */
8766        boolean mScalingRequired;
8767
8768        /**
8769         * Left position of this view's window
8770         */
8771        int mWindowLeft;
8772
8773        /**
8774         * Top position of this view's window
8775         */
8776        int mWindowTop;
8777
8778        /**
8779         * For windows that are full-screen but using insets to layout inside
8780         * of the screen decorations, these are the current insets for the
8781         * content of the window.
8782         */
8783        final Rect mContentInsets = new Rect();
8784
8785        /**
8786         * For windows that are full-screen but using insets to layout inside
8787         * of the screen decorations, these are the current insets for the
8788         * actual visible parts of the window.
8789         */
8790        final Rect mVisibleInsets = new Rect();
8791
8792        /**
8793         * The internal insets given by this window.  This value is
8794         * supplied by the client (through
8795         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
8796         * be given to the window manager when changed to be used in laying
8797         * out windows behind it.
8798         */
8799        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
8800                = new ViewTreeObserver.InternalInsetsInfo();
8801
8802        /**
8803         * All views in the window's hierarchy that serve as scroll containers,
8804         * used to determine if the window can be resized or must be panned
8805         * to adjust for a soft input area.
8806         */
8807        final ArrayList<View> mScrollContainers = new ArrayList<View>();
8808
8809        final KeyEvent.DispatcherState mKeyDispatchState
8810                = new KeyEvent.DispatcherState();
8811
8812        /**
8813         * Indicates whether the view's window currently has the focus.
8814         */
8815        boolean mHasWindowFocus;
8816
8817        /**
8818         * The current visibility of the window.
8819         */
8820        int mWindowVisibility;
8821
8822        /**
8823         * Indicates the time at which drawing started to occur.
8824         */
8825        long mDrawingTime;
8826
8827        /**
8828         * Indicates whether or not ignoring the DIRTY_MASK flags.
8829         */
8830        boolean mIgnoreDirtyState;
8831
8832        /**
8833         * Indicates whether the view's window is currently in touch mode.
8834         */
8835        boolean mInTouchMode;
8836
8837        /**
8838         * Indicates that ViewRoot should trigger a global layout change
8839         * the next time it performs a traversal
8840         */
8841        boolean mRecomputeGlobalAttributes;
8842
8843        /**
8844         * Set to true when attributes (like mKeepScreenOn) need to be
8845         * recomputed.
8846         */
8847        boolean mAttributesChanged;
8848
8849        /**
8850         * Set during a traveral if any views want to keep the screen on.
8851         */
8852        boolean mKeepScreenOn;
8853
8854        /**
8855         * Set if the visibility of any views has changed.
8856         */
8857        boolean mViewVisibilityChanged;
8858
8859        /**
8860         * Set to true if a view has been scrolled.
8861         */
8862        boolean mViewScrollChanged;
8863
8864        /**
8865         * Global to the view hierarchy used as a temporary for dealing with
8866         * x/y points in the transparent region computations.
8867         */
8868        final int[] mTransparentLocation = new int[2];
8869
8870        /**
8871         * Global to the view hierarchy used as a temporary for dealing with
8872         * x/y points in the ViewGroup.invalidateChild implementation.
8873         */
8874        final int[] mInvalidateChildLocation = new int[2];
8875
8876        /**
8877         * The view tree observer used to dispatch global events like
8878         * layout, pre-draw, touch mode change, etc.
8879         */
8880        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
8881
8882        /**
8883         * A Canvas used by the view hierarchy to perform bitmap caching.
8884         */
8885        Canvas mCanvas;
8886
8887        /**
8888         * A Handler supplied by a view's {@link android.view.ViewRoot}. This
8889         * handler can be used to pump events in the UI events queue.
8890         */
8891        final Handler mHandler;
8892
8893        /**
8894         * Identifier for messages requesting the view to be invalidated.
8895         * Such messages should be sent to {@link #mHandler}.
8896         */
8897        static final int INVALIDATE_MSG = 0x1;
8898
8899        /**
8900         * Identifier for messages requesting the view to invalidate a region.
8901         * Such messages should be sent to {@link #mHandler}.
8902         */
8903        static final int INVALIDATE_RECT_MSG = 0x2;
8904
8905        /**
8906         * Temporary for use in computing invalidate rectangles while
8907         * calling up the hierarchy.
8908         */
8909        final Rect mTmpInvalRect = new Rect();
8910
8911        /**
8912         * Temporary list for use in collecting focusable descendents of a view.
8913         */
8914        final ArrayList<View> mFocusablesTempList = new ArrayList<View>(24);
8915
8916        /**
8917         * Creates a new set of attachment information with the specified
8918         * events handler and thread.
8919         *
8920         * @param handler the events handler the view must use
8921         */
8922        AttachInfo(IWindowSession session, IWindow window,
8923                Handler handler, Callbacks effectPlayer) {
8924            mSession = session;
8925            mWindow = window;
8926            mWindowToken = window.asBinder();
8927            mHandler = handler;
8928            mRootCallbacks = effectPlayer;
8929        }
8930    }
8931
8932    /**
8933     * <p>ScrollabilityCache holds various fields used by a View when scrolling
8934     * is supported. This avoids keeping too many unused fields in most
8935     * instances of View.</p>
8936     */
8937    private static class ScrollabilityCache implements Runnable {
8938
8939        /**
8940         * Scrollbars are not visible
8941         */
8942        public static final int OFF = 0;
8943
8944        /**
8945         * Scrollbars are visible
8946         */
8947        public static final int ON = 1;
8948
8949        /**
8950         * Scrollbars are fading away
8951         */
8952        public static final int FADING = 2;
8953
8954        public boolean fadeScrollBars;
8955
8956        public int fadingEdgeLength;
8957        public int scrollBarDefaultDelayBeforeFade;
8958        public int scrollBarFadeDuration;
8959
8960        public int scrollBarSize;
8961        public ScrollBarDrawable scrollBar;
8962        public float[] interpolatorValues;
8963        public View host;
8964
8965        public final Paint paint;
8966        public final Matrix matrix;
8967        public Shader shader;
8968
8969        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
8970
8971        private final float[] mOpaque = {255.0f};
8972        private final float[] mTransparent = {0.0f};
8973
8974        /**
8975         * When fading should start. This time moves into the future every time
8976         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
8977         */
8978        public long fadeStartTime;
8979
8980
8981        /**
8982         * The current state of the scrollbars: ON, OFF, or FADING
8983         */
8984        public int state = OFF;
8985
8986        private int mLastColor;
8987
8988        public ScrollabilityCache(ViewConfiguration configuration, View host) {
8989            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
8990            scrollBarSize = configuration.getScaledScrollBarSize();
8991            scrollBarDefaultDelayBeforeFade = configuration.getScrollDefaultDelay();
8992            scrollBarFadeDuration = configuration.getScrollBarFadeDuration();
8993
8994            paint = new Paint();
8995            matrix = new Matrix();
8996            // use use a height of 1, and then wack the matrix each time we
8997            // actually use it.
8998            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
8999
9000            paint.setShader(shader);
9001            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
9002            this.host = host;
9003        }
9004
9005        public void setFadeColor(int color) {
9006            if (color != 0 && color != mLastColor) {
9007                mLastColor = color;
9008                color |= 0xFF000000;
9009
9010                shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
9011                        color & 0x00FFFFFF, Shader.TileMode.CLAMP);
9012
9013                paint.setShader(shader);
9014                // Restore the default transfer mode (src_over)
9015                paint.setXfermode(null);
9016            }
9017        }
9018
9019        public void run() {
9020            long now = AnimationUtils.currentAnimationTimeMillis();
9021            if (now >= fadeStartTime) {
9022
9023                // the animation fades the scrollbars out by changing
9024                // the opacity (alpha) from fully opaque to fully
9025                // transparent
9026                int nextFrame = (int) now;
9027                int framesCount = 0;
9028
9029                Interpolator interpolator = scrollBarInterpolator;
9030
9031                // Start opaque
9032                interpolator.setKeyFrame(framesCount++, nextFrame, mOpaque);
9033
9034                // End transparent
9035                nextFrame += scrollBarFadeDuration;
9036                interpolator.setKeyFrame(framesCount, nextFrame, mTransparent);
9037
9038                state = FADING;
9039
9040                // Kick off the fade animation
9041                host.invalidate();
9042            }
9043        }
9044
9045    }
9046}
9047