View.java revision 3ecd58c650371206008efd687933c370e4e28a34
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. (See {@link #mScrollX} and {@link #mScrollY})</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 #mScrollX
4735     * @see #mScrollY
4736     * @see #scrollBy(int, int)
4737     * @see #scrollTo(int, int)
4738     * @see #isHorizontalScrollBarEnabled()
4739     * @see #isVerticalScrollBarEnabled()
4740     * @see #setHorizontalScrollBarEnabled(boolean)
4741     * @see #setVerticalScrollBarEnabled(boolean)
4742     */
4743    protected boolean awakenScrollBars() {
4744        return mScrollCache != null &&
4745                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade);
4746    }
4747
4748    /**
4749     * <p>
4750     * Trigger the scrollbars to draw. When invoked this method starts an
4751     * animation to fade the scrollbars out after a fixed delay. If a subclass
4752     * provides animated scrolling, the start delay should equal the duration of
4753     * the scrolling animation.
4754     * </p>
4755     *
4756     * <p>
4757     * The animation starts only if at least one of the scrollbars is enabled,
4758     * as specified by {@link #isHorizontalScrollBarEnabled()} and
4759     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
4760     * this method returns true, and false otherwise. If the animation is
4761     * started, this method calls {@link #invalidate()}; in that case the caller
4762     * should not call {@link #invalidate()}.
4763     * </p>
4764     *
4765     * <p>
4766     * This method should be invoked everytime a subclass directly updates the
4767     * scroll parameters. (See {@link #mScrollX} and {@link #mScrollY})
4768     * </p>
4769     *
4770     * @param startDelay the delay, in milliseconds, after which the animation
4771     *        should start; when the delay is 0, the animation starts
4772     *        immediately
4773     * @return true if the animation is played, false otherwise
4774     *
4775     * @see #mScrollX
4776     * @see #mScrollY
4777     * @see #scrollBy(int, int)
4778     * @see #scrollTo(int, int)
4779     * @see #isHorizontalScrollBarEnabled()
4780     * @see #isVerticalScrollBarEnabled()
4781     * @see #setHorizontalScrollBarEnabled(boolean)
4782     * @see #setVerticalScrollBarEnabled(boolean)
4783     */
4784    protected boolean awakenScrollBars(int startDelay) {
4785        final ScrollabilityCache scrollCache = mScrollCache;
4786
4787        if (scrollCache == null || !scrollCache.fadeScrollBars) {
4788            return false;
4789        }
4790
4791        if (scrollCache.scrollBar == null) {
4792            scrollCache.scrollBar = new ScrollBarDrawable();
4793        }
4794
4795        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
4796
4797            // Invalidate to show the scrollbars
4798            invalidate();
4799
4800            if (scrollCache.state == ScrollabilityCache.OFF) {
4801                // FIXME: this is copied from WindowManagerService.
4802                // We should get this value from the system when it
4803                // is possible to do so.
4804                final int KEY_REPEAT_FIRST_DELAY = 750;
4805                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
4806            }
4807
4808            // Tell mScrollCache when we should start fading. This may
4809            // extend the fade start time if one was already scheduled
4810            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
4811            scrollCache.fadeStartTime = fadeStartTime;
4812            scrollCache.state = ScrollabilityCache.ON;
4813
4814            // Schedule our fader to run, unscheduling any old ones first
4815            if (mAttachInfo != null) {
4816                mAttachInfo.mHandler.removeCallbacks(scrollCache);
4817                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
4818            }
4819
4820            return true;
4821        }
4822
4823        return false;
4824    }
4825
4826    /**
4827     * Mark the the area defined by dirty as needing to be drawn. If the view is
4828     * visible, {@link #onDraw} will be called at some point in the future.
4829     * This must be called from a UI thread. To call from a non-UI thread, call
4830     * {@link #postInvalidate()}.
4831     *
4832     * WARNING: This method is destructive to dirty.
4833     * @param dirty the rectangle representing the bounds of the dirty region
4834     */
4835    public void invalidate(Rect dirty) {
4836        if (ViewDebug.TRACE_HIERARCHY) {
4837            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
4838        }
4839
4840        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) {
4841            mPrivateFlags &= ~DRAWING_CACHE_VALID;
4842            final ViewParent p = mParent;
4843            final AttachInfo ai = mAttachInfo;
4844            if (p != null && ai != null) {
4845                final int scrollX = mScrollX;
4846                final int scrollY = mScrollY;
4847                final Rect r = ai.mTmpInvalRect;
4848                r.set(dirty.left - scrollX, dirty.top - scrollY,
4849                        dirty.right - scrollX, dirty.bottom - scrollY);
4850                mParent.invalidateChild(this, r);
4851            }
4852        }
4853    }
4854
4855    /**
4856     * Mark the the area defined by the rect (l,t,r,b) as needing to be drawn.
4857     * The coordinates of the dirty rect are relative to the view.
4858     * If the view is visible, {@link #onDraw} will be called at some point
4859     * in the future. This must be called from a UI thread. To call
4860     * from a non-UI thread, call {@link #postInvalidate()}.
4861     * @param l the left position of the dirty region
4862     * @param t the top position of the dirty region
4863     * @param r the right position of the dirty region
4864     * @param b the bottom position of the dirty region
4865     */
4866    public void invalidate(int l, int t, int r, int b) {
4867        if (ViewDebug.TRACE_HIERARCHY) {
4868            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
4869        }
4870
4871        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) {
4872            mPrivateFlags &= ~DRAWING_CACHE_VALID;
4873            final ViewParent p = mParent;
4874            final AttachInfo ai = mAttachInfo;
4875            if (p != null && ai != null && l < r && t < b) {
4876                final int scrollX = mScrollX;
4877                final int scrollY = mScrollY;
4878                final Rect tmpr = ai.mTmpInvalRect;
4879                tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY);
4880                p.invalidateChild(this, tmpr);
4881            }
4882        }
4883    }
4884
4885    /**
4886     * Invalidate the whole view. If the view is visible, {@link #onDraw} will
4887     * be called at some point in the future. This must be called from a
4888     * UI thread. To call from a non-UI thread, call {@link #postInvalidate()}.
4889     */
4890    public void invalidate() {
4891        if (ViewDebug.TRACE_HIERARCHY) {
4892            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
4893        }
4894
4895        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) {
4896            mPrivateFlags &= ~DRAWN & ~DRAWING_CACHE_VALID;
4897            final ViewParent p = mParent;
4898            final AttachInfo ai = mAttachInfo;
4899            if (p != null && ai != null) {
4900                final Rect r = ai.mTmpInvalRect;
4901                r.set(0, 0, mRight - mLeft, mBottom - mTop);
4902                // Don't call invalidate -- we don't want to internally scroll
4903                // our own bounds
4904                p.invalidateChild(this, r);
4905            }
4906        }
4907    }
4908
4909    /**
4910     * Indicates whether this View is opaque. An opaque View guarantees that it will
4911     * draw all the pixels overlapping its bounds using a fully opaque color.
4912     *
4913     * Subclasses of View should override this method whenever possible to indicate
4914     * whether an instance is opaque. Opaque Views are treated in a special way by
4915     * the View hierarchy, possibly allowing it to perform optimizations during
4916     * invalidate/draw passes.
4917     *
4918     * @return True if this View is guaranteed to be fully opaque, false otherwise.
4919     *
4920     * @hide Pending API council approval
4921     */
4922    @ViewDebug.ExportedProperty
4923    public boolean isOpaque() {
4924        return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK;
4925    }
4926
4927    private void computeOpaqueFlags() {
4928        // Opaque if:
4929        //   - Has a background
4930        //   - Background is opaque
4931        //   - Doesn't have scrollbars or scrollbars are inside overlay
4932
4933        if (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE) {
4934            mPrivateFlags |= OPAQUE_BACKGROUND;
4935        } else {
4936            mPrivateFlags &= ~OPAQUE_BACKGROUND;
4937        }
4938
4939        final int flags = mViewFlags;
4940        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
4941                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) {
4942            mPrivateFlags |= OPAQUE_SCROLLBARS;
4943        } else {
4944            mPrivateFlags &= ~OPAQUE_SCROLLBARS;
4945        }
4946    }
4947
4948    /**
4949     * @hide
4950     */
4951    protected boolean hasOpaqueScrollbars() {
4952        return (mPrivateFlags & OPAQUE_SCROLLBARS) == OPAQUE_SCROLLBARS;
4953    }
4954
4955    /**
4956     * @return A handler associated with the thread running the View. This
4957     * handler can be used to pump events in the UI events queue.
4958     */
4959    public Handler getHandler() {
4960        if (mAttachInfo != null) {
4961            return mAttachInfo.mHandler;
4962        }
4963        return null;
4964    }
4965
4966    /**
4967     * Causes the Runnable to be added to the message queue.
4968     * The runnable will be run on the user interface thread.
4969     *
4970     * @param action The Runnable that will be executed.
4971     *
4972     * @return Returns true if the Runnable was successfully placed in to the
4973     *         message queue.  Returns false on failure, usually because the
4974     *         looper processing the message queue is exiting.
4975     */
4976    public boolean post(Runnable action) {
4977        Handler handler;
4978        if (mAttachInfo != null) {
4979            handler = mAttachInfo.mHandler;
4980        } else {
4981            // Assume that post will succeed later
4982            ViewRoot.getRunQueue().post(action);
4983            return true;
4984        }
4985
4986        return handler.post(action);
4987    }
4988
4989    /**
4990     * Causes the Runnable to be added to the message queue, to be run
4991     * after the specified amount of time elapses.
4992     * The runnable will be run on the user interface thread.
4993     *
4994     * @param action The Runnable that will be executed.
4995     * @param delayMillis The delay (in milliseconds) until the Runnable
4996     *        will be executed.
4997     *
4998     * @return true if the Runnable was successfully placed in to the
4999     *         message queue.  Returns false on failure, usually because the
5000     *         looper processing the message queue is exiting.  Note that a
5001     *         result of true does not mean the Runnable will be processed --
5002     *         if the looper is quit before the delivery time of the message
5003     *         occurs then the message will be dropped.
5004     */
5005    public boolean postDelayed(Runnable action, long delayMillis) {
5006        Handler handler;
5007        if (mAttachInfo != null) {
5008            handler = mAttachInfo.mHandler;
5009        } else {
5010            // Assume that post will succeed later
5011            ViewRoot.getRunQueue().postDelayed(action, delayMillis);
5012            return true;
5013        }
5014
5015        return handler.postDelayed(action, delayMillis);
5016    }
5017
5018    /**
5019     * Removes the specified Runnable from the message queue.
5020     *
5021     * @param action The Runnable to remove from the message handling queue
5022     *
5023     * @return true if this view could ask the Handler to remove the Runnable,
5024     *         false otherwise. When the returned value is true, the Runnable
5025     *         may or may not have been actually removed from the message queue
5026     *         (for instance, if the Runnable was not in the queue already.)
5027     */
5028    public boolean removeCallbacks(Runnable action) {
5029        Handler handler;
5030        if (mAttachInfo != null) {
5031            handler = mAttachInfo.mHandler;
5032        } else {
5033            // Assume that post will succeed later
5034            ViewRoot.getRunQueue().removeCallbacks(action);
5035            return true;
5036        }
5037
5038        handler.removeCallbacks(action);
5039        return true;
5040    }
5041
5042    /**
5043     * Cause an invalidate to happen on a subsequent cycle through the event loop.
5044     * Use this to invalidate the View from a non-UI thread.
5045     *
5046     * @see #invalidate()
5047     */
5048    public void postInvalidate() {
5049        postInvalidateDelayed(0);
5050    }
5051
5052    /**
5053     * Cause an invalidate of the specified area to happen on a subsequent cycle
5054     * through the event loop. Use this to invalidate the View from a non-UI thread.
5055     *
5056     * @param left The left coordinate of the rectangle to invalidate.
5057     * @param top The top coordinate of the rectangle to invalidate.
5058     * @param right The right coordinate of the rectangle to invalidate.
5059     * @param bottom The bottom coordinate of the rectangle to invalidate.
5060     *
5061     * @see #invalidate(int, int, int, int)
5062     * @see #invalidate(Rect)
5063     */
5064    public void postInvalidate(int left, int top, int right, int bottom) {
5065        postInvalidateDelayed(0, left, top, right, bottom);
5066    }
5067
5068    /**
5069     * Cause an invalidate to happen on a subsequent cycle through the event
5070     * loop. Waits for the specified amount of time.
5071     *
5072     * @param delayMilliseconds the duration in milliseconds to delay the
5073     *         invalidation by
5074     */
5075    public void postInvalidateDelayed(long delayMilliseconds) {
5076        // We try only with the AttachInfo because there's no point in invalidating
5077        // if we are not attached to our window
5078        if (mAttachInfo != null) {
5079            Message msg = Message.obtain();
5080            msg.what = AttachInfo.INVALIDATE_MSG;
5081            msg.obj = this;
5082            mAttachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
5083        }
5084    }
5085
5086    /**
5087     * Cause an invalidate of the specified area to happen on a subsequent cycle
5088     * through the event loop. Waits for the specified amount of time.
5089     *
5090     * @param delayMilliseconds the duration in milliseconds to delay the
5091     *         invalidation by
5092     * @param left The left coordinate of the rectangle to invalidate.
5093     * @param top The top coordinate of the rectangle to invalidate.
5094     * @param right The right coordinate of the rectangle to invalidate.
5095     * @param bottom The bottom coordinate of the rectangle to invalidate.
5096     */
5097    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
5098            int right, int bottom) {
5099
5100        // We try only with the AttachInfo because there's no point in invalidating
5101        // if we are not attached to our window
5102        if (mAttachInfo != null) {
5103            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
5104            info.target = this;
5105            info.left = left;
5106            info.top = top;
5107            info.right = right;
5108            info.bottom = bottom;
5109
5110            final Message msg = Message.obtain();
5111            msg.what = AttachInfo.INVALIDATE_RECT_MSG;
5112            msg.obj = info;
5113            mAttachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
5114        }
5115    }
5116
5117    /**
5118     * Called by a parent to request that a child update its values for mScrollX
5119     * and mScrollY if necessary. This will typically be done if the child is
5120     * animating a scroll using a {@link android.widget.Scroller Scroller}
5121     * object.
5122     */
5123    public void computeScroll() {
5124    }
5125
5126    /**
5127     * <p>Indicate whether the horizontal edges are faded when the view is
5128     * scrolled horizontally.</p>
5129     *
5130     * @return true if the horizontal edges should are faded on scroll, false
5131     *         otherwise
5132     *
5133     * @see #setHorizontalFadingEdgeEnabled(boolean)
5134     * @attr ref android.R.styleable#View_fadingEdge
5135     */
5136    public boolean isHorizontalFadingEdgeEnabled() {
5137        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
5138    }
5139
5140    /**
5141     * <p>Define whether the horizontal edges should be faded when this view
5142     * is scrolled horizontally.</p>
5143     *
5144     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
5145     *                                    be faded when the view is scrolled
5146     *                                    horizontally
5147     *
5148     * @see #isHorizontalFadingEdgeEnabled()
5149     * @attr ref android.R.styleable#View_fadingEdge
5150     */
5151    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
5152        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
5153            if (horizontalFadingEdgeEnabled) {
5154                initScrollCache();
5155            }
5156
5157            mViewFlags ^= FADING_EDGE_HORIZONTAL;
5158        }
5159    }
5160
5161    /**
5162     * <p>Indicate whether the vertical edges are faded when the view is
5163     * scrolled horizontally.</p>
5164     *
5165     * @return true if the vertical edges should are faded on scroll, false
5166     *         otherwise
5167     *
5168     * @see #setVerticalFadingEdgeEnabled(boolean)
5169     * @attr ref android.R.styleable#View_fadingEdge
5170     */
5171    public boolean isVerticalFadingEdgeEnabled() {
5172        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
5173    }
5174
5175    /**
5176     * <p>Define whether the vertical edges should be faded when this view
5177     * is scrolled vertically.</p>
5178     *
5179     * @param verticalFadingEdgeEnabled true if the vertical edges should
5180     *                                  be faded when the view is scrolled
5181     *                                  vertically
5182     *
5183     * @see #isVerticalFadingEdgeEnabled()
5184     * @attr ref android.R.styleable#View_fadingEdge
5185     */
5186    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
5187        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
5188            if (verticalFadingEdgeEnabled) {
5189                initScrollCache();
5190            }
5191
5192            mViewFlags ^= FADING_EDGE_VERTICAL;
5193        }
5194    }
5195
5196    /**
5197     * Returns the strength, or intensity, of the top faded edge. The strength is
5198     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
5199     * returns 0.0 or 1.0 but no value in between.
5200     *
5201     * Subclasses should override this method to provide a smoother fade transition
5202     * when scrolling occurs.
5203     *
5204     * @return the intensity of the top fade as a float between 0.0f and 1.0f
5205     */
5206    protected float getTopFadingEdgeStrength() {
5207        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
5208    }
5209
5210    /**
5211     * Returns the strength, or intensity, of the bottom faded edge. The strength is
5212     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
5213     * returns 0.0 or 1.0 but no value in between.
5214     *
5215     * Subclasses should override this method to provide a smoother fade transition
5216     * when scrolling occurs.
5217     *
5218     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
5219     */
5220    protected float getBottomFadingEdgeStrength() {
5221        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
5222                computeVerticalScrollRange() ? 1.0f : 0.0f;
5223    }
5224
5225    /**
5226     * Returns the strength, or intensity, of the left faded edge. The strength is
5227     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
5228     * returns 0.0 or 1.0 but no value in between.
5229     *
5230     * Subclasses should override this method to provide a smoother fade transition
5231     * when scrolling occurs.
5232     *
5233     * @return the intensity of the left fade as a float between 0.0f and 1.0f
5234     */
5235    protected float getLeftFadingEdgeStrength() {
5236        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
5237    }
5238
5239    /**
5240     * Returns the strength, or intensity, of the right faded edge. The strength is
5241     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
5242     * returns 0.0 or 1.0 but no value in between.
5243     *
5244     * Subclasses should override this method to provide a smoother fade transition
5245     * when scrolling occurs.
5246     *
5247     * @return the intensity of the right fade as a float between 0.0f and 1.0f
5248     */
5249    protected float getRightFadingEdgeStrength() {
5250        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
5251                computeHorizontalScrollRange() ? 1.0f : 0.0f;
5252    }
5253
5254    /**
5255     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
5256     * scrollbar is not drawn by default.</p>
5257     *
5258     * @return true if the horizontal scrollbar should be painted, false
5259     *         otherwise
5260     *
5261     * @see #setHorizontalScrollBarEnabled(boolean)
5262     */
5263    public boolean isHorizontalScrollBarEnabled() {
5264        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
5265    }
5266
5267    /**
5268     * <p>Define whether the horizontal scrollbar should be drawn or not. The
5269     * scrollbar is not drawn by default.</p>
5270     *
5271     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
5272     *                                   be painted
5273     *
5274     * @see #isHorizontalScrollBarEnabled()
5275     */
5276    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
5277        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
5278            mViewFlags ^= SCROLLBARS_HORIZONTAL;
5279            computeOpaqueFlags();
5280            recomputePadding();
5281        }
5282    }
5283
5284    /**
5285     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
5286     * scrollbar is not drawn by default.</p>
5287     *
5288     * @return true if the vertical scrollbar should be painted, false
5289     *         otherwise
5290     *
5291     * @see #setVerticalScrollBarEnabled(boolean)
5292     */
5293    public boolean isVerticalScrollBarEnabled() {
5294        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
5295    }
5296
5297    /**
5298     * <p>Define whether the vertical scrollbar should be drawn or not. The
5299     * scrollbar is not drawn by default.</p>
5300     *
5301     * @param verticalScrollBarEnabled true if the vertical scrollbar should
5302     *                                 be painted
5303     *
5304     * @see #isVerticalScrollBarEnabled()
5305     */
5306    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
5307        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
5308            mViewFlags ^= SCROLLBARS_VERTICAL;
5309            computeOpaqueFlags();
5310            recomputePadding();
5311        }
5312    }
5313
5314    private void recomputePadding() {
5315        setPadding(mPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
5316    }
5317
5318    /**
5319     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
5320     * inset. When inset, they add to the padding of the view. And the scrollbars
5321     * can be drawn inside the padding area or on the edge of the view. For example,
5322     * if a view has a background drawable and you want to draw the scrollbars
5323     * inside the padding specified by the drawable, you can use
5324     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
5325     * appear at the edge of the view, ignoring the padding, then you can use
5326     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
5327     * @param style the style of the scrollbars. Should be one of
5328     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
5329     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
5330     * @see #SCROLLBARS_INSIDE_OVERLAY
5331     * @see #SCROLLBARS_INSIDE_INSET
5332     * @see #SCROLLBARS_OUTSIDE_OVERLAY
5333     * @see #SCROLLBARS_OUTSIDE_INSET
5334     */
5335    public void setScrollBarStyle(int style) {
5336        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
5337            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
5338            computeOpaqueFlags();
5339            recomputePadding();
5340        }
5341    }
5342
5343    /**
5344     * <p>Returns the current scrollbar style.</p>
5345     * @return the current scrollbar style
5346     * @see #SCROLLBARS_INSIDE_OVERLAY
5347     * @see #SCROLLBARS_INSIDE_INSET
5348     * @see #SCROLLBARS_OUTSIDE_OVERLAY
5349     * @see #SCROLLBARS_OUTSIDE_INSET
5350     */
5351    public int getScrollBarStyle() {
5352        return mViewFlags & SCROLLBARS_STYLE_MASK;
5353    }
5354
5355    /**
5356     * <p>Compute the horizontal range that the horizontal scrollbar
5357     * represents.</p>
5358     *
5359     * <p>The range is expressed in arbitrary units that must be the same as the
5360     * units used by {@link #computeHorizontalScrollExtent()} and
5361     * {@link #computeHorizontalScrollOffset()}.</p>
5362     *
5363     * <p>The default range is the drawing width of this view.</p>
5364     *
5365     * @return the total horizontal range represented by the horizontal
5366     *         scrollbar
5367     *
5368     * @see #computeHorizontalScrollExtent()
5369     * @see #computeHorizontalScrollOffset()
5370     * @see android.widget.ScrollBarDrawable
5371     */
5372    protected int computeHorizontalScrollRange() {
5373        return getWidth();
5374    }
5375
5376    /**
5377     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
5378     * within the horizontal range. This value is used to compute the position
5379     * of the thumb within the scrollbar's track.</p>
5380     *
5381     * <p>The range is expressed in arbitrary units that must be the same as the
5382     * units used by {@link #computeHorizontalScrollRange()} and
5383     * {@link #computeHorizontalScrollExtent()}.</p>
5384     *
5385     * <p>The default offset is the scroll offset of this view.</p>
5386     *
5387     * @return the horizontal offset of the scrollbar's thumb
5388     *
5389     * @see #computeHorizontalScrollRange()
5390     * @see #computeHorizontalScrollExtent()
5391     * @see android.widget.ScrollBarDrawable
5392     */
5393    protected int computeHorizontalScrollOffset() {
5394        return mScrollX;
5395    }
5396
5397    /**
5398     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
5399     * within the horizontal range. This value is used to compute the length
5400     * of the thumb within the scrollbar's track.</p>
5401     *
5402     * <p>The range is expressed in arbitrary units that must be the same as the
5403     * units used by {@link #computeHorizontalScrollRange()} and
5404     * {@link #computeHorizontalScrollOffset()}.</p>
5405     *
5406     * <p>The default extent is the drawing width of this view.</p>
5407     *
5408     * @return the horizontal extent of the scrollbar's thumb
5409     *
5410     * @see #computeHorizontalScrollRange()
5411     * @see #computeHorizontalScrollOffset()
5412     * @see android.widget.ScrollBarDrawable
5413     */
5414    protected int computeHorizontalScrollExtent() {
5415        return getWidth();
5416    }
5417
5418    /**
5419     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
5420     *
5421     * <p>The range is expressed in arbitrary units that must be the same as the
5422     * units used by {@link #computeVerticalScrollExtent()} and
5423     * {@link #computeVerticalScrollOffset()}.</p>
5424     *
5425     * @return the total vertical range represented by the vertical scrollbar
5426     *
5427     * <p>The default range is the drawing height of this view.</p>
5428     *
5429     * @see #computeVerticalScrollExtent()
5430     * @see #computeVerticalScrollOffset()
5431     * @see android.widget.ScrollBarDrawable
5432     */
5433    protected int computeVerticalScrollRange() {
5434        return getHeight();
5435    }
5436
5437    /**
5438     * <p>Compute the vertical offset of the vertical scrollbar's thumb
5439     * within the horizontal range. This value is used to compute the position
5440     * of the thumb within the scrollbar's track.</p>
5441     *
5442     * <p>The range is expressed in arbitrary units that must be the same as the
5443     * units used by {@link #computeVerticalScrollRange()} and
5444     * {@link #computeVerticalScrollExtent()}.</p>
5445     *
5446     * <p>The default offset is the scroll offset of this view.</p>
5447     *
5448     * @return the vertical offset of the scrollbar's thumb
5449     *
5450     * @see #computeVerticalScrollRange()
5451     * @see #computeVerticalScrollExtent()
5452     * @see android.widget.ScrollBarDrawable
5453     */
5454    protected int computeVerticalScrollOffset() {
5455        return mScrollY;
5456    }
5457
5458    /**
5459     * <p>Compute the vertical extent of the horizontal scrollbar's thumb
5460     * within the vertical range. This value is used to compute the length
5461     * of the thumb within the scrollbar's track.</p>
5462     *
5463     * <p>The range is expressed in arbitrary units that must be the same as the
5464     * units used by {@link #computeHorizontalScrollRange()} and
5465     * {@link #computeVerticalScrollOffset()}.</p>
5466     *
5467     * <p>The default extent is the drawing height of this view.</p>
5468     *
5469     * @return the vertical extent of the scrollbar's thumb
5470     *
5471     * @see #computeVerticalScrollRange()
5472     * @see #computeVerticalScrollOffset()
5473     * @see android.widget.ScrollBarDrawable
5474     */
5475    protected int computeVerticalScrollExtent() {
5476        return getHeight();
5477    }
5478
5479    /**
5480     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
5481     * scrollbars are painted only if they have been awakened first.</p>
5482     *
5483     * @param canvas the canvas on which to draw the scrollbars
5484     *
5485     * @see #awakenScrollBars(int)
5486     */
5487    private void onDrawScrollBars(Canvas canvas) {
5488        // scrollbars are drawn only when the animation is running
5489        final ScrollabilityCache cache = mScrollCache;
5490        if (cache != null) {
5491
5492            int state = cache.state;
5493
5494            if (state == ScrollabilityCache.OFF) {
5495                return;
5496            }
5497
5498            boolean invalidate = false;
5499
5500            if (state == ScrollabilityCache.FADING) {
5501                // We're fading -- get our fade interpolation
5502                if (cache.interpolatorValues == null) {
5503                    cache.interpolatorValues = new float[1];
5504                }
5505
5506                float[] values = cache.interpolatorValues;
5507
5508                // Stops the animation if we're done
5509                if (cache.scrollBarInterpolator.timeToValues(values) ==
5510                        Interpolator.Result.FREEZE_END) {
5511                    cache.state = ScrollabilityCache.OFF;
5512                } else {
5513                    cache.scrollBar.setAlpha(Math.round(values[0]));
5514                }
5515
5516                // This will make the scroll bars inval themselves after
5517                // drawing. We only want this when we're fading so that
5518                // we prevent excessive redraws
5519                invalidate = true;
5520            } else {
5521                // We're just on -- but we may have been fading before so
5522                // reset alpha
5523                cache.scrollBar.setAlpha(255);
5524            }
5525
5526
5527            final int viewFlags = mViewFlags;
5528
5529            final boolean drawHorizontalScrollBar =
5530                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
5531            final boolean drawVerticalScrollBar =
5532                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
5533                && !isVerticalScrollBarHidden();
5534
5535            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
5536                final int width = mRight - mLeft;
5537                final int height = mBottom - mTop;
5538
5539                final ScrollBarDrawable scrollBar = cache.scrollBar;
5540                int size = scrollBar.getSize(false);
5541                if (size <= 0) {
5542                    size = cache.scrollBarSize;
5543                }
5544
5545                final int scrollX = mScrollX;
5546                final int scrollY = mScrollY;
5547                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
5548
5549                int left, top, right, bottom;
5550
5551                if (drawHorizontalScrollBar) {
5552                    scrollBar.setParameters(computeHorizontalScrollRange(),
5553                                            computeHorizontalScrollOffset(),
5554                                            computeHorizontalScrollExtent(), false);
5555                    final int verticalScrollBarGap = drawVerticalScrollBar ?
5556                            getVerticalScrollbarWidth() : 0;
5557                    top = scrollY + height - size - (mUserPaddingBottom & inside);
5558                    left = scrollX + (mPaddingLeft & inside);
5559                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
5560                    bottom = top + size;
5561                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
5562                    if (invalidate) {
5563                        invalidate(left, top, right, bottom);
5564                    }
5565                }
5566
5567                if (drawVerticalScrollBar) {
5568                    scrollBar.setParameters(computeVerticalScrollRange(),
5569                                            computeVerticalScrollOffset(),
5570                                            computeVerticalScrollExtent(), true);
5571                    // TODO: Deal with RTL languages to position scrollbar on left
5572                    left = scrollX + width - size - (mUserPaddingRight & inside);
5573                    top = scrollY + (mPaddingTop & inside);
5574                    right = left + size;
5575                    bottom = scrollY + height - (mUserPaddingBottom & inside);
5576                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
5577                    if (invalidate) {
5578                        invalidate(left, top, right, bottom);
5579                    }
5580                }
5581            }
5582        }
5583    }
5584
5585    /**
5586     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
5587     * FastScroller is visible.
5588     * @return whether to temporarily hide the vertical scrollbar
5589     * @hide
5590     */
5591    protected boolean isVerticalScrollBarHidden() {
5592        return false;
5593    }
5594
5595    /**
5596     * <p>Draw the horizontal scrollbar if
5597     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
5598     *
5599     * @param canvas the canvas on which to draw the scrollbar
5600     * @param scrollBar the scrollbar's drawable
5601     *
5602     * @see #isHorizontalScrollBarEnabled()
5603     * @see #computeHorizontalScrollRange()
5604     * @see #computeHorizontalScrollExtent()
5605     * @see #computeHorizontalScrollOffset()
5606     * @see android.widget.ScrollBarDrawable
5607     * @hide
5608     */
5609    protected void onDrawHorizontalScrollBar(Canvas canvas,
5610                                             Drawable scrollBar,
5611                                             int l, int t, int r, int b) {
5612        scrollBar.setBounds(l, t, r, b);
5613        scrollBar.draw(canvas);
5614    }
5615
5616    /**
5617     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
5618     * returns true.</p>
5619     *
5620     * @param canvas the canvas on which to draw the scrollbar
5621     * @param scrollBar the scrollbar's drawable
5622     *
5623     * @see #isVerticalScrollBarEnabled()
5624     * @see #computeVerticalScrollRange()
5625     * @see #computeVerticalScrollExtent()
5626     * @see #computeVerticalScrollOffset()
5627     * @see android.widget.ScrollBarDrawable
5628     * @hide
5629     */
5630    protected void onDrawVerticalScrollBar(Canvas canvas,
5631                                           Drawable scrollBar,
5632                                           int l, int t, int r, int b) {
5633        scrollBar.setBounds(l, t, r, b);
5634        scrollBar.draw(canvas);
5635    }
5636
5637    /**
5638     * Implement this to do your drawing.
5639     *
5640     * @param canvas the canvas on which the background will be drawn
5641     */
5642    protected void onDraw(Canvas canvas) {
5643    }
5644
5645    /*
5646     * Caller is responsible for calling requestLayout if necessary.
5647     * (This allows addViewInLayout to not request a new layout.)
5648     */
5649    void assignParent(ViewParent parent) {
5650        if (mParent == null) {
5651            mParent = parent;
5652        } else if (parent == null) {
5653            mParent = null;
5654        } else {
5655            throw new RuntimeException("view " + this + " being added, but"
5656                    + " it already has a parent");
5657        }
5658    }
5659
5660    /**
5661     * This is called when the view is attached to a window.  At this point it
5662     * has a Surface and will start drawing.  Note that this function is
5663     * guaranteed to be called before {@link #onDraw}, however it may be called
5664     * any time before the first onDraw -- including before or after
5665     * {@link #onMeasure}.
5666     *
5667     * @see #onDetachedFromWindow()
5668     */
5669    protected void onAttachedToWindow() {
5670        if ((mPrivateFlags & REQUEST_TRANSPARENT_REGIONS) != 0) {
5671            mParent.requestTransparentRegion(this);
5672        }
5673    }
5674
5675    /**
5676     * This is called when the view is detached from a window.  At this point it
5677     * no longer has a surface for drawing.
5678     *
5679     * @see #onAttachedToWindow()
5680     */
5681    protected void onDetachedFromWindow() {
5682        if (mPendingCheckForLongPress != null) {
5683            removeCallbacks(mPendingCheckForLongPress);
5684        }
5685        destroyDrawingCache();
5686    }
5687
5688    /**
5689     * @return The number of times this view has been attached to a window
5690     */
5691    protected int getWindowAttachCount() {
5692        return mWindowAttachCount;
5693    }
5694
5695    /**
5696     * Retrieve a unique token identifying the window this view is attached to.
5697     * @return Return the window's token for use in
5698     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
5699     */
5700    public IBinder getWindowToken() {
5701        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
5702    }
5703
5704    /**
5705     * Retrieve a unique token identifying the top-level "real" window of
5706     * the window that this view is attached to.  That is, this is like
5707     * {@link #getWindowToken}, except if the window this view in is a panel
5708     * window (attached to another containing window), then the token of
5709     * the containing window is returned instead.
5710     *
5711     * @return Returns the associated window token, either
5712     * {@link #getWindowToken()} or the containing window's token.
5713     */
5714    public IBinder getApplicationWindowToken() {
5715        AttachInfo ai = mAttachInfo;
5716        if (ai != null) {
5717            IBinder appWindowToken = ai.mPanelParentWindowToken;
5718            if (appWindowToken == null) {
5719                appWindowToken = ai.mWindowToken;
5720            }
5721            return appWindowToken;
5722        }
5723        return null;
5724    }
5725
5726    /**
5727     * Retrieve private session object this view hierarchy is using to
5728     * communicate with the window manager.
5729     * @return the session object to communicate with the window manager
5730     */
5731    /*package*/ IWindowSession getWindowSession() {
5732        return mAttachInfo != null ? mAttachInfo.mSession : null;
5733    }
5734
5735    /**
5736     * @param info the {@link android.view.View.AttachInfo} to associated with
5737     *        this view
5738     */
5739    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
5740        //System.out.println("Attached! " + this);
5741        mAttachInfo = info;
5742        mWindowAttachCount++;
5743        if (mFloatingTreeObserver != null) {
5744            info.mTreeObserver.merge(mFloatingTreeObserver);
5745            mFloatingTreeObserver = null;
5746        }
5747        if ((mPrivateFlags&SCROLL_CONTAINER) != 0) {
5748            mAttachInfo.mScrollContainers.add(this);
5749            mPrivateFlags |= SCROLL_CONTAINER_ADDED;
5750        }
5751        performCollectViewAttributes(visibility);
5752        onAttachedToWindow();
5753        int vis = info.mWindowVisibility;
5754        if (vis != GONE) {
5755            onWindowVisibilityChanged(vis);
5756        }
5757    }
5758
5759    void dispatchDetachedFromWindow() {
5760        //System.out.println("Detached! " + this);
5761        AttachInfo info = mAttachInfo;
5762        if (info != null) {
5763            int vis = info.mWindowVisibility;
5764            if (vis != GONE) {
5765                onWindowVisibilityChanged(GONE);
5766            }
5767        }
5768
5769        onDetachedFromWindow();
5770        if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) {
5771            mAttachInfo.mScrollContainers.remove(this);
5772            mPrivateFlags &= ~SCROLL_CONTAINER_ADDED;
5773        }
5774        mAttachInfo = null;
5775    }
5776
5777    /**
5778     * Store this view hierarchy's frozen state into the given container.
5779     *
5780     * @param container The SparseArray in which to save the view's state.
5781     *
5782     * @see #restoreHierarchyState
5783     * @see #dispatchSaveInstanceState
5784     * @see #onSaveInstanceState
5785     */
5786    public void saveHierarchyState(SparseArray<Parcelable> container) {
5787        dispatchSaveInstanceState(container);
5788    }
5789
5790    /**
5791     * Called by {@link #saveHierarchyState} to store the state for this view and its children.
5792     * May be overridden to modify how freezing happens to a view's children; for example, some
5793     * views may want to not store state for their children.
5794     *
5795     * @param container The SparseArray in which to save the view's state.
5796     *
5797     * @see #dispatchRestoreInstanceState
5798     * @see #saveHierarchyState
5799     * @see #onSaveInstanceState
5800     */
5801    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
5802        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
5803            mPrivateFlags &= ~SAVE_STATE_CALLED;
5804            Parcelable state = onSaveInstanceState();
5805            if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
5806                throw new IllegalStateException(
5807                        "Derived class did not call super.onSaveInstanceState()");
5808            }
5809            if (state != null) {
5810                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
5811                // + ": " + state);
5812                container.put(mID, state);
5813            }
5814        }
5815    }
5816
5817    /**
5818     * Hook allowing a view to generate a representation of its internal state
5819     * that can later be used to create a new instance with that same state.
5820     * This state should only contain information that is not persistent or can
5821     * not be reconstructed later. For example, you will never store your
5822     * current position on screen because that will be computed again when a
5823     * new instance of the view is placed in its view hierarchy.
5824     * <p>
5825     * Some examples of things you may store here: the current cursor position
5826     * in a text view (but usually not the text itself since that is stored in a
5827     * content provider or other persistent storage), the currently selected
5828     * item in a list view.
5829     *
5830     * @return Returns a Parcelable object containing the view's current dynamic
5831     *         state, or null if there is nothing interesting to save. The
5832     *         default implementation returns null.
5833     * @see #onRestoreInstanceState
5834     * @see #saveHierarchyState
5835     * @see #dispatchSaveInstanceState
5836     * @see #setSaveEnabled(boolean)
5837     */
5838    protected Parcelable onSaveInstanceState() {
5839        mPrivateFlags |= SAVE_STATE_CALLED;
5840        return BaseSavedState.EMPTY_STATE;
5841    }
5842
5843    /**
5844     * Restore this view hierarchy's frozen state from the given container.
5845     *
5846     * @param container The SparseArray which holds previously frozen states.
5847     *
5848     * @see #saveHierarchyState
5849     * @see #dispatchRestoreInstanceState
5850     * @see #onRestoreInstanceState
5851     */
5852    public void restoreHierarchyState(SparseArray<Parcelable> container) {
5853        dispatchRestoreInstanceState(container);
5854    }
5855
5856    /**
5857     * Called by {@link #restoreHierarchyState} to retrieve the state for this view and its
5858     * children. May be overridden to modify how restoreing happens to a view's children; for
5859     * example, some views may want to not store state for their children.
5860     *
5861     * @param container The SparseArray which holds previously saved state.
5862     *
5863     * @see #dispatchSaveInstanceState
5864     * @see #restoreHierarchyState
5865     * @see #onRestoreInstanceState
5866     */
5867    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
5868        if (mID != NO_ID) {
5869            Parcelable state = container.get(mID);
5870            if (state != null) {
5871                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
5872                // + ": " + state);
5873                mPrivateFlags &= ~SAVE_STATE_CALLED;
5874                onRestoreInstanceState(state);
5875                if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
5876                    throw new IllegalStateException(
5877                            "Derived class did not call super.onRestoreInstanceState()");
5878                }
5879            }
5880        }
5881    }
5882
5883    /**
5884     * Hook allowing a view to re-apply a representation of its internal state that had previously
5885     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
5886     * null state.
5887     *
5888     * @param state The frozen state that had previously been returned by
5889     *        {@link #onSaveInstanceState}.
5890     *
5891     * @see #onSaveInstanceState
5892     * @see #restoreHierarchyState
5893     * @see #dispatchRestoreInstanceState
5894     */
5895    protected void onRestoreInstanceState(Parcelable state) {
5896        mPrivateFlags |= SAVE_STATE_CALLED;
5897        if (state != BaseSavedState.EMPTY_STATE && state != null) {
5898            throw new IllegalArgumentException("Wrong state class -- expecting View State");
5899        }
5900    }
5901
5902    /**
5903     * <p>Return the time at which the drawing of the view hierarchy started.</p>
5904     *
5905     * @return the drawing start time in milliseconds
5906     */
5907    public long getDrawingTime() {
5908        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
5909    }
5910
5911    /**
5912     * <p>Enables or disables the duplication of the parent's state into this view. When
5913     * duplication is enabled, this view gets its drawable state from its parent rather
5914     * than from its own internal properties.</p>
5915     *
5916     * <p>Note: in the current implementation, setting this property to true after the
5917     * view was added to a ViewGroup might have no effect at all. This property should
5918     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
5919     *
5920     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
5921     * property is enabled, an exception will be thrown.</p>
5922     *
5923     * @param enabled True to enable duplication of the parent's drawable state, false
5924     *                to disable it.
5925     *
5926     * @see #getDrawableState()
5927     * @see #isDuplicateParentStateEnabled()
5928     */
5929    public void setDuplicateParentStateEnabled(boolean enabled) {
5930        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
5931    }
5932
5933    /**
5934     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
5935     *
5936     * @return True if this view's drawable state is duplicated from the parent,
5937     *         false otherwise
5938     *
5939     * @see #getDrawableState()
5940     * @see #setDuplicateParentStateEnabled(boolean)
5941     */
5942    public boolean isDuplicateParentStateEnabled() {
5943        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
5944    }
5945
5946    /**
5947     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
5948     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
5949     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
5950     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
5951     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
5952     * null.</p>
5953     *
5954     * @param enabled true to enable the drawing cache, false otherwise
5955     *
5956     * @see #isDrawingCacheEnabled()
5957     * @see #getDrawingCache()
5958     * @see #buildDrawingCache()
5959     */
5960    public void setDrawingCacheEnabled(boolean enabled) {
5961        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
5962    }
5963
5964    /**
5965     * <p>Indicates whether the drawing cache is enabled for this view.</p>
5966     *
5967     * @return true if the drawing cache is enabled
5968     *
5969     * @see #setDrawingCacheEnabled(boolean)
5970     * @see #getDrawingCache()
5971     */
5972    @ViewDebug.ExportedProperty
5973    public boolean isDrawingCacheEnabled() {
5974        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
5975    }
5976
5977    /**
5978     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
5979     *
5980     * @return A non-scaled bitmap representing this view or null if cache is disabled.
5981     *
5982     * @see #getDrawingCache(boolean)
5983     */
5984    public Bitmap getDrawingCache() {
5985        return getDrawingCache(false);
5986    }
5987
5988    /**
5989     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
5990     * is null when caching is disabled. If caching is enabled and the cache is not ready,
5991     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
5992     * draw from the cache when the cache is enabled. To benefit from the cache, you must
5993     * request the drawing cache by calling this method and draw it on screen if the
5994     * returned bitmap is not null.</p>
5995     *
5996     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
5997     * this method will create a bitmap of the same size as this view. Because this bitmap
5998     * will be drawn scaled by the parent ViewGroup, the result on screen might show
5999     * scaling artifacts. To avoid such artifacts, you should call this method by setting
6000     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
6001     * size than the view. This implies that your application must be able to handle this
6002     * size.</p>
6003     *
6004     * @param autoScale Indicates whether the generated bitmap should be scaled based on
6005     *        the current density of the screen when the application is in compatibility
6006     *        mode.
6007     *
6008     * @return A bitmap representing this view or null if cache is disabled.
6009     *
6010     * @see #setDrawingCacheEnabled(boolean)
6011     * @see #isDrawingCacheEnabled()
6012     * @see #buildDrawingCache(boolean)
6013     * @see #destroyDrawingCache()
6014     */
6015    public Bitmap getDrawingCache(boolean autoScale) {
6016        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
6017            return null;
6018        }
6019        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
6020            buildDrawingCache(autoScale);
6021        }
6022        return autoScale ? (mDrawingCache == null ? null : mDrawingCache.get()) :
6023                (mUnscaledDrawingCache == null ? null : mUnscaledDrawingCache.get());
6024    }
6025
6026    /**
6027     * <p>Frees the resources used by the drawing cache. If you call
6028     * {@link #buildDrawingCache()} manually without calling
6029     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
6030     * should cleanup the cache with this method afterwards.</p>
6031     *
6032     * @see #setDrawingCacheEnabled(boolean)
6033     * @see #buildDrawingCache()
6034     * @see #getDrawingCache()
6035     */
6036    public void destroyDrawingCache() {
6037        if (mDrawingCache != null) {
6038            final Bitmap bitmap = mDrawingCache.get();
6039            if (bitmap != null) bitmap.recycle();
6040            mDrawingCache = null;
6041        }
6042        if (mUnscaledDrawingCache != null) {
6043            final Bitmap bitmap = mUnscaledDrawingCache.get();
6044            if (bitmap != null) bitmap.recycle();
6045            mUnscaledDrawingCache = null;
6046        }
6047    }
6048
6049    /**
6050     * Setting a solid background color for the drawing cache's bitmaps will improve
6051     * perfromance and memory usage. Note, though that this should only be used if this
6052     * view will always be drawn on top of a solid color.
6053     *
6054     * @param color The background color to use for the drawing cache's bitmap
6055     *
6056     * @see #setDrawingCacheEnabled(boolean)
6057     * @see #buildDrawingCache()
6058     * @see #getDrawingCache()
6059     */
6060    public void setDrawingCacheBackgroundColor(int color) {
6061        mDrawingCacheBackgroundColor = color;
6062    }
6063
6064    /**
6065     * @see #setDrawingCacheBackgroundColor(int)
6066     *
6067     * @return The background color to used for the drawing cache's bitmap
6068     */
6069    public int getDrawingCacheBackgroundColor() {
6070        return mDrawingCacheBackgroundColor;
6071    }
6072
6073    /**
6074     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
6075     *
6076     * @see #buildDrawingCache(boolean)
6077     */
6078    public void buildDrawingCache() {
6079        buildDrawingCache(false);
6080    }
6081
6082    /**
6083     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
6084     *
6085     * <p>If you call {@link #buildDrawingCache()} manually without calling
6086     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
6087     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
6088     *
6089     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
6090     * this method will create a bitmap of the same size as this view. Because this bitmap
6091     * will be drawn scaled by the parent ViewGroup, the result on screen might show
6092     * scaling artifacts. To avoid such artifacts, you should call this method by setting
6093     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
6094     * size than the view. This implies that your application must be able to handle this
6095     * size.</p>
6096     *
6097     * @see #getDrawingCache()
6098     * @see #destroyDrawingCache()
6099     */
6100    public void buildDrawingCache(boolean autoScale) {
6101        if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || (autoScale ?
6102                (mDrawingCache == null || mDrawingCache.get() == null) :
6103                (mUnscaledDrawingCache == null || mUnscaledDrawingCache.get() == null))) {
6104
6105            if (ViewDebug.TRACE_HIERARCHY) {
6106                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.BUILD_CACHE);
6107            }
6108            if (Config.DEBUG && ViewDebug.profileDrawing) {
6109                EventLog.writeEvent(60002, hashCode());
6110            }
6111
6112            int width = mRight - mLeft;
6113            int height = mBottom - mTop;
6114
6115            final AttachInfo attachInfo = mAttachInfo;
6116            final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
6117
6118            if (autoScale && scalingRequired) {
6119                width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
6120                height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
6121            }
6122
6123            final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
6124            final boolean opaque = drawingCacheBackgroundColor != 0 ||
6125                (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE);
6126
6127            if (width <= 0 || height <= 0 ||
6128                    (width * height * (opaque ? 2 : 4) > // Projected bitmap size in bytes
6129                            ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) {
6130                destroyDrawingCache();
6131                return;
6132            }
6133
6134            boolean clear = true;
6135            Bitmap bitmap = autoScale ? (mDrawingCache == null ? null : mDrawingCache.get()) :
6136                    (mUnscaledDrawingCache == null ? null : mUnscaledDrawingCache.get());
6137
6138            if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
6139
6140                Bitmap.Config quality;
6141                if (!opaque) {
6142                    switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
6143                        case DRAWING_CACHE_QUALITY_AUTO:
6144                            quality = Bitmap.Config.ARGB_8888;
6145                            break;
6146                        case DRAWING_CACHE_QUALITY_LOW:
6147                            quality = Bitmap.Config.ARGB_4444;
6148                            break;
6149                        case DRAWING_CACHE_QUALITY_HIGH:
6150                            quality = Bitmap.Config.ARGB_8888;
6151                            break;
6152                        default:
6153                            quality = Bitmap.Config.ARGB_8888;
6154                            break;
6155                    }
6156                } else {
6157                    quality = Bitmap.Config.RGB_565;
6158                }
6159
6160                // Try to cleanup memory
6161                if (bitmap != null) bitmap.recycle();
6162
6163                try {
6164                    bitmap = Bitmap.createBitmap(width, height, quality);
6165                    bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
6166                    if (autoScale) {
6167                        mDrawingCache = new SoftReference<Bitmap>(bitmap);
6168                    } else {
6169                        mUnscaledDrawingCache = new SoftReference<Bitmap>(bitmap);
6170                    }
6171                } catch (OutOfMemoryError e) {
6172                    // If there is not enough memory to create the bitmap cache, just
6173                    // ignore the issue as bitmap caches are not required to draw the
6174                    // view hierarchy
6175                    if (autoScale) {
6176                        mDrawingCache = null;
6177                    } else {
6178                        mUnscaledDrawingCache = null;
6179                    }
6180                    return;
6181                }
6182
6183                clear = drawingCacheBackgroundColor != 0;
6184            }
6185
6186            Canvas canvas;
6187            if (attachInfo != null) {
6188                canvas = attachInfo.mCanvas;
6189                if (canvas == null) {
6190                    canvas = new Canvas();
6191                }
6192                canvas.setBitmap(bitmap);
6193                // Temporarily clobber the cached Canvas in case one of our children
6194                // is also using a drawing cache. Without this, the children would
6195                // steal the canvas by attaching their own bitmap to it and bad, bad
6196                // thing would happen (invisible views, corrupted drawings, etc.)
6197                attachInfo.mCanvas = null;
6198            } else {
6199                // This case should hopefully never or seldom happen
6200                canvas = new Canvas(bitmap);
6201            }
6202
6203            if (clear) {
6204                bitmap.eraseColor(drawingCacheBackgroundColor);
6205            }
6206
6207            computeScroll();
6208            final int restoreCount = canvas.save();
6209
6210            if (autoScale && scalingRequired) {
6211                final float scale = attachInfo.mApplicationScale;
6212                canvas.scale(scale, scale);
6213            }
6214
6215            canvas.translate(-mScrollX, -mScrollY);
6216
6217            mPrivateFlags |= DRAWN;
6218
6219            // Fast path for layouts with no backgrounds
6220            if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
6221                if (ViewDebug.TRACE_HIERARCHY) {
6222                    ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
6223                }
6224                mPrivateFlags &= ~DIRTY_MASK;
6225                dispatchDraw(canvas);
6226            } else {
6227                draw(canvas);
6228            }
6229
6230            canvas.restoreToCount(restoreCount);
6231
6232            if (attachInfo != null) {
6233                // Restore the cached Canvas for our siblings
6234                attachInfo.mCanvas = canvas;
6235            }
6236            mPrivateFlags |= DRAWING_CACHE_VALID;
6237        }
6238    }
6239
6240    /**
6241     * Create a snapshot of the view into a bitmap.  We should probably make
6242     * some form of this public, but should think about the API.
6243     */
6244    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor) {
6245        int width = mRight - mLeft;
6246        int height = mBottom - mTop;
6247
6248        final AttachInfo attachInfo = mAttachInfo;
6249        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
6250        width = (int) ((width * scale) + 0.5f);
6251        height = (int) ((height * scale) + 0.5f);
6252
6253        Bitmap bitmap = Bitmap.createBitmap(width > 0 ? width : 1, height > 0 ? height : 1, quality);
6254        if (bitmap == null) {
6255            throw new OutOfMemoryError();
6256        }
6257
6258        bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
6259
6260        Canvas canvas;
6261        if (attachInfo != null) {
6262            canvas = attachInfo.mCanvas;
6263            if (canvas == null) {
6264                canvas = new Canvas();
6265            }
6266            canvas.setBitmap(bitmap);
6267            // Temporarily clobber the cached Canvas in case one of our children
6268            // is also using a drawing cache. Without this, the children would
6269            // steal the canvas by attaching their own bitmap to it and bad, bad
6270            // things would happen (invisible views, corrupted drawings, etc.)
6271            attachInfo.mCanvas = null;
6272        } else {
6273            // This case should hopefully never or seldom happen
6274            canvas = new Canvas(bitmap);
6275        }
6276
6277        if ((backgroundColor & 0xff000000) != 0) {
6278            bitmap.eraseColor(backgroundColor);
6279        }
6280
6281        computeScroll();
6282        final int restoreCount = canvas.save();
6283        canvas.scale(scale, scale);
6284        canvas.translate(-mScrollX, -mScrollY);
6285
6286        // Temporarily remove the dirty mask
6287        int flags = mPrivateFlags;
6288        mPrivateFlags &= ~DIRTY_MASK;
6289
6290        // Fast path for layouts with no backgrounds
6291        if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
6292            dispatchDraw(canvas);
6293        } else {
6294            draw(canvas);
6295        }
6296
6297        mPrivateFlags = flags;
6298
6299        canvas.restoreToCount(restoreCount);
6300
6301        if (attachInfo != null) {
6302            // Restore the cached Canvas for our siblings
6303            attachInfo.mCanvas = canvas;
6304        }
6305
6306        return bitmap;
6307    }
6308
6309    /**
6310     * Indicates whether this View is currently in edit mode. A View is usually
6311     * in edit mode when displayed within a developer tool. For instance, if
6312     * this View is being drawn by a visual user interface builder, this method
6313     * should return true.
6314     *
6315     * Subclasses should check the return value of this method to provide
6316     * different behaviors if their normal behavior might interfere with the
6317     * host environment. For instance: the class spawns a thread in its
6318     * constructor, the drawing code relies on device-specific features, etc.
6319     *
6320     * This method is usually checked in the drawing code of custom widgets.
6321     *
6322     * @return True if this View is in edit mode, false otherwise.
6323     */
6324    public boolean isInEditMode() {
6325        return false;
6326    }
6327
6328    /**
6329     * If the View draws content inside its padding and enables fading edges,
6330     * it needs to support padding offsets. Padding offsets are added to the
6331     * fading edges to extend the length of the fade so that it covers pixels
6332     * drawn inside the padding.
6333     *
6334     * Subclasses of this class should override this method if they need
6335     * to draw content inside the padding.
6336     *
6337     * @return True if padding offset must be applied, false otherwise.
6338     *
6339     * @see #getLeftPaddingOffset()
6340     * @see #getRightPaddingOffset()
6341     * @see #getTopPaddingOffset()
6342     * @see #getBottomPaddingOffset()
6343     *
6344     * @since CURRENT
6345     */
6346    protected boolean isPaddingOffsetRequired() {
6347        return false;
6348    }
6349
6350    /**
6351     * Amount by which to extend the left fading region. Called only when
6352     * {@link #isPaddingOffsetRequired()} returns true.
6353     *
6354     * @return The left padding offset in pixels.
6355     *
6356     * @see #isPaddingOffsetRequired()
6357     *
6358     * @since CURRENT
6359     */
6360    protected int getLeftPaddingOffset() {
6361        return 0;
6362    }
6363
6364    /**
6365     * Amount by which to extend the right fading region. Called only when
6366     * {@link #isPaddingOffsetRequired()} returns true.
6367     *
6368     * @return The right padding offset in pixels.
6369     *
6370     * @see #isPaddingOffsetRequired()
6371     *
6372     * @since CURRENT
6373     */
6374    protected int getRightPaddingOffset() {
6375        return 0;
6376    }
6377
6378    /**
6379     * Amount by which to extend the top fading region. Called only when
6380     * {@link #isPaddingOffsetRequired()} returns true.
6381     *
6382     * @return The top padding offset in pixels.
6383     *
6384     * @see #isPaddingOffsetRequired()
6385     *
6386     * @since CURRENT
6387     */
6388    protected int getTopPaddingOffset() {
6389        return 0;
6390    }
6391
6392    /**
6393     * Amount by which to extend the bottom fading region. Called only when
6394     * {@link #isPaddingOffsetRequired()} returns true.
6395     *
6396     * @return The bottom padding offset in pixels.
6397     *
6398     * @see #isPaddingOffsetRequired()
6399     *
6400     * @since CURRENT
6401     */
6402    protected int getBottomPaddingOffset() {
6403        return 0;
6404    }
6405
6406    /**
6407     * Manually render this view (and all of its children) to the given Canvas.
6408     * The view must have already done a full layout before this function is
6409     * called.  When implementing a view, do not override this method; instead,
6410     * you should implement {@link #onDraw}.
6411     *
6412     * @param canvas The Canvas to which the View is rendered.
6413     */
6414    public void draw(Canvas canvas) {
6415        if (ViewDebug.TRACE_HIERARCHY) {
6416            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
6417        }
6418
6419        final int privateFlags = mPrivateFlags;
6420        final boolean dirtyOpaque = (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE &&
6421                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
6422        mPrivateFlags = (privateFlags & ~DIRTY_MASK) | DRAWN;
6423
6424        /*
6425         * Draw traversal performs several drawing steps which must be executed
6426         * in the appropriate order:
6427         *
6428         *      1. Draw the background
6429         *      2. If necessary, save the canvas' layers to prepare for fading
6430         *      3. Draw view's content
6431         *      4. Draw children
6432         *      5. If necessary, draw the fading edges and restore layers
6433         *      6. Draw decorations (scrollbars for instance)
6434         */
6435
6436        // Step 1, draw the background, if needed
6437        int saveCount;
6438
6439        if (!dirtyOpaque) {
6440            final Drawable background = mBGDrawable;
6441            if (background != null) {
6442                final int scrollX = mScrollX;
6443                final int scrollY = mScrollY;
6444
6445                if (mBackgroundSizeChanged) {
6446                    background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
6447                    mBackgroundSizeChanged = false;
6448                }
6449
6450                if ((scrollX | scrollY) == 0) {
6451                    background.draw(canvas);
6452                } else {
6453                    canvas.translate(scrollX, scrollY);
6454                    background.draw(canvas);
6455                    canvas.translate(-scrollX, -scrollY);
6456                }
6457            }
6458        }
6459
6460        // skip step 2 & 5 if possible (common case)
6461        final int viewFlags = mViewFlags;
6462        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
6463        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
6464        if (!verticalEdges && !horizontalEdges) {
6465            // Step 3, draw the content
6466            if (!dirtyOpaque) onDraw(canvas);
6467
6468            // Step 4, draw the children
6469            dispatchDraw(canvas);
6470
6471            // Step 6, draw decorations (scrollbars)
6472            onDrawScrollBars(canvas);
6473
6474            // we're done...
6475            return;
6476        }
6477
6478        /*
6479         * Here we do the full fledged routine...
6480         * (this is an uncommon case where speed matters less,
6481         * this is why we repeat some of the tests that have been
6482         * done above)
6483         */
6484
6485        boolean drawTop = false;
6486        boolean drawBottom = false;
6487        boolean drawLeft = false;
6488        boolean drawRight = false;
6489
6490        float topFadeStrength = 0.0f;
6491        float bottomFadeStrength = 0.0f;
6492        float leftFadeStrength = 0.0f;
6493        float rightFadeStrength = 0.0f;
6494
6495        // Step 2, save the canvas' layers
6496        int paddingLeft = mPaddingLeft;
6497        int paddingTop = mPaddingTop;
6498
6499        final boolean offsetRequired = isPaddingOffsetRequired();
6500        if (offsetRequired) {
6501            paddingLeft += getLeftPaddingOffset();
6502            paddingTop += getTopPaddingOffset();
6503        }
6504
6505        int left = mScrollX + paddingLeft;
6506        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
6507        int top = mScrollY + paddingTop;
6508        int bottom = top + mBottom - mTop - mPaddingBottom - paddingTop;
6509
6510        if (offsetRequired) {
6511            right += getRightPaddingOffset();
6512            bottom += getBottomPaddingOffset();
6513        }
6514
6515        final ScrollabilityCache scrollabilityCache = mScrollCache;
6516        int length = scrollabilityCache.fadingEdgeLength;
6517
6518        // clip the fade length if top and bottom fades overlap
6519        // overlapping fades produce odd-looking artifacts
6520        if (verticalEdges && (top + length > bottom - length)) {
6521            length = (bottom - top) / 2;
6522        }
6523
6524        // also clip horizontal fades if necessary
6525        if (horizontalEdges && (left + length > right - length)) {
6526            length = (right - left) / 2;
6527        }
6528
6529        if (verticalEdges) {
6530            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
6531            drawTop = topFadeStrength >= 0.0f;
6532            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
6533            drawBottom = bottomFadeStrength >= 0.0f;
6534        }
6535
6536        if (horizontalEdges) {
6537            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
6538            drawLeft = leftFadeStrength >= 0.0f;
6539            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
6540            drawRight = rightFadeStrength >= 0.0f;
6541        }
6542
6543        saveCount = canvas.getSaveCount();
6544
6545        int solidColor = getSolidColor();
6546        if (solidColor == 0) {
6547            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
6548
6549            if (drawTop) {
6550                canvas.saveLayer(left, top, right, top + length, null, flags);
6551            }
6552
6553            if (drawBottom) {
6554                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
6555            }
6556
6557            if (drawLeft) {
6558                canvas.saveLayer(left, top, left + length, bottom, null, flags);
6559            }
6560
6561            if (drawRight) {
6562                canvas.saveLayer(right - length, top, right, bottom, null, flags);
6563            }
6564        } else {
6565            scrollabilityCache.setFadeColor(solidColor);
6566        }
6567
6568        // Step 3, draw the content
6569        if (!dirtyOpaque) onDraw(canvas);
6570
6571        // Step 4, draw the children
6572        dispatchDraw(canvas);
6573
6574        // Step 5, draw the fade effect and restore layers
6575        final Paint p = scrollabilityCache.paint;
6576        final Matrix matrix = scrollabilityCache.matrix;
6577        final Shader fade = scrollabilityCache.shader;
6578        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
6579
6580        if (drawTop) {
6581            matrix.setScale(1, fadeHeight * topFadeStrength);
6582            matrix.postTranslate(left, top);
6583            fade.setLocalMatrix(matrix);
6584            canvas.drawRect(left, top, right, top + length, p);
6585        }
6586
6587        if (drawBottom) {
6588            matrix.setScale(1, fadeHeight * bottomFadeStrength);
6589            matrix.postRotate(180);
6590            matrix.postTranslate(left, bottom);
6591            fade.setLocalMatrix(matrix);
6592            canvas.drawRect(left, bottom - length, right, bottom, p);
6593        }
6594
6595        if (drawLeft) {
6596            matrix.setScale(1, fadeHeight * leftFadeStrength);
6597            matrix.postRotate(-90);
6598            matrix.postTranslate(left, top);
6599            fade.setLocalMatrix(matrix);
6600            canvas.drawRect(left, top, left + length, bottom, p);
6601        }
6602
6603        if (drawRight) {
6604            matrix.setScale(1, fadeHeight * rightFadeStrength);
6605            matrix.postRotate(90);
6606            matrix.postTranslate(right, top);
6607            fade.setLocalMatrix(matrix);
6608            canvas.drawRect(right - length, top, right, bottom, p);
6609        }
6610
6611        canvas.restoreToCount(saveCount);
6612
6613        // Step 6, draw decorations (scrollbars)
6614        onDrawScrollBars(canvas);
6615    }
6616
6617    /**
6618     * Override this if your view is known to always be drawn on top of a solid color background,
6619     * and needs to draw fading edges. Returning a non-zero color enables the view system to
6620     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
6621     * should be set to 0xFF.
6622     *
6623     * @see #setVerticalFadingEdgeEnabled
6624     * @see #setHorizontalFadingEdgeEnabled
6625     *
6626     * @return The known solid color background for this view, or 0 if the color may vary
6627     */
6628    public int getSolidColor() {
6629        return 0;
6630    }
6631
6632    /**
6633     * Build a human readable string representation of the specified view flags.
6634     *
6635     * @param flags the view flags to convert to a string
6636     * @return a String representing the supplied flags
6637     */
6638    private static String printFlags(int flags) {
6639        String output = "";
6640        int numFlags = 0;
6641        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
6642            output += "TAKES_FOCUS";
6643            numFlags++;
6644        }
6645
6646        switch (flags & VISIBILITY_MASK) {
6647        case INVISIBLE:
6648            if (numFlags > 0) {
6649                output += " ";
6650            }
6651            output += "INVISIBLE";
6652            // USELESS HERE numFlags++;
6653            break;
6654        case GONE:
6655            if (numFlags > 0) {
6656                output += " ";
6657            }
6658            output += "GONE";
6659            // USELESS HERE numFlags++;
6660            break;
6661        default:
6662            break;
6663        }
6664        return output;
6665    }
6666
6667    /**
6668     * Build a human readable string representation of the specified private
6669     * view flags.
6670     *
6671     * @param privateFlags the private view flags to convert to a string
6672     * @return a String representing the supplied flags
6673     */
6674    private static String printPrivateFlags(int privateFlags) {
6675        String output = "";
6676        int numFlags = 0;
6677
6678        if ((privateFlags & WANTS_FOCUS) == WANTS_FOCUS) {
6679            output += "WANTS_FOCUS";
6680            numFlags++;
6681        }
6682
6683        if ((privateFlags & FOCUSED) == FOCUSED) {
6684            if (numFlags > 0) {
6685                output += " ";
6686            }
6687            output += "FOCUSED";
6688            numFlags++;
6689        }
6690
6691        if ((privateFlags & SELECTED) == SELECTED) {
6692            if (numFlags > 0) {
6693                output += " ";
6694            }
6695            output += "SELECTED";
6696            numFlags++;
6697        }
6698
6699        if ((privateFlags & IS_ROOT_NAMESPACE) == IS_ROOT_NAMESPACE) {
6700            if (numFlags > 0) {
6701                output += " ";
6702            }
6703            output += "IS_ROOT_NAMESPACE";
6704            numFlags++;
6705        }
6706
6707        if ((privateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
6708            if (numFlags > 0) {
6709                output += " ";
6710            }
6711            output += "HAS_BOUNDS";
6712            numFlags++;
6713        }
6714
6715        if ((privateFlags & DRAWN) == DRAWN) {
6716            if (numFlags > 0) {
6717                output += " ";
6718            }
6719            output += "DRAWN";
6720            // USELESS HERE numFlags++;
6721        }
6722        return output;
6723    }
6724
6725    /**
6726     * <p>Indicates whether or not this view's layout will be requested during
6727     * the next hierarchy layout pass.</p>
6728     *
6729     * @return true if the layout will be forced during next layout pass
6730     */
6731    public boolean isLayoutRequested() {
6732        return (mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT;
6733    }
6734
6735    /**
6736     * Assign a size and position to a view and all of its
6737     * descendants
6738     *
6739     * <p>This is the second phase of the layout mechanism.
6740     * (The first is measuring). In this phase, each parent calls
6741     * layout on all of its children to position them.
6742     * This is typically done using the child measurements
6743     * that were stored in the measure pass().
6744     *
6745     * Derived classes with children should override
6746     * onLayout. In that method, they should
6747     * call layout on each of their their children.
6748     *
6749     * @param l Left position, relative to parent
6750     * @param t Top position, relative to parent
6751     * @param r Right position, relative to parent
6752     * @param b Bottom position, relative to parent
6753     */
6754    public final void layout(int l, int t, int r, int b) {
6755        boolean changed = setFrame(l, t, r, b);
6756        if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) {
6757            if (ViewDebug.TRACE_HIERARCHY) {
6758                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_LAYOUT);
6759            }
6760
6761            onLayout(changed, l, t, r, b);
6762            mPrivateFlags &= ~LAYOUT_REQUIRED;
6763        }
6764        mPrivateFlags &= ~FORCE_LAYOUT;
6765    }
6766
6767    /**
6768     * Called from layout when this view should
6769     * assign a size and position to each of its children.
6770     *
6771     * Derived classes with children should override
6772     * this method and call layout on each of
6773     * their their children.
6774     * @param changed This is a new size or position for this view
6775     * @param left Left position, relative to parent
6776     * @param top Top position, relative to parent
6777     * @param right Right position, relative to parent
6778     * @param bottom Bottom position, relative to parent
6779     */
6780    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
6781    }
6782
6783    /**
6784     * Assign a size and position to this view.
6785     *
6786     * This is called from layout.
6787     *
6788     * @param left Left position, relative to parent
6789     * @param top Top position, relative to parent
6790     * @param right Right position, relative to parent
6791     * @param bottom Bottom position, relative to parent
6792     * @return true if the new size and position are different than the
6793     *         previous ones
6794     * {@hide}
6795     */
6796    protected boolean setFrame(int left, int top, int right, int bottom) {
6797        boolean changed = false;
6798
6799        if (DBG) {
6800            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
6801                    + right + "," + bottom + ")");
6802        }
6803
6804        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
6805            changed = true;
6806
6807            // Remember our drawn bit
6808            int drawn = mPrivateFlags & DRAWN;
6809
6810            // Invalidate our old position
6811            invalidate();
6812
6813
6814            int oldWidth = mRight - mLeft;
6815            int oldHeight = mBottom - mTop;
6816
6817            mLeft = left;
6818            mTop = top;
6819            mRight = right;
6820            mBottom = bottom;
6821
6822            mPrivateFlags |= HAS_BOUNDS;
6823
6824            int newWidth = right - left;
6825            int newHeight = bottom - top;
6826
6827            if (newWidth != oldWidth || newHeight != oldHeight) {
6828                onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
6829            }
6830
6831            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
6832                // If we are visible, force the DRAWN bit to on so that
6833                // this invalidate will go through (at least to our parent).
6834                // This is because someone may have invalidated this view
6835                // before this call to setFrame came in, therby clearing
6836                // the DRAWN bit.
6837                mPrivateFlags |= DRAWN;
6838                invalidate();
6839            }
6840
6841            // Reset drawn bit to original value (invalidate turns it off)
6842            mPrivateFlags |= drawn;
6843
6844            mBackgroundSizeChanged = true;
6845        }
6846        return changed;
6847    }
6848
6849    /**
6850     * Finalize inflating a view from XML.  This is called as the last phase
6851     * of inflation, after all child views have been added.
6852     *
6853     * <p>Even if the subclass overrides onFinishInflate, they should always be
6854     * sure to call the super method, so that we get called.
6855     */
6856    protected void onFinishInflate() {
6857    }
6858
6859    /**
6860     * Returns the resources associated with this view.
6861     *
6862     * @return Resources object.
6863     */
6864    public Resources getResources() {
6865        return mResources;
6866    }
6867
6868    /**
6869     * Invalidates the specified Drawable.
6870     *
6871     * @param drawable the drawable to invalidate
6872     */
6873    public void invalidateDrawable(Drawable drawable) {
6874        if (verifyDrawable(drawable)) {
6875            final Rect dirty = drawable.getBounds();
6876            final int scrollX = mScrollX;
6877            final int scrollY = mScrollY;
6878
6879            invalidate(dirty.left + scrollX, dirty.top + scrollY,
6880                    dirty.right + scrollX, dirty.bottom + scrollY);
6881        }
6882    }
6883
6884    /**
6885     * Schedules an action on a drawable to occur at a specified time.
6886     *
6887     * @param who the recipient of the action
6888     * @param what the action to run on the drawable
6889     * @param when the time at which the action must occur. Uses the
6890     *        {@link SystemClock#uptimeMillis} timebase.
6891     */
6892    public void scheduleDrawable(Drawable who, Runnable what, long when) {
6893        if (verifyDrawable(who) && what != null && mAttachInfo != null) {
6894            mAttachInfo.mHandler.postAtTime(what, who, when);
6895        }
6896    }
6897
6898    /**
6899     * Cancels a scheduled action on a drawable.
6900     *
6901     * @param who the recipient of the action
6902     * @param what the action to cancel
6903     */
6904    public void unscheduleDrawable(Drawable who, Runnable what) {
6905        if (verifyDrawable(who) && what != null && mAttachInfo != null) {
6906            mAttachInfo.mHandler.removeCallbacks(what, who);
6907        }
6908    }
6909
6910    /**
6911     * Unschedule any events associated with the given Drawable.  This can be
6912     * used when selecting a new Drawable into a view, so that the previous
6913     * one is completely unscheduled.
6914     *
6915     * @param who The Drawable to unschedule.
6916     *
6917     * @see #drawableStateChanged
6918     */
6919    public void unscheduleDrawable(Drawable who) {
6920        if (mAttachInfo != null) {
6921            mAttachInfo.mHandler.removeCallbacksAndMessages(who);
6922        }
6923    }
6924
6925    /**
6926     * If your view subclass is displaying its own Drawable objects, it should
6927     * override this function and return true for any Drawable it is
6928     * displaying.  This allows animations for those drawables to be
6929     * scheduled.
6930     *
6931     * <p>Be sure to call through to the super class when overriding this
6932     * function.
6933     *
6934     * @param who The Drawable to verify.  Return true if it is one you are
6935     *            displaying, else return the result of calling through to the
6936     *            super class.
6937     *
6938     * @return boolean If true than the Drawable is being displayed in the
6939     *         view; else false and it is not allowed to animate.
6940     *
6941     * @see #unscheduleDrawable
6942     * @see #drawableStateChanged
6943     */
6944    protected boolean verifyDrawable(Drawable who) {
6945        return who == mBGDrawable;
6946    }
6947
6948    /**
6949     * This function is called whenever the state of the view changes in such
6950     * a way that it impacts the state of drawables being shown.
6951     *
6952     * <p>Be sure to call through to the superclass when overriding this
6953     * function.
6954     *
6955     * @see Drawable#setState
6956     */
6957    protected void drawableStateChanged() {
6958        Drawable d = mBGDrawable;
6959        if (d != null && d.isStateful()) {
6960            d.setState(getDrawableState());
6961        }
6962    }
6963
6964    /**
6965     * Call this to force a view to update its drawable state. This will cause
6966     * drawableStateChanged to be called on this view. Views that are interested
6967     * in the new state should call getDrawableState.
6968     *
6969     * @see #drawableStateChanged
6970     * @see #getDrawableState
6971     */
6972    public void refreshDrawableState() {
6973        mPrivateFlags |= DRAWABLE_STATE_DIRTY;
6974        drawableStateChanged();
6975
6976        ViewParent parent = mParent;
6977        if (parent != null) {
6978            parent.childDrawableStateChanged(this);
6979        }
6980    }
6981
6982    /**
6983     * Return an array of resource IDs of the drawable states representing the
6984     * current state of the view.
6985     *
6986     * @return The current drawable state
6987     *
6988     * @see Drawable#setState
6989     * @see #drawableStateChanged
6990     * @see #onCreateDrawableState
6991     */
6992    public final int[] getDrawableState() {
6993        if ((mDrawableState != null) && ((mPrivateFlags & DRAWABLE_STATE_DIRTY) == 0)) {
6994            return mDrawableState;
6995        } else {
6996            mDrawableState = onCreateDrawableState(0);
6997            mPrivateFlags &= ~DRAWABLE_STATE_DIRTY;
6998            return mDrawableState;
6999        }
7000    }
7001
7002    /**
7003     * Generate the new {@link android.graphics.drawable.Drawable} state for
7004     * this view. This is called by the view
7005     * system when the cached Drawable state is determined to be invalid.  To
7006     * retrieve the current state, you should use {@link #getDrawableState}.
7007     *
7008     * @param extraSpace if non-zero, this is the number of extra entries you
7009     * would like in the returned array in which you can place your own
7010     * states.
7011     *
7012     * @return Returns an array holding the current {@link Drawable} state of
7013     * the view.
7014     *
7015     * @see #mergeDrawableStates
7016     */
7017    protected int[] onCreateDrawableState(int extraSpace) {
7018        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
7019                mParent instanceof View) {
7020            return ((View) mParent).onCreateDrawableState(extraSpace);
7021        }
7022
7023        int[] drawableState;
7024
7025        int privateFlags = mPrivateFlags;
7026
7027        int viewStateIndex = (((privateFlags & PRESSED) != 0) ? 1 : 0);
7028
7029        viewStateIndex = (viewStateIndex << 1)
7030                + (((mViewFlags & ENABLED_MASK) == ENABLED) ? 1 : 0);
7031
7032        viewStateIndex = (viewStateIndex << 1) + (isFocused() ? 1 : 0);
7033
7034        viewStateIndex = (viewStateIndex << 1)
7035                + (((privateFlags & SELECTED) != 0) ? 1 : 0);
7036
7037        final boolean hasWindowFocus = hasWindowFocus();
7038        viewStateIndex = (viewStateIndex << 1) + (hasWindowFocus ? 1 : 0);
7039
7040        drawableState = VIEW_STATE_SETS[viewStateIndex];
7041
7042        //noinspection ConstantIfStatement
7043        if (false) {
7044            Log.i("View", "drawableStateIndex=" + viewStateIndex);
7045            Log.i("View", toString()
7046                    + " pressed=" + ((privateFlags & PRESSED) != 0)
7047                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
7048                    + " fo=" + hasFocus()
7049                    + " sl=" + ((privateFlags & SELECTED) != 0)
7050                    + " wf=" + hasWindowFocus
7051                    + ": " + Arrays.toString(drawableState));
7052        }
7053
7054        if (extraSpace == 0) {
7055            return drawableState;
7056        }
7057
7058        final int[] fullState;
7059        if (drawableState != null) {
7060            fullState = new int[drawableState.length + extraSpace];
7061            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
7062        } else {
7063            fullState = new int[extraSpace];
7064        }
7065
7066        return fullState;
7067    }
7068
7069    /**
7070     * Merge your own state values in <var>additionalState</var> into the base
7071     * state values <var>baseState</var> that were returned by
7072     * {@link #onCreateDrawableState}.
7073     *
7074     * @param baseState The base state values returned by
7075     * {@link #onCreateDrawableState}, which will be modified to also hold your
7076     * own additional state values.
7077     *
7078     * @param additionalState The additional state values you would like
7079     * added to <var>baseState</var>; this array is not modified.
7080     *
7081     * @return As a convenience, the <var>baseState</var> array you originally
7082     * passed into the function is returned.
7083     *
7084     * @see #onCreateDrawableState
7085     */
7086    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
7087        final int N = baseState.length;
7088        int i = N - 1;
7089        while (i >= 0 && baseState[i] == 0) {
7090            i--;
7091        }
7092        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
7093        return baseState;
7094    }
7095
7096    /**
7097     * Sets the background color for this view.
7098     * @param color the color of the background
7099     */
7100    public void setBackgroundColor(int color) {
7101        setBackgroundDrawable(new ColorDrawable(color));
7102    }
7103
7104    /**
7105     * Set the background to a given resource. The resource should refer to
7106     * a Drawable object or 0 to remove the background.
7107     * @param resid The identifier of the resource.
7108     * @attr ref android.R.styleable#View_background
7109     */
7110    public void setBackgroundResource(int resid) {
7111        if (resid != 0 && resid == mBackgroundResource) {
7112            return;
7113        }
7114
7115        Drawable d= null;
7116        if (resid != 0) {
7117            d = mResources.getDrawable(resid);
7118        }
7119        setBackgroundDrawable(d);
7120
7121        mBackgroundResource = resid;
7122    }
7123
7124    /**
7125     * Set the background to a given Drawable, or remove the background. If the
7126     * background has padding, this View's padding is set to the background's
7127     * padding. However, when a background is removed, this View's padding isn't
7128     * touched. If setting the padding is desired, please use
7129     * {@link #setPadding(int, int, int, int)}.
7130     *
7131     * @param d The Drawable to use as the background, or null to remove the
7132     *        background
7133     */
7134    public void setBackgroundDrawable(Drawable d) {
7135        boolean requestLayout = false;
7136
7137        mBackgroundResource = 0;
7138
7139        /*
7140         * Regardless of whether we're setting a new background or not, we want
7141         * to clear the previous drawable.
7142         */
7143        if (mBGDrawable != null) {
7144            mBGDrawable.setCallback(null);
7145            unscheduleDrawable(mBGDrawable);
7146        }
7147
7148        if (d != null) {
7149            Rect padding = sThreadLocal.get();
7150            if (padding == null) {
7151                padding = new Rect();
7152                sThreadLocal.set(padding);
7153            }
7154            if (d.getPadding(padding)) {
7155                setPadding(padding.left, padding.top, padding.right, padding.bottom);
7156            }
7157
7158            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
7159            // if it has a different minimum size, we should layout again
7160            if (mBGDrawable == null || mBGDrawable.getMinimumHeight() != d.getMinimumHeight() ||
7161                    mBGDrawable.getMinimumWidth() != d.getMinimumWidth()) {
7162                requestLayout = true;
7163            }
7164
7165            d.setCallback(this);
7166            if (d.isStateful()) {
7167                d.setState(getDrawableState());
7168            }
7169            d.setVisible(getVisibility() == VISIBLE, false);
7170            mBGDrawable = d;
7171
7172            if ((mPrivateFlags & SKIP_DRAW) != 0) {
7173                mPrivateFlags &= ~SKIP_DRAW;
7174                mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
7175                requestLayout = true;
7176            }
7177        } else {
7178            /* Remove the background */
7179            mBGDrawable = null;
7180
7181            if ((mPrivateFlags & ONLY_DRAWS_BACKGROUND) != 0) {
7182                /*
7183                 * This view ONLY drew the background before and we're removing
7184                 * the background, so now it won't draw anything
7185                 * (hence we SKIP_DRAW)
7186                 */
7187                mPrivateFlags &= ~ONLY_DRAWS_BACKGROUND;
7188                mPrivateFlags |= SKIP_DRAW;
7189            }
7190
7191            /*
7192             * When the background is set, we try to apply its padding to this
7193             * View. When the background is removed, we don't touch this View's
7194             * padding. This is noted in the Javadocs. Hence, we don't need to
7195             * requestLayout(), the invalidate() below is sufficient.
7196             */
7197
7198            // The old background's minimum size could have affected this
7199            // View's layout, so let's requestLayout
7200            requestLayout = true;
7201        }
7202
7203        computeOpaqueFlags();
7204
7205        if (requestLayout) {
7206            requestLayout();
7207        }
7208
7209        mBackgroundSizeChanged = true;
7210        invalidate();
7211    }
7212
7213    /**
7214     * Gets the background drawable
7215     * @return The drawable used as the background for this view, if any.
7216     */
7217    public Drawable getBackground() {
7218        return mBGDrawable;
7219    }
7220
7221    /**
7222     * Sets the padding. The view may add on the space required to display
7223     * the scrollbars, depending on the style and visibility of the scrollbars.
7224     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
7225     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
7226     * from the values set in this call.
7227     *
7228     * @attr ref android.R.styleable#View_padding
7229     * @attr ref android.R.styleable#View_paddingBottom
7230     * @attr ref android.R.styleable#View_paddingLeft
7231     * @attr ref android.R.styleable#View_paddingRight
7232     * @attr ref android.R.styleable#View_paddingTop
7233     * @param left the left padding in pixels
7234     * @param top the top padding in pixels
7235     * @param right the right padding in pixels
7236     * @param bottom the bottom padding in pixels
7237     */
7238    public void setPadding(int left, int top, int right, int bottom) {
7239        boolean changed = false;
7240
7241        mUserPaddingRight = right;
7242        mUserPaddingBottom = bottom;
7243
7244        final int viewFlags = mViewFlags;
7245
7246        // Common case is there are no scroll bars.
7247        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
7248            // TODO: Deal with RTL languages to adjust left padding instead of right.
7249            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
7250                right += (viewFlags & SCROLLBARS_INSET_MASK) == 0
7251                        ? 0 : getVerticalScrollbarWidth();
7252            }
7253            if ((viewFlags & SCROLLBARS_HORIZONTAL) == 0) {
7254                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
7255                        ? 0 : getHorizontalScrollbarHeight();
7256            }
7257        }
7258
7259        if (mPaddingLeft != left) {
7260            changed = true;
7261            mPaddingLeft = left;
7262        }
7263        if (mPaddingTop != top) {
7264            changed = true;
7265            mPaddingTop = top;
7266        }
7267        if (mPaddingRight != right) {
7268            changed = true;
7269            mPaddingRight = right;
7270        }
7271        if (mPaddingBottom != bottom) {
7272            changed = true;
7273            mPaddingBottom = bottom;
7274        }
7275
7276        if (changed) {
7277            requestLayout();
7278        }
7279    }
7280
7281    /**
7282     * Returns the top padding of this view.
7283     *
7284     * @return the top padding in pixels
7285     */
7286    public int getPaddingTop() {
7287        return mPaddingTop;
7288    }
7289
7290    /**
7291     * Returns the bottom padding of this view. If there are inset and enabled
7292     * scrollbars, this value may include the space required to display the
7293     * scrollbars as well.
7294     *
7295     * @return the bottom padding in pixels
7296     */
7297    public int getPaddingBottom() {
7298        return mPaddingBottom;
7299    }
7300
7301    /**
7302     * Returns the left padding of this view. If there are inset and enabled
7303     * scrollbars, this value may include the space required to display the
7304     * scrollbars as well.
7305     *
7306     * @return the left padding in pixels
7307     */
7308    public int getPaddingLeft() {
7309        return mPaddingLeft;
7310    }
7311
7312    /**
7313     * Returns the right padding of this view. If there are inset and enabled
7314     * scrollbars, this value may include the space required to display the
7315     * scrollbars as well.
7316     *
7317     * @return the right padding in pixels
7318     */
7319    public int getPaddingRight() {
7320        return mPaddingRight;
7321    }
7322
7323    /**
7324     * Changes the selection state of this view. A view can be selected or not.
7325     * Note that selection is not the same as focus. Views are typically
7326     * selected in the context of an AdapterView like ListView or GridView;
7327     * the selected view is the view that is highlighted.
7328     *
7329     * @param selected true if the view must be selected, false otherwise
7330     */
7331    public void setSelected(boolean selected) {
7332        if (((mPrivateFlags & SELECTED) != 0) != selected) {
7333            mPrivateFlags = (mPrivateFlags & ~SELECTED) | (selected ? SELECTED : 0);
7334            if (!selected) resetPressedState();
7335            invalidate();
7336            refreshDrawableState();
7337            dispatchSetSelected(selected);
7338        }
7339    }
7340
7341    /**
7342     * Dispatch setSelected to all of this View's children.
7343     *
7344     * @see #setSelected(boolean)
7345     *
7346     * @param selected The new selected state
7347     */
7348    protected void dispatchSetSelected(boolean selected) {
7349    }
7350
7351    /**
7352     * Indicates the selection state of this view.
7353     *
7354     * @return true if the view is selected, false otherwise
7355     */
7356    @ViewDebug.ExportedProperty
7357    public boolean isSelected() {
7358        return (mPrivateFlags & SELECTED) != 0;
7359    }
7360
7361    /**
7362     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
7363     * observer can be used to get notifications when global events, like
7364     * layout, happen.
7365     *
7366     * The returned ViewTreeObserver observer is not guaranteed to remain
7367     * valid for the lifetime of this View. If the caller of this method keeps
7368     * a long-lived reference to ViewTreeObserver, it should always check for
7369     * the return value of {@link ViewTreeObserver#isAlive()}.
7370     *
7371     * @return The ViewTreeObserver for this view's hierarchy.
7372     */
7373    public ViewTreeObserver getViewTreeObserver() {
7374        if (mAttachInfo != null) {
7375            return mAttachInfo.mTreeObserver;
7376        }
7377        if (mFloatingTreeObserver == null) {
7378            mFloatingTreeObserver = new ViewTreeObserver();
7379        }
7380        return mFloatingTreeObserver;
7381    }
7382
7383    /**
7384     * <p>Finds the topmost view in the current view hierarchy.</p>
7385     *
7386     * @return the topmost view containing this view
7387     */
7388    public View getRootView() {
7389        if (mAttachInfo != null) {
7390            final View v = mAttachInfo.mRootView;
7391            if (v != null) {
7392                return v;
7393            }
7394        }
7395
7396        View parent = this;
7397
7398        while (parent.mParent != null && parent.mParent instanceof View) {
7399            parent = (View) parent.mParent;
7400        }
7401
7402        return parent;
7403    }
7404
7405    /**
7406     * <p>Computes the coordinates of this view on the screen. The argument
7407     * must be an array of two integers. After the method returns, the array
7408     * contains the x and y location in that order.</p>
7409     *
7410     * @param location an array of two integers in which to hold the coordinates
7411     */
7412    public void getLocationOnScreen(int[] location) {
7413        getLocationInWindow(location);
7414
7415        final AttachInfo info = mAttachInfo;
7416        if (info != null) {
7417            location[0] += info.mWindowLeft;
7418            location[1] += info.mWindowTop;
7419        }
7420    }
7421
7422    /**
7423     * <p>Computes the coordinates of this view in its window. The argument
7424     * must be an array of two integers. After the method returns, the array
7425     * contains the x and y location in that order.</p>
7426     *
7427     * @param location an array of two integers in which to hold the coordinates
7428     */
7429    public void getLocationInWindow(int[] location) {
7430        if (location == null || location.length < 2) {
7431            throw new IllegalArgumentException("location must be an array of "
7432                    + "two integers");
7433        }
7434
7435        location[0] = mLeft;
7436        location[1] = mTop;
7437
7438        ViewParent viewParent = mParent;
7439        while (viewParent instanceof View) {
7440            final View view = (View)viewParent;
7441            location[0] += view.mLeft - view.mScrollX;
7442            location[1] += view.mTop - view.mScrollY;
7443            viewParent = view.mParent;
7444        }
7445
7446        if (viewParent instanceof ViewRoot) {
7447            // *cough*
7448            final ViewRoot vr = (ViewRoot)viewParent;
7449            location[1] -= vr.mCurScrollY;
7450        }
7451    }
7452
7453    /**
7454     * {@hide}
7455     * @param id the id of the view to be found
7456     * @return the view of the specified id, null if cannot be found
7457     */
7458    protected View findViewTraversal(int id) {
7459        if (id == mID) {
7460            return this;
7461        }
7462        return null;
7463    }
7464
7465    /**
7466     * {@hide}
7467     * @param tag the tag of the view to be found
7468     * @return the view of specified tag, null if cannot be found
7469     */
7470    protected View findViewWithTagTraversal(Object tag) {
7471        if (tag != null && tag.equals(mTag)) {
7472            return this;
7473        }
7474        return null;
7475    }
7476
7477    /**
7478     * Look for a child view with the given id.  If this view has the given
7479     * id, return this view.
7480     *
7481     * @param id The id to search for.
7482     * @return The view that has the given id in the hierarchy or null
7483     */
7484    public final View findViewById(int id) {
7485        if (id < 0) {
7486            return null;
7487        }
7488        return findViewTraversal(id);
7489    }
7490
7491    /**
7492     * Look for a child view with the given tag.  If this view has the given
7493     * tag, return this view.
7494     *
7495     * @param tag The tag to search for, using "tag.equals(getTag())".
7496     * @return The View that has the given tag in the hierarchy or null
7497     */
7498    public final View findViewWithTag(Object tag) {
7499        if (tag == null) {
7500            return null;
7501        }
7502        return findViewWithTagTraversal(tag);
7503    }
7504
7505    /**
7506     * Sets the identifier for this view. The identifier does not have to be
7507     * unique in this view's hierarchy. The identifier should be a positive
7508     * number.
7509     *
7510     * @see #NO_ID
7511     * @see #getId
7512     * @see #findViewById
7513     *
7514     * @param id a number used to identify the view
7515     *
7516     * @attr ref android.R.styleable#View_id
7517     */
7518    public void setId(int id) {
7519        mID = id;
7520    }
7521
7522    /**
7523     * {@hide}
7524     *
7525     * @param isRoot true if the view belongs to the root namespace, false
7526     *        otherwise
7527     */
7528    public void setIsRootNamespace(boolean isRoot) {
7529        if (isRoot) {
7530            mPrivateFlags |= IS_ROOT_NAMESPACE;
7531        } else {
7532            mPrivateFlags &= ~IS_ROOT_NAMESPACE;
7533        }
7534    }
7535
7536    /**
7537     * {@hide}
7538     *
7539     * @return true if the view belongs to the root namespace, false otherwise
7540     */
7541    public boolean isRootNamespace() {
7542        return (mPrivateFlags&IS_ROOT_NAMESPACE) != 0;
7543    }
7544
7545    /**
7546     * Returns this view's identifier.
7547     *
7548     * @return a positive integer used to identify the view or {@link #NO_ID}
7549     *         if the view has no ID
7550     *
7551     * @see #setId
7552     * @see #findViewById
7553     * @attr ref android.R.styleable#View_id
7554     */
7555    @ViewDebug.CapturedViewProperty
7556    public int getId() {
7557        return mID;
7558    }
7559
7560    /**
7561     * Returns this view's tag.
7562     *
7563     * @return the Object stored in this view as a tag
7564     *
7565     * @see #setTag(Object)
7566     * @see #getTag(int)
7567     */
7568    @ViewDebug.ExportedProperty
7569    public Object getTag() {
7570        return mTag;
7571    }
7572
7573    /**
7574     * Sets the tag associated with this view. A tag can be used to mark
7575     * a view in its hierarchy and does not have to be unique within the
7576     * hierarchy. Tags can also be used to store data within a view without
7577     * resorting to another data structure.
7578     *
7579     * @param tag an Object to tag the view with
7580     *
7581     * @see #getTag()
7582     * @see #setTag(int, Object)
7583     */
7584    public void setTag(final Object tag) {
7585        mTag = tag;
7586    }
7587
7588    /**
7589     * Returns the tag associated with this view and the specified key.
7590     *
7591     * @param key The key identifying the tag
7592     *
7593     * @return the Object stored in this view as a tag
7594     *
7595     * @see #setTag(int, Object)
7596     * @see #getTag()
7597     */
7598    public Object getTag(int key) {
7599        SparseArray<Object> tags = null;
7600        synchronized (sTagsLock) {
7601            if (sTags != null) {
7602                tags = sTags.get(this);
7603            }
7604        }
7605
7606        if (tags != null) return tags.get(key);
7607        return null;
7608    }
7609
7610    /**
7611     * Sets a tag associated with this view and a key. A tag can be used
7612     * to mark a view in its hierarchy and does not have to be unique within
7613     * the hierarchy. Tags can also be used to store data within a view
7614     * without resorting to another data structure.
7615     *
7616     * The specified key should be an id declared in the resources of the
7617     * application to ensure it is unique. Keys identified as belonging to
7618     * the Android framework or not associated with any package will cause
7619     * an {@link IllegalArgumentException} to be thrown.
7620     *
7621     * @param key The key identifying the tag
7622     * @param tag An Object to tag the view with
7623     *
7624     * @throws IllegalArgumentException If they specified key is not valid
7625     *
7626     * @see #setTag(Object)
7627     * @see #getTag(int)
7628     */
7629    public void setTag(int key, final Object tag) {
7630        // If the package id is 0x00 or 0x01, it's either an undefined package
7631        // or a framework id
7632        if ((key >>> 24) < 2) {
7633            throw new IllegalArgumentException("The key must be an application-specific "
7634                    + "resource id.");
7635        }
7636
7637        setTagInternal(this, key, tag);
7638    }
7639
7640    /**
7641     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
7642     * framework id.
7643     *
7644     * @hide
7645     */
7646    public void setTagInternal(int key, Object tag) {
7647        if ((key >>> 24) != 0x1) {
7648            throw new IllegalArgumentException("The key must be a framework-specific "
7649                    + "resource id.");
7650        }
7651
7652        setTagInternal(this, key, tag);
7653    }
7654
7655    private static void setTagInternal(View view, int key, Object tag) {
7656        SparseArray<Object> tags = null;
7657        synchronized (sTagsLock) {
7658            if (sTags == null) {
7659                sTags = new WeakHashMap<View, SparseArray<Object>>();
7660            } else {
7661                tags = sTags.get(view);
7662            }
7663        }
7664
7665        if (tags == null) {
7666            tags = new SparseArray<Object>(2);
7667            synchronized (sTagsLock) {
7668                sTags.put(view, tags);
7669            }
7670        }
7671
7672        tags.put(key, tag);
7673    }
7674
7675    /**
7676     * @param consistency The type of consistency. See ViewDebug for more information.
7677     *
7678     * @hide
7679     */
7680    protected boolean dispatchConsistencyCheck(int consistency) {
7681        return onConsistencyCheck(consistency);
7682    }
7683
7684    /**
7685     * Method that subclasses should implement to check their consistency. The type of
7686     * consistency check is indicated by the bit field passed as a parameter.
7687     *
7688     * @param consistency The type of consistency. See ViewDebug for more information.
7689     *
7690     * @throws IllegalStateException if the view is in an inconsistent state.
7691     *
7692     * @hide
7693     */
7694    protected boolean onConsistencyCheck(int consistency) {
7695        boolean result = true;
7696
7697        final boolean checkLayout = (consistency & ViewDebug.CONSISTENCY_LAYOUT) != 0;
7698        final boolean checkDrawing = (consistency & ViewDebug.CONSISTENCY_DRAWING) != 0;
7699
7700        if (checkLayout) {
7701            if (getParent() == null) {
7702                result = false;
7703                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
7704                        "View " + this + " does not have a parent.");
7705            }
7706
7707            if (mAttachInfo == null) {
7708                result = false;
7709                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
7710                        "View " + this + " is not attached to a window.");
7711            }
7712        }
7713
7714        if (checkDrawing) {
7715            // Do not check the DIRTY/DRAWN flags because views can call invalidate()
7716            // from their draw() method
7717
7718            if ((mPrivateFlags & DRAWN) != DRAWN &&
7719                    (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
7720                result = false;
7721                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
7722                        "View " + this + " was invalidated but its drawing cache is valid.");
7723            }
7724        }
7725
7726        return result;
7727    }
7728
7729    /**
7730     * Prints information about this view in the log output, with the tag
7731     * {@link #VIEW_LOG_TAG}.
7732     *
7733     * @hide
7734     */
7735    public void debug() {
7736        debug(0);
7737    }
7738
7739    /**
7740     * Prints information about this view in the log output, with the tag
7741     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
7742     * indentation defined by the <code>depth</code>.
7743     *
7744     * @param depth the indentation level
7745     *
7746     * @hide
7747     */
7748    protected void debug(int depth) {
7749        String output = debugIndent(depth - 1);
7750
7751        output += "+ " + this;
7752        int id = getId();
7753        if (id != -1) {
7754            output += " (id=" + id + ")";
7755        }
7756        Object tag = getTag();
7757        if (tag != null) {
7758            output += " (tag=" + tag + ")";
7759        }
7760        Log.d(VIEW_LOG_TAG, output);
7761
7762        if ((mPrivateFlags & FOCUSED) != 0) {
7763            output = debugIndent(depth) + " FOCUSED";
7764            Log.d(VIEW_LOG_TAG, output);
7765        }
7766
7767        output = debugIndent(depth);
7768        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
7769                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
7770                + "} ";
7771        Log.d(VIEW_LOG_TAG, output);
7772
7773        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
7774                || mPaddingBottom != 0) {
7775            output = debugIndent(depth);
7776            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
7777                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
7778            Log.d(VIEW_LOG_TAG, output);
7779        }
7780
7781        output = debugIndent(depth);
7782        output += "mMeasureWidth=" + mMeasuredWidth +
7783                " mMeasureHeight=" + mMeasuredHeight;
7784        Log.d(VIEW_LOG_TAG, output);
7785
7786        output = debugIndent(depth);
7787        if (mLayoutParams == null) {
7788            output += "BAD! no layout params";
7789        } else {
7790            output = mLayoutParams.debug(output);
7791        }
7792        Log.d(VIEW_LOG_TAG, output);
7793
7794        output = debugIndent(depth);
7795        output += "flags={";
7796        output += View.printFlags(mViewFlags);
7797        output += "}";
7798        Log.d(VIEW_LOG_TAG, output);
7799
7800        output = debugIndent(depth);
7801        output += "privateFlags={";
7802        output += View.printPrivateFlags(mPrivateFlags);
7803        output += "}";
7804        Log.d(VIEW_LOG_TAG, output);
7805    }
7806
7807    /**
7808     * Creates an string of whitespaces used for indentation.
7809     *
7810     * @param depth the indentation level
7811     * @return a String containing (depth * 2 + 3) * 2 white spaces
7812     *
7813     * @hide
7814     */
7815    protected static String debugIndent(int depth) {
7816        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
7817        for (int i = 0; i < (depth * 2) + 3; i++) {
7818            spaces.append(' ').append(' ');
7819        }
7820        return spaces.toString();
7821    }
7822
7823    /**
7824     * <p>Return the offset of the widget's text baseline from the widget's top
7825     * boundary. If this widget does not support baseline alignment, this
7826     * method returns -1. </p>
7827     *
7828     * @return the offset of the baseline within the widget's bounds or -1
7829     *         if baseline alignment is not supported
7830     */
7831    @ViewDebug.ExportedProperty
7832    public int getBaseline() {
7833        return -1;
7834    }
7835
7836    /**
7837     * Call this when something has changed which has invalidated the
7838     * layout of this view. This will schedule a layout pass of the view
7839     * tree.
7840     */
7841    public void requestLayout() {
7842        if (ViewDebug.TRACE_HIERARCHY) {
7843            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.REQUEST_LAYOUT);
7844        }
7845
7846        mPrivateFlags |= FORCE_LAYOUT;
7847
7848        if (mParent != null && !mParent.isLayoutRequested()) {
7849            mParent.requestLayout();
7850        }
7851    }
7852
7853    /**
7854     * Forces this view to be laid out during the next layout pass.
7855     * This method does not call requestLayout() or forceLayout()
7856     * on the parent.
7857     */
7858    public void forceLayout() {
7859        mPrivateFlags |= FORCE_LAYOUT;
7860    }
7861
7862    /**
7863     * <p>
7864     * This is called to find out how big a view should be. The parent
7865     * supplies constraint information in the width and height parameters.
7866     * </p>
7867     *
7868     * <p>
7869     * The actual mesurement work of a view is performed in
7870     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
7871     * {@link #onMeasure(int, int)} can and must be overriden by subclasses.
7872     * </p>
7873     *
7874     *
7875     * @param widthMeasureSpec Horizontal space requirements as imposed by the
7876     *        parent
7877     * @param heightMeasureSpec Vertical space requirements as imposed by the
7878     *        parent
7879     *
7880     * @see #onMeasure(int, int)
7881     */
7882    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
7883        if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||
7884                widthMeasureSpec != mOldWidthMeasureSpec ||
7885                heightMeasureSpec != mOldHeightMeasureSpec) {
7886
7887            // first clears the measured dimension flag
7888            mPrivateFlags &= ~MEASURED_DIMENSION_SET;
7889
7890            if (ViewDebug.TRACE_HIERARCHY) {
7891                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE);
7892            }
7893
7894            // measure ourselves, this should set the measured dimension flag back
7895            onMeasure(widthMeasureSpec, heightMeasureSpec);
7896
7897            // flag not set, setMeasuredDimension() was not invoked, we raise
7898            // an exception to warn the developer
7899            if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {
7900                throw new IllegalStateException("onMeasure() did not set the"
7901                        + " measured dimension by calling"
7902                        + " setMeasuredDimension()");
7903            }
7904
7905            mPrivateFlags |= LAYOUT_REQUIRED;
7906        }
7907
7908        mOldWidthMeasureSpec = widthMeasureSpec;
7909        mOldHeightMeasureSpec = heightMeasureSpec;
7910    }
7911
7912    /**
7913     * <p>
7914     * Measure the view and its content to determine the measured width and the
7915     * measured height. This method is invoked by {@link #measure(int, int)} and
7916     * should be overriden by subclasses to provide accurate and efficient
7917     * measurement of their contents.
7918     * </p>
7919     *
7920     * <p>
7921     * <strong>CONTRACT:</strong> When overriding this method, you
7922     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
7923     * measured width and height of this view. Failure to do so will trigger an
7924     * <code>IllegalStateException</code>, thrown by
7925     * {@link #measure(int, int)}. Calling the superclass'
7926     * {@link #onMeasure(int, int)} is a valid use.
7927     * </p>
7928     *
7929     * <p>
7930     * The base class implementation of measure defaults to the background size,
7931     * unless a larger size is allowed by the MeasureSpec. Subclasses should
7932     * override {@link #onMeasure(int, int)} to provide better measurements of
7933     * their content.
7934     * </p>
7935     *
7936     * <p>
7937     * If this method is overridden, it is the subclass's responsibility to make
7938     * sure the measured height and width are at least the view's minimum height
7939     * and width ({@link #getSuggestedMinimumHeight()} and
7940     * {@link #getSuggestedMinimumWidth()}).
7941     * </p>
7942     *
7943     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
7944     *                         The requirements are encoded with
7945     *                         {@link android.view.View.MeasureSpec}.
7946     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
7947     *                         The requirements are encoded with
7948     *                         {@link android.view.View.MeasureSpec}.
7949     *
7950     * @see #getMeasuredWidth()
7951     * @see #getMeasuredHeight()
7952     * @see #setMeasuredDimension(int, int)
7953     * @see #getSuggestedMinimumHeight()
7954     * @see #getSuggestedMinimumWidth()
7955     * @see android.view.View.MeasureSpec#getMode(int)
7956     * @see android.view.View.MeasureSpec#getSize(int)
7957     */
7958    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
7959        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
7960                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
7961    }
7962
7963    /**
7964     * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the
7965     * measured width and measured height. Failing to do so will trigger an
7966     * exception at measurement time.</p>
7967     *
7968     * @param measuredWidth the measured width of this view
7969     * @param measuredHeight the measured height of this view
7970     */
7971    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
7972        mMeasuredWidth = measuredWidth;
7973        mMeasuredHeight = measuredHeight;
7974
7975        mPrivateFlags |= MEASURED_DIMENSION_SET;
7976    }
7977
7978    /**
7979     * Utility to reconcile a desired size with constraints imposed by a MeasureSpec.
7980     * Will take the desired size, unless a different size is imposed by the constraints.
7981     *
7982     * @param size How big the view wants to be
7983     * @param measureSpec Constraints imposed by the parent
7984     * @return The size this view should be.
7985     */
7986    public static int resolveSize(int size, int measureSpec) {
7987        int result = size;
7988        int specMode = MeasureSpec.getMode(measureSpec);
7989        int specSize =  MeasureSpec.getSize(measureSpec);
7990        switch (specMode) {
7991        case MeasureSpec.UNSPECIFIED:
7992            result = size;
7993            break;
7994        case MeasureSpec.AT_MOST:
7995            result = Math.min(size, specSize);
7996            break;
7997        case MeasureSpec.EXACTLY:
7998            result = specSize;
7999            break;
8000        }
8001        return result;
8002    }
8003
8004    /**
8005     * Utility to return a default size. Uses the supplied size if the
8006     * MeasureSpec imposed no contraints. Will get larger if allowed
8007     * by the MeasureSpec.
8008     *
8009     * @param size Default size for this view
8010     * @param measureSpec Constraints imposed by the parent
8011     * @return The size this view should be.
8012     */
8013    public static int getDefaultSize(int size, int measureSpec) {
8014        int result = size;
8015        int specMode = MeasureSpec.getMode(measureSpec);
8016        int specSize =  MeasureSpec.getSize(measureSpec);
8017
8018        switch (specMode) {
8019        case MeasureSpec.UNSPECIFIED:
8020            result = size;
8021            break;
8022        case MeasureSpec.AT_MOST:
8023        case MeasureSpec.EXACTLY:
8024            result = specSize;
8025            break;
8026        }
8027        return result;
8028    }
8029
8030    /**
8031     * Returns the suggested minimum height that the view should use. This
8032     * returns the maximum of the view's minimum height
8033     * and the background's minimum height
8034     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
8035     * <p>
8036     * When being used in {@link #onMeasure(int, int)}, the caller should still
8037     * ensure the returned height is within the requirements of the parent.
8038     *
8039     * @return The suggested minimum height of the view.
8040     */
8041    protected int getSuggestedMinimumHeight() {
8042        int suggestedMinHeight = mMinHeight;
8043
8044        if (mBGDrawable != null) {
8045            final int bgMinHeight = mBGDrawable.getMinimumHeight();
8046            if (suggestedMinHeight < bgMinHeight) {
8047                suggestedMinHeight = bgMinHeight;
8048            }
8049        }
8050
8051        return suggestedMinHeight;
8052    }
8053
8054    /**
8055     * Returns the suggested minimum width that the view should use. This
8056     * returns the maximum of the view's minimum width)
8057     * and the background's minimum width
8058     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
8059     * <p>
8060     * When being used in {@link #onMeasure(int, int)}, the caller should still
8061     * ensure the returned width is within the requirements of the parent.
8062     *
8063     * @return The suggested minimum width of the view.
8064     */
8065    protected int getSuggestedMinimumWidth() {
8066        int suggestedMinWidth = mMinWidth;
8067
8068        if (mBGDrawable != null) {
8069            final int bgMinWidth = mBGDrawable.getMinimumWidth();
8070            if (suggestedMinWidth < bgMinWidth) {
8071                suggestedMinWidth = bgMinWidth;
8072            }
8073        }
8074
8075        return suggestedMinWidth;
8076    }
8077
8078    /**
8079     * Sets the minimum height of the view. It is not guaranteed the view will
8080     * be able to achieve this minimum height (for example, if its parent layout
8081     * constrains it with less available height).
8082     *
8083     * @param minHeight The minimum height the view will try to be.
8084     */
8085    public void setMinimumHeight(int minHeight) {
8086        mMinHeight = minHeight;
8087    }
8088
8089    /**
8090     * Sets the minimum width of the view. It is not guaranteed the view will
8091     * be able to achieve this minimum width (for example, if its parent layout
8092     * constrains it with less available width).
8093     *
8094     * @param minWidth The minimum width the view will try to be.
8095     */
8096    public void setMinimumWidth(int minWidth) {
8097        mMinWidth = minWidth;
8098    }
8099
8100    /**
8101     * Get the animation currently associated with this view.
8102     *
8103     * @return The animation that is currently playing or
8104     *         scheduled to play for this view.
8105     */
8106    public Animation getAnimation() {
8107        return mCurrentAnimation;
8108    }
8109
8110    /**
8111     * Start the specified animation now.
8112     *
8113     * @param animation the animation to start now
8114     */
8115    public void startAnimation(Animation animation) {
8116        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
8117        setAnimation(animation);
8118        invalidate();
8119    }
8120
8121    /**
8122     * Cancels any animations for this view.
8123     */
8124    public void clearAnimation() {
8125        mCurrentAnimation = null;
8126    }
8127
8128    /**
8129     * Sets the next animation to play for this view.
8130     * If you want the animation to play immediately, use
8131     * startAnimation. This method provides allows fine-grained
8132     * control over the start time and invalidation, but you
8133     * must make sure that 1) the animation has a start time set, and
8134     * 2) the view will be invalidated when the animation is supposed to
8135     * start.
8136     *
8137     * @param animation The next animation, or null.
8138     */
8139    public void setAnimation(Animation animation) {
8140        mCurrentAnimation = animation;
8141        if (animation != null) {
8142            animation.reset();
8143        }
8144    }
8145
8146    /**
8147     * Invoked by a parent ViewGroup to notify the start of the animation
8148     * currently associated with this view. If you override this method,
8149     * always call super.onAnimationStart();
8150     *
8151     * @see #setAnimation(android.view.animation.Animation)
8152     * @see #getAnimation()
8153     */
8154    protected void onAnimationStart() {
8155        mPrivateFlags |= ANIMATION_STARTED;
8156    }
8157
8158    /**
8159     * Invoked by a parent ViewGroup to notify the end of the animation
8160     * currently associated with this view. If you override this method,
8161     * always call super.onAnimationEnd();
8162     *
8163     * @see #setAnimation(android.view.animation.Animation)
8164     * @see #getAnimation()
8165     */
8166    protected void onAnimationEnd() {
8167        mPrivateFlags &= ~ANIMATION_STARTED;
8168    }
8169
8170    /**
8171     * Invoked if there is a Transform that involves alpha. Subclass that can
8172     * draw themselves with the specified alpha should return true, and then
8173     * respect that alpha when their onDraw() is called. If this returns false
8174     * then the view may be redirected to draw into an offscreen buffer to
8175     * fulfill the request, which will look fine, but may be slower than if the
8176     * subclass handles it internally. The default implementation returns false.
8177     *
8178     * @param alpha The alpha (0..255) to apply to the view's drawing
8179     * @return true if the view can draw with the specified alpha.
8180     */
8181    protected boolean onSetAlpha(int alpha) {
8182        return false;
8183    }
8184
8185    /**
8186     * This is used by the RootView to perform an optimization when
8187     * the view hierarchy contains one or several SurfaceView.
8188     * SurfaceView is always considered transparent, but its children are not,
8189     * therefore all View objects remove themselves from the global transparent
8190     * region (passed as a parameter to this function).
8191     *
8192     * @param region The transparent region for this ViewRoot (window).
8193     *
8194     * @return Returns true if the effective visibility of the view at this
8195     * point is opaque, regardless of the transparent region; returns false
8196     * if it is possible for underlying windows to be seen behind the view.
8197     *
8198     * {@hide}
8199     */
8200    public boolean gatherTransparentRegion(Region region) {
8201        final AttachInfo attachInfo = mAttachInfo;
8202        if (region != null && attachInfo != null) {
8203            final int pflags = mPrivateFlags;
8204            if ((pflags & SKIP_DRAW) == 0) {
8205                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
8206                // remove it from the transparent region.
8207                final int[] location = attachInfo.mTransparentLocation;
8208                getLocationInWindow(location);
8209                region.op(location[0], location[1], location[0] + mRight - mLeft,
8210                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
8211            } else if ((pflags & ONLY_DRAWS_BACKGROUND) != 0 && mBGDrawable != null) {
8212                // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
8213                // exists, so we remove the background drawable's non-transparent
8214                // parts from this transparent region.
8215                applyDrawableToTransparentRegion(mBGDrawable, region);
8216            }
8217        }
8218        return true;
8219    }
8220
8221    /**
8222     * Play a sound effect for this view.
8223     *
8224     * <p>The framework will play sound effects for some built in actions, such as
8225     * clicking, but you may wish to play these effects in your widget,
8226     * for instance, for internal navigation.
8227     *
8228     * <p>The sound effect will only be played if sound effects are enabled by the user, and
8229     * {@link #isSoundEffectsEnabled()} is true.
8230     *
8231     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
8232     */
8233    public void playSoundEffect(int soundConstant) {
8234        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
8235            return;
8236        }
8237        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
8238    }
8239
8240    /**
8241     * BZZZTT!!1!
8242     *
8243     * <p>Provide haptic feedback to the user for this view.
8244     *
8245     * <p>The framework will provide haptic feedback for some built in actions,
8246     * such as long presses, but you may wish to provide feedback for your
8247     * own widget.
8248     *
8249     * <p>The feedback will only be performed if
8250     * {@link #isHapticFeedbackEnabled()} is true.
8251     *
8252     * @param feedbackConstant One of the constants defined in
8253     * {@link HapticFeedbackConstants}
8254     */
8255    public boolean performHapticFeedback(int feedbackConstant) {
8256        return performHapticFeedback(feedbackConstant, 0);
8257    }
8258
8259    /**
8260     * BZZZTT!!1!
8261     *
8262     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
8263     *
8264     * @param feedbackConstant One of the constants defined in
8265     * {@link HapticFeedbackConstants}
8266     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
8267     */
8268    public boolean performHapticFeedback(int feedbackConstant, int flags) {
8269        if (mAttachInfo == null) {
8270            return false;
8271        }
8272        if ((flags&HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
8273                && !isHapticFeedbackEnabled()) {
8274            return false;
8275        }
8276        return mAttachInfo.mRootCallbacks.performHapticFeedback(
8277                feedbackConstant,
8278                (flags&HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
8279    }
8280
8281    /**
8282     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
8283     * it is ever exposed at all.
8284     */
8285    public void onCloseSystemDialogs(String reason) {
8286    }
8287
8288    /**
8289     * Given a Drawable whose bounds have been set to draw into this view,
8290     * update a Region being computed for {@link #gatherTransparentRegion} so
8291     * that any non-transparent parts of the Drawable are removed from the
8292     * given transparent region.
8293     *
8294     * @param dr The Drawable whose transparency is to be applied to the region.
8295     * @param region A Region holding the current transparency information,
8296     * where any parts of the region that are set are considered to be
8297     * transparent.  On return, this region will be modified to have the
8298     * transparency information reduced by the corresponding parts of the
8299     * Drawable that are not transparent.
8300     * {@hide}
8301     */
8302    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
8303        if (DBG) {
8304            Log.i("View", "Getting transparent region for: " + this);
8305        }
8306        final Region r = dr.getTransparentRegion();
8307        final Rect db = dr.getBounds();
8308        final AttachInfo attachInfo = mAttachInfo;
8309        if (r != null && attachInfo != null) {
8310            final int w = getRight()-getLeft();
8311            final int h = getBottom()-getTop();
8312            if (db.left > 0) {
8313                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
8314                r.op(0, 0, db.left, h, Region.Op.UNION);
8315            }
8316            if (db.right < w) {
8317                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
8318                r.op(db.right, 0, w, h, Region.Op.UNION);
8319            }
8320            if (db.top > 0) {
8321                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
8322                r.op(0, 0, w, db.top, Region.Op.UNION);
8323            }
8324            if (db.bottom < h) {
8325                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
8326                r.op(0, db.bottom, w, h, Region.Op.UNION);
8327            }
8328            final int[] location = attachInfo.mTransparentLocation;
8329            getLocationInWindow(location);
8330            r.translate(location[0], location[1]);
8331            region.op(r, Region.Op.INTERSECT);
8332        } else {
8333            region.op(db, Region.Op.DIFFERENCE);
8334        }
8335    }
8336
8337    private void postCheckForLongClick() {
8338        mHasPerformedLongPress = false;
8339
8340        if (mPendingCheckForLongPress == null) {
8341            mPendingCheckForLongPress = new CheckForLongPress();
8342        }
8343        mPendingCheckForLongPress.rememberWindowAttachCount();
8344        postDelayed(mPendingCheckForLongPress, ViewConfiguration.getLongPressTimeout());
8345    }
8346
8347    private static int[] stateSetUnion(final int[] stateSet1,
8348                                       final int[] stateSet2) {
8349        final int stateSet1Length = stateSet1.length;
8350        final int stateSet2Length = stateSet2.length;
8351        final int[] newSet = new int[stateSet1Length + stateSet2Length];
8352        int k = 0;
8353        int i = 0;
8354        int j = 0;
8355        // This is a merge of the two input state sets and assumes that the
8356        // input sets are sorted by the order imposed by ViewDrawableStates.
8357        for (int viewState : R.styleable.ViewDrawableStates) {
8358            if (i < stateSet1Length && stateSet1[i] == viewState) {
8359                newSet[k++] = viewState;
8360                i++;
8361            } else if (j < stateSet2Length && stateSet2[j] == viewState) {
8362                newSet[k++] = viewState;
8363                j++;
8364            }
8365            if (k > 1) {
8366                assert(newSet[k - 1] > newSet[k - 2]);
8367            }
8368        }
8369        return newSet;
8370    }
8371
8372    /**
8373     * Inflate a view from an XML resource.  This convenience method wraps the {@link
8374     * LayoutInflater} class, which provides a full range of options for view inflation.
8375     *
8376     * @param context The Context object for your activity or application.
8377     * @param resource The resource ID to inflate
8378     * @param root A view group that will be the parent.  Used to properly inflate the
8379     * layout_* parameters.
8380     * @see LayoutInflater
8381     */
8382    public static View inflate(Context context, int resource, ViewGroup root) {
8383        LayoutInflater factory = LayoutInflater.from(context);
8384        return factory.inflate(resource, root);
8385    }
8386
8387    /**
8388     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
8389     * Each MeasureSpec represents a requirement for either the width or the height.
8390     * A MeasureSpec is comprised of a size and a mode. There are three possible
8391     * modes:
8392     * <dl>
8393     * <dt>UNSPECIFIED</dt>
8394     * <dd>
8395     * The parent has not imposed any constraint on the child. It can be whatever size
8396     * it wants.
8397     * </dd>
8398     *
8399     * <dt>EXACTLY</dt>
8400     * <dd>
8401     * The parent has determined an exact size for the child. The child is going to be
8402     * given those bounds regardless of how big it wants to be.
8403     * </dd>
8404     *
8405     * <dt>AT_MOST</dt>
8406     * <dd>
8407     * The child can be as large as it wants up to the specified size.
8408     * </dd>
8409     * </dl>
8410     *
8411     * MeasureSpecs are implemented as ints to reduce object allocation. This class
8412     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
8413     */
8414    public static class MeasureSpec {
8415        private static final int MODE_SHIFT = 30;
8416        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
8417
8418        /**
8419         * Measure specification mode: The parent has not imposed any constraint
8420         * on the child. It can be whatever size it wants.
8421         */
8422        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
8423
8424        /**
8425         * Measure specification mode: The parent has determined an exact size
8426         * for the child. The child is going to be given those bounds regardless
8427         * of how big it wants to be.
8428         */
8429        public static final int EXACTLY     = 1 << MODE_SHIFT;
8430
8431        /**
8432         * Measure specification mode: The child can be as large as it wants up
8433         * to the specified size.
8434         */
8435        public static final int AT_MOST     = 2 << MODE_SHIFT;
8436
8437        /**
8438         * Creates a measure specification based on the supplied size and mode.
8439         *
8440         * The mode must always be one of the following:
8441         * <ul>
8442         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
8443         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
8444         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
8445         * </ul>
8446         *
8447         * @param size the size of the measure specification
8448         * @param mode the mode of the measure specification
8449         * @return the measure specification based on size and mode
8450         */
8451        public static int makeMeasureSpec(int size, int mode) {
8452            return size + mode;
8453        }
8454
8455        /**
8456         * Extracts the mode from the supplied measure specification.
8457         *
8458         * @param measureSpec the measure specification to extract the mode from
8459         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
8460         *         {@link android.view.View.MeasureSpec#AT_MOST} or
8461         *         {@link android.view.View.MeasureSpec#EXACTLY}
8462         */
8463        public static int getMode(int measureSpec) {
8464            return (measureSpec & MODE_MASK);
8465        }
8466
8467        /**
8468         * Extracts the size from the supplied measure specification.
8469         *
8470         * @param measureSpec the measure specification to extract the size from
8471         * @return the size in pixels defined in the supplied measure specification
8472         */
8473        public static int getSize(int measureSpec) {
8474            return (measureSpec & ~MODE_MASK);
8475        }
8476
8477        /**
8478         * Returns a String representation of the specified measure
8479         * specification.
8480         *
8481         * @param measureSpec the measure specification to convert to a String
8482         * @return a String with the following format: "MeasureSpec: MODE SIZE"
8483         */
8484        public static String toString(int measureSpec) {
8485            int mode = getMode(measureSpec);
8486            int size = getSize(measureSpec);
8487
8488            StringBuilder sb = new StringBuilder("MeasureSpec: ");
8489
8490            if (mode == UNSPECIFIED)
8491                sb.append("UNSPECIFIED ");
8492            else if (mode == EXACTLY)
8493                sb.append("EXACTLY ");
8494            else if (mode == AT_MOST)
8495                sb.append("AT_MOST ");
8496            else
8497                sb.append(mode).append(" ");
8498
8499            sb.append(size);
8500            return sb.toString();
8501        }
8502    }
8503
8504    class CheckForLongPress implements Runnable {
8505
8506        private int mOriginalWindowAttachCount;
8507
8508        public void run() {
8509            if (isPressed() && (mParent != null)
8510                    && mOriginalWindowAttachCount == mWindowAttachCount) {
8511                if (performLongClick()) {
8512                    mHasPerformedLongPress = true;
8513                }
8514            }
8515        }
8516
8517        public void rememberWindowAttachCount() {
8518            mOriginalWindowAttachCount = mWindowAttachCount;
8519        }
8520    }
8521
8522    /**
8523     * Interface definition for a callback to be invoked when a key event is
8524     * dispatched to this view. The callback will be invoked before the key
8525     * event is given to the view.
8526     */
8527    public interface OnKeyListener {
8528        /**
8529         * Called when a key is dispatched to a view. This allows listeners to
8530         * get a chance to respond before the target view.
8531         *
8532         * @param v The view the key has been dispatched to.
8533         * @param keyCode The code for the physical key that was pressed
8534         * @param event The KeyEvent object containing full information about
8535         *        the event.
8536         * @return True if the listener has consumed the event, false otherwise.
8537         */
8538        boolean onKey(View v, int keyCode, KeyEvent event);
8539    }
8540
8541    /**
8542     * Interface definition for a callback to be invoked when a touch event is
8543     * dispatched to this view. The callback will be invoked before the touch
8544     * event is given to the view.
8545     */
8546    public interface OnTouchListener {
8547        /**
8548         * Called when a touch event is dispatched to a view. This allows listeners to
8549         * get a chance to respond before the target view.
8550         *
8551         * @param v The view the touch event has been dispatched to.
8552         * @param event The MotionEvent object containing full information about
8553         *        the event.
8554         * @return True if the listener has consumed the event, false otherwise.
8555         */
8556        boolean onTouch(View v, MotionEvent event);
8557    }
8558
8559    /**
8560     * Interface definition for a callback to be invoked when a view has been clicked and held.
8561     */
8562    public interface OnLongClickListener {
8563        /**
8564         * Called when a view has been clicked and held.
8565         *
8566         * @param v The view that was clicked and held.
8567         *
8568         * return True if the callback consumed the long click, false otherwise
8569         */
8570        boolean onLongClick(View v);
8571    }
8572
8573    /**
8574     * Interface definition for a callback to be invoked when the focus state of
8575     * a view changed.
8576     */
8577    public interface OnFocusChangeListener {
8578        /**
8579         * Called when the focus state of a view has changed.
8580         *
8581         * @param v The view whose state has changed.
8582         * @param hasFocus The new focus state of v.
8583         */
8584        void onFocusChange(View v, boolean hasFocus);
8585    }
8586
8587    /**
8588     * Interface definition for a callback to be invoked when a view is clicked.
8589     */
8590    public interface OnClickListener {
8591        /**
8592         * Called when a view has been clicked.
8593         *
8594         * @param v The view that was clicked.
8595         */
8596        void onClick(View v);
8597    }
8598
8599    /**
8600     * Interface definition for a callback to be invoked when the context menu
8601     * for this view is being built.
8602     */
8603    public interface OnCreateContextMenuListener {
8604        /**
8605         * Called when the context menu for this view is being built. It is not
8606         * safe to hold onto the menu after this method returns.
8607         *
8608         * @param menu The context menu that is being built
8609         * @param v The view for which the context menu is being built
8610         * @param menuInfo Extra information about the item for which the
8611         *            context menu should be shown. This information will vary
8612         *            depending on the class of v.
8613         */
8614        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
8615    }
8616
8617    private final class UnsetPressedState implements Runnable {
8618        public void run() {
8619            setPressed(false);
8620        }
8621    }
8622
8623    /**
8624     * Base class for derived classes that want to save and restore their own
8625     * state in {@link android.view.View#onSaveInstanceState()}.
8626     */
8627    public static class BaseSavedState extends AbsSavedState {
8628        /**
8629         * Constructor used when reading from a parcel. Reads the state of the superclass.
8630         *
8631         * @param source
8632         */
8633        public BaseSavedState(Parcel source) {
8634            super(source);
8635        }
8636
8637        /**
8638         * Constructor called by derived classes when creating their SavedState objects
8639         *
8640         * @param superState The state of the superclass of this view
8641         */
8642        public BaseSavedState(Parcelable superState) {
8643            super(superState);
8644        }
8645
8646        public static final Parcelable.Creator<BaseSavedState> CREATOR =
8647                new Parcelable.Creator<BaseSavedState>() {
8648            public BaseSavedState createFromParcel(Parcel in) {
8649                return new BaseSavedState(in);
8650            }
8651
8652            public BaseSavedState[] newArray(int size) {
8653                return new BaseSavedState[size];
8654            }
8655        };
8656    }
8657
8658    /**
8659     * A set of information given to a view when it is attached to its parent
8660     * window.
8661     */
8662    static class AttachInfo {
8663        interface Callbacks {
8664            void playSoundEffect(int effectId);
8665            boolean performHapticFeedback(int effectId, boolean always);
8666        }
8667
8668        /**
8669         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
8670         * to a Handler. This class contains the target (View) to invalidate and
8671         * the coordinates of the dirty rectangle.
8672         *
8673         * For performance purposes, this class also implements a pool of up to
8674         * POOL_LIMIT objects that get reused. This reduces memory allocations
8675         * whenever possible.
8676         */
8677        static class InvalidateInfo implements Poolable<InvalidateInfo> {
8678            private static final int POOL_LIMIT = 10;
8679            private static final Pool<InvalidateInfo> sPool = Pools.synchronizedPool(
8680                    Pools.finitePool(new PoolableManager<InvalidateInfo>() {
8681                        public InvalidateInfo newInstance() {
8682                            return new InvalidateInfo();
8683                        }
8684
8685                        public void onAcquired(InvalidateInfo element) {
8686                        }
8687
8688                        public void onReleased(InvalidateInfo element) {
8689                        }
8690                    }, POOL_LIMIT)
8691            );
8692
8693            private InvalidateInfo mNext;
8694
8695            View target;
8696
8697            int left;
8698            int top;
8699            int right;
8700            int bottom;
8701
8702            public void setNextPoolable(InvalidateInfo element) {
8703                mNext = element;
8704            }
8705
8706            public InvalidateInfo getNextPoolable() {
8707                return mNext;
8708            }
8709
8710            static InvalidateInfo acquire() {
8711                return sPool.acquire();
8712            }
8713
8714            void release() {
8715                sPool.release(this);
8716            }
8717        }
8718
8719        final IWindowSession mSession;
8720
8721        final IWindow mWindow;
8722
8723        final IBinder mWindowToken;
8724
8725        final Callbacks mRootCallbacks;
8726
8727        /**
8728         * The top view of the hierarchy.
8729         */
8730        View mRootView;
8731
8732        IBinder mPanelParentWindowToken;
8733        Surface mSurface;
8734
8735        /**
8736         * Scale factor used by the compatibility mode
8737         */
8738        float mApplicationScale;
8739
8740        /**
8741         * Indicates whether the application is in compatibility mode
8742         */
8743        boolean mScalingRequired;
8744
8745        /**
8746         * Left position of this view's window
8747         */
8748        int mWindowLeft;
8749
8750        /**
8751         * Top position of this view's window
8752         */
8753        int mWindowTop;
8754
8755        /**
8756         * For windows that are full-screen but using insets to layout inside
8757         * of the screen decorations, these are the current insets for the
8758         * content of the window.
8759         */
8760        final Rect mContentInsets = new Rect();
8761
8762        /**
8763         * For windows that are full-screen but using insets to layout inside
8764         * of the screen decorations, these are the current insets for the
8765         * actual visible parts of the window.
8766         */
8767        final Rect mVisibleInsets = new Rect();
8768
8769        /**
8770         * The internal insets given by this window.  This value is
8771         * supplied by the client (through
8772         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
8773         * be given to the window manager when changed to be used in laying
8774         * out windows behind it.
8775         */
8776        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
8777                = new ViewTreeObserver.InternalInsetsInfo();
8778
8779        /**
8780         * All views in the window's hierarchy that serve as scroll containers,
8781         * used to determine if the window can be resized or must be panned
8782         * to adjust for a soft input area.
8783         */
8784        final ArrayList<View> mScrollContainers = new ArrayList<View>();
8785
8786        final KeyEvent.DispatcherState mKeyDispatchState
8787                = new KeyEvent.DispatcherState();
8788
8789        /**
8790         * Indicates whether the view's window currently has the focus.
8791         */
8792        boolean mHasWindowFocus;
8793
8794        /**
8795         * The current visibility of the window.
8796         */
8797        int mWindowVisibility;
8798
8799        /**
8800         * Indicates the time at which drawing started to occur.
8801         */
8802        long mDrawingTime;
8803
8804        /**
8805         * Indicates whether or not ignoring the DIRTY_MASK flags.
8806         */
8807        boolean mIgnoreDirtyState;
8808
8809        /**
8810         * Indicates whether the view's window is currently in touch mode.
8811         */
8812        boolean mInTouchMode;
8813
8814        /**
8815         * Indicates that ViewRoot should trigger a global layout change
8816         * the next time it performs a traversal
8817         */
8818        boolean mRecomputeGlobalAttributes;
8819
8820        /**
8821         * Set to true when attributes (like mKeepScreenOn) need to be
8822         * recomputed.
8823         */
8824        boolean mAttributesChanged;
8825
8826        /**
8827         * Set during a traveral if any views want to keep the screen on.
8828         */
8829        boolean mKeepScreenOn;
8830
8831        /**
8832         * Set if the visibility of any views has changed.
8833         */
8834        boolean mViewVisibilityChanged;
8835
8836        /**
8837         * Set to true if a view has been scrolled.
8838         */
8839        boolean mViewScrollChanged;
8840
8841        /**
8842         * Global to the view hierarchy used as a temporary for dealing with
8843         * x/y points in the transparent region computations.
8844         */
8845        final int[] mTransparentLocation = new int[2];
8846
8847        /**
8848         * Global to the view hierarchy used as a temporary for dealing with
8849         * x/y points in the ViewGroup.invalidateChild implementation.
8850         */
8851        final int[] mInvalidateChildLocation = new int[2];
8852
8853        /**
8854         * The view tree observer used to dispatch global events like
8855         * layout, pre-draw, touch mode change, etc.
8856         */
8857        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
8858
8859        /**
8860         * A Canvas used by the view hierarchy to perform bitmap caching.
8861         */
8862        Canvas mCanvas;
8863
8864        /**
8865         * A Handler supplied by a view's {@link android.view.ViewRoot}. This
8866         * handler can be used to pump events in the UI events queue.
8867         */
8868        final Handler mHandler;
8869
8870        /**
8871         * Identifier for messages requesting the view to be invalidated.
8872         * Such messages should be sent to {@link #mHandler}.
8873         */
8874        static final int INVALIDATE_MSG = 0x1;
8875
8876        /**
8877         * Identifier for messages requesting the view to invalidate a region.
8878         * Such messages should be sent to {@link #mHandler}.
8879         */
8880        static final int INVALIDATE_RECT_MSG = 0x2;
8881
8882        /**
8883         * Temporary for use in computing invalidate rectangles while
8884         * calling up the hierarchy.
8885         */
8886        final Rect mTmpInvalRect = new Rect();
8887
8888        /**
8889         * Temporary list for use in collecting focusable descendents of a view.
8890         */
8891        final ArrayList<View> mFocusablesTempList = new ArrayList<View>(24);
8892
8893        /**
8894         * Creates a new set of attachment information with the specified
8895         * events handler and thread.
8896         *
8897         * @param handler the events handler the view must use
8898         */
8899        AttachInfo(IWindowSession session, IWindow window,
8900                Handler handler, Callbacks effectPlayer) {
8901            mSession = session;
8902            mWindow = window;
8903            mWindowToken = window.asBinder();
8904            mHandler = handler;
8905            mRootCallbacks = effectPlayer;
8906        }
8907    }
8908
8909    /**
8910     * <p>ScrollabilityCache holds various fields used by a View when scrolling
8911     * is supported. This avoids keeping too many unused fields in most
8912     * instances of View.</p>
8913     */
8914    private static class ScrollabilityCache implements Runnable {
8915
8916        /**
8917         * Scrollbars are not visible
8918         */
8919        public static final int OFF = 0;
8920
8921        /**
8922         * Scrollbars are visible
8923         */
8924        public static final int ON = 1;
8925
8926        /**
8927         * Scrollbars are fading away
8928         */
8929        public static final int FADING = 2;
8930
8931        public boolean fadeScrollBars;
8932
8933        public int fadingEdgeLength;
8934        public int scrollBarDefaultDelayBeforeFade;
8935        public int scrollBarFadeDuration;
8936
8937        public int scrollBarSize;
8938        public ScrollBarDrawable scrollBar;
8939        public float[] interpolatorValues;
8940        public View host;
8941
8942        public final Paint paint;
8943        public final Matrix matrix;
8944        public Shader shader;
8945
8946        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
8947
8948        private final float[] mOpaque = {255.0f};
8949        private final float[] mTransparent = {0.0f};
8950
8951        /**
8952         * When fading should start. This time moves into the future every time
8953         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
8954         */
8955        public long fadeStartTime;
8956
8957
8958        /**
8959         * The current state of the scrollbars: ON, OFF, or FADING
8960         */
8961        public int state = OFF;
8962
8963        private int mLastColor;
8964
8965        public ScrollabilityCache(ViewConfiguration configuration, View host) {
8966            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
8967            scrollBarSize = configuration.getScaledScrollBarSize();
8968            scrollBarDefaultDelayBeforeFade = configuration.getScrollDefaultDelay();
8969            scrollBarFadeDuration = configuration.getScrollBarFadeDuration();
8970
8971            paint = new Paint();
8972            matrix = new Matrix();
8973            // use use a height of 1, and then wack the matrix each time we
8974            // actually use it.
8975            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
8976
8977            paint.setShader(shader);
8978            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
8979            this.host = host;
8980        }
8981
8982        public void setFadeColor(int color) {
8983            if (color != 0 && color != mLastColor) {
8984                mLastColor = color;
8985                color |= 0xFF000000;
8986
8987                shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
8988                        color & 0x00FFFFFF, Shader.TileMode.CLAMP);
8989
8990                paint.setShader(shader);
8991                // Restore the default transfer mode (src_over)
8992                paint.setXfermode(null);
8993            }
8994        }
8995
8996        public void run() {
8997            long now = AnimationUtils.currentAnimationTimeMillis();
8998            if (now >= fadeStartTime) {
8999
9000                // the animation fades the scrollbars out by changing
9001                // the opacity (alpha) from fully opaque to fully
9002                // transparent
9003                int nextFrame = (int) now;
9004                int framesCount = 0;
9005
9006                Interpolator interpolator = scrollBarInterpolator;
9007
9008                // Start opaque
9009                interpolator.setKeyFrame(framesCount++, nextFrame, mOpaque);
9010
9011                // End transparent
9012                nextFrame += scrollBarFadeDuration;
9013                interpolator.setKeyFrame(framesCount, nextFrame, mTransparent);
9014
9015                state = FADING;
9016
9017                // Kick off the fade animation
9018                host.invalidate();
9019            }
9020        }
9021
9022    }
9023}
9024