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