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