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