2 * Copyright (C) 2006 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 import android.animation.AnimatorInflater;
20 import android.animation.StateListAnimator;
21 import android.annotation.IntDef;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.content.ClipData;
25 import android.content.Context;
26 import android.content.res.ColorStateList;
27 import android.content.res.Configuration;
28 import android.content.res.Resources;
29 import android.content.res.TypedArray;
30 import android.graphics.Bitmap;
31 import android.graphics.Canvas;
32 import android.graphics.Insets;
33 import android.graphics.Interpolator;
34 import android.graphics.LinearGradient;
35 import android.graphics.Matrix;
36 import android.graphics.Outline;
37 import android.graphics.Paint;
38 import android.graphics.Path;
39 import android.graphics.PathMeasure;
40 import android.graphics.PixelFormat;
41 import android.graphics.Point;
42 import android.graphics.PorterDuff;
43 import android.graphics.PorterDuffXfermode;
44 import android.graphics.Rect;
45 import android.graphics.RectF;
46 import android.graphics.Region;
47 import android.graphics.Shader;
48 import android.graphics.drawable.ColorDrawable;
49 import android.graphics.drawable.Drawable;
50 import android.hardware.display.DisplayManagerGlobal;
51 import android.os.Bundle;
52 import android.os.Handler;
53 import android.os.IBinder;
54 import android.os.Parcel;
55 import android.os.Parcelable;
56 import android.os.RemoteException;
57 import android.os.SystemClock;
58 import android.os.SystemProperties;
59 import android.text.TextUtils;
60 import android.util.AttributeSet;
61 import android.util.FloatProperty;
62 import android.util.LayoutDirection;
63 import android.util.Log;
64 import android.util.LongSparseLongArray;
65 import android.util.Pools.SynchronizedPool;
66 import android.util.Property;
67 import android.util.SparseArray;
68 import android.util.SuperNotCalledException;
69 import android.util.TypedValue;
70 import android.view.ContextMenu.ContextMenuInfo;
71 import android.view.AccessibilityIterators.TextSegmentIterator;
72 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
73 import android.view.AccessibilityIterators.WordTextSegmentIterator;
74 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
75 import android.view.accessibility.AccessibilityEvent;
76 import android.view.accessibility.AccessibilityEventSource;
77 import android.view.accessibility.AccessibilityManager;
78 import android.view.accessibility.AccessibilityNodeInfo;
79 import android.view.accessibility.AccessibilityNodeProvider;
80 import android.view.animation.Animation;
81 import android.view.animation.AnimationUtils;
82 import android.view.animation.Transformation;
83 import android.view.inputmethod.EditorInfo;
84 import android.view.inputmethod.InputConnection;
85 import android.view.inputmethod.InputMethodManager;
86 import android.widget.ScrollBarDrawable;
88 import static android.os.Build.VERSION_CODES.*;
89 import static java.lang.Math.max;
91 import com.android.internal.R;
92 import com.android.internal.util.Predicate;
93 import com.android.internal.view.menu.MenuBuilder;
94 import com.google.android.collect.Lists;
95 import com.google.android.collect.Maps;
97 import java.lang.annotation.Retention;
98 import java.lang.annotation.RetentionPolicy;
99 import java.lang.ref.WeakReference;
100 import java.lang.reflect.Field;
101 import java.lang.reflect.InvocationTargetException;
102 import java.lang.reflect.Method;
103 import java.lang.reflect.Modifier;
104 import java.util.ArrayList;
105 import java.util.Arrays;
106 import java.util.Collections;
107 import java.util.HashMap;
108 import java.util.List;
109 import java.util.Locale;
110 import java.util.Map;
111 import java.util.concurrent.CopyOnWriteArrayList;
112 import java.util.concurrent.atomic.AtomicInteger;
116 * This class represents the basic building block for user interface components. A View
117 * occupies a rectangular area on the screen and is responsible for drawing and
118 * event handling. View is the base class for <em>widgets</em>, which are
119 * used to create interactive UI components (buttons, text fields, etc.). The
120 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
121 * are invisible containers that hold other Views (or other ViewGroups) and define
122 * their layout properties.
125 * <div class="special reference">
126 * <h3>Developer Guides</h3>
127 * <p>For information about using this class to develop your application's user interface,
128 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
131 * <a name="Using"></a>
132 * <h3>Using Views</h3>
134 * All of the views in a window are arranged in a single tree. You can add views
135 * either from code or by specifying a tree of views in one or more XML layout
136 * files. There are many specialized subclasses of views that act as controls or
137 * are capable of displaying text, images, or other content.
140 * Once you have created a tree of views, there are typically a few types of
141 * common operations you may wish to perform:
143 * <li><strong>Set properties:</strong> for example setting the text of a
144 * {@link android.widget.TextView}. The available properties and the methods
145 * that set them will vary among the different subclasses of views. Note that
146 * properties that are known at build time can be set in the XML layout
148 * <li><strong>Set focus:</strong> The framework will handled moving focus in
149 * response to user input. To force focus to a specific view, call
150 * {@link #requestFocus}.</li>
151 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
152 * that will be notified when something interesting happens to the view. For
153 * example, all views will let you set a listener to be notified when the view
154 * gains or loses focus. You can register such a listener using
155 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
156 * Other view subclasses offer more specialized listeners. For example, a Button
157 * exposes a listener to notify clients when the button is clicked.</li>
158 * <li><strong>Set visibility:</strong> You can hide or show views using
159 * {@link #setVisibility(int)}.</li>
163 * Note: The Android framework is responsible for measuring, laying out and
164 * drawing views. You should not call methods that perform these actions on
165 * views yourself unless you are actually implementing a
166 * {@link android.view.ViewGroup}.
169 * <a name="Lifecycle"></a>
170 * <h3>Implementing a Custom View</h3>
173 * To implement a custom view, you will usually begin by providing overrides for
174 * some of the standard methods that the framework calls on all views. You do
175 * not need to override all of these methods. In fact, you can start by just
176 * overriding {@link #onDraw(android.graphics.Canvas)}.
177 * <table border="2" width="85%" align="center" cellpadding="5">
179 * <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
184 * <td rowspan="2">Creation</td>
185 * <td>Constructors</td>
186 * <td>There is a form of the constructor that are called when the view
187 * is created from code and a form that is called when the view is
188 * inflated from a layout file. The second form should parse and apply
189 * any attributes defined in the layout file.
193 * <td><code>{@link #onFinishInflate()}</code></td>
194 * <td>Called after a view and all of its children has been inflated
199 * <td rowspan="3">Layout</td>
200 * <td><code>{@link #onMeasure(int, int)}</code></td>
201 * <td>Called to determine the size requirements for this view and all
206 * <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
207 * <td>Called when this view should assign a size and position to all
212 * <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
213 * <td>Called when the size of this view has changed.
219 * <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
220 * <td>Called when the view should render its content.
225 * <td rowspan="4">Event processing</td>
226 * <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
227 * <td>Called when a new hardware key event occurs.
231 * <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
232 * <td>Called when a hardware key up event occurs.
236 * <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
237 * <td>Called when a trackball motion event occurs.
241 * <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
242 * <td>Called when a touch screen motion event occurs.
247 * <td rowspan="2">Focus</td>
248 * <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
249 * <td>Called when the view gains or loses focus.
254 * <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
255 * <td>Called when the window containing the view gains or loses focus.
260 * <td rowspan="3">Attaching</td>
261 * <td><code>{@link #onAttachedToWindow()}</code></td>
262 * <td>Called when the view is attached to a window.
267 * <td><code>{@link #onDetachedFromWindow}</code></td>
268 * <td>Called when the view is detached from its window.
273 * <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
274 * <td>Called when the visibility of the window containing the view
285 * Views may have an integer id associated with them. These ids are typically
286 * assigned in the layout XML files, and are used to find specific views within
287 * the view tree. A common pattern is to:
289 * <li>Define a Button in the layout file and assign it a unique ID.
292 * android:id="@+id/my_button"
293 * android:layout_width="wrap_content"
294 * android:layout_height="wrap_content"
295 * android:text="@string/my_button_text"/>
297 * <li>From the onCreate method of an Activity, find the Button
298 * <pre class="prettyprint">
299 * Button myButton = (Button) findViewById(R.id.my_button);
303 * View IDs need not be unique throughout the tree, but it is good practice to
304 * ensure that they are at least unique within the part of the tree you are
308 * <a name="Position"></a>
311 * The geometry of a view is that of a rectangle. A view has a location,
312 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
313 * two dimensions, expressed as a width and a height. The unit for location
314 * and dimensions is the pixel.
318 * It is possible to retrieve the location of a view by invoking the methods
319 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
320 * coordinate of the rectangle representing the view. The latter returns the
321 * top, or Y, coordinate of the rectangle representing the view. These methods
322 * both return the location of the view relative to its parent. For instance,
323 * when getLeft() returns 20, that means the view is located 20 pixels to the
324 * right of the left edge of its direct parent.
328 * In addition, several convenience methods are offered to avoid unnecessary
329 * computations, namely {@link #getRight()} and {@link #getBottom()}.
330 * These methods return the coordinates of the right and bottom edges of the
331 * rectangle representing the view. For instance, calling {@link #getRight()}
332 * is similar to the following computation: <code>getLeft() + getWidth()</code>
333 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
336 * <a name="SizePaddingMargins"></a>
337 * <h3>Size, padding and margins</h3>
339 * The size of a view is expressed with a width and a height. A view actually
340 * possess two pairs of width and height values.
344 * The first pair is known as <em>measured width</em> and
345 * <em>measured height</em>. These dimensions define how big a view wants to be
346 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
347 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
348 * and {@link #getMeasuredHeight()}.
352 * The second pair is simply known as <em>width</em> and <em>height</em>, or
353 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
354 * dimensions define the actual size of the view on screen, at drawing time and
355 * after layout. These values may, but do not have to, be different from the
356 * measured width and height. The width and height can be obtained by calling
357 * {@link #getWidth()} and {@link #getHeight()}.
361 * To measure its dimensions, a view takes into account its padding. The padding
362 * is expressed in pixels for the left, top, right and bottom parts of the view.
363 * Padding can be used to offset the content of the view by a specific amount of
364 * pixels. For instance, a left padding of 2 will push the view's content by
365 * 2 pixels to the right of the left edge. Padding can be set using the
366 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
367 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
368 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
369 * {@link #getPaddingEnd()}.
373 * Even though a view can define a padding, it does not provide any support for
374 * margins. However, view groups provide such a support. Refer to
375 * {@link android.view.ViewGroup} and
376 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
379 * <a name="Layout"></a>
382 * Layout is a two pass process: a measure pass and a layout pass. The measuring
383 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
384 * of the view tree. Each view pushes dimension specifications down the tree
385 * during the recursion. At the end of the measure pass, every view has stored
386 * its measurements. The second pass happens in
387 * {@link #layout(int,int,int,int)} and is also top-down. During
388 * this pass each parent is responsible for positioning all of its children
389 * using the sizes computed in the measure pass.
393 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
394 * {@link #getMeasuredHeight()} values must be set, along with those for all of
395 * that view's descendants. A view's measured width and measured height values
396 * must respect the constraints imposed by the view's parents. This guarantees
397 * that at the end of the measure pass, all parents accept all of their
398 * children's measurements. A parent view may call measure() more than once on
399 * its children. For example, the parent may measure each child once with
400 * unspecified dimensions to find out how big they want to be, then call
401 * measure() on them again with actual numbers if the sum of all the children's
402 * unconstrained sizes is too big or too small.
406 * The measure pass uses two classes to communicate dimensions. The
407 * {@link MeasureSpec} class is used by views to tell their parents how they
408 * want to be measured and positioned. The base LayoutParams class just
409 * describes how big the view wants to be for both width and height. For each
410 * dimension, it can specify one of:
412 * <li> an exact number
413 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
415 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
416 * enclose its content (plus padding).
418 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
419 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
424 * MeasureSpecs are used to push requirements down the tree from parent to
425 * child. A MeasureSpec can be in one of three modes:
427 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
428 * of a child view. For example, a LinearLayout may call measure() on its child
429 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
430 * tall the child view wants to be given a width of 240 pixels.
431 * <li>EXACTLY: This is used by the parent to impose an exact size on the
432 * child. The child must use this size, and guarantee that all of its
433 * descendants will fit within this size.
434 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
435 * child. The child must guarantee that it and all of its descendants will fit
441 * To intiate a layout, call {@link #requestLayout}. This method is typically
442 * called by a view on itself when it believes that is can no longer fit within
443 * its current bounds.
446 * <a name="Drawing"></a>
449 * Drawing is handled by walking the tree and recording the drawing commands of
450 * any View that needs to update. After this, the drawing commands of the
451 * entire tree are issued to screen, clipped to the newly damaged area.
455 * The tree is largely recorded and drawn in order, with parents drawn before
456 * (i.e., behind) their children, with siblings drawn in the order they appear
457 * in the tree. If you set a background drawable for a View, then the View will
458 * draw it before calling back to its <code>onDraw()</code> method. The child
459 * drawing order can be overridden with
460 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
461 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
465 * To force a view to draw, call {@link #invalidate()}.
468 * <a name="EventHandlingThreading"></a>
469 * <h3>Event Handling and Threading</h3>
471 * The basic cycle of a view is as follows:
473 * <li>An event comes in and is dispatched to the appropriate view. The view
474 * handles the event and notifies any listeners.</li>
475 * <li>If in the course of processing the event, the view's bounds may need
476 * to be changed, the view will call {@link #requestLayout()}.</li>
477 * <li>Similarly, if in the course of processing the event the view's appearance
478 * may need to be changed, the view will call {@link #invalidate()}.</li>
479 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
480 * the framework will take care of measuring, laying out, and drawing the tree
481 * as appropriate.</li>
485 * <p><em>Note: The entire view tree is single threaded. You must always be on
486 * the UI thread when calling any method on any view.</em>
487 * If you are doing work on other threads and want to update the state of a view
488 * from that thread, you should use a {@link Handler}.
491 * <a name="FocusHandling"></a>
492 * <h3>Focus Handling</h3>
494 * The framework will handle routine focus movement in response to user input.
495 * This includes changing the focus as views are removed or hidden, or as new
496 * views become available. Views indicate their willingness to take focus
497 * through the {@link #isFocusable} method. To change whether a view can take
498 * focus, call {@link #setFocusable(boolean)}. When in touch mode (see notes below)
499 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
500 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
503 * Focus movement is based on an algorithm which finds the nearest neighbor in a
504 * given direction. In rare cases, the default algorithm may not match the
505 * intended behavior of the developer. In these situations, you can provide
506 * explicit overrides by using these XML attributes in the layout file:
517 * To get a particular view to take focus, call {@link #requestFocus()}.
520 * <a name="TouchMode"></a>
521 * <h3>Touch Mode</h3>
523 * When a user is navigating a user interface via directional keys such as a D-pad, it is
524 * necessary to give focus to actionable items such as buttons so the user can see
525 * what will take input. If the device has touch capabilities, however, and the user
526 * begins interacting with the interface by touching it, it is no longer necessary to
527 * always highlight, or give focus to, a particular view. This motivates a mode
528 * for interaction named 'touch mode'.
531 * For a touch capable device, once the user touches the screen, the device
532 * will enter touch mode. From this point onward, only views for which
533 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
534 * Other views that are touchable, like buttons, will not take focus when touched; they will
535 * only fire the on click listeners.
538 * Any time a user hits a directional key, such as a D-pad direction, the view device will
539 * exit touch mode, and find a view to take focus, so that the user may resume interacting
540 * with the user interface without touching the screen again.
543 * The touch mode state is maintained across {@link android.app.Activity}s. Call
544 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
547 * <a name="Scrolling"></a>
550 * The framework provides basic support for views that wish to internally
551 * scroll their content. This includes keeping track of the X and Y scroll
552 * offset as well as mechanisms for drawing scrollbars. See
553 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
554 * {@link #awakenScrollBars()} for more details.
557 * <a name="Tags"></a>
560 * Unlike IDs, tags are not used to identify views. Tags are essentially an
561 * extra piece of information that can be associated with a view. They are most
562 * often used as a convenience to store data related to views in the views
563 * themselves rather than by putting them in a separate structure.
566 * <a name="Properties"></a>
567 * <h3>Properties</h3>
569 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
570 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
571 * available both in the {@link Property} form as well as in similarly-named setter/getter
572 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
573 * be used to set persistent state associated with these rendering-related properties on the view.
574 * The properties and methods can also be used in conjunction with
575 * {@link android.animation.Animator Animator}-based animations, described more in the
576 * <a href="#Animation">Animation</a> section.
579 * <a name="Animation"></a>
582 * Starting with Android 3.0, the preferred way of animating views is to use the
583 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
584 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
585 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
586 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
587 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
588 * makes animating these View properties particularly easy and efficient.
591 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
592 * You can attach an {@link Animation} object to a view using
593 * {@link #setAnimation(Animation)} or
594 * {@link #startAnimation(Animation)}. The animation can alter the scale,
595 * rotation, translation and alpha of a view over time. If the animation is
596 * attached to a view that has children, the animation will affect the entire
597 * subtree rooted by that node. When an animation is started, the framework will
598 * take care of redrawing the appropriate views until the animation completes.
601 * <a name="Security"></a>
604 * Sometimes it is essential that an application be able to verify that an action
605 * is being performed with the full knowledge and consent of the user, such as
606 * granting a permission request, making a purchase or clicking on an advertisement.
607 * Unfortunately, a malicious application could try to spoof the user into
608 * performing these actions, unaware, by concealing the intended purpose of the view.
609 * As a remedy, the framework offers a touch filtering mechanism that can be used to
610 * improve the security of views that provide access to sensitive functionality.
612 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
613 * android:filterTouchesWhenObscured layout attribute to true. When enabled, the framework
614 * will discard touches that are received whenever the view's window is obscured by
615 * another visible window. As a result, the view will not receive touches whenever a
616 * toast, dialog or other window appears above the view's window.
618 * For more fine-grained control over security, consider overriding the
619 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
620 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
623 * @attr ref android.R.styleable#View_alpha
624 * @attr ref android.R.styleable#View_background
625 * @attr ref android.R.styleable#View_clickable
626 * @attr ref android.R.styleable#View_contentDescription
627 * @attr ref android.R.styleable#View_drawingCacheQuality
628 * @attr ref android.R.styleable#View_duplicateParentState
629 * @attr ref android.R.styleable#View_id
630 * @attr ref android.R.styleable#View_requiresFadingEdge
631 * @attr ref android.R.styleable#View_fadeScrollbars
632 * @attr ref android.R.styleable#View_fadingEdgeLength
633 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
634 * @attr ref android.R.styleable#View_fitsSystemWindows
635 * @attr ref android.R.styleable#View_isScrollContainer
636 * @attr ref android.R.styleable#View_focusable
637 * @attr ref android.R.styleable#View_focusableInTouchMode
638 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
639 * @attr ref android.R.styleable#View_keepScreenOn
640 * @attr ref android.R.styleable#View_layerType
641 * @attr ref android.R.styleable#View_layoutDirection
642 * @attr ref android.R.styleable#View_longClickable
643 * @attr ref android.R.styleable#View_minHeight
644 * @attr ref android.R.styleable#View_minWidth
645 * @attr ref android.R.styleable#View_nextFocusDown
646 * @attr ref android.R.styleable#View_nextFocusLeft
647 * @attr ref android.R.styleable#View_nextFocusRight
648 * @attr ref android.R.styleable#View_nextFocusUp
649 * @attr ref android.R.styleable#View_onClick
650 * @attr ref android.R.styleable#View_padding
651 * @attr ref android.R.styleable#View_paddingBottom
652 * @attr ref android.R.styleable#View_paddingLeft
653 * @attr ref android.R.styleable#View_paddingRight
654 * @attr ref android.R.styleable#View_paddingTop
655 * @attr ref android.R.styleable#View_paddingStart
656 * @attr ref android.R.styleable#View_paddingEnd
657 * @attr ref android.R.styleable#View_saveEnabled
658 * @attr ref android.R.styleable#View_rotation
659 * @attr ref android.R.styleable#View_rotationX
660 * @attr ref android.R.styleable#View_rotationY
661 * @attr ref android.R.styleable#View_scaleX
662 * @attr ref android.R.styleable#View_scaleY
663 * @attr ref android.R.styleable#View_scrollX
664 * @attr ref android.R.styleable#View_scrollY
665 * @attr ref android.R.styleable#View_scrollbarSize
666 * @attr ref android.R.styleable#View_scrollbarStyle
667 * @attr ref android.R.styleable#View_scrollbars
668 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
669 * @attr ref android.R.styleable#View_scrollbarFadeDuration
670 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
671 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
672 * @attr ref android.R.styleable#View_scrollbarThumbVertical
673 * @attr ref android.R.styleable#View_scrollbarTrackVertical
674 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
675 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
676 * @attr ref android.R.styleable#View_stateListAnimator
677 * @attr ref android.R.styleable#View_transitionName
678 * @attr ref android.R.styleable#View_soundEffectsEnabled
679 * @attr ref android.R.styleable#View_tag
680 * @attr ref android.R.styleable#View_textAlignment
681 * @attr ref android.R.styleable#View_textDirection
682 * @attr ref android.R.styleable#View_transformPivotX
683 * @attr ref android.R.styleable#View_transformPivotY
684 * @attr ref android.R.styleable#View_translationX
685 * @attr ref android.R.styleable#View_translationY
686 * @attr ref android.R.styleable#View_translationZ
687 * @attr ref android.R.styleable#View_visibility
689 * @see android.view.ViewGroup
691 public class View implements Drawable.Callback, KeyEvent.Callback,
692 AccessibilityEventSource {
693 private static final boolean DBG = false;
696 * The logging tag used by this class with android.util.Log.
698 protected static final String VIEW_LOG_TAG = "View";
701 * When set to true, apps will draw debugging information about their layouts.
705 public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
708 * When set to true, this view will save its attribute data.
712 public static boolean mDebugViewAttributes = false;
715 * Used to mark a View that has no ID.
717 public static final int NO_ID = -1;
720 * Signals that compatibility booleans have been initialized according to
721 * target SDK versions.
723 private static boolean sCompatibilityDone = false;
726 * Use the old (broken) way of building MeasureSpecs.
728 private static boolean sUseBrokenMakeMeasureSpec = false;
731 * Ignore any optimizations using the measure cache.
733 private static boolean sIgnoreMeasureCache = false;
736 * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
739 private static final int NOT_FOCUSABLE = 0x00000000;
742 * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
745 private static final int FOCUSABLE = 0x00000001;
748 * Mask for use with setFlags indicating bits used for focus.
750 private static final int FOCUSABLE_MASK = 0x00000001;
753 * This view will adjust its padding to fit sytem windows (e.g. status bar)
755 private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
758 @IntDef({VISIBLE, INVISIBLE, GONE})
759 @Retention(RetentionPolicy.SOURCE)
760 public @interface Visibility {}
763 * This view is visible.
764 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
765 * android:visibility}.
767 public static final int VISIBLE = 0x00000000;
770 * This view is invisible, but it still takes up space for layout purposes.
771 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
772 * android:visibility}.
774 public static final int INVISIBLE = 0x00000004;
777 * This view is invisible, and it doesn't take any space for layout
778 * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
779 * android:visibility}.
781 public static final int GONE = 0x00000008;
784 * Mask for use with setFlags indicating bits used for visibility.
787 static final int VISIBILITY_MASK = 0x0000000C;
789 private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
792 * This view is enabled. Interpretation varies by subclass.
793 * Use with ENABLED_MASK when calling setFlags.
796 static final int ENABLED = 0x00000000;
799 * This view is disabled. Interpretation varies by subclass.
800 * Use with ENABLED_MASK when calling setFlags.
803 static final int DISABLED = 0x00000020;
806 * Mask for use with setFlags indicating bits used for indicating whether
807 * this view is enabled
810 static final int ENABLED_MASK = 0x00000020;
813 * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
814 * called and further optimizations will be performed. It is okay to have
815 * this flag set and a background. Use with DRAW_MASK when calling setFlags.
818 static final int WILL_NOT_DRAW = 0x00000080;
821 * Mask for use with setFlags indicating bits used for indicating whether
822 * this view is will draw
825 static final int DRAW_MASK = 0x00000080;
828 * <p>This view doesn't show scrollbars.</p>
831 static final int SCROLLBARS_NONE = 0x00000000;
834 * <p>This view shows horizontal scrollbars.</p>
837 static final int SCROLLBARS_HORIZONTAL = 0x00000100;
840 * <p>This view shows vertical scrollbars.</p>
843 static final int SCROLLBARS_VERTICAL = 0x00000200;
846 * <p>Mask for use with setFlags indicating bits used for indicating which
847 * scrollbars are enabled.</p>
850 static final int SCROLLBARS_MASK = 0x00000300;
853 * Indicates that the view should filter touches when its window is obscured.
854 * Refer to the class comments for more information about this security feature.
857 static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
860 * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
861 * that they are optional and should be skipped if the window has
862 * requested system UI flags that ignore those insets for layout.
864 static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
867 * <p>This view doesn't show fading edges.</p>
870 static final int FADING_EDGE_NONE = 0x00000000;
873 * <p>This view shows horizontal fading edges.</p>
876 static final int FADING_EDGE_HORIZONTAL = 0x00001000;
879 * <p>This view shows vertical fading edges.</p>
882 static final int FADING_EDGE_VERTICAL = 0x00002000;
885 * <p>Mask for use with setFlags indicating bits used for indicating which
886 * fading edges are enabled.</p>
889 static final int FADING_EDGE_MASK = 0x00003000;
892 * <p>Indicates this view can be clicked. When clickable, a View reacts
893 * to clicks by notifying the OnClickListener.<p>
896 static final int CLICKABLE = 0x00004000;
899 * <p>Indicates this view is caching its drawing into a bitmap.</p>
902 static final int DRAWING_CACHE_ENABLED = 0x00008000;
905 * <p>Indicates that no icicle should be saved for this view.<p>
908 static final int SAVE_DISABLED = 0x000010000;
911 * <p>Mask for use with setFlags indicating bits used for the saveEnabled
915 static final int SAVE_DISABLED_MASK = 0x000010000;
918 * <p>Indicates that no drawing cache should ever be created for this view.<p>
921 static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
924 * <p>Indicates this view can take / keep focus when int touch mode.</p>
927 static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
930 @Retention(RetentionPolicy.SOURCE)
931 @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
932 public @interface DrawingCacheQuality {}
935 * <p>Enables low quality mode for the drawing cache.</p>
937 public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
940 * <p>Enables high quality mode for the drawing cache.</p>
942 public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
945 * <p>Enables automatic quality mode for the drawing cache.</p>
947 public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
949 private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
950 DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
954 * <p>Mask for use with setFlags indicating bits used for the cache
955 * quality property.</p>
958 static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
962 * Indicates this view can be long clicked. When long clickable, a View
963 * reacts to long clicks by notifying the OnLongClickListener or showing a
968 static final int LONG_CLICKABLE = 0x00200000;
971 * <p>Indicates that this view gets its drawable states from its direct parent
972 * and ignores its original internal states.</p>
976 static final int DUPLICATE_PARENT_STATE = 0x00400000;
980 SCROLLBARS_INSIDE_OVERLAY,
981 SCROLLBARS_INSIDE_INSET,
982 SCROLLBARS_OUTSIDE_OVERLAY,
983 SCROLLBARS_OUTSIDE_INSET
985 @Retention(RetentionPolicy.SOURCE)
986 public @interface ScrollBarStyle {}
989 * The scrollbar style to display the scrollbars inside the content area,
990 * without increasing the padding. The scrollbars will be overlaid with
991 * translucency on the view's content.
993 public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
996 * The scrollbar style to display the scrollbars inside the padded area,
997 * increasing the padding of the view. The scrollbars will not overlap the
998 * content area of the view.
1000 public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1003 * The scrollbar style to display the scrollbars at the edge of the view,
1004 * without increasing the padding. The scrollbars will be overlaid with
1007 public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1010 * The scrollbar style to display the scrollbars at the edge of the view,
1011 * increasing the padding of the view. The scrollbars will only overlap the
1012 * background, if any.
1014 public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1017 * Mask to check if the scrollbar style is overlay or inset.
1020 static final int SCROLLBARS_INSET_MASK = 0x01000000;
1023 * Mask to check if the scrollbar style is inside or outside.
1026 static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1029 * Mask for scrollbar style.
1032 static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1035 * View flag indicating that the screen should remain on while the
1036 * window containing this view is visible to the user. This effectively
1037 * takes care of automatically setting the WindowManager's
1038 * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1040 public static final int KEEP_SCREEN_ON = 0x04000000;
1043 * View flag indicating whether this view should have sound effects enabled
1044 * for events such as clicking and touching.
1046 public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1049 * View flag indicating whether this view should have haptic feedback
1050 * enabled for events such as long presses.
1052 public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1055 * <p>Indicates that the view hierarchy should stop saving state when
1056 * it reaches this view. If state saving is initiated immediately at
1057 * the view, it will be allowed.
1060 static final int PARENT_SAVE_DISABLED = 0x20000000;
1063 * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1066 static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1069 @IntDef(flag = true,
1072 FOCUSABLES_TOUCH_MODE
1074 @Retention(RetentionPolicy.SOURCE)
1075 public @interface FocusableMode {}
1078 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1079 * should add all focusable Views regardless if they are focusable in touch mode.
1081 public static final int FOCUSABLES_ALL = 0x00000000;
1084 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1085 * should add only Views focusable in touch mode.
1087 public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1098 @Retention(RetentionPolicy.SOURCE)
1099 public @interface FocusDirection {}
1108 @Retention(RetentionPolicy.SOURCE)
1109 public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1112 * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1115 public static final int FOCUS_BACKWARD = 0x00000001;
1118 * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1121 public static final int FOCUS_FORWARD = 0x00000002;
1124 * Use with {@link #focusSearch(int)}. Move focus to the left.
1126 public static final int FOCUS_LEFT = 0x00000011;
1129 * Use with {@link #focusSearch(int)}. Move focus up.
1131 public static final int FOCUS_UP = 0x00000021;
1134 * Use with {@link #focusSearch(int)}. Move focus to the right.
1136 public static final int FOCUS_RIGHT = 0x00000042;
1139 * Use with {@link #focusSearch(int)}. Move focus down.
1141 public static final int FOCUS_DOWN = 0x00000082;
1144 * Bits of {@link #getMeasuredWidthAndState()} and
1145 * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1147 public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1150 * Bits of {@link #getMeasuredWidthAndState()} and
1151 * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1153 public static final int MEASURED_STATE_MASK = 0xff000000;
1156 * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1157 * for functions that combine both width and height into a single int,
1158 * such as {@link #getMeasuredState()} and the childState argument of
1159 * {@link #resolveSizeAndState(int, int, int)}.
1161 public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1164 * Bit of {@link #getMeasuredWidthAndState()} and
1165 * {@link #getMeasuredWidthAndState()} that indicates the measured size
1166 * is smaller that the space the view would like to have.
1168 public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1171 * Base View state sets
1175 * Indicates the view has no states set. States are used with
1176 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1177 * view depending on its state.
1179 * @see android.graphics.drawable.Drawable
1180 * @see #getDrawableState()
1182 protected static final int[] EMPTY_STATE_SET;
1184 * Indicates the view is enabled. States are used with
1185 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1186 * view depending on its state.
1188 * @see android.graphics.drawable.Drawable
1189 * @see #getDrawableState()
1191 protected static final int[] ENABLED_STATE_SET;
1193 * Indicates the view is focused. States are used with
1194 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1195 * view depending on its state.
1197 * @see android.graphics.drawable.Drawable
1198 * @see #getDrawableState()
1200 protected static final int[] FOCUSED_STATE_SET;
1202 * Indicates the view is selected. States are used with
1203 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1204 * view depending on its state.
1206 * @see android.graphics.drawable.Drawable
1207 * @see #getDrawableState()
1209 protected static final int[] SELECTED_STATE_SET;
1211 * Indicates the view is pressed. States are used with
1212 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1213 * view depending on its state.
1215 * @see android.graphics.drawable.Drawable
1216 * @see #getDrawableState()
1218 protected static final int[] PRESSED_STATE_SET;
1220 * Indicates the view's window has focus. States are used with
1221 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1222 * view depending on its state.
1224 * @see android.graphics.drawable.Drawable
1225 * @see #getDrawableState()
1227 protected static final int[] WINDOW_FOCUSED_STATE_SET;
1230 * Indicates the view is enabled and has the focus.
1232 * @see #ENABLED_STATE_SET
1233 * @see #FOCUSED_STATE_SET
1235 protected static final int[] ENABLED_FOCUSED_STATE_SET;
1237 * Indicates the view is enabled and selected.
1239 * @see #ENABLED_STATE_SET
1240 * @see #SELECTED_STATE_SET
1242 protected static final int[] ENABLED_SELECTED_STATE_SET;
1244 * Indicates the view is enabled and that its window has focus.
1246 * @see #ENABLED_STATE_SET
1247 * @see #WINDOW_FOCUSED_STATE_SET
1249 protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1251 * Indicates the view is focused and selected.
1253 * @see #FOCUSED_STATE_SET
1254 * @see #SELECTED_STATE_SET
1256 protected static final int[] FOCUSED_SELECTED_STATE_SET;
1258 * Indicates the view has the focus and that its window has the focus.
1260 * @see #FOCUSED_STATE_SET
1261 * @see #WINDOW_FOCUSED_STATE_SET
1263 protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1265 * Indicates the view is selected and that its window has the focus.
1267 * @see #SELECTED_STATE_SET
1268 * @see #WINDOW_FOCUSED_STATE_SET
1270 protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1273 * Indicates the view is enabled, focused and selected.
1275 * @see #ENABLED_STATE_SET
1276 * @see #FOCUSED_STATE_SET
1277 * @see #SELECTED_STATE_SET
1279 protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1281 * Indicates the view is enabled, focused and its window has the focus.
1283 * @see #ENABLED_STATE_SET
1284 * @see #FOCUSED_STATE_SET
1285 * @see #WINDOW_FOCUSED_STATE_SET
1287 protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1289 * Indicates the view is enabled, selected and its window has the focus.
1291 * @see #ENABLED_STATE_SET
1292 * @see #SELECTED_STATE_SET
1293 * @see #WINDOW_FOCUSED_STATE_SET
1295 protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1297 * Indicates the view is focused, selected and its window has the focus.
1299 * @see #FOCUSED_STATE_SET
1300 * @see #SELECTED_STATE_SET
1301 * @see #WINDOW_FOCUSED_STATE_SET
1303 protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1305 * Indicates the view is enabled, focused, selected and its window
1308 * @see #ENABLED_STATE_SET
1309 * @see #FOCUSED_STATE_SET
1310 * @see #SELECTED_STATE_SET
1311 * @see #WINDOW_FOCUSED_STATE_SET
1313 protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1315 * Indicates the view is pressed and its window has the focus.
1317 * @see #PRESSED_STATE_SET
1318 * @see #WINDOW_FOCUSED_STATE_SET
1320 protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1322 * Indicates the view is pressed and selected.
1324 * @see #PRESSED_STATE_SET
1325 * @see #SELECTED_STATE_SET
1327 protected static final int[] PRESSED_SELECTED_STATE_SET;
1329 * Indicates the view is pressed, selected and its window has the focus.
1331 * @see #PRESSED_STATE_SET
1332 * @see #SELECTED_STATE_SET
1333 * @see #WINDOW_FOCUSED_STATE_SET
1335 protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1337 * Indicates the view is pressed and focused.
1339 * @see #PRESSED_STATE_SET
1340 * @see #FOCUSED_STATE_SET
1342 protected static final int[] PRESSED_FOCUSED_STATE_SET;
1344 * Indicates the view is pressed, focused and its window has the focus.
1346 * @see #PRESSED_STATE_SET
1347 * @see #FOCUSED_STATE_SET
1348 * @see #WINDOW_FOCUSED_STATE_SET
1350 protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1352 * Indicates the view is pressed, focused and selected.
1354 * @see #PRESSED_STATE_SET
1355 * @see #SELECTED_STATE_SET
1356 * @see #FOCUSED_STATE_SET
1358 protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1360 * Indicates the view is pressed, focused, selected and its window has the focus.
1362 * @see #PRESSED_STATE_SET
1363 * @see #FOCUSED_STATE_SET
1364 * @see #SELECTED_STATE_SET
1365 * @see #WINDOW_FOCUSED_STATE_SET
1367 protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1369 * Indicates the view is pressed and enabled.
1371 * @see #PRESSED_STATE_SET
1372 * @see #ENABLED_STATE_SET
1374 protected static final int[] PRESSED_ENABLED_STATE_SET;
1376 * Indicates the view is pressed, enabled and its window has the focus.
1378 * @see #PRESSED_STATE_SET
1379 * @see #ENABLED_STATE_SET
1380 * @see #WINDOW_FOCUSED_STATE_SET
1382 protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1384 * Indicates the view is pressed, enabled and selected.
1386 * @see #PRESSED_STATE_SET
1387 * @see #ENABLED_STATE_SET
1388 * @see #SELECTED_STATE_SET
1390 protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1392 * Indicates the view is pressed, enabled, selected and its window has the
1395 * @see #PRESSED_STATE_SET
1396 * @see #ENABLED_STATE_SET
1397 * @see #SELECTED_STATE_SET
1398 * @see #WINDOW_FOCUSED_STATE_SET
1400 protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1402 * Indicates the view is pressed, enabled and focused.
1404 * @see #PRESSED_STATE_SET
1405 * @see #ENABLED_STATE_SET
1406 * @see #FOCUSED_STATE_SET
1408 protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1410 * Indicates the view is pressed, enabled, focused and its window has the
1413 * @see #PRESSED_STATE_SET
1414 * @see #ENABLED_STATE_SET
1415 * @see #FOCUSED_STATE_SET
1416 * @see #WINDOW_FOCUSED_STATE_SET
1418 protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1420 * Indicates the view is pressed, enabled, focused and selected.
1422 * @see #PRESSED_STATE_SET
1423 * @see #ENABLED_STATE_SET
1424 * @see #SELECTED_STATE_SET
1425 * @see #FOCUSED_STATE_SET
1427 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1429 * Indicates the view is pressed, enabled, focused, selected and its window
1432 * @see #PRESSED_STATE_SET
1433 * @see #ENABLED_STATE_SET
1434 * @see #SELECTED_STATE_SET
1435 * @see #FOCUSED_STATE_SET
1436 * @see #WINDOW_FOCUSED_STATE_SET
1438 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1441 * The order here is very important to {@link #getDrawableState()}
1443 private static final int[][] VIEW_STATE_SETS;
1445 static final int VIEW_STATE_WINDOW_FOCUSED = 1;
1446 static final int VIEW_STATE_SELECTED = 1 << 1;
1447 static final int VIEW_STATE_FOCUSED = 1 << 2;
1448 static final int VIEW_STATE_ENABLED = 1 << 3;
1449 static final int VIEW_STATE_PRESSED = 1 << 4;
1450 static final int VIEW_STATE_ACTIVATED = 1 << 5;
1451 static final int VIEW_STATE_ACCELERATED = 1 << 6;
1452 static final int VIEW_STATE_HOVERED = 1 << 7;
1453 static final int VIEW_STATE_DRAG_CAN_ACCEPT = 1 << 8;
1454 static final int VIEW_STATE_DRAG_HOVERED = 1 << 9;
1456 static final int[] VIEW_STATE_IDS = new int[] {
1457 R.attr.state_window_focused, VIEW_STATE_WINDOW_FOCUSED,
1458 R.attr.state_selected, VIEW_STATE_SELECTED,
1459 R.attr.state_focused, VIEW_STATE_FOCUSED,
1460 R.attr.state_enabled, VIEW_STATE_ENABLED,
1461 R.attr.state_pressed, VIEW_STATE_PRESSED,
1462 R.attr.state_activated, VIEW_STATE_ACTIVATED,
1463 R.attr.state_accelerated, VIEW_STATE_ACCELERATED,
1464 R.attr.state_hovered, VIEW_STATE_HOVERED,
1465 R.attr.state_drag_can_accept, VIEW_STATE_DRAG_CAN_ACCEPT,
1466 R.attr.state_drag_hovered, VIEW_STATE_DRAG_HOVERED
1470 if ((VIEW_STATE_IDS.length/2) != R.styleable.ViewDrawableStates.length) {
1471 throw new IllegalStateException(
1472 "VIEW_STATE_IDs array length does not match ViewDrawableStates style array");
1474 int[] orderedIds = new int[VIEW_STATE_IDS.length];
1475 for (int i = 0; i < R.styleable.ViewDrawableStates.length; i++) {
1476 int viewState = R.styleable.ViewDrawableStates[i];
1477 for (int j = 0; j<VIEW_STATE_IDS.length; j += 2) {
1478 if (VIEW_STATE_IDS[j] == viewState) {
1479 orderedIds[i * 2] = viewState;
1480 orderedIds[i * 2 + 1] = VIEW_STATE_IDS[j + 1];
1484 final int NUM_BITS = VIEW_STATE_IDS.length / 2;
1485 VIEW_STATE_SETS = new int[1 << NUM_BITS][];
1486 for (int i = 0; i < VIEW_STATE_SETS.length; i++) {
1487 int numBits = Integer.bitCount(i);
1488 int[] set = new int[numBits];
1490 for (int j = 0; j < orderedIds.length; j += 2) {
1491 if ((i & orderedIds[j+1]) != 0) {
1492 set[pos++] = orderedIds[j];
1495 VIEW_STATE_SETS[i] = set;
1498 EMPTY_STATE_SET = VIEW_STATE_SETS[0];
1499 WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_WINDOW_FOCUSED];
1500 SELECTED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_SELECTED];
1501 SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1502 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED];
1503 FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_FOCUSED];
1504 FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1505 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED];
1506 FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1507 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED];
1508 FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1509 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1510 | VIEW_STATE_FOCUSED];
1511 ENABLED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_ENABLED];
1512 ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1513 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED];
1514 ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1515 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED];
1516 ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1517 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1518 | VIEW_STATE_ENABLED];
1519 ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1520 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED];
1521 ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1522 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1523 | VIEW_STATE_ENABLED];
1524 ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1525 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1526 | VIEW_STATE_ENABLED];
1527 ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1528 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1529 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED];
1531 PRESSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_PRESSED];
1532 PRESSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1533 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_PRESSED];
1534 PRESSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1535 VIEW_STATE_SELECTED | VIEW_STATE_PRESSED];
1536 PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1537 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1538 | VIEW_STATE_PRESSED];
1539 PRESSED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1540 VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1541 PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1542 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1543 | VIEW_STATE_PRESSED];
1544 PRESSED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1545 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1546 | VIEW_STATE_PRESSED];
1547 PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1548 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1549 | VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1550 PRESSED_ENABLED_STATE_SET = VIEW_STATE_SETS[
1551 VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1552 PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1553 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED
1554 | VIEW_STATE_PRESSED];
1555 PRESSED_ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1556 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED
1557 | VIEW_STATE_PRESSED];
1558 PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1559 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1560 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1561 PRESSED_ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1562 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED
1563 | VIEW_STATE_PRESSED];
1564 PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1565 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1566 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1567 PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1568 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1569 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1570 PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1571 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1572 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED
1573 | VIEW_STATE_PRESSED];
1577 * Accessibility event types that are dispatched for text population.
1579 private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1580 AccessibilityEvent.TYPE_VIEW_CLICKED
1581 | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1582 | AccessibilityEvent.TYPE_VIEW_SELECTED
1583 | AccessibilityEvent.TYPE_VIEW_FOCUSED
1584 | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1585 | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1586 | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1587 | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1588 | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1589 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1590 | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1593 * Temporary Rect currently for use in setBackground(). This will probably
1594 * be extended in the future to hold our own class with more than just
1597 static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1600 * Map used to store views' tags.
1602 private SparseArray<Object> mKeyedTags;
1605 * The next available accessibility id.
1607 private static int sNextAccessibilityViewId;
1610 * The animation currently associated with this view.
1613 protected Animation mCurrentAnimation = null;
1616 * Width as measured during measure pass.
1619 @ViewDebug.ExportedProperty(category = "measurement")
1623 * Height as measured during measure pass.
1626 @ViewDebug.ExportedProperty(category = "measurement")
1627 int mMeasuredHeight;
1630 * Flag to indicate that this view was marked INVALIDATED, or had its display list
1631 * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1632 * its display list. This flag, used only when hw accelerated, allows us to clear the
1633 * flag while retaining this information until it's needed (at getDisplayList() time and
1634 * in drawChild(), when we decide to draw a view's children's display lists into our own).
1638 boolean mRecreateDisplayList = false;
1641 * The view's identifier.
1647 @ViewDebug.ExportedProperty(resolveId = true)
1651 * The stable ID of this view for accessibility purposes.
1653 int mAccessibilityViewId = NO_ID;
1655 private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1657 SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1663 * @see #setTag(Object)
1666 protected Object mTag = null;
1668 // for mPrivateFlags:
1670 static final int PFLAG_WANTS_FOCUS = 0x00000001;
1672 static final int PFLAG_FOCUSED = 0x00000002;
1674 static final int PFLAG_SELECTED = 0x00000004;
1676 static final int PFLAG_IS_ROOT_NAMESPACE = 0x00000008;
1678 static final int PFLAG_HAS_BOUNDS = 0x00000010;
1680 static final int PFLAG_DRAWN = 0x00000020;
1682 * When this flag is set, this view is running an animation on behalf of its
1683 * children and should therefore not cancel invalidate requests, even if they
1684 * lie outside of this view's bounds.
1688 static final int PFLAG_DRAW_ANIMATION = 0x00000040;
1690 static final int PFLAG_SKIP_DRAW = 0x00000080;
1692 static final int PFLAG_ONLY_DRAWS_BACKGROUND = 0x00000100;
1694 static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1696 static final int PFLAG_DRAWABLE_STATE_DIRTY = 0x00000400;
1698 static final int PFLAG_MEASURED_DIMENSION_SET = 0x00000800;
1700 static final int PFLAG_FORCE_LAYOUT = 0x00001000;
1702 static final int PFLAG_LAYOUT_REQUIRED = 0x00002000;
1704 private static final int PFLAG_PRESSED = 0x00004000;
1707 static final int PFLAG_DRAWING_CACHE_VALID = 0x00008000;
1709 * Flag used to indicate that this view should be drawn once more (and only once
1710 * more) after its animation has completed.
1713 static final int PFLAG_ANIMATION_STARTED = 0x00010000;
1715 private static final int PFLAG_SAVE_STATE_CALLED = 0x00020000;
1718 * Indicates that the View returned true when onSetAlpha() was called and that
1719 * the alpha must be restored.
1722 static final int PFLAG_ALPHA_SET = 0x00040000;
1725 * Set by {@link #setScrollContainer(boolean)}.
1727 static final int PFLAG_SCROLL_CONTAINER = 0x00080000;
1730 * Set by {@link #setScrollContainer(boolean)}.
1732 static final int PFLAG_SCROLL_CONTAINER_ADDED = 0x00100000;
1735 * View flag indicating whether this view was invalidated (fully or partially.)
1739 static final int PFLAG_DIRTY = 0x00200000;
1742 * View flag indicating whether this view was invalidated by an opaque
1743 * invalidate request.
1747 static final int PFLAG_DIRTY_OPAQUE = 0x00400000;
1750 * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1754 static final int PFLAG_DIRTY_MASK = 0x00600000;
1757 * Indicates whether the background is opaque.
1761 static final int PFLAG_OPAQUE_BACKGROUND = 0x00800000;
1764 * Indicates whether the scrollbars are opaque.
1768 static final int PFLAG_OPAQUE_SCROLLBARS = 0x01000000;
1771 * Indicates whether the view is opaque.
1775 static final int PFLAG_OPAQUE_MASK = 0x01800000;
1778 * Indicates a prepressed state;
1779 * the short time between ACTION_DOWN and recognizing
1780 * a 'real' press. Prepressed is used to recognize quick taps
1781 * even when they are shorter than ViewConfiguration.getTapTimeout().
1785 private static final int PFLAG_PREPRESSED = 0x02000000;
1788 * Indicates whether the view is temporarily detached.
1792 static final int PFLAG_CANCEL_NEXT_UP_EVENT = 0x04000000;
1795 * Indicates that we should awaken scroll bars once attached
1799 private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1802 * Indicates that the view has received HOVER_ENTER. Cleared on HOVER_EXIT.
1805 private static final int PFLAG_HOVERED = 0x10000000;
1808 * no longer needed, should be reused
1810 private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1813 static final int PFLAG_ACTIVATED = 0x40000000;
1816 * Indicates that this view was specifically invalidated, not just dirtied because some
1817 * child view was invalidated. The flag is used to determine when we need to recreate
1818 * a view's display list (as opposed to just returning a reference to its existing
1823 static final int PFLAG_INVALIDATED = 0x80000000;
1826 * Masks for mPrivateFlags2, as generated by dumpFlags():
1828 * |-------|-------|-------|-------|
1829 * 1 PFLAG2_DRAG_CAN_ACCEPT
1830 * 1 PFLAG2_DRAG_HOVERED
1831 * 11 PFLAG2_LAYOUT_DIRECTION_MASK
1832 * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1833 * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED
1834 * 11 PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1835 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[1]
1836 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[2]
1837 * 11 PFLAG2_TEXT_DIRECTION_FLAGS[3]
1838 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[4]
1839 * 1 1 PFLAG2_TEXT_DIRECTION_FLAGS[5]
1840 * 111 PFLAG2_TEXT_DIRECTION_MASK
1841 * 1 PFLAG2_TEXT_DIRECTION_RESOLVED
1842 * 1 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1843 * 111 PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1844 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1845 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1846 * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1847 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1848 * 1 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1849 * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1850 * 111 PFLAG2_TEXT_ALIGNMENT_MASK
1851 * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1852 * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1853 * 111 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1854 * 111 PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1855 * 11 PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1856 * 1 PFLAG2_ACCESSIBILITY_FOCUSED
1857 * 1 PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1858 * 1 PFLAG2_VIEW_QUICK_REJECTED
1859 * 1 PFLAG2_PADDING_RESOLVED
1860 * 1 PFLAG2_DRAWABLE_RESOLVED
1861 * 1 PFLAG2_HAS_TRANSIENT_STATE
1862 * |-------|-------|-------|-------|
1866 * Indicates that this view has reported that it can accept the current drag's content.
1867 * Cleared when the drag operation concludes.
1870 static final int PFLAG2_DRAG_CAN_ACCEPT = 0x00000001;
1873 * Indicates that this view is currently directly under the drag location in a
1874 * drag-and-drop operation involving content that it can accept. Cleared when
1875 * the drag exits the view, or when the drag operation concludes.
1878 static final int PFLAG2_DRAG_HOVERED = 0x00000002;
1882 LAYOUT_DIRECTION_LTR,
1883 LAYOUT_DIRECTION_RTL,
1884 LAYOUT_DIRECTION_INHERIT,
1885 LAYOUT_DIRECTION_LOCALE
1887 @Retention(RetentionPolicy.SOURCE)
1888 // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1889 public @interface LayoutDir {}
1893 LAYOUT_DIRECTION_LTR,
1894 LAYOUT_DIRECTION_RTL
1896 @Retention(RetentionPolicy.SOURCE)
1897 public @interface ResolvedLayoutDir {}
1900 * Horizontal layout direction of this view is from Left to Right.
1901 * Use with {@link #setLayoutDirection}.
1903 public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1906 * Horizontal layout direction of this view is from Right to Left.
1907 * Use with {@link #setLayoutDirection}.
1909 public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1912 * Horizontal layout direction of this view is inherited from its parent.
1913 * Use with {@link #setLayoutDirection}.
1915 public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1918 * Horizontal layout direction of this view is from deduced from the default language
1919 * script for the locale. Use with {@link #setLayoutDirection}.
1921 public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1924 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1927 static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1930 * Mask for use with private flags indicating bits used for horizontal layout direction.
1933 static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1936 * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1937 * right-to-left direction.
1940 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1943 * Indicates whether the view horizontal layout direction has been resolved.
1946 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1949 * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1952 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1953 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1956 * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1960 private static final int[] LAYOUT_DIRECTION_FLAGS = {
1961 LAYOUT_DIRECTION_LTR,
1962 LAYOUT_DIRECTION_RTL,
1963 LAYOUT_DIRECTION_INHERIT,
1964 LAYOUT_DIRECTION_LOCALE
1968 * Default horizontal layout direction.
1970 private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
1973 * Default horizontal layout direction.
1976 static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
1979 * Text direction is inherited thru {@link ViewGroup}
1981 public static final int TEXT_DIRECTION_INHERIT = 0;
1984 * Text direction is using "first strong algorithm". The first strong directional character
1985 * determines the paragraph direction. If there is no strong directional character, the
1986 * paragraph direction is the view's resolved layout direction.
1988 public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
1991 * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
1992 * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
1993 * If there are neither, the paragraph direction is the view's resolved layout direction.
1995 public static final int TEXT_DIRECTION_ANY_RTL = 2;
1998 * Text direction is forced to LTR.
2000 public static final int TEXT_DIRECTION_LTR = 3;
2003 * Text direction is forced to RTL.
2005 public static final int TEXT_DIRECTION_RTL = 4;
2008 * Text direction is coming from the system Locale.
2010 public static final int TEXT_DIRECTION_LOCALE = 5;
2013 * Default text direction is inherited
2015 private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2018 * Default resolved text direction
2021 static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2024 * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2027 static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2030 * Mask for use with private flags indicating bits used for text direction.
2033 static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2034 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2037 * Array of text direction flags for mapping attribute "textDirection" to correct
2041 private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2042 TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2043 TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2044 TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2045 TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2046 TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2047 TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2051 * Indicates whether the view text direction has been resolved.
2054 static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2055 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2058 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2061 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2064 * Mask for use with private flags indicating bits used for resolved text direction.
2067 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2068 << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2071 * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2074 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2075 TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2079 TEXT_ALIGNMENT_INHERIT,
2080 TEXT_ALIGNMENT_GRAVITY,
2081 TEXT_ALIGNMENT_CENTER,
2082 TEXT_ALIGNMENT_TEXT_START,
2083 TEXT_ALIGNMENT_TEXT_END,
2084 TEXT_ALIGNMENT_VIEW_START,
2085 TEXT_ALIGNMENT_VIEW_END
2087 @Retention(RetentionPolicy.SOURCE)
2088 public @interface TextAlignment {}
2091 * Default text alignment. The text alignment of this View is inherited from its parent.
2092 * Use with {@link #setTextAlignment(int)}
2094 public static final int TEXT_ALIGNMENT_INHERIT = 0;
2097 * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2098 * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2100 * Use with {@link #setTextAlignment(int)}
2102 public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2105 * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2107 * Use with {@link #setTextAlignment(int)}
2109 public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2112 * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2114 * Use with {@link #setTextAlignment(int)}
2116 public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2119 * Center the paragraph, e.g. ALIGN_CENTER.
2121 * Use with {@link #setTextAlignment(int)}
2123 public static final int TEXT_ALIGNMENT_CENTER = 4;
2126 * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2127 * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2129 * Use with {@link #setTextAlignment(int)}
2131 public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2134 * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2135 * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2137 * Use with {@link #setTextAlignment(int)}
2139 public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2142 * Default text alignment is inherited
2144 private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2147 * Default resolved text alignment
2150 static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2153 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2156 static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2159 * Mask for use with private flags indicating bits used for text alignment.
2162 static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2165 * Array of text direction flags for mapping attribute "textAlignment" to correct
2169 private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2170 TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2171 TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2172 TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2173 TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2174 TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2175 TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2176 TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2180 * Indicates whether the view text alignment has been resolved.
2183 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2186 * Bit shift to get the resolved text alignment.
2189 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2192 * Mask for use with private flags indicating bits used for text alignment.
2195 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2196 << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2199 * Indicates whether if the view text alignment has been resolved to gravity
2201 private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2202 TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2204 // Accessiblity constants for mPrivateFlags2
2207 * Shift for the bits in {@link #mPrivateFlags2} related to the
2208 * "importantForAccessibility" attribute.
2210 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2213 * Automatically determine whether a view is important for accessibility.
2215 public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2218 * The view is important for accessibility.
2220 public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2223 * The view is not important for accessibility.
2225 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2228 * The view is not important for accessibility, nor are any of its
2231 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2234 * The default whether the view is important for accessibility.
2236 static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2239 * Mask for obtainig the bits which specify how to determine
2240 * whether a view is important for accessibility.
2242 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2243 | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2244 | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2245 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2248 * Shift for the bits in {@link #mPrivateFlags2} related to the
2249 * "accessibilityLiveRegion" attribute.
2251 static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2254 * Live region mode specifying that accessibility services should not
2255 * automatically announce changes to this view. This is the default live
2256 * region mode for most views.
2258 * Use with {@link #setAccessibilityLiveRegion(int)}.
2260 public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2263 * Live region mode specifying that accessibility services should announce
2264 * changes to this view.
2266 * Use with {@link #setAccessibilityLiveRegion(int)}.
2268 public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2271 * Live region mode specifying that accessibility services should interrupt
2272 * ongoing speech to immediately announce changes to this view.
2274 * Use with {@link #setAccessibilityLiveRegion(int)}.
2276 public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2279 * The default whether the view is important for accessibility.
2281 static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2284 * Mask for obtaining the bits which specify a view's accessibility live
2287 static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2288 | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2289 << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2292 * Flag indicating whether a view has accessibility focus.
2294 static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2297 * Flag whether the accessibility state of the subtree rooted at this view changed.
2299 static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2302 * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2303 * is used to check whether later changes to the view's transform should invalidate the
2304 * view to force the quickReject test to run again.
2306 static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2309 * Flag indicating that start/end padding has been resolved into left/right padding
2310 * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2311 * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2312 * during measurement. In some special cases this is required such as when an adapter-based
2313 * view measures prospective children without attaching them to a window.
2315 static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2318 * Flag indicating that the start/end drawables has been resolved into left/right ones.
2320 static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2323 * Indicates that the view is tracking some sort of transient state
2324 * that the app should not need to be aware of, but that the framework
2325 * should take special care to preserve.
2327 static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2330 * Group of bits indicating that RTL properties resolution is done.
2332 static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2333 PFLAG2_TEXT_DIRECTION_RESOLVED |
2334 PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2335 PFLAG2_PADDING_RESOLVED |
2336 PFLAG2_DRAWABLE_RESOLVED;
2338 // There are a couple of flags left in mPrivateFlags2
2340 /* End of masks for mPrivateFlags2 */
2343 * Masks for mPrivateFlags3, as generated by dumpFlags():
2345 * |-------|-------|-------|-------|
2346 * 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2347 * 1 PFLAG3_VIEW_IS_ANIMATING_ALPHA
2348 * 1 PFLAG3_IS_LAID_OUT
2349 * 1 PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2350 * 1 PFLAG3_CALLED_SUPER
2351 * |-------|-------|-------|-------|
2355 * Flag indicating that view has a transform animation set on it. This is used to track whether
2356 * an animation is cleared between successive frames, in order to tell the associated
2357 * DisplayList to clear its animation matrix.
2359 static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2362 * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2363 * animation is cleared between successive frames, in order to tell the associated
2364 * DisplayList to restore its alpha value.
2366 static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2369 * Flag indicating that the view has been through at least one layout since it
2370 * was last attached to a window.
2372 static final int PFLAG3_IS_LAID_OUT = 0x4;
2375 * Flag indicating that a call to measure() was skipped and should be done
2376 * instead when layout() is invoked.
2378 static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2381 * Flag indicating that an overridden method correctly called down to
2382 * the superclass implementation as required by the API spec.
2384 static final int PFLAG3_CALLED_SUPER = 0x10;
2387 * Flag indicating that we're in the process of applying window insets.
2389 static final int PFLAG3_APPLYING_INSETS = 0x20;
2392 * Flag indicating that we're in the process of fitting system windows using the old method.
2394 static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2397 * Flag indicating that nested scrolling is enabled for this view.
2398 * The view will optionally cooperate with views up its parent chain to allow for
2399 * integrated nested scrolling along the same axis.
2401 static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2403 /* End of masks for mPrivateFlags3 */
2405 static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2408 * Always allow a user to over-scroll this view, provided it is a
2409 * view that can scroll.
2411 * @see #getOverScrollMode()
2412 * @see #setOverScrollMode(int)
2414 public static final int OVER_SCROLL_ALWAYS = 0;
2417 * Allow a user to over-scroll this view only if the content is large
2418 * enough to meaningfully scroll, provided it is a view that can scroll.
2420 * @see #getOverScrollMode()
2421 * @see #setOverScrollMode(int)
2423 public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2426 * Never allow a user to over-scroll this view.
2428 * @see #getOverScrollMode()
2429 * @see #setOverScrollMode(int)
2431 public static final int OVER_SCROLL_NEVER = 2;
2434 * Special constant for {@link #setSystemUiVisibility(int)}: View has
2435 * requested the system UI (status bar) to be visible (the default).
2437 * @see #setSystemUiVisibility(int)
2439 public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2442 * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2443 * system UI to enter an unobtrusive "low profile" mode.
2445 * <p>This is for use in games, book readers, video players, or any other
2446 * "immersive" application where the usual system chrome is deemed too distracting.
2448 * <p>In low profile mode, the status bar and/or navigation icons may dim.
2450 * @see #setSystemUiVisibility(int)
2452 public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2455 * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2456 * system navigation be temporarily hidden.
2458 * <p>This is an even less obtrusive state than that called for by
2459 * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2460 * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2461 * those to disappear. This is useful (in conjunction with the
2462 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2463 * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2464 * window flags) for displaying content using every last pixel on the display.
2466 * <p>There is a limitation: because navigation controls are so important, the least user
2467 * interaction will cause them to reappear immediately. When this happens, both
2468 * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2469 * so that both elements reappear at the same time.
2471 * @see #setSystemUiVisibility(int)
2473 public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2476 * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2477 * into the normal fullscreen mode so that its content can take over the screen
2478 * while still allowing the user to interact with the application.
2480 * <p>This has the same visual effect as
2481 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2482 * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2483 * meaning that non-critical screen decorations (such as the status bar) will be
2484 * hidden while the user is in the View's window, focusing the experience on
2485 * that content. Unlike the window flag, if you are using ActionBar in
2486 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2487 * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2488 * hide the action bar.
2490 * <p>This approach to going fullscreen is best used over the window flag when
2491 * it is a transient state -- that is, the application does this at certain
2492 * points in its user interaction where it wants to allow the user to focus
2493 * on content, but not as a continuous state. For situations where the application
2494 * would like to simply stay full screen the entire time (such as a game that
2495 * wants to take over the screen), the
2496 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2497 * is usually a better approach. The state set here will be removed by the system
2498 * in various situations (such as the user moving to another application) like
2499 * the other system UI states.
2501 * <p>When using this flag, the application should provide some easy facility
2502 * for the user to go out of it. A common example would be in an e-book
2503 * reader, where tapping on the screen brings back whatever screen and UI
2504 * decorations that had been hidden while the user was immersed in reading
2507 * @see #setSystemUiVisibility(int)
2509 public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2512 * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2513 * flags, we would like a stable view of the content insets given to
2514 * {@link #fitSystemWindows(Rect)}. This means that the insets seen there
2515 * will always represent the worst case that the application can expect
2516 * as a continuous state. In the stock Android UI this is the space for
2517 * the system bar, nav bar, and status bar, but not more transient elements
2518 * such as an input method.
2520 * The stable layout your UI sees is based on the system UI modes you can
2521 * switch to. That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2522 * then you will get a stable layout for changes of the
2523 * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2524 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2525 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2526 * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2527 * with a stable layout. (Note that you should avoid using
2528 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2530 * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2531 * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2532 * then a hidden status bar will be considered a "stable" state for purposes
2533 * here. This allows your UI to continually hide the status bar, while still
2534 * using the system UI flags to hide the action bar while still retaining
2535 * a stable layout. Note that changing the window fullscreen flag will never
2536 * provide a stable layout for a clean transition.
2538 * <p>If you are using ActionBar in
2539 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2540 * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2541 * insets it adds to those given to the application.
2543 public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2546 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2547 * to be layed out as if it has requested
2548 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't. This
2549 * allows it to avoid artifacts when switching in and out of that mode, at
2550 * the expense that some of its user interface may be covered by screen
2551 * decorations when they are shown. You can perform layout of your inner
2552 * UI elements to account for the navigation system UI through the
2553 * {@link #fitSystemWindows(Rect)} method.
2555 public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2558 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2559 * to be layed out as if it has requested
2560 * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't. This
2561 * allows it to avoid artifacts when switching in and out of that mode, at
2562 * the expense that some of its user interface may be covered by screen
2563 * decorations when they are shown. You can perform layout of your inner
2564 * UI elements to account for non-fullscreen system UI through the
2565 * {@link #fitSystemWindows(Rect)} method.
2567 public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2570 * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2571 * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. If this flag is
2572 * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2574 * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2575 * has an effect when used in combination with that flag.</p>
2577 public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2580 * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2581 * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2582 * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. Use this flag to create an immersive
2583 * experience while also hiding the system bars. If this flag is not set,
2584 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2585 * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2586 * if the user swipes from the top of the screen.
2587 * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2588 * system gestures, such as swiping from the top of the screen. These transient system bars
2589 * will overlay app’s content, may have some degree of transparency, and will automatically
2590 * hide after a short timeout.
2591 * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2592 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2593 * with one or both of those flags.</p>
2595 public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2598 * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2600 public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2603 * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2605 public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2610 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2611 * out of the public fields to keep the undefined bits out of the developer's way.
2613 * Flag to make the status bar not expandable. Unless you also
2614 * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2616 public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2621 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2622 * out of the public fields to keep the undefined bits out of the developer's way.
2624 * Flag to hide notification icons and scrolling ticker text.
2626 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2631 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2632 * out of the public fields to keep the undefined bits out of the developer's way.
2634 * Flag to disable incoming notification alerts. This will not block
2635 * icons, but it will block sound, vibrating and other visual or aural notifications.
2637 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2642 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2643 * out of the public fields to keep the undefined bits out of the developer's way.
2645 * Flag to hide only the scrolling ticker. Note that
2646 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2647 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2649 public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2654 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2655 * out of the public fields to keep the undefined bits out of the developer's way.
2657 * Flag to hide the center system info area.
2659 public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2664 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2665 * out of the public fields to keep the undefined bits out of the developer's way.
2667 * Flag to hide only the home button. Don't use this
2668 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2670 public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2675 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2676 * out of the public fields to keep the undefined bits out of the developer's way.
2678 * Flag to hide only the back button. Don't use this
2679 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2681 public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2686 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2687 * out of the public fields to keep the undefined bits out of the developer's way.
2689 * Flag to hide only the clock. You might use this if your activity has
2690 * its own clock making the status bar's clock redundant.
2692 public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2697 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2698 * out of the public fields to keep the undefined bits out of the developer's way.
2700 * Flag to hide only the recent apps button. Don't use this
2701 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2703 public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2708 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2709 * out of the public fields to keep the undefined bits out of the developer's way.
2711 * Flag to disable the global search gesture. Don't use this
2712 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2714 public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2719 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2720 * out of the public fields to keep the undefined bits out of the developer's way.
2722 * Flag to specify that the status bar is displayed in transient mode.
2724 public static final int STATUS_BAR_TRANSIENT = 0x04000000;
2729 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2730 * out of the public fields to keep the undefined bits out of the developer's way.
2732 * Flag to specify that the navigation bar is displayed in transient mode.
2734 public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
2739 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2740 * out of the public fields to keep the undefined bits out of the developer's way.
2742 * Flag to specify that the hidden status bar would like to be shown.
2744 public static final int STATUS_BAR_UNHIDE = 0x10000000;
2749 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2750 * out of the public fields to keep the undefined bits out of the developer's way.
2752 * Flag to specify that the hidden navigation bar would like to be shown.
2754 public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
2759 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2760 * out of the public fields to keep the undefined bits out of the developer's way.
2762 * Flag to specify that the status bar is displayed in translucent mode.
2764 public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
2769 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2770 * out of the public fields to keep the undefined bits out of the developer's way.
2772 * Flag to specify that the navigation bar is displayed in translucent mode.
2774 public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
2779 * Whether Recents is visible or not.
2781 public static final int RECENT_APPS_VISIBLE = 0x00004000;
2786 * Makes system ui transparent.
2788 public static final int SYSTEM_UI_TRANSPARENT = 0x00008000;
2793 public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FFF;
2796 * These are the system UI flags that can be cleared by events outside
2797 * of an application. Currently this is just the ability to tap on the
2798 * screen while hiding the navigation bar to have it return.
2801 public static final int SYSTEM_UI_CLEARABLE_FLAGS =
2802 SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2803 | SYSTEM_UI_FLAG_FULLSCREEN;
2806 * Flags that can impact the layout in relation to system UI.
2808 public static final int SYSTEM_UI_LAYOUT_FLAGS =
2809 SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2810 | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2813 @IntDef(flag = true,
2814 value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
2815 @Retention(RetentionPolicy.SOURCE)
2816 public @interface FindViewFlags {}
2819 * Find views that render the specified text.
2821 * @see #findViewsWithText(ArrayList, CharSequence, int)
2823 public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2826 * Find find views that contain the specified content description.
2828 * @see #findViewsWithText(ArrayList, CharSequence, int)
2830 public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2833 * Find views that contain {@link AccessibilityNodeProvider}. Such
2834 * a View is a root of virtual view hierarchy and may contain the searched
2835 * text. If this flag is set Views with providers are automatically
2836 * added and it is a responsibility of the client to call the APIs of
2837 * the provider to determine whether the virtual tree rooted at this View
2838 * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
2839 * representing the virtual views with this text.
2841 * @see #findViewsWithText(ArrayList, CharSequence, int)
2845 public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
2848 * The undefined cursor position.
2852 public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
2855 * Indicates that the screen has changed state and is now off.
2857 * @see #onScreenStateChanged(int)
2859 public static final int SCREEN_STATE_OFF = 0x0;
2862 * Indicates that the screen has changed state and is now on.
2864 * @see #onScreenStateChanged(int)
2866 public static final int SCREEN_STATE_ON = 0x1;
2869 * Indicates no axis of view scrolling.
2871 public static final int SCROLL_AXIS_NONE = 0;
2874 * Indicates scrolling along the horizontal axis.
2876 public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
2879 * Indicates scrolling along the vertical axis.
2881 public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
2884 * Controls the over-scroll mode for this view.
2885 * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
2886 * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
2887 * and {@link #OVER_SCROLL_NEVER}.
2889 private int mOverScrollMode;
2892 * The parent this view is attached to.
2897 protected ViewParent mParent;
2902 AttachInfo mAttachInfo;
2907 @ViewDebug.ExportedProperty(flagMapping = {
2908 @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
2909 name = "FORCE_LAYOUT"),
2910 @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
2911 name = "LAYOUT_REQUIRED"),
2912 @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
2913 name = "DRAWING_CACHE_INVALID", outputIf = false),
2914 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
2915 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
2916 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
2917 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
2918 }, formatToHexString = true)
2924 * This view's request for the visibility of the status bar.
2927 @ViewDebug.ExportedProperty(flagMapping = {
2928 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
2929 equals = SYSTEM_UI_FLAG_LOW_PROFILE,
2930 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
2931 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2932 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2933 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
2934 @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
2935 equals = SYSTEM_UI_FLAG_VISIBLE,
2936 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
2937 }, formatToHexString = true)
2938 int mSystemUiVisibility;
2941 * Reference count for transient state.
2942 * @see #setHasTransientState(boolean)
2944 int mTransientStateCount = 0;
2947 * Count of how many windows this view has been attached to.
2949 int mWindowAttachCount;
2952 * The layout parameters associated with this view and used by the parent
2953 * {@link android.view.ViewGroup} to determine how this view should be
2957 protected ViewGroup.LayoutParams mLayoutParams;
2960 * The view flags hold various views states.
2963 @ViewDebug.ExportedProperty(formatToHexString = true)
2966 static class TransformationInfo {
2968 * The transform matrix for the View. This transform is calculated internally
2969 * based on the translation, rotation, and scale properties.
2971 * Do *not* use this variable directly; instead call getMatrix(), which will
2972 * load the value from the View's RenderNode.
2974 private final Matrix mMatrix = new Matrix();
2977 * The inverse transform matrix for the View. This transform is calculated
2978 * internally based on the translation, rotation, and scale properties.
2980 * Do *not* use this variable directly; instead call getInverseMatrix(),
2981 * which will load the value from the View's RenderNode.
2983 private Matrix mInverseMatrix;
2986 * The opacity of the View. This is a value from 0 to 1, where 0 means
2987 * completely transparent and 1 means completely opaque.
2989 @ViewDebug.ExportedProperty
2993 * The opacity of the view as manipulated by the Fade transition. This is a hidden
2994 * property only used by transitions, which is composited with the other alpha
2995 * values to calculate the final visual alpha value.
2997 float mTransitionAlpha = 1f;
3000 TransformationInfo mTransformationInfo;
3003 * Current clip bounds. to which all drawing of this view are constrained.
3005 Rect mClipBounds = null;
3007 private boolean mLastIsOpaque;
3010 * The distance in pixels from the left edge of this view's parent
3011 * to the left edge of this view.
3014 @ViewDebug.ExportedProperty(category = "layout")
3015 protected int mLeft;
3017 * The distance in pixels from the left edge of this view's parent
3018 * to the right edge of this view.
3021 @ViewDebug.ExportedProperty(category = "layout")
3022 protected int mRight;
3024 * The distance in pixels from the top edge of this view's parent
3025 * to the top edge of this view.
3028 @ViewDebug.ExportedProperty(category = "layout")
3031 * The distance in pixels from the top edge of this view's parent
3032 * to the bottom edge of this view.
3035 @ViewDebug.ExportedProperty(category = "layout")
3036 protected int mBottom;
3039 * The offset, in pixels, by which the content of this view is scrolled
3043 @ViewDebug.ExportedProperty(category = "scrolling")
3044 protected int mScrollX;
3046 * The offset, in pixels, by which the content of this view is scrolled
3050 @ViewDebug.ExportedProperty(category = "scrolling")
3051 protected int mScrollY;
3054 * The left padding in pixels, that is the distance in pixels between the
3055 * left edge of this view and the left edge of its content.
3058 @ViewDebug.ExportedProperty(category = "padding")
3059 protected int mPaddingLeft = 0;
3061 * The right padding in pixels, that is the distance in pixels between the
3062 * right edge of this view and the right edge of its content.
3065 @ViewDebug.ExportedProperty(category = "padding")
3066 protected int mPaddingRight = 0;
3068 * The top padding in pixels, that is the distance in pixels between the
3069 * top edge of this view and the top edge of its content.
3072 @ViewDebug.ExportedProperty(category = "padding")
3073 protected int mPaddingTop;
3075 * The bottom padding in pixels, that is the distance in pixels between the
3076 * bottom edge of this view and the bottom edge of its content.
3079 @ViewDebug.ExportedProperty(category = "padding")
3080 protected int mPaddingBottom;
3083 * The layout insets in pixels, that is the distance in pixels between the
3084 * visible edges of this view its bounds.
3086 private Insets mLayoutInsets;
3089 * Briefly describes the view and is primarily used for accessibility support.
3091 private CharSequence mContentDescription;
3094 * Specifies the id of a view for which this view serves as a label for
3095 * accessibility purposes.
3097 private int mLabelForId = View.NO_ID;
3100 * Predicate for matching labeled view id with its label for
3101 * accessibility purposes.
3103 private MatchLabelForPredicate mMatchLabelForPredicate;
3106 * Predicate for matching a view by its id.
3108 private MatchIdPredicate mMatchIdPredicate;
3111 * Cache the paddingRight set by the user to append to the scrollbar's size.
3115 @ViewDebug.ExportedProperty(category = "padding")
3116 protected int mUserPaddingRight;
3119 * Cache the paddingBottom set by the user to append to the scrollbar's size.
3123 @ViewDebug.ExportedProperty(category = "padding")
3124 protected int mUserPaddingBottom;
3127 * Cache the paddingLeft set by the user to append to the scrollbar's size.
3131 @ViewDebug.ExportedProperty(category = "padding")
3132 protected int mUserPaddingLeft;
3135 * Cache the paddingStart set by the user to append to the scrollbar's size.
3138 @ViewDebug.ExportedProperty(category = "padding")
3139 int mUserPaddingStart;
3142 * Cache the paddingEnd set by the user to append to the scrollbar's size.
3145 @ViewDebug.ExportedProperty(category = "padding")
3146 int mUserPaddingEnd;
3149 * Cache initial left padding.
3153 int mUserPaddingLeftInitial;
3156 * Cache initial right padding.
3160 int mUserPaddingRightInitial;
3163 * Default undefined padding
3165 private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3168 * Cache if a left padding has been defined
3170 private boolean mLeftPaddingDefined = false;
3173 * Cache if a right padding has been defined
3175 private boolean mRightPaddingDefined = false;
3180 int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3184 int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3186 private LongSparseLongArray mMeasureCache;
3188 @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3189 private Drawable mBackground;
3190 private ColorStateList mBackgroundTintList = null;
3191 private PorterDuff.Mode mBackgroundTintMode = PorterDuff.Mode.SRC_ATOP;
3192 private boolean mHasBackgroundTint = false;
3195 * RenderNode used for backgrounds.
3197 * When non-null and valid, this is expected to contain an up-to-date copy
3198 * of the background drawable. It is cleared on temporary detach, and reset
3201 private RenderNode mBackgroundRenderNode;
3203 private int mBackgroundResource;
3204 private boolean mBackgroundSizeChanged;
3206 private String mTransitionName;
3208 static class ListenerInfo {
3210 * Listener used to dispatch focus change events.
3211 * This field should be made private, so it is hidden from the SDK.
3214 protected OnFocusChangeListener mOnFocusChangeListener;
3217 * Listeners for layout change events.
3219 private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3222 * Listeners for attach events.
3224 private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3227 * Listener used to dispatch click events.
3228 * This field should be made private, so it is hidden from the SDK.
3231 public OnClickListener mOnClickListener;
3234 * Listener used to dispatch long click events.
3235 * This field should be made private, so it is hidden from the SDK.
3238 protected OnLongClickListener mOnLongClickListener;
3241 * Listener used to build the context menu.
3242 * This field should be made private, so it is hidden from the SDK.
3245 protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3247 private OnKeyListener mOnKeyListener;
3249 private OnTouchListener mOnTouchListener;
3251 private OnHoverListener mOnHoverListener;
3253 private OnGenericMotionListener mOnGenericMotionListener;
3255 private OnDragListener mOnDragListener;
3257 private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3259 OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3262 ListenerInfo mListenerInfo;
3265 * The application environment this view lives in.
3266 * This field should be made private, so it is hidden from the SDK.
3269 @ViewDebug.ExportedProperty(deepExport = true)
3270 protected Context mContext;
3272 private final Resources mResources;
3274 private ScrollabilityCache mScrollCache;
3276 private int[] mDrawableState = null;
3278 ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3281 * Animator that automatically runs based on state changes.
3283 private StateListAnimator mStateListAnimator;
3286 * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3287 * the user may specify which view to go to next.
3289 private int mNextFocusLeftId = View.NO_ID;
3292 * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3293 * the user may specify which view to go to next.
3295 private int mNextFocusRightId = View.NO_ID;
3298 * When this view has focus and the next focus is {@link #FOCUS_UP},
3299 * the user may specify which view to go to next.
3301 private int mNextFocusUpId = View.NO_ID;
3304 * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3305 * the user may specify which view to go to next.
3307 private int mNextFocusDownId = View.NO_ID;
3310 * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3311 * the user may specify which view to go to next.
3313 int mNextFocusForwardId = View.NO_ID;
3315 private CheckForLongPress mPendingCheckForLongPress;
3316 private CheckForTap mPendingCheckForTap = null;
3317 private PerformClick mPerformClick;
3318 private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3320 private UnsetPressedState mUnsetPressedState;
3323 * Whether the long press's action has been invoked. The tap's action is invoked on the
3324 * up event while a long press is invoked as soon as the long press duration is reached, so
3325 * a long press could be performed before the tap is checked, in which case the tap's action
3326 * should not be invoked.
3328 private boolean mHasPerformedLongPress;
3331 * The minimum height of the view. We'll try our best to have the height
3332 * of this view to at least this amount.
3334 @ViewDebug.ExportedProperty(category = "measurement")
3335 private int mMinHeight;
3338 * The minimum width of the view. We'll try our best to have the width
3339 * of this view to at least this amount.
3341 @ViewDebug.ExportedProperty(category = "measurement")
3342 private int mMinWidth;
3345 * The delegate to handle touch events that are physically in this view
3346 * but should be handled by another view.
3348 private TouchDelegate mTouchDelegate = null;
3351 * Solid color to use as a background when creating the drawing cache. Enables
3352 * the cache to use 16 bit bitmaps instead of 32 bit.
3354 private int mDrawingCacheBackgroundColor = 0;
3357 * Special tree observer used when mAttachInfo is null.
3359 private ViewTreeObserver mFloatingTreeObserver;
3362 * Cache the touch slop from the context that created the view.
3364 private int mTouchSlop;
3367 * Object that handles automatic animation of view properties.
3369 private ViewPropertyAnimator mAnimator = null;
3372 * Flag indicating that a drag can cross window boundaries. When
3373 * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3374 * with this flag set, all visible applications will be able to participate
3375 * in the drag operation and receive the dragged content.
3379 public static final int DRAG_FLAG_GLOBAL = 1;
3382 * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3384 private float mVerticalScrollFactor;
3387 * Position of the vertical scroll bar.
3389 private int mVerticalScrollbarPosition;
3392 * Position the scroll bar at the default position as determined by the system.
3394 public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3397 * Position the scroll bar along the left edge.
3399 public static final int SCROLLBAR_POSITION_LEFT = 1;
3402 * Position the scroll bar along the right edge.
3404 public static final int SCROLLBAR_POSITION_RIGHT = 2;
3407 * Indicates that the view does not have a layer.
3409 * @see #getLayerType()
3410 * @see #setLayerType(int, android.graphics.Paint)
3411 * @see #LAYER_TYPE_SOFTWARE
3412 * @see #LAYER_TYPE_HARDWARE
3414 public static final int LAYER_TYPE_NONE = 0;
3417 * <p>Indicates that the view has a software layer. A software layer is backed
3418 * by a bitmap and causes the view to be rendered using Android's software
3419 * rendering pipeline, even if hardware acceleration is enabled.</p>
3421 * <p>Software layers have various usages:</p>
3422 * <p>When the application is not using hardware acceleration, a software layer
3423 * is useful to apply a specific color filter and/or blending mode and/or
3424 * translucency to a view and all its children.</p>
3425 * <p>When the application is using hardware acceleration, a software layer
3426 * is useful to render drawing primitives not supported by the hardware
3427 * accelerated pipeline. It can also be used to cache a complex view tree
3428 * into a texture and reduce the complexity of drawing operations. For instance,
3429 * when animating a complex view tree with a translation, a software layer can
3430 * be used to render the view tree only once.</p>
3431 * <p>Software layers should be avoided when the affected view tree updates
3432 * often. Every update will require to re-render the software layer, which can
3433 * potentially be slow (particularly when hardware acceleration is turned on
3434 * since the layer will have to be uploaded into a hardware texture after every
3437 * @see #getLayerType()
3438 * @see #setLayerType(int, android.graphics.Paint)
3439 * @see #LAYER_TYPE_NONE
3440 * @see #LAYER_TYPE_HARDWARE
3442 public static final int LAYER_TYPE_SOFTWARE = 1;
3445 * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3446 * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3447 * OpenGL hardware) and causes the view to be rendered using Android's hardware
3448 * rendering pipeline, but only if hardware acceleration is turned on for the
3449 * view hierarchy. When hardware acceleration is turned off, hardware layers
3450 * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3452 * <p>A hardware layer is useful to apply a specific color filter and/or
3453 * blending mode and/or translucency to a view and all its children.</p>
3454 * <p>A hardware layer can be used to cache a complex view tree into a
3455 * texture and reduce the complexity of drawing operations. For instance,
3456 * when animating a complex view tree with a translation, a hardware layer can
3457 * be used to render the view tree only once.</p>
3458 * <p>A hardware layer can also be used to increase the rendering quality when
3459 * rotation transformations are applied on a view. It can also be used to
3460 * prevent potential clipping issues when applying 3D transforms on a view.</p>
3462 * @see #getLayerType()
3463 * @see #setLayerType(int, android.graphics.Paint)
3464 * @see #LAYER_TYPE_NONE
3465 * @see #LAYER_TYPE_SOFTWARE
3467 public static final int LAYER_TYPE_HARDWARE = 2;
3469 @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3470 @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3471 @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3472 @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3474 int mLayerType = LAYER_TYPE_NONE;
3478 * Set to true when drawing cache is enabled and cannot be created.
3482 public boolean mCachingFailed;
3483 private Bitmap mDrawingCache;
3484 private Bitmap mUnscaledDrawingCache;
3487 * RenderNode holding View properties, potentially holding a DisplayList of View content.
3489 * When non-null and valid, this is expected to contain an up-to-date copy
3490 * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3493 final RenderNode mRenderNode;
3496 * Set to true when the view is sending hover accessibility events because it
3497 * is the innermost hovered view.
3499 private boolean mSendingHoverAccessibilityEvents;
3502 * Delegate for injecting accessibility functionality.
3504 AccessibilityDelegate mAccessibilityDelegate;
3507 * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3508 * and add/remove objects to/from the overlay directly through the Overlay methods.
3510 ViewOverlay mOverlay;
3513 * The currently active parent view for receiving delegated nested scrolling events.
3514 * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3515 * by {@link #stopNestedScroll()} at the same point where we clear
3516 * requestDisallowInterceptTouchEvent.
3518 private ViewParent mNestedScrollingParent;
3521 * Consistency verifier for debugging purposes.
3524 protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3525 InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3526 new InputEventConsistencyVerifier(this, 0) : null;
3528 private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3530 private int[] mTempNestedScrollConsumed;
3533 * An overlay is going to draw this View instead of being drawn as part of this
3534 * View's parent. mGhostView is the View in the Overlay that must be invalidated
3535 * when this view is invalidated.
3537 GhostView mGhostView;
3540 * Holds pairs of adjacent attribute data: attribute name followed by its value.
3543 @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3544 public String[] mAttributes;
3547 * Maps a Resource id to its name.
3549 private static SparseArray<String> mAttributeMap;
3552 * Simple constructor to use when creating a view from code.
3554 * @param context The Context the view is running in, through which it can
3555 * access the current theme, resources, etc.
3557 public View(Context context) {
3559 mResources = context != null ? context.getResources() : null;
3560 mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3561 // Set some flags defaults
3563 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3564 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3565 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3566 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3567 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3568 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3569 mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3570 setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3571 mUserPaddingStart = UNDEFINED_PADDING;
3572 mUserPaddingEnd = UNDEFINED_PADDING;
3573 mRenderNode = RenderNode.create(getClass().getName(), this);
3575 if (!sCompatibilityDone && context != null) {
3576 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3578 // Older apps may need this compatibility hack for measurement.
3579 sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
3581 // Older apps expect onMeasure() to always be called on a layout pass, regardless
3582 // of whether a layout was requested on that View.
3583 sIgnoreMeasureCache = targetSdkVersion < KITKAT;
3585 sCompatibilityDone = true;
3590 * Constructor that is called when inflating a view from XML. This is called
3591 * when a view is being constructed from an XML file, supplying attributes
3592 * that were specified in the XML file. This version uses a default style of
3593 * 0, so the only attribute values applied are those in the Context's Theme
3594 * and the given AttributeSet.
3597 * The method onFinishInflate() will be called after all children have been
3600 * @param context The Context the view is running in, through which it can
3601 * access the current theme, resources, etc.
3602 * @param attrs The attributes of the XML tag that is inflating the view.
3603 * @see #View(Context, AttributeSet, int)
3605 public View(Context context, AttributeSet attrs) {
3606 this(context, attrs, 0);
3610 * Perform inflation from XML and apply a class-specific base style from a
3611 * theme attribute. This constructor of View allows subclasses to use their
3612 * own base style when they are inflating. For example, a Button class's
3613 * constructor would call this version of the super class constructor and
3614 * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
3615 * allows the theme's button style to modify all of the base view attributes
3616 * (in particular its background) as well as the Button class's attributes.
3618 * @param context The Context the view is running in, through which it can
3619 * access the current theme, resources, etc.
3620 * @param attrs The attributes of the XML tag that is inflating the view.
3621 * @param defStyleAttr An attribute in the current theme that contains a
3622 * reference to a style resource that supplies default values for
3623 * the view. Can be 0 to not look for defaults.
3624 * @see #View(Context, AttributeSet)
3626 public View(Context context, AttributeSet attrs, int defStyleAttr) {
3627 this(context, attrs, defStyleAttr, 0);
3631 * Perform inflation from XML and apply a class-specific base style from a
3632 * theme attribute or style resource. This constructor of View allows
3633 * subclasses to use their own base style when they are inflating.
3635 * When determining the final value of a particular attribute, there are
3636 * four inputs that come into play:
3638 * <li>Any attribute values in the given AttributeSet.
3639 * <li>The style resource specified in the AttributeSet (named "style").
3640 * <li>The default style specified by <var>defStyleAttr</var>.
3641 * <li>The default style specified by <var>defStyleRes</var>.
3642 * <li>The base values in this theme.
3645 * Each of these inputs is considered in-order, with the first listed taking
3646 * precedence over the following ones. In other words, if in the
3647 * AttributeSet you have supplied <code><Button * textColor="#ff000000"></code>
3648 * , then the button's text will <em>always</em> be black, regardless of
3649 * what is specified in any of the styles.
3651 * @param context The Context the view is running in, through which it can
3652 * access the current theme, resources, etc.
3653 * @param attrs The attributes of the XML tag that is inflating the view.
3654 * @param defStyleAttr An attribute in the current theme that contains a
3655 * reference to a style resource that supplies default values for
3656 * the view. Can be 0 to not look for defaults.
3657 * @param defStyleRes A resource identifier of a style resource that
3658 * supplies default values for the view, used only if
3659 * defStyleAttr is 0 or can not be found in the theme. Can be 0
3660 * to not look for defaults.
3661 * @see #View(Context, AttributeSet, int)
3663 public View(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
3666 final TypedArray a = context.obtainStyledAttributes(
3667 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
3669 if (mDebugViewAttributes) {
3670 saveAttributeData(attrs, a);
3673 Drawable background = null;
3675 int leftPadding = -1;
3676 int topPadding = -1;
3677 int rightPadding = -1;
3678 int bottomPadding = -1;
3679 int startPadding = UNDEFINED_PADDING;
3680 int endPadding = UNDEFINED_PADDING;
3684 int viewFlagValues = 0;
3685 int viewFlagMasks = 0;
3687 boolean setScrollContainer = false;
3695 float elevation = 0;
3697 float rotationX = 0;
3698 float rotationY = 0;
3701 boolean transformSet = false;
3703 int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
3704 int overScrollMode = mOverScrollMode;
3705 boolean initializeScrollbars = false;
3707 boolean startPaddingDefined = false;
3708 boolean endPaddingDefined = false;
3709 boolean leftPaddingDefined = false;
3710 boolean rightPaddingDefined = false;
3712 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3714 final int N = a.getIndexCount();
3715 for (int i = 0; i < N; i++) {
3716 int attr = a.getIndex(i);
3718 case com.android.internal.R.styleable.View_background:
3719 background = a.getDrawable(attr);
3721 case com.android.internal.R.styleable.View_padding:
3722 padding = a.getDimensionPixelSize(attr, -1);
3723 mUserPaddingLeftInitial = padding;
3724 mUserPaddingRightInitial = padding;
3725 leftPaddingDefined = true;
3726 rightPaddingDefined = true;
3728 case com.android.internal.R.styleable.View_paddingLeft:
3729 leftPadding = a.getDimensionPixelSize(attr, -1);
3730 mUserPaddingLeftInitial = leftPadding;
3731 leftPaddingDefined = true;
3733 case com.android.internal.R.styleable.View_paddingTop:
3734 topPadding = a.getDimensionPixelSize(attr, -1);
3736 case com.android.internal.R.styleable.View_paddingRight:
3737 rightPadding = a.getDimensionPixelSize(attr, -1);
3738 mUserPaddingRightInitial = rightPadding;
3739 rightPaddingDefined = true;
3741 case com.android.internal.R.styleable.View_paddingBottom:
3742 bottomPadding = a.getDimensionPixelSize(attr, -1);
3744 case com.android.internal.R.styleable.View_paddingStart:
3745 startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3746 startPaddingDefined = (startPadding != UNDEFINED_PADDING);
3748 case com.android.internal.R.styleable.View_paddingEnd:
3749 endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3750 endPaddingDefined = (endPadding != UNDEFINED_PADDING);
3752 case com.android.internal.R.styleable.View_scrollX:
3753 x = a.getDimensionPixelOffset(attr, 0);
3755 case com.android.internal.R.styleable.View_scrollY:
3756 y = a.getDimensionPixelOffset(attr, 0);
3758 case com.android.internal.R.styleable.View_alpha:
3759 setAlpha(a.getFloat(attr, 1f));
3761 case com.android.internal.R.styleable.View_transformPivotX:
3762 setPivotX(a.getDimensionPixelOffset(attr, 0));
3764 case com.android.internal.R.styleable.View_transformPivotY:
3765 setPivotY(a.getDimensionPixelOffset(attr, 0));
3767 case com.android.internal.R.styleable.View_translationX:
3768 tx = a.getDimensionPixelOffset(attr, 0);
3769 transformSet = true;
3771 case com.android.internal.R.styleable.View_translationY:
3772 ty = a.getDimensionPixelOffset(attr, 0);
3773 transformSet = true;
3775 case com.android.internal.R.styleable.View_translationZ:
3776 tz = a.getDimensionPixelOffset(attr, 0);
3777 transformSet = true;
3779 case com.android.internal.R.styleable.View_elevation:
3780 elevation = a.getDimensionPixelOffset(attr, 0);
3781 transformSet = true;
3783 case com.android.internal.R.styleable.View_rotation:
3784 rotation = a.getFloat(attr, 0);
3785 transformSet = true;
3787 case com.android.internal.R.styleable.View_rotationX:
3788 rotationX = a.getFloat(attr, 0);
3789 transformSet = true;
3791 case com.android.internal.R.styleable.View_rotationY:
3792 rotationY = a.getFloat(attr, 0);
3793 transformSet = true;
3795 case com.android.internal.R.styleable.View_scaleX:
3796 sx = a.getFloat(attr, 1f);
3797 transformSet = true;
3799 case com.android.internal.R.styleable.View_scaleY:
3800 sy = a.getFloat(attr, 1f);
3801 transformSet = true;
3803 case com.android.internal.R.styleable.View_id:
3804 mID = a.getResourceId(attr, NO_ID);
3806 case com.android.internal.R.styleable.View_tag:
3807 mTag = a.getText(attr);
3809 case com.android.internal.R.styleable.View_fitsSystemWindows:
3810 if (a.getBoolean(attr, false)) {
3811 viewFlagValues |= FITS_SYSTEM_WINDOWS;
3812 viewFlagMasks |= FITS_SYSTEM_WINDOWS;
3815 case com.android.internal.R.styleable.View_focusable:
3816 if (a.getBoolean(attr, false)) {
3817 viewFlagValues |= FOCUSABLE;
3818 viewFlagMasks |= FOCUSABLE_MASK;
3821 case com.android.internal.R.styleable.View_focusableInTouchMode:
3822 if (a.getBoolean(attr, false)) {
3823 viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
3824 viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
3827 case com.android.internal.R.styleable.View_clickable:
3828 if (a.getBoolean(attr, false)) {
3829 viewFlagValues |= CLICKABLE;
3830 viewFlagMasks |= CLICKABLE;
3833 case com.android.internal.R.styleable.View_longClickable:
3834 if (a.getBoolean(attr, false)) {
3835 viewFlagValues |= LONG_CLICKABLE;
3836 viewFlagMasks |= LONG_CLICKABLE;
3839 case com.android.internal.R.styleable.View_saveEnabled:
3840 if (!a.getBoolean(attr, true)) {
3841 viewFlagValues |= SAVE_DISABLED;
3842 viewFlagMasks |= SAVE_DISABLED_MASK;
3845 case com.android.internal.R.styleable.View_duplicateParentState:
3846 if (a.getBoolean(attr, false)) {
3847 viewFlagValues |= DUPLICATE_PARENT_STATE;
3848 viewFlagMasks |= DUPLICATE_PARENT_STATE;
3851 case com.android.internal.R.styleable.View_visibility:
3852 final int visibility = a.getInt(attr, 0);
3853 if (visibility != 0) {
3854 viewFlagValues |= VISIBILITY_FLAGS[visibility];
3855 viewFlagMasks |= VISIBILITY_MASK;
3858 case com.android.internal.R.styleable.View_layoutDirection:
3859 // Clear any layout direction flags (included resolved bits) already set
3861 ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
3862 // Set the layout direction flags depending on the value of the attribute
3863 final int layoutDirection = a.getInt(attr, -1);
3864 final int value = (layoutDirection != -1) ?
3865 LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
3866 mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
3868 case com.android.internal.R.styleable.View_drawingCacheQuality:
3869 final int cacheQuality = a.getInt(attr, 0);
3870 if (cacheQuality != 0) {
3871 viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
3872 viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
3875 case com.android.internal.R.styleable.View_contentDescription:
3876 setContentDescription(a.getString(attr));
3878 case com.android.internal.R.styleable.View_labelFor:
3879 setLabelFor(a.getResourceId(attr, NO_ID));
3881 case com.android.internal.R.styleable.View_soundEffectsEnabled:
3882 if (!a.getBoolean(attr, true)) {
3883 viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
3884 viewFlagMasks |= SOUND_EFFECTS_ENABLED;
3887 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
3888 if (!a.getBoolean(attr, true)) {
3889 viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
3890 viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
3893 case R.styleable.View_scrollbars:
3894 final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
3895 if (scrollbars != SCROLLBARS_NONE) {
3896 viewFlagValues |= scrollbars;
3897 viewFlagMasks |= SCROLLBARS_MASK;
3898 initializeScrollbars = true;
3901 //noinspection deprecation
3902 case R.styleable.View_fadingEdge:
3903 if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
3904 // Ignore the attribute starting with ICS
3907 // With builds < ICS, fall through and apply fading edges
3908 case R.styleable.View_requiresFadingEdge:
3909 final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
3910 if (fadingEdge != FADING_EDGE_NONE) {
3911 viewFlagValues |= fadingEdge;
3912 viewFlagMasks |= FADING_EDGE_MASK;
3913 initializeFadingEdgeInternal(a);
3916 case R.styleable.View_scrollbarStyle:
3917 scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
3918 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3919 viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
3920 viewFlagMasks |= SCROLLBARS_STYLE_MASK;
3923 case R.styleable.View_isScrollContainer:
3924 setScrollContainer = true;
3925 if (a.getBoolean(attr, false)) {
3926 setScrollContainer(true);
3929 case com.android.internal.R.styleable.View_keepScreenOn:
3930 if (a.getBoolean(attr, false)) {
3931 viewFlagValues |= KEEP_SCREEN_ON;
3932 viewFlagMasks |= KEEP_SCREEN_ON;
3935 case R.styleable.View_filterTouchesWhenObscured:
3936 if (a.getBoolean(attr, false)) {
3937 viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
3938 viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
3941 case R.styleable.View_nextFocusLeft:
3942 mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
3944 case R.styleable.View_nextFocusRight:
3945 mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
3947 case R.styleable.View_nextFocusUp:
3948 mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
3950 case R.styleable.View_nextFocusDown:
3951 mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
3953 case R.styleable.View_nextFocusForward:
3954 mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
3956 case R.styleable.View_minWidth:
3957 mMinWidth = a.getDimensionPixelSize(attr, 0);
3959 case R.styleable.View_minHeight:
3960 mMinHeight = a.getDimensionPixelSize(attr, 0);
3962 case R.styleable.View_onClick:
3963 if (context.isRestricted()) {
3964 throw new IllegalStateException("The android:onClick attribute cannot "
3965 + "be used within a restricted context");
3968 final String handlerName = a.getString(attr);
3969 if (handlerName != null) {
3970 setOnClickListener(new OnClickListener() {
3971 private Method mHandler;
3973 public void onClick(View v) {
3974 if (mHandler == null) {
3976 mHandler = getContext().getClass().getMethod(handlerName,
3978 } catch (NoSuchMethodException e) {
3980 String idText = id == NO_ID ? "" : " with id '"
3981 + getContext().getResources().getResourceEntryName(
3983 throw new IllegalStateException("Could not find a method " +
3984 handlerName + "(View) in the activity "
3985 + getContext().getClass() + " for onClick handler"
3986 + " on view " + View.this.getClass() + idText, e);
3991 mHandler.invoke(getContext(), View.this);
3992 } catch (IllegalAccessException e) {
3993 throw new IllegalStateException("Could not execute non "
3994 + "public method of the activity", e);
3995 } catch (InvocationTargetException e) {
3996 throw new IllegalStateException("Could not execute "
3997 + "method of the activity", e);
4003 case R.styleable.View_overScrollMode:
4004 overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4006 case R.styleable.View_verticalScrollbarPosition:
4007 mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4009 case R.styleable.View_layerType:
4010 setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4012 case R.styleable.View_textDirection:
4013 // Clear any text direction flag already set
4014 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4015 // Set the text direction flags depending on the value of the attribute
4016 final int textDirection = a.getInt(attr, -1);
4017 if (textDirection != -1) {
4018 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4021 case R.styleable.View_textAlignment:
4022 // Clear any text alignment flag already set
4023 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4024 // Set the text alignment flag depending on the value of the attribute
4025 final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4026 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4028 case R.styleable.View_importantForAccessibility:
4029 setImportantForAccessibility(a.getInt(attr,
4030 IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4032 case R.styleable.View_accessibilityLiveRegion:
4033 setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4035 case R.styleable.View_transitionName:
4036 setTransitionName(a.getString(attr));
4038 case R.styleable.View_nestedScrollingEnabled:
4039 setNestedScrollingEnabled(a.getBoolean(attr, false));
4041 case R.styleable.View_stateListAnimator:
4042 setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4043 a.getResourceId(attr, 0)));
4045 case R.styleable.View_backgroundTint:
4046 // This will get applied later during setBackground().
4047 mBackgroundTintList = a.getColorStateList(R.styleable.View_backgroundTint);
4048 mHasBackgroundTint = true;
4050 case R.styleable.View_backgroundTintMode:
4051 // This will get applied later during setBackground().
4052 mBackgroundTintMode = Drawable.parseTintMode(a.getInt(
4053 R.styleable.View_backgroundTintMode, -1), mBackgroundTintMode);
4055 case R.styleable.View_outlineProvider:
4056 setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4057 PROVIDER_BACKGROUND));
4062 setOverScrollMode(overScrollMode);
4064 // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4065 // the resolved layout direction). Those cached values will be used later during padding
4067 mUserPaddingStart = startPadding;
4068 mUserPaddingEnd = endPadding;
4070 if (background != null) {
4071 setBackground(background);
4074 // setBackground above will record that padding is currently provided by the background.
4075 // If we have padding specified via xml, record that here instead and use it.
4076 mLeftPaddingDefined = leftPaddingDefined;
4077 mRightPaddingDefined = rightPaddingDefined;
4080 leftPadding = padding;
4081 topPadding = padding;
4082 rightPadding = padding;
4083 bottomPadding = padding;
4084 mUserPaddingLeftInitial = padding;
4085 mUserPaddingRightInitial = padding;
4088 if (isRtlCompatibilityMode()) {
4089 // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4090 // left / right padding are used if defined (meaning here nothing to do). If they are not
4091 // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4092 // start / end and resolve them as left / right (layout direction is not taken into account).
4093 // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4094 // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4096 if (!mLeftPaddingDefined && startPaddingDefined) {
4097 leftPadding = startPadding;
4099 mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4100 if (!mRightPaddingDefined && endPaddingDefined) {
4101 rightPadding = endPadding;
4103 mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4105 // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4106 // values defined. Otherwise, left /right values are used.
4107 // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4108 // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4110 final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4112 if (mLeftPaddingDefined && !hasRelativePadding) {
4113 mUserPaddingLeftInitial = leftPadding;
4115 if (mRightPaddingDefined && !hasRelativePadding) {
4116 mUserPaddingRightInitial = rightPadding;
4121 mUserPaddingLeftInitial,
4122 topPadding >= 0 ? topPadding : mPaddingTop,
4123 mUserPaddingRightInitial,
4124 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4126 if (viewFlagMasks != 0) {
4127 setFlags(viewFlagValues, viewFlagMasks);
4130 if (initializeScrollbars) {
4131 initializeScrollbarsInternal(a);
4136 // Needs to be called after mViewFlags is set
4137 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4141 if (x != 0 || y != 0) {
4146 setTranslationX(tx);
4147 setTranslationY(ty);
4148 setTranslationZ(tz);
4149 setElevation(elevation);
4150 setRotation(rotation);
4151 setRotationX(rotationX);
4152 setRotationY(rotationY);
4157 if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4158 setScrollContainer(true);
4161 computeOpaqueFlags();
4165 * Non-public constructor for use in testing
4169 mRenderNode = RenderNode.create(getClass().getName(), this);
4172 private static SparseArray<String> getAttributeMap() {
4173 if (mAttributeMap == null) {
4174 mAttributeMap = new SparseArray<String>();
4176 return mAttributeMap;
4179 private void saveAttributeData(AttributeSet attrs, TypedArray a) {
4180 int length = ((attrs == null ? 0 : attrs.getAttributeCount()) + a.getIndexCount()) * 2;
4181 mAttributes = new String[length];
4184 if (attrs != null) {
4185 for (i = 0; i < attrs.getAttributeCount(); i += 2) {
4186 mAttributes[i] = attrs.getAttributeName(i);
4187 mAttributes[i + 1] = attrs.getAttributeValue(i);
4192 SparseArray<String> attributeMap = getAttributeMap();
4193 for (int j = 0; j < a.length(); ++j) {
4194 if (a.hasValue(j)) {
4196 int resourceId = a.getResourceId(j, 0);
4197 if (resourceId == 0) {
4201 String resourceName = attributeMap.get(resourceId);
4202 if (resourceName == null) {
4203 resourceName = a.getResources().getResourceName(resourceId);
4204 attributeMap.put(resourceId, resourceName);
4207 mAttributes[i] = resourceName;
4208 mAttributes[i + 1] = a.getText(j).toString();
4210 } catch (Resources.NotFoundException e) {
4211 // if we can't get the resource name, we just ignore it
4217 public String toString() {
4218 StringBuilder out = new StringBuilder(128);
4219 out.append(getClass().getName());
4221 out.append(Integer.toHexString(System.identityHashCode(this)));
4223 switch (mViewFlags&VISIBILITY_MASK) {
4224 case VISIBLE: out.append('V'); break;
4225 case INVISIBLE: out.append('I'); break;
4226 case GONE: out.append('G'); break;
4227 default: out.append('.'); break;
4229 out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4230 out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4231 out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4232 out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4233 out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4234 out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4235 out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4237 out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4238 out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4239 out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4240 if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4243 out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4245 out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4246 out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4247 out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4248 out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4256 out.append(mBottom);
4257 final int id = getId();
4260 out.append(Integer.toHexString(id));
4261 final Resources r = mResources;
4262 if (Resources.resourceHasPackage(id) && r != null) {
4265 switch (id&0xff000000) {
4273 pkgname = r.getResourcePackageName(id);
4276 String typename = r.getResourceTypeName(id);
4277 String entryname = r.getResourceEntryName(id);
4279 out.append(pkgname);
4281 out.append(typename);
4283 out.append(entryname);
4284 } catch (Resources.NotFoundException e) {
4289 return out.toString();
4294 * Initializes the fading edges from a given set of styled attributes. This
4295 * method should be called by subclasses that need fading edges and when an
4296 * instance of these subclasses is created programmatically rather than
4297 * being inflated from XML. This method is automatically called when the XML
4301 * @param a the styled attributes set to initialize the fading edges from
4303 protected void initializeFadingEdge(TypedArray a) {
4304 // This method probably shouldn't have been included in the SDK to begin with.
4305 // It relies on 'a' having been initialized using an attribute filter array that is
4306 // not publicly available to the SDK. The old method has been renamed
4307 // to initializeFadingEdgeInternal and hidden for framework use only;
4308 // this one initializes using defaults to make it safe to call for apps.
4310 TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4312 initializeFadingEdgeInternal(arr);
4319 * Initializes the fading edges from a given set of styled attributes. This
4320 * method should be called by subclasses that need fading edges and when an
4321 * instance of these subclasses is created programmatically rather than
4322 * being inflated from XML. This method is automatically called when the XML
4326 * @param a the styled attributes set to initialize the fading edges from
4327 * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4329 protected void initializeFadingEdgeInternal(TypedArray a) {
4332 mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4333 R.styleable.View_fadingEdgeLength,
4334 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4338 * Returns the size of the vertical faded edges used to indicate that more
4339 * content in this view is visible.
4341 * @return The size in pixels of the vertical faded edge or 0 if vertical
4342 * faded edges are not enabled for this view.
4343 * @attr ref android.R.styleable#View_fadingEdgeLength
4345 public int getVerticalFadingEdgeLength() {
4346 if (isVerticalFadingEdgeEnabled()) {
4347 ScrollabilityCache cache = mScrollCache;
4348 if (cache != null) {
4349 return cache.fadingEdgeLength;
4356 * Set the size of the faded edge used to indicate that more content in this
4357 * view is available. Will not change whether the fading edge is enabled; use
4358 * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4359 * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4360 * for the vertical or horizontal fading edges.
4362 * @param length The size in pixels of the faded edge used to indicate that more
4363 * content in this view is visible.
4365 public void setFadingEdgeLength(int length) {
4367 mScrollCache.fadingEdgeLength = length;
4371 * Returns the size of the horizontal faded edges used to indicate that more
4372 * content in this view is visible.
4374 * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4375 * faded edges are not enabled for this view.
4376 * @attr ref android.R.styleable#View_fadingEdgeLength
4378 public int getHorizontalFadingEdgeLength() {
4379 if (isHorizontalFadingEdgeEnabled()) {
4380 ScrollabilityCache cache = mScrollCache;
4381 if (cache != null) {
4382 return cache.fadingEdgeLength;
4389 * Returns the width of the vertical scrollbar.
4391 * @return The width in pixels of the vertical scrollbar or 0 if there
4392 * is no vertical scrollbar.
4394 public int getVerticalScrollbarWidth() {
4395 ScrollabilityCache cache = mScrollCache;
4396 if (cache != null) {
4397 ScrollBarDrawable scrollBar = cache.scrollBar;
4398 if (scrollBar != null) {
4399 int size = scrollBar.getSize(true);
4401 size = cache.scrollBarSize;
4411 * Returns the height of the horizontal scrollbar.
4413 * @return The height in pixels of the horizontal scrollbar or 0 if
4414 * there is no horizontal scrollbar.
4416 protected int getHorizontalScrollbarHeight() {
4417 ScrollabilityCache cache = mScrollCache;
4418 if (cache != null) {
4419 ScrollBarDrawable scrollBar = cache.scrollBar;
4420 if (scrollBar != null) {
4421 int size = scrollBar.getSize(false);
4423 size = cache.scrollBarSize;
4434 * Initializes the scrollbars from a given set of styled attributes. This
4435 * method should be called by subclasses that need scrollbars and when an
4436 * instance of these subclasses is created programmatically rather than
4437 * being inflated from XML. This method is automatically called when the XML
4441 * @param a the styled attributes set to initialize the scrollbars from
4443 protected void initializeScrollbars(TypedArray a) {
4444 // It's not safe to use this method from apps. The parameter 'a' must have been obtained
4445 // using the View filter array which is not available to the SDK. As such, internal
4446 // framework usage now uses initializeScrollbarsInternal and we grab a default
4447 // TypedArray with the right filter instead here.
4448 TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4450 initializeScrollbarsInternal(arr);
4452 // We ignored the method parameter. Recycle the one we actually did use.
4458 * Initializes the scrollbars from a given set of styled attributes. This
4459 * method should be called by subclasses that need scrollbars and when an
4460 * instance of these subclasses is created programmatically rather than
4461 * being inflated from XML. This method is automatically called when the XML
4465 * @param a the styled attributes set to initialize the scrollbars from
4468 protected void initializeScrollbarsInternal(TypedArray a) {
4471 final ScrollabilityCache scrollabilityCache = mScrollCache;
4473 if (scrollabilityCache.scrollBar == null) {
4474 scrollabilityCache.scrollBar = new ScrollBarDrawable();
4477 final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
4479 if (!fadeScrollbars) {
4480 scrollabilityCache.state = ScrollabilityCache.ON;
4482 scrollabilityCache.fadeScrollBars = fadeScrollbars;
4485 scrollabilityCache.scrollBarFadeDuration = a.getInt(
4486 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
4487 .getScrollBarFadeDuration());
4488 scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
4489 R.styleable.View_scrollbarDefaultDelayBeforeFade,
4490 ViewConfiguration.getScrollDefaultDelay());
4493 scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
4494 com.android.internal.R.styleable.View_scrollbarSize,
4495 ViewConfiguration.get(mContext).getScaledScrollBarSize());
4497 Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
4498 scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
4500 Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
4501 if (thumb != null) {
4502 scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
4505 boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
4508 scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
4511 track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
4512 scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
4514 thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
4515 if (thumb != null) {
4516 scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
4519 alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
4522 scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
4525 // Apply layout direction to the new Drawables if needed
4526 final int layoutDirection = getLayoutDirection();
4527 if (track != null) {
4528 track.setLayoutDirection(layoutDirection);
4530 if (thumb != null) {
4531 thumb.setLayoutDirection(layoutDirection);
4534 // Re-apply user/background padding so that scrollbar(s) get added
4540 * Initalizes the scrollability cache if necessary.
4543 private void initScrollCache() {
4544 if (mScrollCache == null) {
4545 mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
4549 private ScrollabilityCache getScrollCache() {
4551 return mScrollCache;
4555 * Set the position of the vertical scroll bar. Should be one of
4556 * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
4557 * {@link #SCROLLBAR_POSITION_RIGHT}.
4559 * @param position Where the vertical scroll bar should be positioned.
4561 public void setVerticalScrollbarPosition(int position) {
4562 if (mVerticalScrollbarPosition != position) {
4563 mVerticalScrollbarPosition = position;
4564 computeOpaqueFlags();
4570 * @return The position where the vertical scroll bar will show, if applicable.
4571 * @see #setVerticalScrollbarPosition(int)
4573 public int getVerticalScrollbarPosition() {
4574 return mVerticalScrollbarPosition;
4577 ListenerInfo getListenerInfo() {
4578 if (mListenerInfo != null) {
4579 return mListenerInfo;
4581 mListenerInfo = new ListenerInfo();
4582 return mListenerInfo;
4586 * Register a callback to be invoked when focus of this view changed.
4588 * @param l The callback that will run.
4590 public void setOnFocusChangeListener(OnFocusChangeListener l) {
4591 getListenerInfo().mOnFocusChangeListener = l;
4595 * Add a listener that will be called when the bounds of the view change due to
4596 * layout processing.
4598 * @param listener The listener that will be called when layout bounds change.
4600 public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
4601 ListenerInfo li = getListenerInfo();
4602 if (li.mOnLayoutChangeListeners == null) {
4603 li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
4605 if (!li.mOnLayoutChangeListeners.contains(listener)) {
4606 li.mOnLayoutChangeListeners.add(listener);
4611 * Remove a listener for layout changes.
4613 * @param listener The listener for layout bounds change.
4615 public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
4616 ListenerInfo li = mListenerInfo;
4617 if (li == null || li.mOnLayoutChangeListeners == null) {
4620 li.mOnLayoutChangeListeners.remove(listener);
4624 * Add a listener for attach state changes.
4626 * This listener will be called whenever this view is attached or detached
4627 * from a window. Remove the listener using
4628 * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
4630 * @param listener Listener to attach
4631 * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
4633 public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4634 ListenerInfo li = getListenerInfo();
4635 if (li.mOnAttachStateChangeListeners == null) {
4636 li.mOnAttachStateChangeListeners
4637 = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
4639 li.mOnAttachStateChangeListeners.add(listener);
4643 * Remove a listener for attach state changes. The listener will receive no further
4644 * notification of window attach/detach events.
4646 * @param listener Listener to remove
4647 * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
4649 public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4650 ListenerInfo li = mListenerInfo;
4651 if (li == null || li.mOnAttachStateChangeListeners == null) {
4654 li.mOnAttachStateChangeListeners.remove(listener);
4658 * Returns the focus-change callback registered for this view.
4660 * @return The callback, or null if one is not registered.
4662 public OnFocusChangeListener getOnFocusChangeListener() {
4663 ListenerInfo li = mListenerInfo;
4664 return li != null ? li.mOnFocusChangeListener : null;
4668 * Register a callback to be invoked when this view is clicked. If this view is not
4669 * clickable, it becomes clickable.
4671 * @param l The callback that will run
4673 * @see #setClickable(boolean)
4675 public void setOnClickListener(OnClickListener l) {
4676 if (!isClickable()) {
4679 getListenerInfo().mOnClickListener = l;
4683 * Return whether this view has an attached OnClickListener. Returns
4684 * true if there is a listener, false if there is none.
4686 public boolean hasOnClickListeners() {
4687 ListenerInfo li = mListenerInfo;
4688 return (li != null && li.mOnClickListener != null);
4692 * Register a callback to be invoked when this view is clicked and held. If this view is not
4693 * long clickable, it becomes long clickable.
4695 * @param l The callback that will run
4697 * @see #setLongClickable(boolean)
4699 public void setOnLongClickListener(OnLongClickListener l) {
4700 if (!isLongClickable()) {
4701 setLongClickable(true);
4703 getListenerInfo().mOnLongClickListener = l;
4707 * Register a callback to be invoked when the context menu for this view is
4708 * being built. If this view is not long clickable, it becomes long clickable.
4710 * @param l The callback that will run
4713 public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
4714 if (!isLongClickable()) {
4715 setLongClickable(true);
4717 getListenerInfo().mOnCreateContextMenuListener = l;
4721 * Call this view's OnClickListener, if it is defined. Performs all normal
4722 * actions associated with clicking: reporting accessibility event, playing
4725 * @return True there was an assigned OnClickListener that was called, false
4726 * otherwise is returned.
4728 public boolean performClick() {
4729 final boolean result;
4730 final ListenerInfo li = mListenerInfo;
4731 if (li != null && li.mOnClickListener != null) {
4732 playSoundEffect(SoundEffectConstants.CLICK);
4733 li.mOnClickListener.onClick(this);
4739 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
4744 * Directly call any attached OnClickListener. Unlike {@link #performClick()},
4745 * this only calls the listener, and does not do any associated clicking
4746 * actions like reporting an accessibility event.
4748 * @return True there was an assigned OnClickListener that was called, false
4749 * otherwise is returned.
4751 public boolean callOnClick() {
4752 ListenerInfo li = mListenerInfo;
4753 if (li != null && li.mOnClickListener != null) {
4754 li.mOnClickListener.onClick(this);
4761 * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
4762 * OnLongClickListener did not consume the event.
4764 * @return True if one of the above receivers consumed the event, false otherwise.
4766 public boolean performLongClick() {
4767 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
4769 boolean handled = false;
4770 ListenerInfo li = mListenerInfo;
4771 if (li != null && li.mOnLongClickListener != null) {
4772 handled = li.mOnLongClickListener.onLongClick(View.this);
4775 handled = showContextMenu();
4778 performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
4784 * Performs button-related actions during a touch down event.
4786 * @param event The event.
4787 * @return True if the down was consumed.
4791 protected boolean performButtonActionOnTouchDown(MotionEvent event) {
4792 if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
4793 if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) {
4801 * Bring up the context menu for this view.
4803 * @return Whether a context menu was displayed.
4805 public boolean showContextMenu() {
4806 return getParent().showContextMenuForChild(this);
4810 * Bring up the context menu for this view, referring to the item under the specified point.
4812 * @param x The referenced x coordinate.
4813 * @param y The referenced y coordinate.
4814 * @param metaState The keyboard modifiers that were pressed.
4815 * @return Whether a context menu was displayed.
4819 public boolean showContextMenu(float x, float y, int metaState) {
4820 return showContextMenu();
4824 * Start an action mode.
4826 * @param callback Callback that will control the lifecycle of the action mode
4827 * @return The new action mode if it is started, null otherwise
4831 public ActionMode startActionMode(ActionMode.Callback callback) {
4832 ViewParent parent = getParent();
4833 if (parent == null) return null;
4834 return parent.startActionModeForChild(this, callback);
4838 * Register a callback to be invoked when a hardware key is pressed in this view.
4839 * Key presses in software input methods will generally not trigger the methods of
4841 * @param l the key listener to attach to this view
4843 public void setOnKeyListener(OnKeyListener l) {
4844 getListenerInfo().mOnKeyListener = l;
4848 * Register a callback to be invoked when a touch event is sent to this view.
4849 * @param l the touch listener to attach to this view
4851 public void setOnTouchListener(OnTouchListener l) {
4852 getListenerInfo().mOnTouchListener = l;
4856 * Register a callback to be invoked when a generic motion event is sent to this view.
4857 * @param l the generic motion listener to attach to this view
4859 public void setOnGenericMotionListener(OnGenericMotionListener l) {
4860 getListenerInfo().mOnGenericMotionListener = l;
4864 * Register a callback to be invoked when a hover event is sent to this view.
4865 * @param l the hover listener to attach to this view
4867 public void setOnHoverListener(OnHoverListener l) {
4868 getListenerInfo().mOnHoverListener = l;
4872 * Register a drag event listener callback object for this View. The parameter is
4873 * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
4874 * View, the system calls the
4875 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
4876 * @param l An implementation of {@link android.view.View.OnDragListener}.
4878 public void setOnDragListener(OnDragListener l) {
4879 getListenerInfo().mOnDragListener = l;
4883 * Give this view focus. This will cause
4884 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
4886 * Note: this does not check whether this {@link View} should get focus, it just
4887 * gives it focus no matter what. It should only be called internally by framework
4888 * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
4890 * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
4891 * {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
4892 * focus moved when requestFocus() is called. It may not always
4893 * apply, in which case use the default View.FOCUS_DOWN.
4894 * @param previouslyFocusedRect The rectangle of the view that had focus
4895 * prior in this View's coordinate system.
4897 void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
4899 System.out.println(this + " requestFocus()");
4902 if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
4903 mPrivateFlags |= PFLAG_FOCUSED;
4905 View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
4907 if (mParent != null) {
4908 mParent.requestChildFocus(this, this);
4911 if (mAttachInfo != null) {
4912 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
4915 onFocusChanged(true, direction, previouslyFocusedRect);
4916 refreshDrawableState();
4921 * Populates <code>outRect</code> with the hotspot bounds. By default,
4922 * the hotspot bounds are identical to the screen bounds.
4924 * @param outRect rect to populate with hotspot bounds
4925 * @hide Only for internal use by views and widgets.
4927 public void getHotspotBounds(Rect outRect) {
4928 final Drawable background = getBackground();
4929 if (background != null) {
4930 background.getHotspotBounds(outRect);
4932 getBoundsOnScreen(outRect);
4937 * Request that a rectangle of this view be visible on the screen,
4938 * scrolling if necessary just enough.
4940 * <p>A View should call this if it maintains some notion of which part
4941 * of its content is interesting. For example, a text editing view
4942 * should call this when its cursor moves.
4944 * @param rectangle The rectangle.
4945 * @return Whether any parent scrolled.
4947 public boolean requestRectangleOnScreen(Rect rectangle) {
4948 return requestRectangleOnScreen(rectangle, false);
4952 * Request that a rectangle of this view be visible on the screen,
4953 * scrolling if necessary just enough.
4955 * <p>A View should call this if it maintains some notion of which part
4956 * of its content is interesting. For example, a text editing view
4957 * should call this when its cursor moves.
4959 * <p>When <code>immediate</code> is set to true, scrolling will not be
4962 * @param rectangle The rectangle.
4963 * @param immediate True to forbid animated scrolling, false otherwise
4964 * @return Whether any parent scrolled.
4966 public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
4967 if (mParent == null) {
4973 RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
4974 position.set(rectangle);
4976 ViewParent parent = mParent;
4977 boolean scrolled = false;
4978 while (parent != null) {
4979 rectangle.set((int) position.left, (int) position.top,
4980 (int) position.right, (int) position.bottom);
4982 scrolled |= parent.requestChildRectangleOnScreen(child,
4983 rectangle, immediate);
4985 if (!child.hasIdentityMatrix()) {
4986 child.getMatrix().mapRect(position);
4989 position.offset(child.mLeft, child.mTop);
4991 if (!(parent instanceof View)) {
4995 View parentView = (View) parent;
4997 position.offset(-parentView.getScrollX(), -parentView.getScrollY());
5000 parent = child.getParent();
5007 * Called when this view wants to give up focus. If focus is cleared
5008 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
5010 * <strong>Note:</strong> When a View clears focus the framework is trying
5011 * to give focus to the first focusable View from the top. Hence, if this
5012 * View is the first from the top that can take focus, then all callbacks
5013 * related to clearing focus will be invoked after wich the framework will
5014 * give focus to this view.
5017 public void clearFocus() {
5019 System.out.println(this + " clearFocus()");
5022 clearFocusInternal(null, true, true);
5026 * Clears focus from the view, optionally propagating the change up through
5027 * the parent hierarchy and requesting that the root view place new focus.
5029 * @param propagate whether to propagate the change up through the parent
5031 * @param refocus when propagate is true, specifies whether to request the
5032 * root view place new focus
5034 void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
5035 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
5036 mPrivateFlags &= ~PFLAG_FOCUSED;
5038 if (propagate && mParent != null) {
5039 mParent.clearChildFocus(this);
5042 onFocusChanged(false, 0, null);
5043 refreshDrawableState();
5045 if (propagate && (!refocus || !rootViewRequestFocus())) {
5046 notifyGlobalFocusCleared(this);
5051 void notifyGlobalFocusCleared(View oldFocus) {
5052 if (oldFocus != null && mAttachInfo != null) {
5053 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
5057 boolean rootViewRequestFocus() {
5058 final View root = getRootView();
5059 return root != null && root.requestFocus();
5063 * Called internally by the view system when a new view is getting focus.
5064 * This is what clears the old focus.
5066 * <b>NOTE:</b> The parent view's focused child must be updated manually
5067 * after calling this method. Otherwise, the view hierarchy may be left in
5068 * an inconstent state.
5070 void unFocus(View focused) {
5072 System.out.println(this + " unFocus()");
5075 clearFocusInternal(focused, false, false);
5079 * Returns true if this view has focus iteself, or is the ancestor of the
5080 * view that has focus.
5082 * @return True if this view has or contains focus, false otherwise.
5084 @ViewDebug.ExportedProperty(category = "focus")
5085 public boolean hasFocus() {
5086 return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5090 * Returns true if this view is focusable or if it contains a reachable View
5091 * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
5092 * is a View whose parents do not block descendants focus.
5094 * Only {@link #VISIBLE} views are considered focusable.
5096 * @return True if the view is focusable or if the view contains a focusable
5097 * View, false otherwise.
5099 * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
5100 * @see ViewGroup#getTouchscreenBlocksFocus()
5102 public boolean hasFocusable() {
5103 if (!isFocusableInTouchMode()) {
5104 for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
5105 final ViewGroup g = (ViewGroup) p;
5106 if (g.shouldBlockFocusForTouchscreen()) {
5111 return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
5115 * Called by the view system when the focus state of this view changes.
5116 * When the focus change event is caused by directional navigation, direction
5117 * and previouslyFocusedRect provide insight into where the focus is coming from.
5118 * When overriding, be sure to call up through to the super class so that
5119 * the standard focus handling will occur.
5121 * @param gainFocus True if the View has focus; false otherwise.
5122 * @param direction The direction focus has moved when requestFocus()
5123 * is called to give this view focus. Values are
5124 * {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
5125 * {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
5126 * It may not always apply, in which case use the default.
5127 * @param previouslyFocusedRect The rectangle, in this view's coordinate
5128 * system, of the previously focused view. If applicable, this will be
5129 * passed in as finer grained information about where the focus is coming
5130 * from (in addition to direction). Will be <code>null</code> otherwise.
5132 protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
5133 @Nullable Rect previouslyFocusedRect) {
5135 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
5137 notifyViewAccessibilityStateChangedIfNeeded(
5138 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5141 InputMethodManager imm = InputMethodManager.peekInstance();
5146 if (imm != null && mAttachInfo != null
5147 && mAttachInfo.mHasWindowFocus) {
5151 } else if (imm != null && mAttachInfo != null
5152 && mAttachInfo.mHasWindowFocus) {
5157 ListenerInfo li = mListenerInfo;
5158 if (li != null && li.mOnFocusChangeListener != null) {
5159 li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
5162 if (mAttachInfo != null) {
5163 mAttachInfo.mKeyDispatchState.reset(this);
5168 * Sends an accessibility event of the given type. If accessibility is
5169 * not enabled this method has no effect. The default implementation calls
5170 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
5171 * to populate information about the event source (this View), then calls
5172 * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
5173 * populate the text content of the event source including its descendants,
5175 * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
5176 * on its parent to resuest sending of the event to interested parties.
5178 * If an {@link AccessibilityDelegate} has been specified via calling
5179 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5180 * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
5181 * responsible for handling this call.
5184 * @param eventType The type of the event to send, as defined by several types from
5185 * {@link android.view.accessibility.AccessibilityEvent}, such as
5186 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
5187 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
5189 * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5190 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5191 * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
5192 * @see AccessibilityDelegate
5194 public void sendAccessibilityEvent(int eventType) {
5195 if (mAccessibilityDelegate != null) {
5196 mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
5198 sendAccessibilityEventInternal(eventType);
5203 * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
5204 * {@link AccessibilityEvent} to make an announcement which is related to some
5205 * sort of a context change for which none of the events representing UI transitions
5206 * is a good fit. For example, announcing a new page in a book. If accessibility
5207 * is not enabled this method does nothing.
5209 * @param text The announcement text.
5211 public void announceForAccessibility(CharSequence text) {
5212 if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
5213 AccessibilityEvent event = AccessibilityEvent.obtain(
5214 AccessibilityEvent.TYPE_ANNOUNCEMENT);
5215 onInitializeAccessibilityEvent(event);
5216 event.getText().add(text);
5217 event.setContentDescription(null);
5218 mParent.requestSendAccessibilityEvent(this, event);
5223 * @see #sendAccessibilityEvent(int)
5225 * Note: Called from the default {@link AccessibilityDelegate}.
5227 void sendAccessibilityEventInternal(int eventType) {
5228 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
5229 sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
5234 * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
5235 * takes as an argument an empty {@link AccessibilityEvent} and does not
5236 * perform a check whether accessibility is enabled.
5238 * If an {@link AccessibilityDelegate} has been specified via calling
5239 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5240 * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
5241 * is responsible for handling this call.
5244 * @param event The event to send.
5246 * @see #sendAccessibilityEvent(int)
5248 public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
5249 if (mAccessibilityDelegate != null) {
5250 mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
5252 sendAccessibilityEventUncheckedInternal(event);
5257 * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
5259 * Note: Called from the default {@link AccessibilityDelegate}.
5261 void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
5265 onInitializeAccessibilityEvent(event);
5266 // Only a subset of accessibility events populates text content.
5267 if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
5268 dispatchPopulateAccessibilityEvent(event);
5270 // In the beginning we called #isShown(), so we know that getParent() is not null.
5271 getParent().requestSendAccessibilityEvent(this, event);
5275 * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
5276 * to its children for adding their text content to the event. Note that the
5277 * event text is populated in a separate dispatch path since we add to the
5278 * event not only the text of the source but also the text of all its descendants.
5279 * A typical implementation will call
5280 * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
5281 * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5282 * on each child. Override this method if custom population of the event text
5283 * content is required.
5285 * If an {@link AccessibilityDelegate} has been specified via calling
5286 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5287 * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
5288 * is responsible for handling this call.
5291 * <em>Note:</em> Accessibility events of certain types are not dispatched for
5292 * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
5295 * @param event The event.
5297 * @return True if the event population was completed.
5299 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
5300 if (mAccessibilityDelegate != null) {
5301 return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
5303 return dispatchPopulateAccessibilityEventInternal(event);
5308 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5310 * Note: Called from the default {@link AccessibilityDelegate}.
5312 boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5313 onPopulateAccessibilityEvent(event);
5318 * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5319 * giving a chance to this View to populate the accessibility event with its
5320 * text content. While this method is free to modify event
5321 * attributes other than text content, doing so should normally be performed in
5322 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
5324 * Example: Adding formatted date string to an accessibility event in addition
5325 * to the text added by the super implementation:
5326 * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5327 * super.onPopulateAccessibilityEvent(event);
5328 * final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
5329 * String selectedDateUtterance = DateUtils.formatDateTime(mContext,
5330 * mCurrentDate.getTimeInMillis(), flags);
5331 * event.getText().add(selectedDateUtterance);
5334 * If an {@link AccessibilityDelegate} has been specified via calling
5335 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5336 * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
5337 * is responsible for handling this call.
5339 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5340 * information to the event, in case the default implementation has basic information to add.
5343 * @param event The accessibility event which to populate.
5345 * @see #sendAccessibilityEvent(int)
5346 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5348 public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5349 if (mAccessibilityDelegate != null) {
5350 mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
5352 onPopulateAccessibilityEventInternal(event);
5357 * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
5359 * Note: Called from the default {@link AccessibilityDelegate}.
5361 void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5365 * Initializes an {@link AccessibilityEvent} with information about
5366 * this View which is the event source. In other words, the source of
5367 * an accessibility event is the view whose state change triggered firing
5370 * Example: Setting the password property of an event in addition
5371 * to properties set by the super implementation:
5372 * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5373 * super.onInitializeAccessibilityEvent(event);
5374 * event.setPassword(true);
5377 * If an {@link AccessibilityDelegate} has been specified via calling
5378 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5379 * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
5380 * is responsible for handling this call.
5382 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5383 * information to the event, in case the default implementation has basic information to add.
5385 * @param event The event to initialize.
5387 * @see #sendAccessibilityEvent(int)
5388 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5390 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5391 if (mAccessibilityDelegate != null) {
5392 mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
5394 onInitializeAccessibilityEventInternal(event);
5399 * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5401 * Note: Called from the default {@link AccessibilityDelegate}.
5403 void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
5404 event.setSource(this);
5405 event.setClassName(View.class.getName());
5406 event.setPackageName(getContext().getPackageName());
5407 event.setEnabled(isEnabled());
5408 event.setContentDescription(mContentDescription);
5410 switch (event.getEventType()) {
5411 case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
5412 ArrayList<View> focusablesTempList = (mAttachInfo != null)
5413 ? mAttachInfo.mTempArrayList : new ArrayList<View>();
5414 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
5415 event.setItemCount(focusablesTempList.size());
5416 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
5417 if (mAttachInfo != null) {
5418 focusablesTempList.clear();
5421 case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
5422 CharSequence text = getIterableTextForAccessibility();
5423 if (text != null && text.length() > 0) {
5424 event.setFromIndex(getAccessibilitySelectionStart());
5425 event.setToIndex(getAccessibilitySelectionEnd());
5426 event.setItemCount(text.length());
5433 * Returns an {@link AccessibilityNodeInfo} representing this view from the
5434 * point of view of an {@link android.accessibilityservice.AccessibilityService}.
5435 * This method is responsible for obtaining an accessibility node info from a
5436 * pool of reusable instances and calling
5437 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
5438 * initialize the former.
5440 * Note: The client is responsible for recycling the obtained instance by calling
5441 * {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
5444 * @return A populated {@link AccessibilityNodeInfo}.
5446 * @see AccessibilityNodeInfo
5448 public AccessibilityNodeInfo createAccessibilityNodeInfo() {
5449 if (mAccessibilityDelegate != null) {
5450 return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
5452 return createAccessibilityNodeInfoInternal();
5457 * @see #createAccessibilityNodeInfo()
5459 AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
5460 AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
5461 if (provider != null) {
5462 return provider.createAccessibilityNodeInfo(View.NO_ID);
5464 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
5465 onInitializeAccessibilityNodeInfo(info);
5471 * Initializes an {@link AccessibilityNodeInfo} with information about this view.
5472 * The base implementation sets:
5474 * <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
5475 * <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
5476 * <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
5477 * <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
5478 * <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
5479 * <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
5480 * <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
5481 * <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
5482 * <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
5483 * <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
5484 * <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
5485 * <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
5488 * Subclasses should override this method, call the super implementation,
5489 * and set additional attributes.
5492 * If an {@link AccessibilityDelegate} has been specified via calling
5493 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5494 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
5495 * is responsible for handling this call.
5498 * @param info The instance to initialize.
5500 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
5501 if (mAccessibilityDelegate != null) {
5502 mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
5504 onInitializeAccessibilityNodeInfoInternal(info);
5509 * Gets the location of this view in screen coordintates.
5511 * @param outRect The output location
5514 public void getBoundsOnScreen(Rect outRect) {
5515 if (mAttachInfo == null) {
5519 RectF position = mAttachInfo.mTmpTransformRect;
5520 position.set(0, 0, mRight - mLeft, mBottom - mTop);
5522 if (!hasIdentityMatrix()) {
5523 getMatrix().mapRect(position);
5526 position.offset(mLeft, mTop);
5528 ViewParent parent = mParent;
5529 while (parent instanceof View) {
5530 View parentView = (View) parent;
5532 position.offset(-parentView.mScrollX, -parentView.mScrollY);
5534 if (!parentView.hasIdentityMatrix()) {
5535 parentView.getMatrix().mapRect(position);
5538 position.offset(parentView.mLeft, parentView.mTop);
5540 parent = parentView.mParent;
5543 if (parent instanceof ViewRootImpl) {
5544 ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
5545 position.offset(0, -viewRootImpl.mCurScrollY);
5548 position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
5550 outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
5551 (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
5555 * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
5557 * Note: Called from the default {@link AccessibilityDelegate}.
5559 void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
5560 Rect bounds = mAttachInfo.mTmpInvalRect;
5562 getDrawingRect(bounds);
5563 info.setBoundsInParent(bounds);
5565 getBoundsOnScreen(bounds);
5566 info.setBoundsInScreen(bounds);
5568 ViewParent parent = getParentForAccessibility();
5569 if (parent instanceof View) {
5570 info.setParent((View) parent);
5573 if (mID != View.NO_ID) {
5574 View rootView = getRootView();
5575 if (rootView == null) {
5578 View label = rootView.findLabelForView(this, mID);
5579 if (label != null) {
5580 info.setLabeledBy(label);
5583 if ((mAttachInfo.mAccessibilityFetchFlags
5584 & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
5585 && Resources.resourceHasPackage(mID)) {
5587 String viewId = getResources().getResourceName(mID);
5588 info.setViewIdResourceName(viewId);
5589 } catch (Resources.NotFoundException nfe) {
5595 if (mLabelForId != View.NO_ID) {
5596 View rootView = getRootView();
5597 if (rootView == null) {
5600 View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
5601 if (labeled != null) {
5602 info.setLabelFor(labeled);
5606 info.setVisibleToUser(isVisibleToUser());
5608 info.setPackageName(mContext.getPackageName());
5609 info.setClassName(View.class.getName());
5610 info.setContentDescription(getContentDescription());
5612 info.setEnabled(isEnabled());
5613 info.setClickable(isClickable());
5614 info.setFocusable(isFocusable());
5615 info.setFocused(isFocused());
5616 info.setAccessibilityFocused(isAccessibilityFocused());
5617 info.setSelected(isSelected());
5618 info.setLongClickable(isLongClickable());
5619 info.setLiveRegion(getAccessibilityLiveRegion());
5621 // TODO: These make sense only if we are in an AdapterView but all
5622 // views can be selected. Maybe from accessibility perspective
5623 // we should report as selectable view in an AdapterView.
5624 info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
5625 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
5627 if (isFocusable()) {
5629 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
5631 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
5635 if (!isAccessibilityFocused()) {
5636 info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
5638 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
5641 if (isClickable() && isEnabled()) {
5642 info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
5645 if (isLongClickable() && isEnabled()) {
5646 info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
5649 CharSequence text = getIterableTextForAccessibility();
5650 if (text != null && text.length() > 0) {
5651 info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
5653 info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
5654 info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
5655 info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
5656 info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
5657 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
5658 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
5662 private View findLabelForView(View view, int labeledId) {
5663 if (mMatchLabelForPredicate == null) {
5664 mMatchLabelForPredicate = new MatchLabelForPredicate();
5666 mMatchLabelForPredicate.mLabeledId = labeledId;
5667 return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
5671 * Computes whether this view is visible to the user. Such a view is
5672 * attached, visible, all its predecessors are visible, it is not clipped
5673 * entirely by its predecessors, and has an alpha greater than zero.
5675 * @return Whether the view is visible on the screen.
5679 protected boolean isVisibleToUser() {
5680 return isVisibleToUser(null);
5684 * Computes whether the given portion of this view is visible to the user.
5685 * Such a view is attached, visible, all its predecessors are visible,
5686 * has an alpha greater than zero, and the specified portion is not
5687 * clipped entirely by its predecessors.
5689 * @param boundInView the portion of the view to test; coordinates should be relative; may be
5690 * <code>null</code>, and the entire view will be tested in this case.
5691 * When <code>true</code> is returned by the function, the actual visible
5692 * region will be stored in this parameter; that is, if boundInView is fully
5693 * contained within the view, no modification will be made, otherwise regions
5694 * outside of the visible area of the view will be clipped.
5696 * @return Whether the specified portion of the view is visible on the screen.
5700 protected boolean isVisibleToUser(Rect boundInView) {
5701 if (mAttachInfo != null) {
5702 // Attached to invisible window means this view is not visible.
5703 if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
5706 // An invisible predecessor or one with alpha zero means
5707 // that this view is not visible to the user.
5708 Object current = this;
5709 while (current instanceof View) {
5710 View view = (View) current;
5711 // We have attach info so this view is attached and there is no
5712 // need to check whether we reach to ViewRootImpl on the way up.
5713 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
5714 view.getVisibility() != VISIBLE) {
5717 current = view.mParent;
5719 // Check if the view is entirely covered by its predecessors.
5720 Rect visibleRect = mAttachInfo.mTmpInvalRect;
5721 Point offset = mAttachInfo.mPoint;
5722 if (!getGlobalVisibleRect(visibleRect, offset)) {
5725 // Check if the visible portion intersects the rectangle of interest.
5726 if (boundInView != null) {
5727 visibleRect.offset(-offset.x, -offset.y);
5728 return boundInView.intersect(visibleRect);
5736 * Computes a point on which a sequence of a down/up event can be sent to
5737 * trigger clicking this view. This method is for the exclusive use by the
5738 * accessibility layer to determine where to send a click event in explore
5741 * @param interactiveRegion The interactive portion of this window.
5742 * @param outPoint The point to populate.
5743 * @return True of such a point exists.
5745 boolean computeClickPointInScreenForAccessibility(Region interactiveRegion,
5747 // Since the interactive portion of the view is a region but as a view
5748 // may have a transformation matrix which cannot be applied to a
5749 // region we compute the view bounds rectangle and all interactive
5750 // predecessor's and sibling's (siblings of predecessors included)
5751 // rectangles that intersect the view bounds. At the
5752 // end if the view was partially covered by another interactive
5753 // view we compute the view's interactive region and pick a point
5754 // on its boundary path as regions do not offer APIs to get inner
5755 // points. Note that the the code is optimized to fail early and
5756 // avoid unnecessary allocations plus computations.
5758 // The current approach has edge cases that may produce false
5759 // positives or false negatives. For example, a portion of the
5760 // view may be covered by an interactive descendant of a
5761 // predecessor, which we do not compute. Also a view may be handling
5762 // raw touch events instead registering click listeners, which
5763 // we cannot compute. Despite these limitations this approach will
5764 // work most of the time and it is a huge improvement over just
5765 // blindly sending the down and up events in the center of the
5768 // Cannot click on an unattached view.
5769 if (mAttachInfo == null) {
5773 // Attached to an invisible window means this view is not visible.
5774 if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
5778 RectF bounds = mAttachInfo.mTmpTransformRect;
5779 bounds.set(0, 0, getWidth(), getHeight());
5780 List<RectF> intersections = mAttachInfo.mTmpRectList;
5781 intersections.clear();
5783 if (mParent instanceof ViewGroup) {
5784 ViewGroup parentGroup = (ViewGroup) mParent;
5785 if (!parentGroup.translateBoundsAndIntersectionsInWindowCoordinates(
5786 this, bounds, intersections)) {
5787 intersections.clear();
5792 // Take into account the window location.
5793 final int dx = mAttachInfo.mWindowLeft;
5794 final int dy = mAttachInfo.mWindowTop;
5795 bounds.offset(dx, dy);
5796 offsetRects(intersections, dx, dy);
5798 if (intersections.isEmpty() && interactiveRegion == null) {
5799 outPoint.set((int) bounds.centerX(), (int) bounds.centerY());
5801 // This view is partially covered by other views, then compute
5802 // the not covered region and pick a point on its boundary.
5803 Region region = new Region();
5804 region.set((int) bounds.left, (int) bounds.top,
5805 (int) bounds.right, (int) bounds.bottom);
5807 final int intersectionCount = intersections.size();
5808 for (int i = intersectionCount - 1; i >= 0; i--) {
5809 RectF intersection = intersections.remove(i);
5810 region.op((int) intersection.left, (int) intersection.top,
5811 (int) intersection.right, (int) intersection.bottom,
5812 Region.Op.DIFFERENCE);
5815 // If the view is completely covered, done.
5816 if (region.isEmpty()) {
5820 // Take into account the interactive portion of the window
5821 // as the rest is covered by other windows. If no such a region
5822 // then the whole window is interactive.
5823 if (interactiveRegion != null) {
5824 region.op(interactiveRegion, Region.Op.INTERSECT);
5827 // If the view is completely covered, done.
5828 if (region.isEmpty()) {
5832 // Try a shortcut here.
5833 if (region.isRect()) {
5834 Rect regionBounds = mAttachInfo.mTmpInvalRect;
5835 region.getBounds(regionBounds);
5836 outPoint.set(regionBounds.centerX(), regionBounds.centerY());
5840 // Get the a point on the region boundary path.
5841 Path path = region.getBoundaryPath();
5842 PathMeasure pathMeasure = new PathMeasure(path, false);
5843 final float[] coordinates = mAttachInfo.mTmpTransformLocation;
5845 // Without loss of generality pick a point.
5846 final float point = pathMeasure.getLength() * 0.01f;
5847 if (!pathMeasure.getPosTan(point, coordinates, null)) {
5851 outPoint.set(Math.round(coordinates[0]), Math.round(coordinates[1]));
5857 static void offsetRects(List<RectF> rects, float offsetX, float offsetY) {
5858 final int rectCount = rects.size();
5859 for (int i = 0; i < rectCount; i++) {
5860 RectF intersection = rects.get(i);
5861 intersection.offset(offsetX, offsetY);
5866 * Returns the delegate for implementing accessibility support via
5867 * composition. For more details see {@link AccessibilityDelegate}.
5869 * @return The delegate, or null if none set.
5873 public AccessibilityDelegate getAccessibilityDelegate() {
5874 return mAccessibilityDelegate;
5878 * Sets a delegate for implementing accessibility support via composition as
5879 * opposed to inheritance. The delegate's primary use is for implementing
5880 * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
5882 * @param delegate The delegate instance.
5884 * @see AccessibilityDelegate
5886 public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
5887 mAccessibilityDelegate = delegate;
5891 * Gets the provider for managing a virtual view hierarchy rooted at this View
5892 * and reported to {@link android.accessibilityservice.AccessibilityService}s
5893 * that explore the window content.
5895 * If this method returns an instance, this instance is responsible for managing
5896 * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
5897 * View including the one representing the View itself. Similarly the returned
5898 * instance is responsible for performing accessibility actions on any virtual
5899 * view or the root view itself.
5902 * If an {@link AccessibilityDelegate} has been specified via calling
5903 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5904 * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
5905 * is responsible for handling this call.
5908 * @return The provider.
5910 * @see AccessibilityNodeProvider
5912 public AccessibilityNodeProvider getAccessibilityNodeProvider() {
5913 if (mAccessibilityDelegate != null) {
5914 return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
5921 * Gets the unique identifier of this view on the screen for accessibility purposes.
5922 * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
5924 * @return The view accessibility id.
5928 public int getAccessibilityViewId() {
5929 if (mAccessibilityViewId == NO_ID) {
5930 mAccessibilityViewId = sNextAccessibilityViewId++;
5932 return mAccessibilityViewId;
5936 * Gets the unique identifier of the window in which this View reseides.
5938 * @return The window accessibility id.
5942 public int getAccessibilityWindowId() {
5943 return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
5944 : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
5948 * Gets the {@link View} description. It briefly describes the view and is
5949 * primarily used for accessibility support. Set this property to enable
5950 * better accessibility support for your application. This is especially
5951 * true for views that do not have textual representation (For example,
5954 * @return The content description.
5956 * @attr ref android.R.styleable#View_contentDescription
5958 @ViewDebug.ExportedProperty(category = "accessibility")
5959 public CharSequence getContentDescription() {
5960 return mContentDescription;
5964 * Sets the {@link View} description. It briefly describes the view and is
5965 * primarily used for accessibility support. Set this property to enable
5966 * better accessibility support for your application. This is especially
5967 * true for views that do not have textual representation (For example,
5970 * @param contentDescription The content description.
5972 * @attr ref android.R.styleable#View_contentDescription
5974 @RemotableViewMethod
5975 public void setContentDescription(CharSequence contentDescription) {
5976 if (mContentDescription == null) {
5977 if (contentDescription == null) {
5980 } else if (mContentDescription.equals(contentDescription)) {
5983 mContentDescription = contentDescription;
5984 final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
5985 if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
5986 setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
5987 notifySubtreeAccessibilityStateChangedIfNeeded();
5989 notifyViewAccessibilityStateChangedIfNeeded(
5990 AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
5995 * Gets the id of a view for which this view serves as a label for
5996 * accessibility purposes.
5998 * @return The labeled view id.
6000 @ViewDebug.ExportedProperty(category = "accessibility")
6001 public int getLabelFor() {
6006 * Sets the id of a view for which this view serves as a label for
6007 * accessibility purposes.
6009 * @param id The labeled view id.
6011 @RemotableViewMethod
6012 public void setLabelFor(int id) {
6014 if (mLabelForId != View.NO_ID
6015 && mID == View.NO_ID) {
6016 mID = generateViewId();
6021 * Invoked whenever this view loses focus, either by losing window focus or by losing
6022 * focus within its window. This method can be used to clear any state tied to the
6023 * focus. For instance, if a button is held pressed with the trackball and the window
6024 * loses focus, this method can be used to cancel the press.
6026 * Subclasses of View overriding this method should always call super.onFocusLost().
6028 * @see #onFocusChanged(boolean, int, android.graphics.Rect)
6029 * @see #onWindowFocusChanged(boolean)
6031 * @hide pending API council approval
6033 protected void onFocusLost() {
6034 resetPressedState();
6037 private void resetPressedState() {
6038 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
6045 if (!mHasPerformedLongPress) {
6046 removeLongPressCallback();
6052 * Returns true if this view has focus
6054 * @return True if this view has focus, false otherwise.
6056 @ViewDebug.ExportedProperty(category = "focus")
6057 public boolean isFocused() {
6058 return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6062 * Find the view in the hierarchy rooted at this view that currently has
6065 * @return The view that currently has focus, or null if no focused view can
6068 public View findFocus() {
6069 return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
6073 * Indicates whether this view is one of the set of scrollable containers in
6076 * @return whether this view is one of the set of scrollable containers in
6079 * @attr ref android.R.styleable#View_isScrollContainer
6081 public boolean isScrollContainer() {
6082 return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
6086 * Change whether this view is one of the set of scrollable containers in
6087 * its window. This will be used to determine whether the window can
6088 * resize or must pan when a soft input area is open -- scrollable
6089 * containers allow the window to use resize mode since the container
6090 * will appropriately shrink.
6092 * @attr ref android.R.styleable#View_isScrollContainer
6094 public void setScrollContainer(boolean isScrollContainer) {
6095 if (isScrollContainer) {
6096 if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
6097 mAttachInfo.mScrollContainers.add(this);
6098 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
6100 mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
6102 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
6103 mAttachInfo.mScrollContainers.remove(this);
6105 mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
6110 * Returns the quality of the drawing cache.
6112 * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6113 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6115 * @see #setDrawingCacheQuality(int)
6116 * @see #setDrawingCacheEnabled(boolean)
6117 * @see #isDrawingCacheEnabled()
6119 * @attr ref android.R.styleable#View_drawingCacheQuality
6121 @DrawingCacheQuality
6122 public int getDrawingCacheQuality() {
6123 return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
6127 * Set the drawing cache quality of this view. This value is used only when the
6128 * drawing cache is enabled
6130 * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6131 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6133 * @see #getDrawingCacheQuality()
6134 * @see #setDrawingCacheEnabled(boolean)
6135 * @see #isDrawingCacheEnabled()
6137 * @attr ref android.R.styleable#View_drawingCacheQuality
6139 public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
6140 setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
6144 * Returns whether the screen should remain on, corresponding to the current
6145 * value of {@link #KEEP_SCREEN_ON}.
6147 * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
6149 * @see #setKeepScreenOn(boolean)
6151 * @attr ref android.R.styleable#View_keepScreenOn
6153 public boolean getKeepScreenOn() {
6154 return (mViewFlags & KEEP_SCREEN_ON) != 0;
6158 * Controls whether the screen should remain on, modifying the
6159 * value of {@link #KEEP_SCREEN_ON}.
6161 * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
6163 * @see #getKeepScreenOn()
6165 * @attr ref android.R.styleable#View_keepScreenOn
6167 public void setKeepScreenOn(boolean keepScreenOn) {
6168 setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
6172 * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6173 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6175 * @attr ref android.R.styleable#View_nextFocusLeft
6177 public int getNextFocusLeftId() {
6178 return mNextFocusLeftId;
6182 * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6183 * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
6184 * decide automatically.
6186 * @attr ref android.R.styleable#View_nextFocusLeft
6188 public void setNextFocusLeftId(int nextFocusLeftId) {
6189 mNextFocusLeftId = nextFocusLeftId;
6193 * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6194 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6196 * @attr ref android.R.styleable#View_nextFocusRight
6198 public int getNextFocusRightId() {
6199 return mNextFocusRightId;
6203 * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6204 * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
6205 * decide automatically.
6207 * @attr ref android.R.styleable#View_nextFocusRight
6209 public void setNextFocusRightId(int nextFocusRightId) {
6210 mNextFocusRightId = nextFocusRightId;
6214 * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6215 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6217 * @attr ref android.R.styleable#View_nextFocusUp
6219 public int getNextFocusUpId() {
6220 return mNextFocusUpId;
6224 * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6225 * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
6226 * decide automatically.
6228 * @attr ref android.R.styleable#View_nextFocusUp
6230 public void setNextFocusUpId(int nextFocusUpId) {
6231 mNextFocusUpId = nextFocusUpId;
6235 * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
6236 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6238 * @attr ref android.R.styleable#View_nextFocusDown
6240 public int getNextFocusDownId() {
6241 return mNextFocusDownId;
6245 * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
6246 * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
6247 * decide automatically.
6249 * @attr ref android.R.styleable#View_nextFocusDown
6251 public void setNextFocusDownId(int nextFocusDownId) {
6252 mNextFocusDownId = nextFocusDownId;
6256 * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
6257 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6259 * @attr ref android.R.styleable#View_nextFocusForward
6261 public int getNextFocusForwardId() {
6262 return mNextFocusForwardId;
6266 * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
6267 * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
6268 * decide automatically.
6270 * @attr ref android.R.styleable#View_nextFocusForward
6272 public void setNextFocusForwardId(int nextFocusForwardId) {
6273 mNextFocusForwardId = nextFocusForwardId;
6277 * Returns the visibility of this view and all of its ancestors
6279 * @return True if this view and all of its ancestors are {@link #VISIBLE}
6281 public boolean isShown() {
6282 View current = this;
6283 //noinspection ConstantConditions
6285 if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6288 ViewParent parent = current.mParent;
6289 if (parent == null) {
6290 return false; // We are not attached to the view root
6292 if (!(parent instanceof View)) {
6295 current = (View) parent;
6296 } while (current != null);
6302 * Called by the view hierarchy when the content insets for a window have
6303 * changed, to allow it to adjust its content to fit within those windows.
6304 * The content insets tell you the space that the status bar, input method,
6305 * and other system windows infringe on the application's window.
6307 * <p>You do not normally need to deal with this function, since the default
6308 * window decoration given to applications takes care of applying it to the
6309 * content of the window. If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
6310 * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
6311 * and your content can be placed under those system elements. You can then
6312 * use this method within your view hierarchy if you have parts of your UI
6313 * which you would like to ensure are not being covered.
6315 * <p>The default implementation of this method simply applies the content
6316 * insets to the view's padding, consuming that content (modifying the
6317 * insets to be 0), and returning true. This behavior is off by default, but can
6318 * be enabled through {@link #setFitsSystemWindows(boolean)}.
6320 * <p>This function's traversal down the hierarchy is depth-first. The same content
6321 * insets object is propagated down the hierarchy, so any changes made to it will
6322 * be seen by all following views (including potentially ones above in
6323 * the hierarchy since this is a depth-first traversal). The first view
6324 * that returns true will abort the entire traversal.
6326 * <p>The default implementation works well for a situation where it is
6327 * used with a container that covers the entire window, allowing it to
6328 * apply the appropriate insets to its content on all edges. If you need
6329 * a more complicated layout (such as two different views fitting system
6330 * windows, one on the top of the window, and one on the bottom),
6331 * you can override the method and handle the insets however you would like.
6332 * Note that the insets provided by the framework are always relative to the
6333 * far edges of the window, not accounting for the location of the called view
6334 * within that window. (In fact when this method is called you do not yet know
6335 * where the layout will place the view, as it is done before layout happens.)
6337 * <p>Note: unlike many View methods, there is no dispatch phase to this
6338 * call. If you are overriding it in a ViewGroup and want to allow the
6339 * call to continue to your children, you must be sure to call the super
6342 * <p>Here is a sample layout that makes use of fitting system windows
6343 * to have controls for a video view placed inside of the window decorations
6344 * that it hides and shows. This can be used with code like the second
6345 * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
6347 * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
6349 * @param insets Current content insets of the window. Prior to
6350 * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
6351 * the insets or else you and Android will be unhappy.
6353 * @return {@code true} if this view applied the insets and it should not
6354 * continue propagating further down the hierarchy, {@code false} otherwise.
6355 * @see #getFitsSystemWindows()
6356 * @see #setFitsSystemWindows(boolean)
6357 * @see #setSystemUiVisibility(int)
6359 * @deprecated As of API XX use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
6360 * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
6361 * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
6362 * to implement handling their own insets.
6364 protected boolean fitSystemWindows(Rect insets) {
6365 if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
6366 if (insets == null) {
6367 // Null insets by definition have already been consumed.
6368 // This call cannot apply insets since there are none to apply,
6372 // If we're not in the process of dispatching the newer apply insets call,
6373 // that means we're not in the compatibility path. Dispatch into the newer
6374 // apply insets path and take things from there.
6376 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
6377 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
6379 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
6382 // We're being called from the newer apply insets path.
6383 // Perform the standard fallback behavior.
6384 return fitSystemWindowsInt(insets);
6388 private boolean fitSystemWindowsInt(Rect insets) {
6389 if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
6390 mUserPaddingStart = UNDEFINED_PADDING;
6391 mUserPaddingEnd = UNDEFINED_PADDING;
6392 Rect localInsets = sThreadLocal.get();
6393 if (localInsets == null) {
6394 localInsets = new Rect();
6395 sThreadLocal.set(localInsets);
6397 boolean res = computeFitSystemWindows(insets, localInsets);
6398 mUserPaddingLeftInitial = localInsets.left;
6399 mUserPaddingRightInitial = localInsets.right;
6400 internalSetPadding(localInsets.left, localInsets.top,
6401 localInsets.right, localInsets.bottom);
6408 * Called when the view should apply {@link WindowInsets} according to its internal policy.
6410 * <p>This method should be overridden by views that wish to apply a policy different from or
6411 * in addition to the default behavior. Clients that wish to force a view subtree
6412 * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
6414 * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
6415 * it will be called during dispatch instead of this method. The listener may optionally
6416 * call this method from its own implementation if it wishes to apply the view's default
6417 * insets policy in addition to its own.</p>
6419 * <p>Implementations of this method should either return the insets parameter unchanged
6420 * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
6421 * that this view applied itself. This allows new inset types added in future platform
6422 * versions to pass through existing implementations unchanged without being erroneously
6425 * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
6426 * property is set then the view will consume the system window insets and apply them
6427 * as padding for the view.</p>
6429 * @param insets Insets to apply
6430 * @return The supplied insets with any applied insets consumed
6432 public WindowInsets onApplyWindowInsets(WindowInsets insets) {
6433 if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
6434 // We weren't called from within a direct call to fitSystemWindows,
6435 // call into it as a fallback in case we're in a class that overrides it
6436 // and has logic to perform.
6437 if (fitSystemWindows(insets.getSystemWindowInsets())) {
6438 return insets.consumeSystemWindowInsets();
6441 // We were called from within a direct call to fitSystemWindows.
6442 if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
6443 return insets.consumeSystemWindowInsets();
6450 * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
6451 * window insets to this view. The listener's
6452 * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
6453 * method will be called instead of the view's
6454 * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
6456 * @param listener Listener to set
6458 * @see #onApplyWindowInsets(WindowInsets)
6460 public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
6461 getListenerInfo().mOnApplyWindowInsetsListener = listener;
6465 * Request to apply the given window insets to this view or another view in its subtree.
6467 * <p>This method should be called by clients wishing to apply insets corresponding to areas
6468 * obscured by window decorations or overlays. This can include the status and navigation bars,
6469 * action bars, input methods and more. New inset categories may be added in the future.
6470 * The method returns the insets provided minus any that were applied by this view or its
6473 * <p>Clients wishing to provide custom behavior should override the
6474 * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
6475 * {@link OnApplyWindowInsetsListener} via the
6476 * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
6479 * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
6482 * @param insets Insets to apply
6483 * @return The provided insets minus the insets that were consumed
6485 public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
6487 mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
6488 if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
6489 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
6491 return onApplyWindowInsets(insets);
6494 mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
6499 * @hide Compute the insets that should be consumed by this view and the ones
6500 * that should propagate to those under it.
6502 protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
6503 if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
6504 || mAttachInfo == null
6505 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
6506 && !mAttachInfo.mOverscanRequested)) {
6507 outLocalInsets.set(inoutInsets);
6508 inoutInsets.set(0, 0, 0, 0);
6511 // The application wants to take care of fitting system window for
6512 // the content... however we still need to take care of any overscan here.
6513 final Rect overscan = mAttachInfo.mOverscanInsets;
6514 outLocalInsets.set(overscan);
6515 inoutInsets.left -= overscan.left;
6516 inoutInsets.top -= overscan.top;
6517 inoutInsets.right -= overscan.right;
6518 inoutInsets.bottom -= overscan.bottom;
6524 * Sets whether or not this view should account for system screen decorations
6525 * such as the status bar and inset its content; that is, controlling whether
6526 * the default implementation of {@link #fitSystemWindows(Rect)} will be
6527 * executed. See that method for more details.
6529 * <p>Note that if you are providing your own implementation of
6530 * {@link #fitSystemWindows(Rect)}, then there is no need to set this
6531 * flag to true -- your implementation will be overriding the default
6532 * implementation that checks this flag.
6534 * @param fitSystemWindows If true, then the default implementation of
6535 * {@link #fitSystemWindows(Rect)} will be executed.
6537 * @attr ref android.R.styleable#View_fitsSystemWindows
6538 * @see #getFitsSystemWindows()
6539 * @see #fitSystemWindows(Rect)
6540 * @see #setSystemUiVisibility(int)
6542 public void setFitsSystemWindows(boolean fitSystemWindows) {
6543 setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
6547 * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
6548 * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
6551 * @return {@code true} if the default implementation of
6552 * {@link #fitSystemWindows(Rect)} will be executed.
6554 * @attr ref android.R.styleable#View_fitsSystemWindows
6555 * @see #setFitsSystemWindows(boolean)
6556 * @see #fitSystemWindows(Rect)
6557 * @see #setSystemUiVisibility(int)
6559 public boolean getFitsSystemWindows() {
6560 return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
6564 public boolean fitsSystemWindows() {
6565 return getFitsSystemWindows();
6569 * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
6570 * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
6572 public void requestFitSystemWindows() {
6573 if (mParent != null) {
6574 mParent.requestFitSystemWindows();
6579 * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
6581 public void requestApplyInsets() {
6582 requestFitSystemWindows();
6586 * For use by PhoneWindow to make its own system window fitting optional.
6589 public void makeOptionalFitsSystemWindows() {
6590 setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
6594 * Returns the visibility status for this view.
6596 * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
6597 * @attr ref android.R.styleable#View_visibility
6599 @ViewDebug.ExportedProperty(mapping = {
6600 @ViewDebug.IntToString(from = VISIBLE, to = "VISIBLE"),
6601 @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
6602 @ViewDebug.IntToString(from = GONE, to = "GONE")
6605 public int getVisibility() {
6606 return mViewFlags & VISIBILITY_MASK;
6610 * Set the enabled state of this view.
6612 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
6613 * @attr ref android.R.styleable#View_visibility
6615 @RemotableViewMethod
6616 public void setVisibility(@Visibility int visibility) {
6617 setFlags(visibility, VISIBILITY_MASK);
6618 if (mBackground != null) mBackground.setVisible(visibility == VISIBLE, false);
6622 * Returns the enabled status for this view. The interpretation of the
6623 * enabled state varies by subclass.
6625 * @return True if this view is enabled, false otherwise.
6627 @ViewDebug.ExportedProperty
6628 public boolean isEnabled() {
6629 return (mViewFlags & ENABLED_MASK) == ENABLED;
6633 * Set the enabled state of this view. The interpretation of the enabled
6634 * state varies by subclass.
6636 * @param enabled True if this view is enabled, false otherwise.
6638 @RemotableViewMethod
6639 public void setEnabled(boolean enabled) {
6640 if (enabled == isEnabled()) return;
6642 setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
6645 * The View most likely has to change its appearance, so refresh
6646 * the drawable state.
6648 refreshDrawableState();
6650 // Invalidate too, since the default behavior for views is to be
6651 // be drawn at 50% alpha rather than to change the drawable.
6655 cancelPendingInputEvents();
6660 * Set whether this view can receive the focus.
6662 * Setting this to false will also ensure that this view is not focusable
6665 * @param focusable If true, this view can receive the focus.
6667 * @see #setFocusableInTouchMode(boolean)
6668 * @attr ref android.R.styleable#View_focusable
6670 public void setFocusable(boolean focusable) {
6672 setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
6674 setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
6678 * Set whether this view can receive focus while in touch mode.
6680 * Setting this to true will also ensure that this view is focusable.
6682 * @param focusableInTouchMode If true, this view can receive the focus while
6685 * @see #setFocusable(boolean)
6686 * @attr ref android.R.styleable#View_focusableInTouchMode
6688 public void setFocusableInTouchMode(boolean focusableInTouchMode) {
6689 // Focusable in touch mode should always be set before the focusable flag
6690 // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
6691 // which, in touch mode, will not successfully request focus on this view
6692 // because the focusable in touch mode flag is not set
6693 setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
6694 if (focusableInTouchMode) {
6695 setFlags(FOCUSABLE, FOCUSABLE_MASK);
6700 * Set whether this view should have sound effects enabled for events such as
6701 * clicking and touching.
6703 * <p>You may wish to disable sound effects for a view if you already play sounds,
6704 * for instance, a dial key that plays dtmf tones.
6706 * @param soundEffectsEnabled whether sound effects are enabled for this view.
6707 * @see #isSoundEffectsEnabled()
6708 * @see #playSoundEffect(int)
6709 * @attr ref android.R.styleable#View_soundEffectsEnabled
6711 public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
6712 setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
6716 * @return whether this view should have sound effects enabled for events such as
6717 * clicking and touching.
6719 * @see #setSoundEffectsEnabled(boolean)
6720 * @see #playSoundEffect(int)
6721 * @attr ref android.R.styleable#View_soundEffectsEnabled
6723 @ViewDebug.ExportedProperty
6724 public boolean isSoundEffectsEnabled() {
6725 return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
6729 * Set whether this view should have haptic feedback for events such as
6732 * <p>You may wish to disable haptic feedback if your view already controls
6733 * its own haptic feedback.
6735 * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
6736 * @see #isHapticFeedbackEnabled()
6737 * @see #performHapticFeedback(int)
6738 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
6740 public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
6741 setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
6745 * @return whether this view should have haptic feedback enabled for events
6748 * @see #setHapticFeedbackEnabled(boolean)
6749 * @see #performHapticFeedback(int)
6750 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
6752 @ViewDebug.ExportedProperty
6753 public boolean isHapticFeedbackEnabled() {
6754 return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
6758 * Returns the layout direction for this view.
6760 * @return One of {@link #LAYOUT_DIRECTION_LTR},
6761 * {@link #LAYOUT_DIRECTION_RTL},
6762 * {@link #LAYOUT_DIRECTION_INHERIT} or
6763 * {@link #LAYOUT_DIRECTION_LOCALE}.
6765 * @attr ref android.R.styleable#View_layoutDirection
6769 @ViewDebug.ExportedProperty(category = "layout", mapping = {
6770 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "LTR"),
6771 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RTL"),
6772 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
6773 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE, to = "LOCALE")
6776 public int getRawLayoutDirection() {
6777 return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
6781 * Set the layout direction for this view. This will propagate a reset of layout direction
6782 * resolution to the view's children and resolve layout direction for this view.
6784 * @param layoutDirection the layout direction to set. Should be one of:
6786 * {@link #LAYOUT_DIRECTION_LTR},
6787 * {@link #LAYOUT_DIRECTION_RTL},
6788 * {@link #LAYOUT_DIRECTION_INHERIT},
6789 * {@link #LAYOUT_DIRECTION_LOCALE}.
6791 * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
6792 * proceeds up the parent chain of the view to get the value. If there is no parent, then it
6793 * will return the default {@link #LAYOUT_DIRECTION_LTR}.
6795 * @attr ref android.R.styleable#View_layoutDirection
6797 @RemotableViewMethod
6798 public void setLayoutDirection(@LayoutDir int layoutDirection) {
6799 if (getRawLayoutDirection() != layoutDirection) {
6800 // Reset the current layout direction and the resolved one
6801 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
6802 resetRtlProperties();
6803 // Set the new layout direction (filtered)
6805 ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
6806 // We need to resolve all RTL properties as they all depend on layout direction
6807 resolveRtlPropertiesIfNeeded();
6814 * Returns the resolved layout direction for this view.
6816 * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
6817 * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
6819 * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
6820 * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
6822 * @attr ref android.R.styleable#View_layoutDirection
6824 @ViewDebug.ExportedProperty(category = "layout", mapping = {
6825 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
6826 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
6829 public int getLayoutDirection() {
6830 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
6831 if (targetSdkVersion < JELLY_BEAN_MR1) {
6832 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
6833 return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
6835 return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
6836 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
6840 * Indicates whether or not this view's layout is right-to-left. This is resolved from
6841 * layout attribute and/or the inherited value from the parent
6843 * @return true if the layout is right-to-left.
6847 @ViewDebug.ExportedProperty(category = "layout")
6848 public boolean isLayoutRtl() {
6849 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
6853 * Indicates whether the view is currently tracking transient state that the
6854 * app should not need to concern itself with saving and restoring, but that
6855 * the framework should take special note to preserve when possible.
6857 * <p>A view with transient state cannot be trivially rebound from an external
6858 * data source, such as an adapter binding item views in a list. This may be
6859 * because the view is performing an animation, tracking user selection
6860 * of content, or similar.</p>
6862 * @return true if the view has transient state
6864 @ViewDebug.ExportedProperty(category = "layout")
6865 public boolean hasTransientState() {
6866 return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
6870 * Set whether this view is currently tracking transient state that the
6871 * framework should attempt to preserve when possible. This flag is reference counted,
6872 * so every call to setHasTransientState(true) should be paired with a later call
6873 * to setHasTransientState(false).
6875 * <p>A view with transient state cannot be trivially rebound from an external
6876 * data source, such as an adapter binding item views in a list. This may be
6877 * because the view is performing an animation, tracking user selection
6878 * of content, or similar.</p>
6880 * @param hasTransientState true if this view has transient state
6882 public void setHasTransientState(boolean hasTransientState) {
6883 mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
6884 mTransientStateCount - 1;
6885 if (mTransientStateCount < 0) {
6886 mTransientStateCount = 0;
6887 Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
6888 "unmatched pair of setHasTransientState calls");
6889 } else if ((hasTransientState && mTransientStateCount == 1) ||
6890 (!hasTransientState && mTransientStateCount == 0)) {
6891 // update flag if we've just incremented up from 0 or decremented down to 0
6892 mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
6893 (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
6894 if (mParent != null) {
6896 mParent.childHasTransientStateChanged(this, hasTransientState);
6897 } catch (AbstractMethodError e) {
6898 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
6899 " does not fully implement ViewParent", e);
6906 * Returns true if this view is currently attached to a window.
6908 public boolean isAttachedToWindow() {
6909 return mAttachInfo != null;
6913 * Returns true if this view has been through at least one layout since it
6914 * was last attached to or detached from a window.
6916 public boolean isLaidOut() {
6917 return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
6921 * If this view doesn't do any drawing on its own, set this flag to
6922 * allow further optimizations. By default, this flag is not set on
6923 * View, but could be set on some View subclasses such as ViewGroup.
6925 * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
6926 * you should clear this flag.
6928 * @param willNotDraw whether or not this View draw on its own
6930 public void setWillNotDraw(boolean willNotDraw) {
6931 setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
6935 * Returns whether or not this View draws on its own.
6937 * @return true if this view has nothing to draw, false otherwise
6939 @ViewDebug.ExportedProperty(category = "drawing")
6940 public boolean willNotDraw() {
6941 return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
6945 * When a View's drawing cache is enabled, drawing is redirected to an
6946 * offscreen bitmap. Some views, like an ImageView, must be able to
6947 * bypass this mechanism if they already draw a single bitmap, to avoid
6948 * unnecessary usage of the memory.
6950 * @param willNotCacheDrawing true if this view does not cache its
6951 * drawing, false otherwise
6953 public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
6954 setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
6958 * Returns whether or not this View can cache its drawing or not.
6960 * @return true if this view does not cache its drawing, false otherwise
6962 @ViewDebug.ExportedProperty(category = "drawing")
6963 public boolean willNotCacheDrawing() {
6964 return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
6968 * Indicates whether this view reacts to click events or not.
6970 * @return true if the view is clickable, false otherwise
6972 * @see #setClickable(boolean)
6973 * @attr ref android.R.styleable#View_clickable
6975 @ViewDebug.ExportedProperty
6976 public boolean isClickable() {
6977 return (mViewFlags & CLICKABLE) == CLICKABLE;
6981 * Enables or disables click events for this view. When a view
6982 * is clickable it will change its state to "pressed" on every click.
6983 * Subclasses should set the view clickable to visually react to
6986 * @param clickable true to make the view clickable, false otherwise
6988 * @see #isClickable()
6989 * @attr ref android.R.styleable#View_clickable
6991 public void setClickable(boolean clickable) {
6992 setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
6996 * Indicates whether this view reacts to long click events or not.
6998 * @return true if the view is long clickable, false otherwise
7000 * @see #setLongClickable(boolean)
7001 * @attr ref android.R.styleable#View_longClickable
7003 public boolean isLongClickable() {
7004 return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
7008 * Enables or disables long click events for this view. When a view is long
7009 * clickable it reacts to the user holding down the button for a longer
7010 * duration than a tap. This event can either launch the listener or a
7013 * @param longClickable true to make the view long clickable, false otherwise
7014 * @see #isLongClickable()
7015 * @attr ref android.R.styleable#View_longClickable
7017 public void setLongClickable(boolean longClickable) {
7018 setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
7022 * Sets the pressed state for this view and provides a touch coordinate for
7023 * animation hinting.
7025 * @param pressed Pass true to set the View's internal state to "pressed",
7026 * or false to reverts the View's internal state from a
7027 * previously set "pressed" state.
7028 * @param x The x coordinate of the touch that caused the press
7029 * @param y The y coordinate of the touch that caused the press
7031 private void setPressed(boolean pressed, float x, float y) {
7033 drawableHotspotChanged(x, y);
7036 setPressed(pressed);
7040 * Sets the pressed state for this view.
7042 * @see #isClickable()
7043 * @see #setClickable(boolean)
7045 * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
7046 * the View's internal state from a previously set "pressed" state.
7048 public void setPressed(boolean pressed) {
7049 final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
7052 mPrivateFlags |= PFLAG_PRESSED;
7054 mPrivateFlags &= ~PFLAG_PRESSED;
7058 refreshDrawableState();
7060 dispatchSetPressed(pressed);
7064 * Dispatch setPressed to all of this View's children.
7066 * @see #setPressed(boolean)
7068 * @param pressed The new pressed state
7070 protected void dispatchSetPressed(boolean pressed) {
7074 * Indicates whether the view is currently in pressed state. Unless
7075 * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
7076 * the pressed state.
7078 * @see #setPressed(boolean)
7079 * @see #isClickable()
7080 * @see #setClickable(boolean)
7082 * @return true if the view is currently pressed, false otherwise
7084 @ViewDebug.ExportedProperty
7085 public boolean isPressed() {
7086 return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
7090 * Indicates whether this view will save its state (that is,
7091 * whether its {@link #onSaveInstanceState} method will be called).
7093 * @return Returns true if the view state saving is enabled, else false.
7095 * @see #setSaveEnabled(boolean)
7096 * @attr ref android.R.styleable#View_saveEnabled
7098 public boolean isSaveEnabled() {
7099 return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
7103 * Controls whether the saving of this view's state is
7104 * enabled (that is, whether its {@link #onSaveInstanceState} method
7105 * will be called). Note that even if freezing is enabled, the
7106 * view still must have an id assigned to it (via {@link #setId(int)})
7107 * for its state to be saved. This flag can only disable the
7108 * saving of this view; any child views may still have their state saved.
7110 * @param enabled Set to false to <em>disable</em> state saving, or true
7111 * (the default) to allow it.
7113 * @see #isSaveEnabled()
7115 * @see #onSaveInstanceState()
7116 * @attr ref android.R.styleable#View_saveEnabled
7118 public void setSaveEnabled(boolean enabled) {
7119 setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
7123 * Gets whether the framework should discard touches when the view's
7124 * window is obscured by another visible window.
7125 * Refer to the {@link View} security documentation for more details.
7127 * @return True if touch filtering is enabled.
7129 * @see #setFilterTouchesWhenObscured(boolean)
7130 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
7132 @ViewDebug.ExportedProperty
7133 public boolean getFilterTouchesWhenObscured() {
7134 return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
7138 * Sets whether the framework should discard touches when the view's
7139 * window is obscured by another visible window.
7140 * Refer to the {@link View} security documentation for more details.
7142 * @param enabled True if touch filtering should be enabled.
7144 * @see #getFilterTouchesWhenObscured
7145 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
7147 public void setFilterTouchesWhenObscured(boolean enabled) {
7148 setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
7149 FILTER_TOUCHES_WHEN_OBSCURED);
7153 * Indicates whether the entire hierarchy under this view will save its
7154 * state when a state saving traversal occurs from its parent. The default
7155 * is true; if false, these views will not be saved unless
7156 * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
7158 * @return Returns true if the view state saving from parent is enabled, else false.
7160 * @see #setSaveFromParentEnabled(boolean)
7162 public boolean isSaveFromParentEnabled() {
7163 return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
7167 * Controls whether the entire hierarchy under this view will save its
7168 * state when a state saving traversal occurs from its parent. The default
7169 * is true; if false, these views will not be saved unless
7170 * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
7172 * @param enabled Set to false to <em>disable</em> state saving, or true
7173 * (the default) to allow it.
7175 * @see #isSaveFromParentEnabled()
7177 * @see #onSaveInstanceState()
7179 public void setSaveFromParentEnabled(boolean enabled) {
7180 setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
7185 * Returns whether this View is able to take focus.
7187 * @return True if this view can take focus, or false otherwise.
7188 * @attr ref android.R.styleable#View_focusable
7190 @ViewDebug.ExportedProperty(category = "focus")
7191 public final boolean isFocusable() {
7192 return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
7196 * When a view is focusable, it may not want to take focus when in touch mode.
7197 * For example, a button would like focus when the user is navigating via a D-pad
7198 * so that the user can click on it, but once the user starts touching the screen,
7199 * the button shouldn't take focus
7200 * @return Whether the view is focusable in touch mode.
7201 * @attr ref android.R.styleable#View_focusableInTouchMode
7203 @ViewDebug.ExportedProperty
7204 public final boolean isFocusableInTouchMode() {
7205 return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
7209 * Find the nearest view in the specified direction that can take focus.
7210 * This does not actually give focus to that view.
7212 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7214 * @return The nearest focusable in the specified direction, or null if none
7217 public View focusSearch(@FocusRealDirection int direction) {
7218 if (mParent != null) {
7219 return mParent.focusSearch(this, direction);
7226 * This method is the last chance for the focused view and its ancestors to
7227 * respond to an arrow key. This is called when the focused view did not
7228 * consume the key internally, nor could the view system find a new view in
7229 * the requested direction to give focus to.
7231 * @param focused The currently focused view.
7232 * @param direction The direction focus wants to move. One of FOCUS_UP,
7233 * FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
7234 * @return True if the this view consumed this unhandled move.
7236 public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
7241 * If a user manually specified the next view id for a particular direction,
7242 * use the root to look up the view.
7243 * @param root The root view of the hierarchy containing this view.
7244 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
7245 * or FOCUS_BACKWARD.
7246 * @return The user specified next view, or null if there is none.
7248 View findUserSetNextFocus(View root, @FocusDirection int direction) {
7249 switch (direction) {
7251 if (mNextFocusLeftId == View.NO_ID) return null;
7252 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
7254 if (mNextFocusRightId == View.NO_ID) return null;
7255 return findViewInsideOutShouldExist(root, mNextFocusRightId);
7257 if (mNextFocusUpId == View.NO_ID) return null;
7258 return findViewInsideOutShouldExist(root, mNextFocusUpId);
7260 if (mNextFocusDownId == View.NO_ID) return null;
7261 return findViewInsideOutShouldExist(root, mNextFocusDownId);
7263 if (mNextFocusForwardId == View.NO_ID) return null;
7264 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
7265 case FOCUS_BACKWARD: {
7266 if (mID == View.NO_ID) return null;
7268 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
7270 public boolean apply(View t) {
7271 return t.mNextFocusForwardId == id;
7279 private View findViewInsideOutShouldExist(View root, int id) {
7280 if (mMatchIdPredicate == null) {
7281 mMatchIdPredicate = new MatchIdPredicate();
7283 mMatchIdPredicate.mId = id;
7284 View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
7285 if (result == null) {
7286 Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
7292 * Find and return all focusable views that are descendants of this view,
7293 * possibly including this view if it is focusable itself.
7295 * @param direction The direction of the focus
7296 * @return A list of focusable views
7298 public ArrayList<View> getFocusables(@FocusDirection int direction) {
7299 ArrayList<View> result = new ArrayList<View>(24);
7300 addFocusables(result, direction);
7305 * Add any focusable views that are descendants of this view (possibly
7306 * including this view if it is focusable itself) to views. If we are in touch mode,
7307 * only add views that are also focusable in touch mode.
7309 * @param views Focusable views found so far
7310 * @param direction The direction of the focus
7312 public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
7313 addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
7317 * Adds any focusable views that are descendants of this view (possibly
7318 * including this view if it is focusable itself) to views. This method
7319 * adds all focusable views regardless if we are in touch mode or
7320 * only views focusable in touch mode if we are in touch mode or
7321 * only views that can take accessibility focus if accessibility is enabeld
7322 * depending on the focusable mode paramater.
7324 * @param views Focusable views found so far or null if all we are interested is
7325 * the number of focusables.
7326 * @param direction The direction of the focus.
7327 * @param focusableMode The type of focusables to be added.
7329 * @see #FOCUSABLES_ALL
7330 * @see #FOCUSABLES_TOUCH_MODE
7332 public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
7333 @FocusableMode int focusableMode) {
7334 if (views == null) {
7337 if (!isFocusable()) {
7340 if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
7341 && isInTouchMode() && !isFocusableInTouchMode()) {
7348 * Finds the Views that contain given text. The containment is case insensitive.
7349 * The search is performed by either the text that the View renders or the content
7350 * description that describes the view for accessibility purposes and the view does
7351 * not render or both. Clients can specify how the search is to be performed via
7352 * passing the {@link #FIND_VIEWS_WITH_TEXT} and
7353 * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
7355 * @param outViews The output list of matching Views.
7356 * @param searched The text to match against.
7358 * @see #FIND_VIEWS_WITH_TEXT
7359 * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
7360 * @see #setContentDescription(CharSequence)
7362 public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
7363 @FindViewFlags int flags) {
7364 if (getAccessibilityNodeProvider() != null) {
7365 if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
7368 } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
7369 && (searched != null && searched.length() > 0)
7370 && (mContentDescription != null && mContentDescription.length() > 0)) {
7371 String searchedLowerCase = searched.toString().toLowerCase();
7372 String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
7373 if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
7380 * Find and return all touchable views that are descendants of this view,
7381 * possibly including this view if it is touchable itself.
7383 * @return A list of touchable views
7385 public ArrayList<View> getTouchables() {
7386 ArrayList<View> result = new ArrayList<View>();
7387 addTouchables(result);
7392 * Add any touchable views that are descendants of this view (possibly
7393 * including this view if it is touchable itself) to views.
7395 * @param views Touchable views found so far
7397 public void addTouchables(ArrayList<View> views) {
7398 final int viewFlags = mViewFlags;
7400 if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
7401 && (viewFlags & ENABLED_MASK) == ENABLED) {
7407 * Returns whether this View is accessibility focused.
7409 * @return True if this View is accessibility focused.
7411 public boolean isAccessibilityFocused() {
7412 return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
7416 * Call this to try to give accessibility focus to this view.
7418 * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
7419 * returns false or the view is no visible or the view already has accessibility
7422 * See also {@link #focusSearch(int)}, which is what you call to say that you
7423 * have focus, and you want your parent to look for the next one.
7425 * @return Whether this view actually took accessibility focus.
7429 public boolean requestAccessibilityFocus() {
7430 AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
7431 if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
7434 if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7437 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
7438 mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
7439 ViewRootImpl viewRootImpl = getViewRootImpl();
7440 if (viewRootImpl != null) {
7441 viewRootImpl.setAccessibilityFocus(this, null);
7444 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
7451 * Call this to try to clear accessibility focus of this view.
7453 * See also {@link #focusSearch(int)}, which is what you call to say that you
7454 * have focus, and you want your parent to look for the next one.
7458 public void clearAccessibilityFocus() {
7459 clearAccessibilityFocusNoCallbacks();
7460 // Clear the global reference of accessibility focus if this
7461 // view or any of its descendants had accessibility focus.
7462 ViewRootImpl viewRootImpl = getViewRootImpl();
7463 if (viewRootImpl != null) {
7464 View focusHost = viewRootImpl.getAccessibilityFocusedHost();
7465 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
7466 viewRootImpl.setAccessibilityFocus(null, null);
7471 private void sendAccessibilityHoverEvent(int eventType) {
7472 // Since we are not delivering to a client accessibility events from not
7473 // important views (unless the clinet request that) we need to fire the
7474 // event from the deepest view exposed to the client. As a consequence if
7475 // the user crosses a not exposed view the client will see enter and exit
7476 // of the exposed predecessor followed by and enter and exit of that same
7477 // predecessor when entering and exiting the not exposed descendant. This
7478 // is fine since the client has a clear idea which view is hovered at the
7479 // price of a couple more events being sent. This is a simple and
7480 // working solution.
7483 if (source.includeForAccessibility()) {
7484 source.sendAccessibilityEvent(eventType);
7487 ViewParent parent = source.getParent();
7488 if (parent instanceof View) {
7489 source = (View) parent;
7497 * Clears accessibility focus without calling any callback methods
7498 * normally invoked in {@link #clearAccessibilityFocus()}. This method
7499 * is used for clearing accessibility focus when giving this focus to
7502 void clearAccessibilityFocusNoCallbacks() {
7503 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
7504 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
7506 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
7511 * Call this to try to give focus to a specific view or to one of its
7514 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7515 * false), or if it is focusable and it is not focusable in touch mode
7516 * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7518 * See also {@link #focusSearch(int)}, which is what you call to say that you
7519 * have focus, and you want your parent to look for the next one.
7521 * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
7522 * {@link #FOCUS_DOWN} and <code>null</code>.
7524 * @return Whether this view or one of its descendants actually took focus.
7526 public final boolean requestFocus() {
7527 return requestFocus(View.FOCUS_DOWN);
7531 * Call this to try to give focus to a specific view or to one of its
7532 * descendants and give it a hint about what direction focus is heading.
7534 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7535 * false), or if it is focusable and it is not focusable in touch mode
7536 * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7538 * See also {@link #focusSearch(int)}, which is what you call to say that you
7539 * have focus, and you want your parent to look for the next one.
7541 * This is equivalent to calling {@link #requestFocus(int, Rect)} with
7542 * <code>null</code> set for the previously focused rectangle.
7544 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7545 * @return Whether this view or one of its descendants actually took focus.
7547 public final boolean requestFocus(int direction) {
7548 return requestFocus(direction, null);
7552 * Call this to try to give focus to a specific view or to one of its descendants
7553 * and give it hints about the direction and a specific rectangle that the focus
7554 * is coming from. The rectangle can help give larger views a finer grained hint
7555 * about where focus is coming from, and therefore, where to show selection, or
7556 * forward focus change internally.
7558 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7559 * false), or if it is focusable and it is not focusable in touch mode
7560 * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7562 * A View will not take focus if it is not visible.
7564 * A View will not take focus if one of its parents has
7565 * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
7566 * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
7568 * See also {@link #focusSearch(int)}, which is what you call to say that you
7569 * have focus, and you want your parent to look for the next one.
7571 * You may wish to override this method if your custom {@link View} has an internal
7572 * {@link View} that it wishes to forward the request to.
7574 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7575 * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
7576 * to give a finer grained hint about where focus is coming from. May be null
7577 * if there is no hint.
7578 * @return Whether this view or one of its descendants actually took focus.
7580 public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
7581 return requestFocusNoSearch(direction, previouslyFocusedRect);
7584 private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
7585 // need to be focusable
7586 if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
7587 (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7591 // need to be focusable in touch mode if in touch mode
7592 if (isInTouchMode() &&
7593 (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
7597 // need to not have any parents blocking us
7598 if (hasAncestorThatBlocksDescendantFocus()) {
7602 handleFocusGainInternal(direction, previouslyFocusedRect);
7607 * Call this to try to give focus to a specific view or to one of its descendants. This is a
7608 * special variant of {@link #requestFocus() } that will allow views that are not focuable in
7609 * touch mode to request focus when they are touched.
7611 * @return Whether this view or one of its descendants actually took focus.
7613 * @see #isInTouchMode()
7616 public final boolean requestFocusFromTouch() {
7617 // Leave touch mode if we need to
7618 if (isInTouchMode()) {
7619 ViewRootImpl viewRoot = getViewRootImpl();
7620 if (viewRoot != null) {
7621 viewRoot.ensureTouchMode(false);
7624 return requestFocus(View.FOCUS_DOWN);
7628 * @return Whether any ancestor of this view blocks descendant focus.
7630 private boolean hasAncestorThatBlocksDescendantFocus() {
7631 final boolean focusableInTouchMode = isFocusableInTouchMode();
7632 ViewParent ancestor = mParent;
7633 while (ancestor instanceof ViewGroup) {
7634 final ViewGroup vgAncestor = (ViewGroup) ancestor;
7635 if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
7636 || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
7639 ancestor = vgAncestor.getParent();
7646 * Gets the mode for determining whether this View is important for accessibility
7647 * which is if it fires accessibility events and if it is reported to
7648 * accessibility services that query the screen.
7650 * @return The mode for determining whether a View is important for accessibility.
7652 * @attr ref android.R.styleable#View_importantForAccessibility
7654 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
7655 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
7656 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
7657 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
7659 @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
7660 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
7661 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
7662 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
7663 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
7664 to = "noHideDescendants")
7666 public int getImportantForAccessibility() {
7667 return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
7668 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
7672 * Sets the live region mode for this view. This indicates to accessibility
7673 * services whether they should automatically notify the user about changes
7674 * to the view's content description or text, or to the content descriptions
7675 * or text of the view's children (where applicable).
7677 * For example, in a login screen with a TextView that displays an "incorrect
7678 * password" notification, that view should be marked as a live region with
7679 * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
7681 * To disable change notifications for this view, use
7682 * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
7683 * mode for most views.
7685 * To indicate that the user should be notified of changes, use
7686 * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
7688 * If the view's changes should interrupt ongoing speech and notify the user
7689 * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
7691 * @param mode The live region mode for this view, one of:
7693 * <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
7694 * <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
7695 * <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
7697 * @attr ref android.R.styleable#View_accessibilityLiveRegion
7699 public void setAccessibilityLiveRegion(int mode) {
7700 if (mode != getAccessibilityLiveRegion()) {
7701 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
7702 mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
7703 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
7704 notifyViewAccessibilityStateChangedIfNeeded(
7705 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7710 * Gets the live region mode for this View.
7712 * @return The live region mode for the view.
7714 * @attr ref android.R.styleable#View_accessibilityLiveRegion
7716 * @see #setAccessibilityLiveRegion(int)
7718 public int getAccessibilityLiveRegion() {
7719 return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
7720 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
7724 * Sets how to determine whether this view is important for accessibility
7725 * which is if it fires accessibility events and if it is reported to
7726 * accessibility services that query the screen.
7728 * @param mode How to determine whether this view is important for accessibility.
7730 * @attr ref android.R.styleable#View_importantForAccessibility
7732 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
7733 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
7734 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
7735 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
7737 public void setImportantForAccessibility(int mode) {
7738 final int oldMode = getImportantForAccessibility();
7739 if (mode != oldMode) {
7740 // If we're moving between AUTO and another state, we might not need
7741 // to send a subtree changed notification. We'll store the computed
7742 // importance, since we'll need to check it later to make sure.
7743 final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
7744 || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
7745 final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
7746 mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
7747 mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
7748 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
7749 if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
7750 notifySubtreeAccessibilityStateChangedIfNeeded();
7752 notifyViewAccessibilityStateChangedIfNeeded(
7753 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7759 * Computes whether this view should be exposed for accessibility. In
7760 * general, views that are interactive or provide information are exposed
7761 * while views that serve only as containers are hidden.
7763 * If an ancestor of this view has importance
7764 * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
7765 * returns <code>false</code>.
7767 * Otherwise, the value is computed according to the view's
7768 * {@link #getImportantForAccessibility()} value:
7770 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
7771 * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
7773 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
7774 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
7775 * view satisfies any of the following:
7777 * <li>Is actionable, e.g. {@link #isClickable()},
7778 * {@link #isLongClickable()}, or {@link #isFocusable()}
7779 * <li>Has an {@link AccessibilityDelegate}
7780 * <li>Has an interaction listener, e.g. {@link OnTouchListener},
7781 * {@link OnKeyListener}, etc.
7782 * <li>Is an accessibility live region, e.g.
7783 * {@link #getAccessibilityLiveRegion()} is not
7784 * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
7788 * @return Whether the view is exposed for accessibility.
7789 * @see #setImportantForAccessibility(int)
7790 * @see #getImportantForAccessibility()
7792 public boolean isImportantForAccessibility() {
7793 final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
7794 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
7795 if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
7796 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
7800 // Check parent mode to ensure we're not hidden.
7801 ViewParent parent = mParent;
7802 while (parent instanceof View) {
7803 if (((View) parent).getImportantForAccessibility()
7804 == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
7807 parent = parent.getParent();
7810 return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
7811 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
7812 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
7816 * Gets the parent for accessibility purposes. Note that the parent for
7817 * accessibility is not necessary the immediate parent. It is the first
7818 * predecessor that is important for accessibility.
7820 * @return The parent for accessibility purposes.
7822 public ViewParent getParentForAccessibility() {
7823 if (mParent instanceof View) {
7824 View parentView = (View) mParent;
7825 if (parentView.includeForAccessibility()) {
7828 return mParent.getParentForAccessibility();
7835 * Adds the children of a given View for accessibility. Since some Views are
7836 * not important for accessibility the children for accessibility are not
7837 * necessarily direct children of the view, rather they are the first level of
7838 * descendants important for accessibility.
7840 * @param children The list of children for accessibility.
7842 public void addChildrenForAccessibility(ArrayList<View> children) {
7847 * Whether to regard this view for accessibility. A view is regarded for
7848 * accessibility if it is important for accessibility or the querying
7849 * accessibility service has explicitly requested that view not
7850 * important for accessibility are regarded.
7852 * @return Whether to regard the view for accessibility.
7856 public boolean includeForAccessibility() {
7857 if (mAttachInfo != null) {
7858 return (mAttachInfo.mAccessibilityFetchFlags
7859 & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
7860 || isImportantForAccessibility();
7866 * Returns whether the View is considered actionable from
7867 * accessibility perspective. Such view are important for
7870 * @return True if the view is actionable for accessibility.
7874 public boolean isActionableForAccessibility() {
7875 return (isClickable() || isLongClickable() || isFocusable());
7879 * Returns whether the View has registered callbacks which makes it
7880 * important for accessibility.
7882 * @return True if the view is actionable for accessibility.
7884 private boolean hasListenersForAccessibility() {
7885 ListenerInfo info = getListenerInfo();
7886 return mTouchDelegate != null || info.mOnKeyListener != null
7887 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
7888 || info.mOnHoverListener != null || info.mOnDragListener != null;
7892 * Notifies that the accessibility state of this view changed. The change
7893 * is local to this view and does not represent structural changes such
7894 * as children and parent. For example, the view became focusable. The
7895 * notification is at at most once every
7896 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
7897 * to avoid unnecessary load to the system. Also once a view has a pending
7898 * notification this method is a NOP until the notification has been sent.
7902 public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
7903 if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
7906 if (mSendViewStateChangedAccessibilityEvent == null) {
7907 mSendViewStateChangedAccessibilityEvent =
7908 new SendViewStateChangedAccessibilityEvent();
7910 mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
7914 * Notifies that the accessibility state of this view changed. The change
7915 * is *not* local to this view and does represent structural changes such
7916 * as children and parent. For example, the view size changed. The
7917 * notification is at at most once every
7918 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
7919 * to avoid unnecessary load to the system. Also once a view has a pending
7920 * notification this method is a NOP until the notification has been sent.
7924 public void notifySubtreeAccessibilityStateChangedIfNeeded() {
7925 if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
7928 if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
7929 mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
7930 if (mParent != null) {
7932 mParent.notifySubtreeAccessibilityStateChanged(
7933 this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
7934 } catch (AbstractMethodError e) {
7935 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
7936 " does not fully implement ViewParent", e);
7943 * Reset the flag indicating the accessibility state of the subtree rooted
7944 * at this view changed.
7946 void resetSubtreeAccessibilityStateChanged() {
7947 mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
7951 * Performs the specified accessibility action on the view. For
7952 * possible accessibility actions look at {@link AccessibilityNodeInfo}.
7954 * If an {@link AccessibilityDelegate} has been specified via calling
7955 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7956 * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
7957 * is responsible for handling this call.
7960 * @param action The action to perform.
7961 * @param arguments Optional action arguments.
7962 * @return Whether the action was performed.
7964 public boolean performAccessibilityAction(int action, Bundle arguments) {
7965 if (mAccessibilityDelegate != null) {
7966 return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
7968 return performAccessibilityActionInternal(action, arguments);
7973 * @see #performAccessibilityAction(int, Bundle)
7975 * Note: Called from the default {@link AccessibilityDelegate}.
7977 boolean performAccessibilityActionInternal(int action, Bundle arguments) {
7979 case AccessibilityNodeInfo.ACTION_CLICK: {
7980 if (isClickable()) {
7985 case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
7986 if (isLongClickable()) {
7991 case AccessibilityNodeInfo.ACTION_FOCUS: {
7993 // Get out of touch mode since accessibility
7994 // wants to move focus around.
7995 getViewRootImpl().ensureTouchMode(false);
7996 return requestFocus();
7999 case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
8002 return !isFocused();
8005 case AccessibilityNodeInfo.ACTION_SELECT: {
8006 if (!isSelected()) {
8008 return isSelected();
8011 case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
8014 return !isSelected();
8017 case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
8018 if (!isAccessibilityFocused()) {
8019 return requestAccessibilityFocus();
8022 case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
8023 if (isAccessibilityFocused()) {
8024 clearAccessibilityFocus();
8028 case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
8029 if (arguments != null) {
8030 final int granularity = arguments.getInt(
8031 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8032 final boolean extendSelection = arguments.getBoolean(
8033 AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8034 return traverseAtGranularity(granularity, true, extendSelection);
8037 case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
8038 if (arguments != null) {
8039 final int granularity = arguments.getInt(
8040 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8041 final boolean extendSelection = arguments.getBoolean(
8042 AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8043 return traverseAtGranularity(granularity, false, extendSelection);
8046 case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
8047 CharSequence text = getIterableTextForAccessibility();
8051 final int start = (arguments != null) ? arguments.getInt(
8052 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
8053 final int end = (arguments != null) ? arguments.getInt(
8054 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
8055 // Only cursor position can be specified (selection length == 0)
8056 if ((getAccessibilitySelectionStart() != start
8057 || getAccessibilitySelectionEnd() != end)
8058 && (start == end)) {
8059 setAccessibilitySelection(start, end);
8060 notifyViewAccessibilityStateChangedIfNeeded(
8061 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8069 private boolean traverseAtGranularity(int granularity, boolean forward,
8070 boolean extendSelection) {
8071 CharSequence text = getIterableTextForAccessibility();
8072 if (text == null || text.length() == 0) {
8075 TextSegmentIterator iterator = getIteratorForGranularity(granularity);
8076 if (iterator == null) {
8079 int current = getAccessibilitySelectionEnd();
8080 if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
8081 current = forward ? 0 : text.length();
8083 final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
8084 if (range == null) {
8087 final int segmentStart = range[0];
8088 final int segmentEnd = range[1];
8091 if (extendSelection && isAccessibilitySelectionExtendable()) {
8092 selectionStart = getAccessibilitySelectionStart();
8093 if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
8094 selectionStart = forward ? segmentStart : segmentEnd;
8096 selectionEnd = forward ? segmentEnd : segmentStart;
8098 selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
8100 setAccessibilitySelection(selectionStart, selectionEnd);
8101 final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
8102 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
8103 sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
8108 * Gets the text reported for accessibility purposes.
8110 * @return The accessibility text.
8114 public CharSequence getIterableTextForAccessibility() {
8115 return getContentDescription();
8119 * Gets whether accessibility selection can be extended.
8121 * @return If selection is extensible.
8125 public boolean isAccessibilitySelectionExtendable() {
8132 public int getAccessibilitySelectionStart() {
8133 return mAccessibilityCursorPosition;
8139 public int getAccessibilitySelectionEnd() {
8140 return getAccessibilitySelectionStart();
8146 public void setAccessibilitySelection(int start, int end) {
8147 if (start == end && end == mAccessibilityCursorPosition) {
8150 if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
8151 mAccessibilityCursorPosition = start;
8153 mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
8155 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
8158 private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
8159 int fromIndex, int toIndex) {
8160 if (mParent == null) {
8163 AccessibilityEvent event = AccessibilityEvent.obtain(
8164 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
8165 onInitializeAccessibilityEvent(event);
8166 onPopulateAccessibilityEvent(event);
8167 event.setFromIndex(fromIndex);
8168 event.setToIndex(toIndex);
8169 event.setAction(action);
8170 event.setMovementGranularity(granularity);
8171 mParent.requestSendAccessibilityEvent(this, event);
8177 public TextSegmentIterator getIteratorForGranularity(int granularity) {
8178 switch (granularity) {
8179 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
8180 CharSequence text = getIterableTextForAccessibility();
8181 if (text != null && text.length() > 0) {
8182 CharacterTextSegmentIterator iterator =
8183 CharacterTextSegmentIterator.getInstance(
8184 mContext.getResources().getConfiguration().locale);
8185 iterator.initialize(text.toString());
8189 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
8190 CharSequence text = getIterableTextForAccessibility();
8191 if (text != null && text.length() > 0) {
8192 WordTextSegmentIterator iterator =
8193 WordTextSegmentIterator.getInstance(
8194 mContext.getResources().getConfiguration().locale);
8195 iterator.initialize(text.toString());
8199 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
8200 CharSequence text = getIterableTextForAccessibility();
8201 if (text != null && text.length() > 0) {
8202 ParagraphTextSegmentIterator iterator =
8203 ParagraphTextSegmentIterator.getInstance();
8204 iterator.initialize(text.toString());
8215 public void dispatchStartTemporaryDetach() {
8216 onStartTemporaryDetach();
8220 * This is called when a container is going to temporarily detach a child, with
8221 * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
8222 * It will either be followed by {@link #onFinishTemporaryDetach()} or
8223 * {@link #onDetachedFromWindow()} when the container is done.
8225 public void onStartTemporaryDetach() {
8226 removeUnsetPressCallback();
8227 mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
8233 public void dispatchFinishTemporaryDetach() {
8234 onFinishTemporaryDetach();
8238 * Called after {@link #onStartTemporaryDetach} when the container is done
8239 * changing the view.
8241 public void onFinishTemporaryDetach() {
8245 * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
8246 * for this view's window. Returns null if the view is not currently attached
8247 * to the window. Normally you will not need to use this directly, but
8248 * just use the standard high-level event callbacks like
8249 * {@link #onKeyDown(int, KeyEvent)}.
8251 public KeyEvent.DispatcherState getKeyDispatcherState() {
8252 return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
8256 * Dispatch a key event before it is processed by any input method
8257 * associated with the view hierarchy. This can be used to intercept
8258 * key events in special situations before the IME consumes them; a
8259 * typical example would be handling the BACK key to update the application's
8260 * UI instead of allowing the IME to see it and close itself.
8262 * @param event The key event to be dispatched.
8263 * @return True if the event was handled, false otherwise.
8265 public boolean dispatchKeyEventPreIme(KeyEvent event) {
8266 return onKeyPreIme(event.getKeyCode(), event);
8270 * Dispatch a key event to the next view on the focus path. This path runs
8271 * from the top of the view tree down to the currently focused view. If this
8272 * view has focus, it will dispatch to itself. Otherwise it will dispatch
8273 * the next node down the focus path. This method also fires any key
8276 * @param event The key event to be dispatched.
8277 * @return True if the event was handled, false otherwise.
8279 public boolean dispatchKeyEvent(KeyEvent event) {
8280 if (mInputEventConsistencyVerifier != null) {
8281 mInputEventConsistencyVerifier.onKeyEvent(event, 0);
8284 // Give any attached key listener a first crack at the event.
8285 //noinspection SimplifiableIfStatement
8286 ListenerInfo li = mListenerInfo;
8287 if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
8288 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
8292 if (event.dispatch(this, mAttachInfo != null
8293 ? mAttachInfo.mKeyDispatchState : null, this)) {
8297 if (mInputEventConsistencyVerifier != null) {
8298 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8304 * Dispatches a key shortcut event.
8306 * @param event The key event to be dispatched.
8307 * @return True if the event was handled by the view, false otherwise.
8309 public boolean dispatchKeyShortcutEvent(KeyEvent event) {
8310 return onKeyShortcut(event.getKeyCode(), event);
8314 * Pass the touch screen motion event down to the target view, or this
8315 * view if it is the target.
8317 * @param event The motion event to be dispatched.
8318 * @return True if the event was handled by the view, false otherwise.
8320 public boolean dispatchTouchEvent(MotionEvent event) {
8321 boolean result = false;
8323 if (mInputEventConsistencyVerifier != null) {
8324 mInputEventConsistencyVerifier.onTouchEvent(event, 0);
8327 final int actionMasked = event.getActionMasked();
8328 if (actionMasked == MotionEvent.ACTION_DOWN) {
8329 // Defensive cleanup for new gesture
8333 if (onFilterTouchEventForSecurity(event)) {
8334 //noinspection SimplifiableIfStatement
8335 ListenerInfo li = mListenerInfo;
8336 if (li != null && li.mOnTouchListener != null
8337 && (mViewFlags & ENABLED_MASK) == ENABLED
8338 && li.mOnTouchListener.onTouch(this, event)) {
8342 if (!result && onTouchEvent(event)) {
8347 if (!result && mInputEventConsistencyVerifier != null) {
8348 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8351 // Clean up after nested scrolls if this is the end of a gesture;
8352 // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
8354 if (actionMasked == MotionEvent.ACTION_UP ||
8355 actionMasked == MotionEvent.ACTION_CANCEL ||
8356 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
8364 * Filter the touch event to apply security policies.
8366 * @param event The motion event to be filtered.
8367 * @return True if the event should be dispatched, false if the event should be dropped.
8369 * @see #getFilterTouchesWhenObscured
8371 public boolean onFilterTouchEventForSecurity(MotionEvent event) {
8372 //noinspection RedundantIfStatement
8373 if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
8374 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
8375 // Window is obscured, drop this touch.
8382 * Pass a trackball motion event down to the focused view.
8384 * @param event The motion event to be dispatched.
8385 * @return True if the event was handled by the view, false otherwise.
8387 public boolean dispatchTrackballEvent(MotionEvent event) {
8388 if (mInputEventConsistencyVerifier != null) {
8389 mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
8392 return onTrackballEvent(event);
8396 * Dispatch a generic motion event.
8398 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
8399 * are delivered to the view under the pointer. All other generic motion events are
8400 * delivered to the focused view. Hover events are handled specially and are delivered
8401 * to {@link #onHoverEvent(MotionEvent)}.
8404 * @param event The motion event to be dispatched.
8405 * @return True if the event was handled by the view, false otherwise.
8407 public boolean dispatchGenericMotionEvent(MotionEvent event) {
8408 if (mInputEventConsistencyVerifier != null) {
8409 mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
8412 final int source = event.getSource();
8413 if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
8414 final int action = event.getAction();
8415 if (action == MotionEvent.ACTION_HOVER_ENTER
8416 || action == MotionEvent.ACTION_HOVER_MOVE
8417 || action == MotionEvent.ACTION_HOVER_EXIT) {
8418 if (dispatchHoverEvent(event)) {
8421 } else if (dispatchGenericPointerEvent(event)) {
8424 } else if (dispatchGenericFocusedEvent(event)) {
8428 if (dispatchGenericMotionEventInternal(event)) {
8432 if (mInputEventConsistencyVerifier != null) {
8433 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8438 private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
8439 //noinspection SimplifiableIfStatement
8440 ListenerInfo li = mListenerInfo;
8441 if (li != null && li.mOnGenericMotionListener != null
8442 && (mViewFlags & ENABLED_MASK) == ENABLED
8443 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
8447 if (onGenericMotionEvent(event)) {
8451 if (mInputEventConsistencyVerifier != null) {
8452 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8458 * Dispatch a hover event.
8460 * Do not call this method directly.
8461 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8464 * @param event The motion event to be dispatched.
8465 * @return True if the event was handled by the view, false otherwise.
8467 protected boolean dispatchHoverEvent(MotionEvent event) {
8468 ListenerInfo li = mListenerInfo;
8469 //noinspection SimplifiableIfStatement
8470 if (li != null && li.mOnHoverListener != null
8471 && (mViewFlags & ENABLED_MASK) == ENABLED
8472 && li.mOnHoverListener.onHover(this, event)) {
8476 return onHoverEvent(event);
8480 * Returns true if the view has a child to which it has recently sent
8481 * {@link MotionEvent#ACTION_HOVER_ENTER}. If this view is hovered and
8482 * it does not have a hovered child, then it must be the innermost hovered view.
8485 protected boolean hasHoveredChild() {
8490 * Dispatch a generic motion event to the view under the first pointer.
8492 * Do not call this method directly.
8493 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8496 * @param event The motion event to be dispatched.
8497 * @return True if the event was handled by the view, false otherwise.
8499 protected boolean dispatchGenericPointerEvent(MotionEvent event) {
8504 * Dispatch a generic motion event to the currently focused view.
8506 * Do not call this method directly.
8507 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8510 * @param event The motion event to be dispatched.
8511 * @return True if the event was handled by the view, false otherwise.
8513 protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
8518 * Dispatch a pointer event.
8520 * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
8521 * other events to {@link #onGenericMotionEvent(MotionEvent)}. This separation of concerns
8522 * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
8523 * and should not be expected to handle other pointing device features.
8526 * @param event The motion event to be dispatched.
8527 * @return True if the event was handled by the view, false otherwise.
8530 public final boolean dispatchPointerEvent(MotionEvent event) {
8531 if (event.isTouchEvent()) {
8532 return dispatchTouchEvent(event);
8534 return dispatchGenericMotionEvent(event);
8539 * Called when the window containing this view gains or loses window focus.
8540 * ViewGroups should override to route to their children.
8542 * @param hasFocus True if the window containing this view now has focus,
8545 public void dispatchWindowFocusChanged(boolean hasFocus) {
8546 onWindowFocusChanged(hasFocus);
8550 * Called when the window containing this view gains or loses focus. Note
8551 * that this is separate from view focus: to receive key events, both
8552 * your view and its window must have focus. If a window is displayed
8553 * on top of yours that takes input focus, then your own window will lose
8554 * focus but the view focus will remain unchanged.
8556 * @param hasWindowFocus True if the window containing this view now has
8557 * focus, false otherwise.
8559 public void onWindowFocusChanged(boolean hasWindowFocus) {
8560 InputMethodManager imm = InputMethodManager.peekInstance();
8561 if (!hasWindowFocus) {
8565 if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
8568 removeLongPressCallback();
8569 removeTapCallback();
8571 } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
8574 refreshDrawableState();
8578 * Returns true if this view is in a window that currently has window focus.
8579 * Note that this is not the same as the view itself having focus.
8581 * @return True if this view is in a window that currently has window focus.
8583 public boolean hasWindowFocus() {
8584 return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
8588 * Dispatch a view visibility change down the view hierarchy.
8589 * ViewGroups should override to route to their children.
8590 * @param changedView The view whose visibility changed. Could be 'this' or
8592 * @param visibility The new visibility of changedView: {@link #VISIBLE},
8593 * {@link #INVISIBLE} or {@link #GONE}.
8595 protected void dispatchVisibilityChanged(@NonNull View changedView,
8596 @Visibility int visibility) {
8597 onVisibilityChanged(changedView, visibility);
8601 * Called when the visibility of the view or an ancestor of the view is changed.
8602 * @param changedView The view whose visibility changed. Could be 'this' or
8604 * @param visibility The new visibility of changedView: {@link #VISIBLE},
8605 * {@link #INVISIBLE} or {@link #GONE}.
8607 protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
8608 if (visibility == VISIBLE) {
8609 if (mAttachInfo != null) {
8610 initialAwakenScrollBars();
8612 mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
8618 * Dispatch a hint about whether this view is displayed. For instance, when
8619 * a View moves out of the screen, it might receives a display hint indicating
8620 * the view is not displayed. Applications should not <em>rely</em> on this hint
8621 * as there is no guarantee that they will receive one.
8623 * @param hint A hint about whether or not this view is displayed:
8624 * {@link #VISIBLE} or {@link #INVISIBLE}.
8626 public void dispatchDisplayHint(@Visibility int hint) {
8627 onDisplayHint(hint);
8631 * Gives this view a hint about whether is displayed or not. For instance, when
8632 * a View moves out of the screen, it might receives a display hint indicating
8633 * the view is not displayed. Applications should not <em>rely</em> on this hint
8634 * as there is no guarantee that they will receive one.
8636 * @param hint A hint about whether or not this view is displayed:
8637 * {@link #VISIBLE} or {@link #INVISIBLE}.
8639 protected void onDisplayHint(@Visibility int hint) {
8643 * Dispatch a window visibility change down the view hierarchy.
8644 * ViewGroups should override to route to their children.
8646 * @param visibility The new visibility of the window.
8648 * @see #onWindowVisibilityChanged(int)
8650 public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
8651 onWindowVisibilityChanged(visibility);
8655 * Called when the window containing has change its visibility
8656 * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}). Note
8657 * that this tells you whether or not your window is being made visible
8658 * to the window manager; this does <em>not</em> tell you whether or not
8659 * your window is obscured by other windows on the screen, even if it
8660 * is itself visible.
8662 * @param visibility The new visibility of the window.
8664 protected void onWindowVisibilityChanged(@Visibility int visibility) {
8665 if (visibility == VISIBLE) {
8666 initialAwakenScrollBars();
8671 * Returns the current visibility of the window this view is attached to
8672 * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
8674 * @return Returns the current visibility of the view's window.
8677 public int getWindowVisibility() {
8678 return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
8682 * Retrieve the overall visible display size in which the window this view is
8683 * attached to has been positioned in. This takes into account screen
8684 * decorations above the window, for both cases where the window itself
8685 * is being position inside of them or the window is being placed under
8686 * then and covered insets are used for the window to position its content
8687 * inside. In effect, this tells you the available area where content can
8688 * be placed and remain visible to users.
8690 * <p>This function requires an IPC back to the window manager to retrieve
8691 * the requested information, so should not be used in performance critical
8692 * code like drawing.
8694 * @param outRect Filled in with the visible display frame. If the view
8695 * is not attached to a window, this is simply the raw display size.
8697 public void getWindowVisibleDisplayFrame(Rect outRect) {
8698 if (mAttachInfo != null) {
8700 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
8701 } catch (RemoteException e) {
8704 // XXX This is really broken, and probably all needs to be done
8705 // in the window manager, and we need to know more about whether
8706 // we want the area behind or in front of the IME.
8707 final Rect insets = mAttachInfo.mVisibleInsets;
8708 outRect.left += insets.left;
8709 outRect.top += insets.top;
8710 outRect.right -= insets.right;
8711 outRect.bottom -= insets.bottom;
8714 // The view is not attached to a display so we don't have a context.
8715 // Make a best guess about the display size.
8716 Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
8717 d.getRectSize(outRect);
8721 * Dispatch a notification about a resource configuration change down
8722 * the view hierarchy.
8723 * ViewGroups should override to route to their children.
8725 * @param newConfig The new resource configuration.
8727 * @see #onConfigurationChanged(android.content.res.Configuration)
8729 public void dispatchConfigurationChanged(Configuration newConfig) {
8730 onConfigurationChanged(newConfig);
8734 * Called when the current configuration of the resources being used
8735 * by the application have changed. You can use this to decide when
8736 * to reload resources that can changed based on orientation and other
8737 * configuration characterstics. You only need to use this if you are
8738 * not relying on the normal {@link android.app.Activity} mechanism of
8739 * recreating the activity instance upon a configuration change.
8741 * @param newConfig The new resource configuration.
8743 protected void onConfigurationChanged(Configuration newConfig) {
8747 * Private function to aggregate all per-view attributes in to the view
8750 void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
8751 performCollectViewAttributes(attachInfo, visibility);
8754 void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
8755 if ((visibility & VISIBILITY_MASK) == VISIBLE) {
8756 if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
8757 attachInfo.mKeepScreenOn = true;
8759 attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
8760 ListenerInfo li = mListenerInfo;
8761 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
8762 attachInfo.mHasSystemUiListeners = true;
8767 void needGlobalAttributesUpdate(boolean force) {
8768 final AttachInfo ai = mAttachInfo;
8769 if (ai != null && !ai.mRecomputeGlobalAttributes) {
8770 if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
8771 || ai.mHasSystemUiListeners) {
8772 ai.mRecomputeGlobalAttributes = true;
8778 * Returns whether the device is currently in touch mode. Touch mode is entered
8779 * once the user begins interacting with the device by touch, and affects various
8780 * things like whether focus is always visible to the user.
8782 * @return Whether the device is in touch mode.
8784 @ViewDebug.ExportedProperty
8785 public boolean isInTouchMode() {
8786 if (mAttachInfo != null) {
8787 return mAttachInfo.mInTouchMode;
8789 return ViewRootImpl.isInTouchMode();
8794 * Returns the context the view is running in, through which it can
8795 * access the current theme, resources, etc.
8797 * @return The view's Context.
8799 @ViewDebug.CapturedViewProperty
8800 public final Context getContext() {
8805 * Handle a key event before it is processed by any input method
8806 * associated with the view hierarchy. This can be used to intercept
8807 * key events in special situations before the IME consumes them; a
8808 * typical example would be handling the BACK key to update the application's
8809 * UI instead of allowing the IME to see it and close itself.
8811 * @param keyCode The value in event.getKeyCode().
8812 * @param event Description of the key event.
8813 * @return If you handled the event, return true. If you want to allow the
8814 * event to be handled by the next receiver, return false.
8816 public boolean onKeyPreIme(int keyCode, KeyEvent event) {
8821 * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
8822 * KeyEvent.Callback.onKeyDown()}: perform press of the view
8823 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
8824 * is released, if the view is enabled and clickable.
8826 * <p>Key presses in software keyboards will generally NOT trigger this listener,
8827 * although some may elect to do so in some situations. Do not rely on this to
8828 * catch software key presses.
8830 * @param keyCode A key code that represents the button pressed, from
8831 * {@link android.view.KeyEvent}.
8832 * @param event The KeyEvent object that defines the button action.
8834 public boolean onKeyDown(int keyCode, KeyEvent event) {
8835 boolean result = false;
8837 if (KeyEvent.isConfirmKey(keyCode)) {
8838 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8841 // Long clickable items don't necessarily have to be clickable
8842 if (((mViewFlags & CLICKABLE) == CLICKABLE ||
8843 (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
8844 (event.getRepeatCount() == 0)) {
8846 checkForLongClick(0);
8854 * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
8855 * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
8857 * <p>Key presses in software keyboards will generally NOT trigger this listener,
8858 * although some may elect to do so in some situations. Do not rely on this to
8859 * catch software key presses.
8861 public boolean onKeyLongPress(int keyCode, KeyEvent event) {
8866 * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
8867 * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
8868 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
8869 * {@link KeyEvent#KEYCODE_ENTER} is released.
8870 * <p>Key presses in software keyboards will generally NOT trigger this listener,
8871 * although some may elect to do so in some situations. Do not rely on this to
8872 * catch software key presses.
8874 * @param keyCode A key code that represents the button pressed, from
8875 * {@link android.view.KeyEvent}.
8876 * @param event The KeyEvent object that defines the button action.
8878 public boolean onKeyUp(int keyCode, KeyEvent event) {
8879 if (KeyEvent.isConfirmKey(keyCode)) {
8880 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8883 if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
8886 if (!mHasPerformedLongPress) {
8887 // This is a tap, so remove the longpress check
8888 removeLongPressCallback();
8889 return performClick();
8897 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
8898 * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
8900 * <p>Key presses in software keyboards will generally NOT trigger this listener,
8901 * although some may elect to do so in some situations. Do not rely on this to
8902 * catch software key presses.
8904 * @param keyCode A key code that represents the button pressed, from
8905 * {@link android.view.KeyEvent}.
8906 * @param repeatCount The number of times the action was made.
8907 * @param event The KeyEvent object that defines the button action.
8909 public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
8914 * Called on the focused view when a key shortcut event is not handled.
8915 * Override this method to implement local key shortcuts for the View.
8916 * Key shortcuts can also be implemented by setting the
8917 * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
8919 * @param keyCode The value in event.getKeyCode().
8920 * @param event Description of the key event.
8921 * @return If you handled the event, return true. If you want to allow the
8922 * event to be handled by the next receiver, return false.
8924 public boolean onKeyShortcut(int keyCode, KeyEvent event) {
8929 * Check whether the called view is a text editor, in which case it
8930 * would make sense to automatically display a soft input window for
8931 * it. Subclasses should override this if they implement
8932 * {@link #onCreateInputConnection(EditorInfo)} to return true if
8933 * a call on that method would return a non-null InputConnection, and
8934 * they are really a first-class editor that the user would normally
8935 * start typing on when the go into a window containing your view.
8937 * <p>The default implementation always returns false. This does
8938 * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
8939 * will not be called or the user can not otherwise perform edits on your
8940 * view; it is just a hint to the system that this is not the primary
8941 * purpose of this view.
8943 * @return Returns true if this view is a text editor, else false.
8945 public boolean onCheckIsTextEditor() {
8950 * Create a new InputConnection for an InputMethod to interact
8951 * with the view. The default implementation returns null, since it doesn't
8952 * support input methods. You can override this to implement such support.
8953 * This is only needed for views that take focus and text input.
8955 * <p>When implementing this, you probably also want to implement
8956 * {@link #onCheckIsTextEditor()} to indicate you will return a
8957 * non-null InputConnection.</p>
8959 * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
8960 * object correctly and in its entirety, so that the connected IME can rely
8961 * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
8962 * and {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
8963 * must be filled in with the correct cursor position for IMEs to work correctly
8964 * with your application.</p>
8966 * @param outAttrs Fill in with attribute information about the connection.
8968 public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
8973 * Called by the {@link android.view.inputmethod.InputMethodManager}
8974 * when a view who is not the current
8975 * input connection target is trying to make a call on the manager. The
8976 * default implementation returns false; you can override this to return
8977 * true for certain views if you are performing InputConnection proxying
8979 * @param view The View that is making the InputMethodManager call.
8980 * @return Return true to allow the call, false to reject.
8982 public boolean checkInputConnectionProxy(View view) {
8987 * Show the context menu for this view. It is not safe to hold on to the
8988 * menu after returning from this method.
8990 * You should normally not overload this method. Overload
8991 * {@link #onCreateContextMenu(ContextMenu)} or define an
8992 * {@link OnCreateContextMenuListener} to add items to the context menu.
8994 * @param menu The context menu to populate
8996 public void createContextMenu(ContextMenu menu) {
8997 ContextMenuInfo menuInfo = getContextMenuInfo();
8999 // Sets the current menu info so all items added to menu will have
9000 // my extra info set.
9001 ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
9003 onCreateContextMenu(menu);
9004 ListenerInfo li = mListenerInfo;
9005 if (li != null && li.mOnCreateContextMenuListener != null) {
9006 li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
9009 // Clear the extra information so subsequent items that aren't mine don't
9010 // have my extra info.
9011 ((MenuBuilder)menu).setCurrentMenuInfo(null);
9013 if (mParent != null) {
9014 mParent.createContextMenu(menu);
9019 * Views should implement this if they have extra information to associate
9020 * with the context menu. The return result is supplied as a parameter to
9021 * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
9024 * @return Extra information about the item for which the context menu
9025 * should be shown. This information will vary across different
9026 * subclasses of View.
9028 protected ContextMenuInfo getContextMenuInfo() {
9033 * Views should implement this if the view itself is going to add items to
9036 * @param menu the context menu to populate
9038 protected void onCreateContextMenu(ContextMenu menu) {
9042 * Implement this method to handle trackball motion events. The
9043 * <em>relative</em> movement of the trackball since the last event
9044 * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
9045 * {@link MotionEvent#getY MotionEvent.getY()}. These are normalized so
9046 * that a movement of 1 corresponds to the user pressing one DPAD key (so
9047 * they will often be fractional values, representing the more fine-grained
9048 * movement information available from a trackball).
9050 * @param event The motion event.
9051 * @return True if the event was handled, false otherwise.
9053 public boolean onTrackballEvent(MotionEvent event) {
9058 * Implement this method to handle generic motion events.
9060 * Generic motion events describe joystick movements, mouse hovers, track pad
9061 * touches, scroll wheel movements and other input events. The
9062 * {@link MotionEvent#getSource() source} of the motion event specifies
9063 * the class of input that was received. Implementations of this method
9064 * must examine the bits in the source before processing the event.
9065 * The following code example shows how this is done.
9067 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
9068 * are delivered to the view under the pointer. All other generic motion events are
9069 * delivered to the focused view.
9071 * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
9072 * if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
9073 * if (event.getAction() == MotionEvent.ACTION_MOVE) {
9074 * // process the joystick movement...
9078 * if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
9079 * switch (event.getAction()) {
9080 * case MotionEvent.ACTION_HOVER_MOVE:
9081 * // process the mouse hover movement...
9083 * case MotionEvent.ACTION_SCROLL:
9084 * // process the scroll wheel movement...
9088 * return super.onGenericMotionEvent(event);
9091 * @param event The generic motion event being processed.
9092 * @return True if the event was handled, false otherwise.
9094 public boolean onGenericMotionEvent(MotionEvent event) {
9099 * Implement this method to handle hover events.
9101 * This method is called whenever a pointer is hovering into, over, or out of the
9102 * bounds of a view and the view is not currently being touched.
9103 * Hover events are represented as pointer events with action
9104 * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
9105 * or {@link MotionEvent#ACTION_HOVER_EXIT}.
9108 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
9109 * when the pointer enters the bounds of the view.</li>
9110 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
9111 * when the pointer has already entered the bounds of the view and has moved.</li>
9112 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
9113 * when the pointer has exited the bounds of the view or when the pointer is
9114 * about to go down due to a button click, tap, or similar user action that
9115 * causes the view to be touched.</li>
9118 * The view should implement this method to return true to indicate that it is
9119 * handling the hover event, such as by changing its drawable state.
9121 * The default implementation calls {@link #setHovered} to update the hovered state
9122 * of the view when a hover enter or hover exit event is received, if the view
9123 * is enabled and is clickable. The default implementation also sends hover
9124 * accessibility events.
9127 * @param event The motion event that describes the hover.
9128 * @return True if the view handled the hover event.
9132 * @see #onHoverChanged
9134 public boolean onHoverEvent(MotionEvent event) {
9135 // The root view may receive hover (or touch) events that are outside the bounds of
9136 // the window. This code ensures that we only send accessibility events for
9137 // hovers that are actually within the bounds of the root view.
9138 final int action = event.getActionMasked();
9139 if (!mSendingHoverAccessibilityEvents) {
9140 if ((action == MotionEvent.ACTION_HOVER_ENTER
9141 || action == MotionEvent.ACTION_HOVER_MOVE)
9142 && !hasHoveredChild()
9143 && pointInView(event.getX(), event.getY())) {
9144 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
9145 mSendingHoverAccessibilityEvents = true;
9148 if (action == MotionEvent.ACTION_HOVER_EXIT
9149 || (action == MotionEvent.ACTION_MOVE
9150 && !pointInView(event.getX(), event.getY()))) {
9151 mSendingHoverAccessibilityEvents = false;
9152 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
9156 if (isHoverable()) {
9158 case MotionEvent.ACTION_HOVER_ENTER:
9161 case MotionEvent.ACTION_HOVER_EXIT:
9166 // Dispatch the event to onGenericMotionEvent before returning true.
9167 // This is to provide compatibility with existing applications that
9168 // handled HOVER_MOVE events in onGenericMotionEvent and that would
9169 // break because of the new default handling for hoverable views
9171 // Note that onGenericMotionEvent will be called by default when
9172 // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
9173 dispatchGenericMotionEventInternal(event);
9174 // The event was already handled by calling setHovered(), so always
9183 * Returns true if the view should handle {@link #onHoverEvent}
9184 * by calling {@link #setHovered} to change its hovered state.
9186 * @return True if the view is hoverable.
9188 private boolean isHoverable() {
9189 final int viewFlags = mViewFlags;
9190 if ((viewFlags & ENABLED_MASK) == DISABLED) {
9194 return (viewFlags & CLICKABLE) == CLICKABLE
9195 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
9199 * Returns true if the view is currently hovered.
9201 * @return True if the view is currently hovered.
9204 * @see #onHoverChanged
9206 @ViewDebug.ExportedProperty
9207 public boolean isHovered() {
9208 return (mPrivateFlags & PFLAG_HOVERED) != 0;
9212 * Sets whether the view is currently hovered.
9214 * Calling this method also changes the drawable state of the view. This
9215 * enables the view to react to hover by using different drawable resources
9216 * to change its appearance.
9218 * The {@link #onHoverChanged} method is called when the hovered state changes.
9221 * @param hovered True if the view is hovered.
9224 * @see #onHoverChanged
9226 public void setHovered(boolean hovered) {
9228 if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
9229 mPrivateFlags |= PFLAG_HOVERED;
9230 refreshDrawableState();
9231 onHoverChanged(true);
9234 if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
9235 mPrivateFlags &= ~PFLAG_HOVERED;
9236 refreshDrawableState();
9237 onHoverChanged(false);
9243 * Implement this method to handle hover state changes.
9245 * This method is called whenever the hover state changes as a result of a
9246 * call to {@link #setHovered}.
9249 * @param hovered The current hover state, as returned by {@link #isHovered}.
9254 public void onHoverChanged(boolean hovered) {
9258 * Implement this method to handle touch screen motion events.
9260 * If this method is used to detect click actions, it is recommended that
9261 * the actions be performed by implementing and calling
9262 * {@link #performClick()}. This will ensure consistent system behavior,
9265 * <li>obeying click sound preferences
9266 * <li>dispatching OnClickListener calls
9267 * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
9268 * accessibility features are enabled
9271 * @param event The motion event.
9272 * @return True if the event was handled, false otherwise.
9274 public boolean onTouchEvent(MotionEvent event) {
9275 final float x = event.getX();
9276 final float y = event.getY();
9277 final int viewFlags = mViewFlags;
9279 if ((viewFlags & ENABLED_MASK) == DISABLED) {
9280 if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
9283 // A disabled view that is clickable still consumes the touch
9284 // events, it just doesn't respond to them.
9285 return (((viewFlags & CLICKABLE) == CLICKABLE ||
9286 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
9289 if (mTouchDelegate != null) {
9290 if (mTouchDelegate.onTouchEvent(event)) {
9295 if (((viewFlags & CLICKABLE) == CLICKABLE ||
9296 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
9297 switch (event.getAction()) {
9298 case MotionEvent.ACTION_UP:
9299 boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
9300 if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
9301 // take focus if we don't have it already and we should in
9303 boolean focusTaken = false;
9304 if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
9305 focusTaken = requestFocus();
9309 // The button is being released before we actually
9310 // showed it as pressed. Make it show the pressed
9311 // state now (before scheduling the click) to ensure
9312 // the user sees it.
9313 setPressed(true, x, y);
9316 if (!mHasPerformedLongPress) {
9317 // This is a tap, so remove the longpress check
9318 removeLongPressCallback();
9320 // Only perform take click actions if we were in the pressed state
9322 // Use a Runnable and post this rather than calling
9323 // performClick directly. This lets other visual state
9324 // of the view update before click actions start.
9325 if (mPerformClick == null) {
9326 mPerformClick = new PerformClick();
9328 if (!post(mPerformClick)) {
9334 if (mUnsetPressedState == null) {
9335 mUnsetPressedState = new UnsetPressedState();
9339 postDelayed(mUnsetPressedState,
9340 ViewConfiguration.getPressedStateDuration());
9341 } else if (!post(mUnsetPressedState)) {
9342 // If the post failed, unpress right now
9343 mUnsetPressedState.run();
9346 removeTapCallback();
9350 case MotionEvent.ACTION_DOWN:
9351 mHasPerformedLongPress = false;
9353 if (performButtonActionOnTouchDown(event)) {
9357 // Walk up the hierarchy to determine if we're inside a scrolling container.
9358 boolean isInScrollingContainer = isInScrollingContainer();
9360 // For views inside a scrolling container, delay the pressed feedback for
9361 // a short period in case this is a scroll.
9362 if (isInScrollingContainer) {
9363 mPrivateFlags |= PFLAG_PREPRESSED;
9364 if (mPendingCheckForTap == null) {
9365 mPendingCheckForTap = new CheckForTap();
9367 mPendingCheckForTap.x = event.getX();
9368 mPendingCheckForTap.y = event.getY();
9369 postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
9371 // Not inside a scrolling container, so show the feedback right away
9372 setPressed(true, x, y);
9373 checkForLongClick(0);
9377 case MotionEvent.ACTION_CANCEL:
9379 removeTapCallback();
9380 removeLongPressCallback();
9383 case MotionEvent.ACTION_MOVE:
9384 drawableHotspotChanged(x, y);
9386 // Be lenient about moving outside of buttons
9387 if (!pointInView(x, y, mTouchSlop)) {
9389 removeTapCallback();
9390 if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
9391 // Remove any future long press/tap checks
9392 removeLongPressCallback();
9409 public boolean isInScrollingContainer() {
9410 ViewParent p = getParent();
9411 while (p != null && p instanceof ViewGroup) {
9412 if (((ViewGroup) p).shouldDelayChildPressedState()) {
9421 * Remove the longpress detection timer.
9423 private void removeLongPressCallback() {
9424 if (mPendingCheckForLongPress != null) {
9425 removeCallbacks(mPendingCheckForLongPress);
9430 * Remove the pending click action
9432 private void removePerformClickCallback() {
9433 if (mPerformClick != null) {
9434 removeCallbacks(mPerformClick);
9439 * Remove the prepress detection timer.
9441 private void removeUnsetPressCallback() {
9442 if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
9444 removeCallbacks(mUnsetPressedState);
9449 * Remove the tap detection timer.
9451 private void removeTapCallback() {
9452 if (mPendingCheckForTap != null) {
9453 mPrivateFlags &= ~PFLAG_PREPRESSED;
9454 removeCallbacks(mPendingCheckForTap);
9459 * Cancels a pending long press. Your subclass can use this if you
9460 * want the context menu to come up if the user presses and holds
9461 * at the same place, but you don't want it to come up if they press
9462 * and then move around enough to cause scrolling.
9464 public void cancelLongPress() {
9465 removeLongPressCallback();
9468 * The prepressed state handled by the tap callback is a display
9469 * construct, but the tap callback will post a long press callback
9470 * less its own timeout. Remove it here.
9472 removeTapCallback();
9476 * Remove the pending callback for sending a
9477 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
9479 private void removeSendViewScrolledAccessibilityEventCallback() {
9480 if (mSendViewScrolledAccessibilityEvent != null) {
9481 removeCallbacks(mSendViewScrolledAccessibilityEvent);
9482 mSendViewScrolledAccessibilityEvent.mIsPending = false;
9487 * Sets the TouchDelegate for this View.
9489 public void setTouchDelegate(TouchDelegate delegate) {
9490 mTouchDelegate = delegate;
9494 * Gets the TouchDelegate for this View.
9496 public TouchDelegate getTouchDelegate() {
9497 return mTouchDelegate;
9501 * Request unbuffered dispatch of the given stream of MotionEvents to this View.
9503 * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
9504 * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
9505 * available. This method should only be called for touch events.
9507 * <p class="note">This api is not intended for most applications. Buffered dispatch
9508 * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
9509 * streams will not improve your input latency. Side effects include: increased latency,
9510 * jittery scrolls and inability to take advantage of system resampling. Talk to your input
9511 * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
9514 public final void requestUnbufferedDispatch(MotionEvent event) {
9515 final int action = event.getAction();
9516 if (mAttachInfo == null
9517 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
9518 || !event.isTouchEvent()) {
9521 mAttachInfo.mUnbufferedDispatchRequested = true;
9525 * Set flags controlling behavior of this view.
9527 * @param flags Constant indicating the value which should be set
9528 * @param mask Constant indicating the bit range that should be changed
9530 void setFlags(int flags, int mask) {
9531 final boolean accessibilityEnabled =
9532 AccessibilityManager.getInstance(mContext).isEnabled();
9533 final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
9535 int old = mViewFlags;
9536 mViewFlags = (mViewFlags & ~mask) | (flags & mask);
9538 int changed = mViewFlags ^ old;
9542 int privateFlags = mPrivateFlags;
9544 /* Check if the FOCUSABLE bit has changed */
9545 if (((changed & FOCUSABLE_MASK) != 0) &&
9546 ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
9547 if (((old & FOCUSABLE_MASK) == FOCUSABLE)
9548 && ((privateFlags & PFLAG_FOCUSED) != 0)) {
9549 /* Give up focus if we are no longer focusable */
9551 } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
9552 && ((privateFlags & PFLAG_FOCUSED) == 0)) {
9554 * Tell the view system that we are now available to take focus
9555 * if no one else already has it.
9557 if (mParent != null) mParent.focusableViewAvailable(this);
9561 final int newVisibility = flags & VISIBILITY_MASK;
9562 if (newVisibility == VISIBLE) {
9563 if ((changed & VISIBILITY_MASK) != 0) {
9565 * If this view is becoming visible, invalidate it in case it changed while
9566 * it was not visible. Marking it drawn ensures that the invalidation will
9569 mPrivateFlags |= PFLAG_DRAWN;
9572 needGlobalAttributesUpdate(true);
9574 // a view becoming visible is worth notifying the parent
9575 // about in case nothing has focus. even if this specific view
9576 // isn't focusable, it may contain something that is, so let
9577 // the root view try to give this focus if nothing else does.
9578 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
9579 mParent.focusableViewAvailable(this);
9584 /* Check if the GONE bit has changed */
9585 if ((changed & GONE) != 0) {
9586 needGlobalAttributesUpdate(false);
9589 if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
9590 if (hasFocus()) clearFocus();
9591 clearAccessibilityFocus();
9592 destroyDrawingCache();
9593 if (mParent instanceof View) {
9594 // GONE views noop invalidation, so invalidate the parent
9595 ((View) mParent).invalidate(true);
9597 // Mark the view drawn to ensure that it gets invalidated properly the next
9598 // time it is visible and gets invalidated
9599 mPrivateFlags |= PFLAG_DRAWN;
9601 if (mAttachInfo != null) {
9602 mAttachInfo.mViewVisibilityChanged = true;
9606 /* Check if the VISIBLE bit has changed */
9607 if ((changed & INVISIBLE) != 0) {
9608 needGlobalAttributesUpdate(false);
9610 * If this view is becoming invisible, set the DRAWN flag so that
9611 * the next invalidate() will not be skipped.
9613 mPrivateFlags |= PFLAG_DRAWN;
9615 if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
9616 // root view becoming invisible shouldn't clear focus and accessibility focus
9617 if (getRootView() != this) {
9618 if (hasFocus()) clearFocus();
9619 clearAccessibilityFocus();
9622 if (mAttachInfo != null) {
9623 mAttachInfo.mViewVisibilityChanged = true;
9627 if ((changed & VISIBILITY_MASK) != 0) {
9628 // If the view is invisible, cleanup its display list to free up resources
9629 if (newVisibility != VISIBLE && mAttachInfo != null) {
9633 if (mParent instanceof ViewGroup) {
9634 ((ViewGroup) mParent).onChildVisibilityChanged(this,
9635 (changed & VISIBILITY_MASK), newVisibility);
9636 ((View) mParent).invalidate(true);
9637 } else if (mParent != null) {
9638 mParent.invalidateChild(this, null);
9640 dispatchVisibilityChanged(this, newVisibility);
9642 notifySubtreeAccessibilityStateChangedIfNeeded();
9645 if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
9646 destroyDrawingCache();
9649 if ((changed & DRAWING_CACHE_ENABLED) != 0) {
9650 destroyDrawingCache();
9651 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
9652 invalidateParentCaches();
9655 if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
9656 destroyDrawingCache();
9657 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
9660 if ((changed & DRAW_MASK) != 0) {
9661 if ((mViewFlags & WILL_NOT_DRAW) != 0) {
9662 if (mBackground != null) {
9663 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
9664 mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
9666 mPrivateFlags |= PFLAG_SKIP_DRAW;
9669 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
9675 if ((changed & KEEP_SCREEN_ON) != 0) {
9676 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
9677 mParent.recomputeViewAttributes(this);
9681 if (accessibilityEnabled) {
9682 if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
9683 || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0) {
9684 if (oldIncludeForAccessibility != includeForAccessibility()) {
9685 notifySubtreeAccessibilityStateChangedIfNeeded();
9687 notifyViewAccessibilityStateChangedIfNeeded(
9688 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9690 } else if ((changed & ENABLED_MASK) != 0) {
9691 notifyViewAccessibilityStateChangedIfNeeded(
9692 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9698 * Change the view's z order in the tree, so it's on top of other sibling
9699 * views. This ordering change may affect layout, if the parent container
9700 * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
9701 * to {@link android.os.Build.VERSION_CODES#KITKAT} this
9702 * method should be followed by calls to {@link #requestLayout()} and
9703 * {@link View#invalidate()} on the view's parent to force the parent to redraw
9704 * with the new child ordering.
9706 * @see ViewGroup#bringChildToFront(View)
9708 public void bringToFront() {
9709 if (mParent != null) {
9710 mParent.bringChildToFront(this);
9715 * This is called in response to an internal scroll in this view (i.e., the
9716 * view scrolled its own contents). This is typically as a result of
9717 * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
9720 * @param l Current horizontal scroll origin.
9721 * @param t Current vertical scroll origin.
9722 * @param oldl Previous horizontal scroll origin.
9723 * @param oldt Previous vertical scroll origin.
9725 protected void onScrollChanged(int l, int t, int oldl, int oldt) {
9726 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
9727 postSendViewScrolledAccessibilityEventCallback();
9730 mBackgroundSizeChanged = true;
9732 final AttachInfo ai = mAttachInfo;
9734 ai.mViewScrollChanged = true;
9739 * Interface definition for a callback to be invoked when the layout bounds of a view
9740 * changes due to layout processing.
9742 public interface OnLayoutChangeListener {
9744 * Called when the layout bounds of a view changes due to layout processing.
9746 * @param v The view whose bounds have changed.
9747 * @param left The new value of the view's left property.
9748 * @param top The new value of the view's top property.
9749 * @param right The new value of the view's right property.
9750 * @param bottom The new value of the view's bottom property.
9751 * @param oldLeft The previous value of the view's left property.
9752 * @param oldTop The previous value of the view's top property.
9753 * @param oldRight The previous value of the view's right property.
9754 * @param oldBottom The previous value of the view's bottom property.
9756 void onLayoutChange(View v, int left, int top, int right, int bottom,
9757 int oldLeft, int oldTop, int oldRight, int oldBottom);
9761 * This is called during layout when the size of this view has changed. If
9762 * you were just added to the view hierarchy, you're called with the old
9765 * @param w Current width of this view.
9766 * @param h Current height of this view.
9767 * @param oldw Old width of this view.
9768 * @param oldh Old height of this view.
9770 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
9774 * Called by draw to draw the child views. This may be overridden
9775 * by derived classes to gain control just before its children are drawn
9776 * (but after its own view has been drawn).
9777 * @param canvas the canvas on which to draw the view
9779 protected void dispatchDraw(Canvas canvas) {
9784 * Gets the parent of this view. Note that the parent is a
9785 * ViewParent and not necessarily a View.
9787 * @return Parent of this view.
9789 public final ViewParent getParent() {
9794 * Set the horizontal scrolled position of your view. This will cause a call to
9795 * {@link #onScrollChanged(int, int, int, int)} and the view will be
9797 * @param value the x position to scroll to
9799 public void setScrollX(int value) {
9800 scrollTo(value, mScrollY);
9804 * Set the vertical scrolled position of your view. This will cause a call to
9805 * {@link #onScrollChanged(int, int, int, int)} and the view will be
9807 * @param value the y position to scroll to
9809 public void setScrollY(int value) {
9810 scrollTo(mScrollX, value);
9814 * Return the scrolled left position of this view. This is the left edge of
9815 * the displayed part of your view. You do not need to draw any pixels
9816 * farther left, since those are outside of the frame of your view on
9819 * @return The left edge of the displayed part of your view, in pixels.
9821 public final int getScrollX() {
9826 * Return the scrolled top position of this view. This is the top edge of
9827 * the displayed part of your view. You do not need to draw any pixels above
9828 * it, since those are outside of the frame of your view on screen.
9830 * @return The top edge of the displayed part of your view, in pixels.
9832 public final int getScrollY() {
9837 * Return the width of the your view.
9839 * @return The width of your view, in pixels.
9841 @ViewDebug.ExportedProperty(category = "layout")
9842 public final int getWidth() {
9843 return mRight - mLeft;
9847 * Return the height of your view.
9849 * @return The height of your view, in pixels.
9851 @ViewDebug.ExportedProperty(category = "layout")
9852 public final int getHeight() {
9853 return mBottom - mTop;
9857 * Return the visible drawing bounds of your view. Fills in the output
9858 * rectangle with the values from getScrollX(), getScrollY(),
9859 * getWidth(), and getHeight(). These bounds do not account for any
9860 * transformation properties currently set on the view, such as
9861 * {@link #setScaleX(float)} or {@link #setRotation(float)}.
9863 * @param outRect The (scrolled) drawing bounds of the view.
9865 public void getDrawingRect(Rect outRect) {
9866 outRect.left = mScrollX;
9867 outRect.top = mScrollY;
9868 outRect.right = mScrollX + (mRight - mLeft);
9869 outRect.bottom = mScrollY + (mBottom - mTop);
9873 * Like {@link #getMeasuredWidthAndState()}, but only returns the
9874 * raw width component (that is the result is masked by
9875 * {@link #MEASURED_SIZE_MASK}).
9877 * @return The raw measured width of this view.
9879 public final int getMeasuredWidth() {
9880 return mMeasuredWidth & MEASURED_SIZE_MASK;
9884 * Return the full width measurement information for this view as computed
9885 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask
9886 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
9887 * This should be used during measurement and layout calculations only. Use
9888 * {@link #getWidth()} to see how wide a view is after layout.
9890 * @return The measured width of this view as a bit mask.
9892 public final int getMeasuredWidthAndState() {
9893 return mMeasuredWidth;
9897 * Like {@link #getMeasuredHeightAndState()}, but only returns the
9898 * raw width component (that is the result is masked by
9899 * {@link #MEASURED_SIZE_MASK}).
9901 * @return The raw measured height of this view.
9903 public final int getMeasuredHeight() {
9904 return mMeasuredHeight & MEASURED_SIZE_MASK;
9908 * Return the full height measurement information for this view as computed
9909 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask
9910 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
9911 * This should be used during measurement and layout calculations only. Use
9912 * {@link #getHeight()} to see how wide a view is after layout.
9914 * @return The measured width of this view as a bit mask.
9916 public final int getMeasuredHeightAndState() {
9917 return mMeasuredHeight;
9921 * Return only the state bits of {@link #getMeasuredWidthAndState()}
9922 * and {@link #getMeasuredHeightAndState()}, combined into one integer.
9923 * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
9924 * and the height component is at the shifted bits
9925 * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
9927 public final int getMeasuredState() {
9928 return (mMeasuredWidth&MEASURED_STATE_MASK)
9929 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
9930 & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
9934 * The transform matrix of this view, which is calculated based on the current
9935 * rotation, scale, and pivot properties.
9937 * @see #getRotation()
9942 * @return The current transform matrix for the view
9944 public Matrix getMatrix() {
9945 ensureTransformationInfo();
9946 final Matrix matrix = mTransformationInfo.mMatrix;
9947 mRenderNode.getMatrix(matrix);
9952 * Returns true if the transform matrix is the identity matrix.
9953 * Recomputes the matrix if necessary.
9955 * @return True if the transform matrix is the identity matrix, false otherwise.
9957 final boolean hasIdentityMatrix() {
9958 return mRenderNode.hasIdentityMatrix();
9961 void ensureTransformationInfo() {
9962 if (mTransformationInfo == null) {
9963 mTransformationInfo = new TransformationInfo();
9968 * Utility method to retrieve the inverse of the current mMatrix property.
9969 * We cache the matrix to avoid recalculating it when transform properties
9972 * @return The inverse of the current matrix of this view.
9975 public final Matrix getInverseMatrix() {
9976 ensureTransformationInfo();
9977 if (mTransformationInfo.mInverseMatrix == null) {
9978 mTransformationInfo.mInverseMatrix = new Matrix();
9980 final Matrix matrix = mTransformationInfo.mInverseMatrix;
9981 mRenderNode.getInverseMatrix(matrix);
9986 * Gets the distance along the Z axis from the camera to this view.
9988 * @see #setCameraDistance(float)
9990 * @return The distance along the Z axis.
9992 public float getCameraDistance() {
9993 final float dpi = mResources.getDisplayMetrics().densityDpi;
9994 return -(mRenderNode.getCameraDistance() * dpi);
9998 * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
9999 * views are drawn) from the camera to this view. The camera's distance
10000 * affects 3D transformations, for instance rotations around the X and Y
10001 * axis. If the rotationX or rotationY properties are changed and this view is
10002 * large (more than half the size of the screen), it is recommended to always
10003 * use a camera distance that's greater than the height (X axis rotation) or
10004 * the width (Y axis rotation) of this view.</p>
10006 * <p>The distance of the camera from the view plane can have an affect on the
10007 * perspective distortion of the view when it is rotated around the x or y axis.
10008 * For example, a large distance will result in a large viewing angle, and there
10009 * will not be much perspective distortion of the view as it rotates. A short
10010 * distance may cause much more perspective distortion upon rotation, and can
10011 * also result in some drawing artifacts if the rotated view ends up partially
10012 * behind the camera (which is why the recommendation is to use a distance at
10013 * least as far as the size of the view, if the view is to be rotated.)</p>
10015 * <p>The distance is expressed in "depth pixels." The default distance depends
10016 * on the screen density. For instance, on a medium density display, the
10017 * default distance is 1280. On a high density display, the default distance
10020 * <p>If you want to specify a distance that leads to visually consistent
10021 * results across various densities, use the following formula:</p>
10023 * float scale = context.getResources().getDisplayMetrics().density;
10024 * view.setCameraDistance(distance * scale);
10027 * <p>The density scale factor of a high density display is 1.5,
10028 * and 1920 = 1280 * 1.5.</p>
10030 * @param distance The distance in "depth pixels", if negative the opposite
10033 * @see #setRotationX(float)
10034 * @see #setRotationY(float)
10036 public void setCameraDistance(float distance) {
10037 final float dpi = mResources.getDisplayMetrics().densityDpi;
10039 invalidateViewProperty(true, false);
10040 mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
10041 invalidateViewProperty(false, false);
10043 invalidateParentIfNeededAndWasQuickRejected();
10047 * The degrees that the view is rotated around the pivot point.
10049 * @see #setRotation(float)
10050 * @see #getPivotX()
10051 * @see #getPivotY()
10053 * @return The degrees of rotation.
10055 @ViewDebug.ExportedProperty(category = "drawing")
10056 public float getRotation() {
10057 return mRenderNode.getRotation();
10061 * Sets the degrees that the view is rotated around the pivot point. Increasing values
10062 * result in clockwise rotation.
10064 * @param rotation The degrees of rotation.
10066 * @see #getRotation()
10067 * @see #getPivotX()
10068 * @see #getPivotY()
10069 * @see #setRotationX(float)
10070 * @see #setRotationY(float)
10072 * @attr ref android.R.styleable#View_rotation
10074 public void setRotation(float rotation) {
10075 if (rotation != getRotation()) {
10076 // Double-invalidation is necessary to capture view's old and new areas
10077 invalidateViewProperty(true, false);
10078 mRenderNode.setRotation(rotation);
10079 invalidateViewProperty(false, true);
10081 invalidateParentIfNeededAndWasQuickRejected();
10082 notifySubtreeAccessibilityStateChangedIfNeeded();
10087 * The degrees that the view is rotated around the vertical axis through the pivot point.
10089 * @see #getPivotX()
10090 * @see #getPivotY()
10091 * @see #setRotationY(float)
10093 * @return The degrees of Y rotation.
10095 @ViewDebug.ExportedProperty(category = "drawing")
10096 public float getRotationY() {
10097 return mRenderNode.getRotationY();
10101 * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
10102 * Increasing values result in counter-clockwise rotation from the viewpoint of looking
10105 * When rotating large views, it is recommended to adjust the camera distance
10106 * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
10108 * @param rotationY The degrees of Y rotation.
10110 * @see #getRotationY()
10111 * @see #getPivotX()
10112 * @see #getPivotY()
10113 * @see #setRotation(float)
10114 * @see #setRotationX(float)
10115 * @see #setCameraDistance(float)
10117 * @attr ref android.R.styleable#View_rotationY
10119 public void setRotationY(float rotationY) {
10120 if (rotationY != getRotationY()) {
10121 invalidateViewProperty(true, false);
10122 mRenderNode.setRotationY(rotationY);
10123 invalidateViewProperty(false, true);
10125 invalidateParentIfNeededAndWasQuickRejected();
10126 notifySubtreeAccessibilityStateChangedIfNeeded();
10131 * The degrees that the view is rotated around the horizontal axis through the pivot point.
10133 * @see #getPivotX()
10134 * @see #getPivotY()
10135 * @see #setRotationX(float)
10137 * @return The degrees of X rotation.
10139 @ViewDebug.ExportedProperty(category = "drawing")
10140 public float getRotationX() {
10141 return mRenderNode.getRotationX();
10145 * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
10146 * Increasing values result in clockwise rotation from the viewpoint of looking down the
10149 * When rotating large views, it is recommended to adjust the camera distance
10150 * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
10152 * @param rotationX The degrees of X rotation.
10154 * @see #getRotationX()
10155 * @see #getPivotX()
10156 * @see #getPivotY()
10157 * @see #setRotation(float)
10158 * @see #setRotationY(float)
10159 * @see #setCameraDistance(float)
10161 * @attr ref android.R.styleable#View_rotationX
10163 public void setRotationX(float rotationX) {
10164 if (rotationX != getRotationX()) {
10165 invalidateViewProperty(true, false);
10166 mRenderNode.setRotationX(rotationX);
10167 invalidateViewProperty(false, true);
10169 invalidateParentIfNeededAndWasQuickRejected();
10170 notifySubtreeAccessibilityStateChangedIfNeeded();
10175 * The amount that the view is scaled in x around the pivot point, as a proportion of
10176 * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
10178 * <p>By default, this is 1.0f.
10180 * @see #getPivotX()
10181 * @see #getPivotY()
10182 * @return The scaling factor.
10184 @ViewDebug.ExportedProperty(category = "drawing")
10185 public float getScaleX() {
10186 return mRenderNode.getScaleX();
10190 * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
10191 * the view's unscaled width. A value of 1 means that no scaling is applied.
10193 * @param scaleX The scaling factor.
10194 * @see #getPivotX()
10195 * @see #getPivotY()
10197 * @attr ref android.R.styleable#View_scaleX
10199 public void setScaleX(float scaleX) {
10200 if (scaleX != getScaleX()) {
10201 invalidateViewProperty(true, false);
10202 mRenderNode.setScaleX(scaleX);
10203 invalidateViewProperty(false, true);
10205 invalidateParentIfNeededAndWasQuickRejected();
10206 notifySubtreeAccessibilityStateChangedIfNeeded();
10211 * The amount that the view is scaled in y around the pivot point, as a proportion of
10212 * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
10214 * <p>By default, this is 1.0f.
10216 * @see #getPivotX()
10217 * @see #getPivotY()
10218 * @return The scaling factor.
10220 @ViewDebug.ExportedProperty(category = "drawing")
10221 public float getScaleY() {
10222 return mRenderNode.getScaleY();
10226 * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
10227 * the view's unscaled width. A value of 1 means that no scaling is applied.
10229 * @param scaleY The scaling factor.
10230 * @see #getPivotX()
10231 * @see #getPivotY()
10233 * @attr ref android.R.styleable#View_scaleY
10235 public void setScaleY(float scaleY) {
10236 if (scaleY != getScaleY()) {
10237 invalidateViewProperty(true, false);
10238 mRenderNode.setScaleY(scaleY);
10239 invalidateViewProperty(false, true);
10241 invalidateParentIfNeededAndWasQuickRejected();
10242 notifySubtreeAccessibilityStateChangedIfNeeded();
10247 * The x location of the point around which the view is {@link #setRotation(float) rotated}
10248 * and {@link #setScaleX(float) scaled}.
10250 * @see #getRotation()
10251 * @see #getScaleX()
10252 * @see #getScaleY()
10253 * @see #getPivotY()
10254 * @return The x location of the pivot point.
10256 * @attr ref android.R.styleable#View_transformPivotX
10258 @ViewDebug.ExportedProperty(category = "drawing")
10259 public float getPivotX() {
10260 return mRenderNode.getPivotX();
10264 * Sets the x location of the point around which the view is
10265 * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
10266 * By default, the pivot point is centered on the object.
10267 * Setting this property disables this behavior and causes the view to use only the
10268 * explicitly set pivotX and pivotY values.
10270 * @param pivotX The x location of the pivot point.
10271 * @see #getRotation()
10272 * @see #getScaleX()
10273 * @see #getScaleY()
10274 * @see #getPivotY()
10276 * @attr ref android.R.styleable#View_transformPivotX
10278 public void setPivotX(float pivotX) {
10279 if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
10280 invalidateViewProperty(true, false);
10281 mRenderNode.setPivotX(pivotX);
10282 invalidateViewProperty(false, true);
10284 invalidateParentIfNeededAndWasQuickRejected();
10289 * The y location of the point around which the view is {@link #setRotation(float) rotated}
10290 * and {@link #setScaleY(float) scaled}.
10292 * @see #getRotation()
10293 * @see #getScaleX()
10294 * @see #getScaleY()
10295 * @see #getPivotY()
10296 * @return The y location of the pivot point.
10298 * @attr ref android.R.styleable#View_transformPivotY
10300 @ViewDebug.ExportedProperty(category = "drawing")
10301 public float getPivotY() {
10302 return mRenderNode.getPivotY();
10306 * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
10307 * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
10308 * Setting this property disables this behavior and causes the view to use only the
10309 * explicitly set pivotX and pivotY values.
10311 * @param pivotY The y location of the pivot point.
10312 * @see #getRotation()
10313 * @see #getScaleX()
10314 * @see #getScaleY()
10315 * @see #getPivotY()
10317 * @attr ref android.R.styleable#View_transformPivotY
10319 public void setPivotY(float pivotY) {
10320 if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
10321 invalidateViewProperty(true, false);
10322 mRenderNode.setPivotY(pivotY);
10323 invalidateViewProperty(false, true);
10325 invalidateParentIfNeededAndWasQuickRejected();
10330 * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
10331 * completely transparent and 1 means the view is completely opaque.
10333 * <p>By default this is 1.0f.
10334 * @return The opacity of the view.
10336 @ViewDebug.ExportedProperty(category = "drawing")
10337 public float getAlpha() {
10338 return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
10342 * Returns whether this View has content which overlaps.
10344 * <p>This function, intended to be overridden by specific View types, is an optimization when
10345 * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
10346 * an offscreen buffer and then composited into place, which can be expensive. If the view has
10347 * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
10348 * directly. An example of overlapping rendering is a TextView with a background image, such as
10349 * a Button. An example of non-overlapping rendering is a TextView with no background, or an
10350 * ImageView with only the foreground image. The default implementation returns true; subclasses
10351 * should override if they have cases which can be optimized.</p>
10353 * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
10354 * necessitates that a View return true if it uses the methods internally without passing the
10355 * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
10357 * @return true if the content in this view might overlap, false otherwise.
10359 @ViewDebug.ExportedProperty(category = "drawing")
10360 public boolean hasOverlappingRendering() {
10365 * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
10366 * completely transparent and 1 means the view is completely opaque.</p>
10368 * <p> Note that setting alpha to a translucent value (0 < alpha < 1) can have significant
10369 * performance implications, especially for large views. It is best to use the alpha property
10370 * sparingly and transiently, as in the case of fading animations.</p>
10372 * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
10373 * strongly recommended for performance reasons to either override
10374 * {@link #hasOverlappingRendering()} to return false if appropriate, or setting a
10375 * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view.</p>
10377 * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
10378 * responsible for applying the opacity itself.</p>
10380 * <p>Note that if the view is backed by a
10381 * {@link #setLayerType(int, android.graphics.Paint) layer} and is associated with a
10382 * {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an alpha value less than
10383 * 1.0 will supercede the alpha of the layer paint.</p>
10385 * @param alpha The opacity of the view.
10387 * @see #hasOverlappingRendering()
10388 * @see #setLayerType(int, android.graphics.Paint)
10390 * @attr ref android.R.styleable#View_alpha
10392 public void setAlpha(float alpha) {
10393 ensureTransformationInfo();
10394 if (mTransformationInfo.mAlpha != alpha) {
10395 mTransformationInfo.mAlpha = alpha;
10396 if (onSetAlpha((int) (alpha * 255))) {
10397 mPrivateFlags |= PFLAG_ALPHA_SET;
10398 // subclass is handling alpha - don't optimize rendering cache invalidation
10399 invalidateParentCaches();
10402 mPrivateFlags &= ~PFLAG_ALPHA_SET;
10403 invalidateViewProperty(true, false);
10404 mRenderNode.setAlpha(getFinalAlpha());
10405 notifyViewAccessibilityStateChangedIfNeeded(
10406 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10412 * Faster version of setAlpha() which performs the same steps except there are
10413 * no calls to invalidate(). The caller of this function should perform proper invalidation
10414 * on the parent and this object. The return value indicates whether the subclass handles
10415 * alpha (the return value for onSetAlpha()).
10417 * @param alpha The new value for the alpha property
10418 * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
10419 * the new value for the alpha property is different from the old value
10421 boolean setAlphaNoInvalidation(float alpha) {
10422 ensureTransformationInfo();
10423 if (mTransformationInfo.mAlpha != alpha) {
10424 mTransformationInfo.mAlpha = alpha;
10425 boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
10426 if (subclassHandlesAlpha) {
10427 mPrivateFlags |= PFLAG_ALPHA_SET;
10430 mPrivateFlags &= ~PFLAG_ALPHA_SET;
10431 mRenderNode.setAlpha(getFinalAlpha());
10438 * This property is hidden and intended only for use by the Fade transition, which
10439 * animates it to produce a visual translucency that does not side-effect (or get
10440 * affected by) the real alpha property. This value is composited with the other
10441 * alpha value (and the AlphaAnimation value, when that is present) to produce
10442 * a final visual translucency result, which is what is passed into the DisplayList.
10446 public void setTransitionAlpha(float alpha) {
10447 ensureTransformationInfo();
10448 if (mTransformationInfo.mTransitionAlpha != alpha) {
10449 mTransformationInfo.mTransitionAlpha = alpha;
10450 mPrivateFlags &= ~PFLAG_ALPHA_SET;
10451 invalidateViewProperty(true, false);
10452 mRenderNode.setAlpha(getFinalAlpha());
10457 * Calculates the visual alpha of this view, which is a combination of the actual
10458 * alpha value and the transitionAlpha value (if set).
10460 private float getFinalAlpha() {
10461 if (mTransformationInfo != null) {
10462 return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
10468 * This property is hidden and intended only for use by the Fade transition, which
10469 * animates it to produce a visual translucency that does not side-effect (or get
10470 * affected by) the real alpha property. This value is composited with the other
10471 * alpha value (and the AlphaAnimation value, when that is present) to produce
10472 * a final visual translucency result, which is what is passed into the DisplayList.
10476 @ViewDebug.ExportedProperty(category = "drawing")
10477 public float getTransitionAlpha() {
10478 return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
10482 * Top position of this view relative to its parent.
10484 * @return The top of this view, in pixels.
10486 @ViewDebug.CapturedViewProperty
10487 public final int getTop() {
10492 * Sets the top position of this view relative to its parent. This method is meant to be called
10493 * by the layout system and should not generally be called otherwise, because the property
10494 * may be changed at any time by the layout.
10496 * @param top The top of this view, in pixels.
10498 public final void setTop(int top) {
10500 final boolean matrixIsIdentity = hasIdentityMatrix();
10501 if (matrixIsIdentity) {
10502 if (mAttachInfo != null) {
10512 invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
10515 // Double-invalidation is necessary to capture view's old and new areas
10519 int width = mRight - mLeft;
10520 int oldHeight = mBottom - mTop;
10523 mRenderNode.setTop(mTop);
10525 sizeChange(width, mBottom - mTop, width, oldHeight);
10527 if (!matrixIsIdentity) {
10528 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10531 mBackgroundSizeChanged = true;
10532 invalidateParentIfNeeded();
10533 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10534 // View was rejected last time it was drawn by its parent; this may have changed
10535 invalidateParentIfNeeded();
10541 * Bottom position of this view relative to its parent.
10543 * @return The bottom of this view, in pixels.
10545 @ViewDebug.CapturedViewProperty
10546 public final int getBottom() {
10551 * True if this view has changed since the last time being drawn.
10553 * @return The dirty state of this view.
10555 public boolean isDirty() {
10556 return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
10560 * Sets the bottom position of this view relative to its parent. This method is meant to be
10561 * called by the layout system and should not generally be called otherwise, because the
10562 * property may be changed at any time by the layout.
10564 * @param bottom The bottom of this view, in pixels.
10566 public final void setBottom(int bottom) {
10567 if (bottom != mBottom) {
10568 final boolean matrixIsIdentity = hasIdentityMatrix();
10569 if (matrixIsIdentity) {
10570 if (mAttachInfo != null) {
10572 if (bottom < mBottom) {
10573 maxBottom = mBottom;
10575 maxBottom = bottom;
10577 invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
10580 // Double-invalidation is necessary to capture view's old and new areas
10584 int width = mRight - mLeft;
10585 int oldHeight = mBottom - mTop;
10588 mRenderNode.setBottom(mBottom);
10590 sizeChange(width, mBottom - mTop, width, oldHeight);
10592 if (!matrixIsIdentity) {
10593 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10596 mBackgroundSizeChanged = true;
10597 invalidateParentIfNeeded();
10598 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10599 // View was rejected last time it was drawn by its parent; this may have changed
10600 invalidateParentIfNeeded();
10606 * Left position of this view relative to its parent.
10608 * @return The left edge of this view, in pixels.
10610 @ViewDebug.CapturedViewProperty
10611 public final int getLeft() {
10616 * Sets the left position of this view relative to its parent. This method is meant to be called
10617 * by the layout system and should not generally be called otherwise, because the property
10618 * may be changed at any time by the layout.
10620 * @param left The left of this view, in pixels.
10622 public final void setLeft(int left) {
10623 if (left != mLeft) {
10624 final boolean matrixIsIdentity = hasIdentityMatrix();
10625 if (matrixIsIdentity) {
10626 if (mAttachInfo != null) {
10629 if (left < mLeft) {
10631 xLoc = left - mLeft;
10636 invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
10639 // Double-invalidation is necessary to capture view's old and new areas
10643 int oldWidth = mRight - mLeft;
10644 int height = mBottom - mTop;
10647 mRenderNode.setLeft(left);
10649 sizeChange(mRight - mLeft, height, oldWidth, height);
10651 if (!matrixIsIdentity) {
10652 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10655 mBackgroundSizeChanged = true;
10656 invalidateParentIfNeeded();
10657 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10658 // View was rejected last time it was drawn by its parent; this may have changed
10659 invalidateParentIfNeeded();
10665 * Right position of this view relative to its parent.
10667 * @return The right edge of this view, in pixels.
10669 @ViewDebug.CapturedViewProperty
10670 public final int getRight() {
10675 * Sets the right position of this view relative to its parent. This method is meant to be called
10676 * by the layout system and should not generally be called otherwise, because the property
10677 * may be changed at any time by the layout.
10679 * @param right The right of this view, in pixels.
10681 public final void setRight(int right) {
10682 if (right != mRight) {
10683 final boolean matrixIsIdentity = hasIdentityMatrix();
10684 if (matrixIsIdentity) {
10685 if (mAttachInfo != null) {
10687 if (right < mRight) {
10692 invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
10695 // Double-invalidation is necessary to capture view's old and new areas
10699 int oldWidth = mRight - mLeft;
10700 int height = mBottom - mTop;
10703 mRenderNode.setRight(mRight);
10705 sizeChange(mRight - mLeft, height, oldWidth, height);
10707 if (!matrixIsIdentity) {
10708 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10711 mBackgroundSizeChanged = true;
10712 invalidateParentIfNeeded();
10713 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10714 // View was rejected last time it was drawn by its parent; this may have changed
10715 invalidateParentIfNeeded();
10721 * The visual x position of this view, in pixels. This is equivalent to the
10722 * {@link #setTranslationX(float) translationX} property plus the current
10723 * {@link #getLeft() left} property.
10725 * @return The visual x position of this view, in pixels.
10727 @ViewDebug.ExportedProperty(category = "drawing")
10728 public float getX() {
10729 return mLeft + getTranslationX();
10733 * Sets the visual x position of this view, in pixels. This is equivalent to setting the
10734 * {@link #setTranslationX(float) translationX} property to be the difference between
10735 * the x value passed in and the current {@link #getLeft() left} property.
10737 * @param x The visual x position of this view, in pixels.
10739 public void setX(float x) {
10740 setTranslationX(x - mLeft);
10744 * The visual y position of this view, in pixels. This is equivalent to the
10745 * {@link #setTranslationY(float) translationY} property plus the current
10746 * {@link #getTop() top} property.
10748 * @return The visual y position of this view, in pixels.
10750 @ViewDebug.ExportedProperty(category = "drawing")
10751 public float getY() {
10752 return mTop + getTranslationY();
10756 * Sets the visual y position of this view, in pixels. This is equivalent to setting the
10757 * {@link #setTranslationY(float) translationY} property to be the difference between
10758 * the y value passed in and the current {@link #getTop() top} property.
10760 * @param y The visual y position of this view, in pixels.
10762 public void setY(float y) {
10763 setTranslationY(y - mTop);
10767 * The visual z position of this view, in pixels. This is equivalent to the
10768 * {@link #setTranslationZ(float) translationZ} property plus the current
10769 * {@link #getElevation() elevation} property.
10771 * @return The visual z position of this view, in pixels.
10773 @ViewDebug.ExportedProperty(category = "drawing")
10774 public float getZ() {
10775 return getElevation() + getTranslationZ();
10779 * Sets the visual z position of this view, in pixels. This is equivalent to setting the
10780 * {@link #setTranslationZ(float) translationZ} property to be the difference between
10781 * the x value passed in and the current {@link #getElevation() elevation} property.
10783 * @param z The visual z position of this view, in pixels.
10785 public void setZ(float z) {
10786 setTranslationZ(z - getElevation());
10790 * The base elevation of this view relative to its parent, in pixels.
10792 * @return The base depth position of the view, in pixels.
10794 @ViewDebug.ExportedProperty(category = "drawing")
10795 public float getElevation() {
10796 return mRenderNode.getElevation();
10800 * Sets the base elevation of this view, in pixels.
10802 * @attr ref android.R.styleable#View_elevation
10804 public void setElevation(float elevation) {
10805 if (elevation != getElevation()) {
10806 invalidateViewProperty(true, false);
10807 mRenderNode.setElevation(elevation);
10808 invalidateViewProperty(false, true);
10810 invalidateParentIfNeededAndWasQuickRejected();
10815 * The horizontal location of this view relative to its {@link #getLeft() left} position.
10816 * This position is post-layout, in addition to wherever the object's
10817 * layout placed it.
10819 * @return The horizontal position of this view relative to its left position, in pixels.
10821 @ViewDebug.ExportedProperty(category = "drawing")
10822 public float getTranslationX() {
10823 return mRenderNode.getTranslationX();
10827 * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
10828 * This effectively positions the object post-layout, in addition to wherever the object's
10829 * layout placed it.
10831 * @param translationX The horizontal position of this view relative to its left position,
10834 * @attr ref android.R.styleable#View_translationX
10836 public void setTranslationX(float translationX) {
10837 if (translationX != getTranslationX()) {
10838 invalidateViewProperty(true, false);
10839 mRenderNode.setTranslationX(translationX);
10840 invalidateViewProperty(false, true);
10842 invalidateParentIfNeededAndWasQuickRejected();
10843 notifySubtreeAccessibilityStateChangedIfNeeded();
10848 * The vertical location of this view relative to its {@link #getTop() top} position.
10849 * This position is post-layout, in addition to wherever the object's
10850 * layout placed it.
10852 * @return The vertical position of this view relative to its top position,
10855 @ViewDebug.ExportedProperty(category = "drawing")
10856 public float getTranslationY() {
10857 return mRenderNode.getTranslationY();
10861 * Sets the vertical location of this view relative to its {@link #getTop() top} position.
10862 * This effectively positions the object post-layout, in addition to wherever the object's
10863 * layout placed it.
10865 * @param translationY The vertical position of this view relative to its top position,
10868 * @attr ref android.R.styleable#View_translationY
10870 public void setTranslationY(float translationY) {
10871 if (translationY != getTranslationY()) {
10872 invalidateViewProperty(true, false);
10873 mRenderNode.setTranslationY(translationY);
10874 invalidateViewProperty(false, true);
10876 invalidateParentIfNeededAndWasQuickRejected();
10881 * The depth location of this view relative to its {@link #getElevation() elevation}.
10883 * @return The depth of this view relative to its elevation.
10885 @ViewDebug.ExportedProperty(category = "drawing")
10886 public float getTranslationZ() {
10887 return mRenderNode.getTranslationZ();
10891 * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
10893 * @attr ref android.R.styleable#View_translationZ
10895 public void setTranslationZ(float translationZ) {
10896 if (translationZ != getTranslationZ()) {
10897 invalidateViewProperty(true, false);
10898 mRenderNode.setTranslationZ(translationZ);
10899 invalidateViewProperty(false, true);
10901 invalidateParentIfNeededAndWasQuickRejected();
10906 public void setAnimationMatrix(Matrix matrix) {
10907 invalidateViewProperty(true, false);
10908 mRenderNode.setAnimationMatrix(matrix);
10909 invalidateViewProperty(false, true);
10911 invalidateParentIfNeededAndWasQuickRejected();
10915 * Returns the current StateListAnimator if exists.
10917 * @return StateListAnimator or null if it does not exists
10918 * @see #setStateListAnimator(android.animation.StateListAnimator)
10920 public StateListAnimator getStateListAnimator() {
10921 return mStateListAnimator;
10925 * Attaches the provided StateListAnimator to this View.
10927 * Any previously attached StateListAnimator will be detached.
10929 * @param stateListAnimator The StateListAnimator to update the view
10930 * @see {@link android.animation.StateListAnimator}
10932 public void setStateListAnimator(StateListAnimator stateListAnimator) {
10933 if (mStateListAnimator == stateListAnimator) {
10936 if (mStateListAnimator != null) {
10937 mStateListAnimator.setTarget(null);
10939 mStateListAnimator = stateListAnimator;
10940 if (stateListAnimator != null) {
10941 stateListAnimator.setTarget(this);
10942 if (isAttachedToWindow()) {
10943 stateListAnimator.setState(getDrawableState());
10949 * Returns whether the Outline should be used to clip the contents of the View.
10951 * Note that this flag will only be respected if the View's Outline returns true from
10952 * {@link Outline#canClip()}.
10954 * @see #setOutlineProvider(ViewOutlineProvider)
10955 * @see #setClipToOutline(boolean)
10957 public final boolean getClipToOutline() {
10958 return mRenderNode.getClipToOutline();
10962 * Sets whether the View's Outline should be used to clip the contents of the View.
10964 * Only a single non-rectangular clip can be applied on a View at any time.
10965 * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
10966 * circular reveal} animation take priority over Outline clipping, and
10967 * child Outline clipping takes priority over Outline clipping done by a
10970 * Note that this flag will only be respected if the View's Outline returns true from
10971 * {@link Outline#canClip()}.
10973 * @see #setOutlineProvider(ViewOutlineProvider)
10974 * @see #getClipToOutline()
10976 public void setClipToOutline(boolean clipToOutline) {
10978 if (getClipToOutline() != clipToOutline) {
10979 mRenderNode.setClipToOutline(clipToOutline);
10983 // correspond to the enum values of View_outlineProvider
10984 private static final int PROVIDER_BACKGROUND = 0;
10985 private static final int PROVIDER_NONE = 1;
10986 private static final int PROVIDER_BOUNDS = 2;
10987 private static final int PROVIDER_PADDED_BOUNDS = 3;
10988 private void setOutlineProviderFromAttribute(int providerInt) {
10989 switch (providerInt) {
10990 case PROVIDER_BACKGROUND:
10991 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
10993 case PROVIDER_NONE:
10994 setOutlineProvider(null);
10996 case PROVIDER_BOUNDS:
10997 setOutlineProvider(ViewOutlineProvider.BOUNDS);
10999 case PROVIDER_PADDED_BOUNDS:
11000 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
11006 * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
11007 * the shape of the shadow it casts, and enables outline clipping.
11009 * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
11010 * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
11011 * outline provider with this method allows this behavior to be overridden.
11013 * If the ViewOutlineProvider is null, if querying it for an outline returns false,
11014 * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
11016 * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
11018 * @see #setClipToOutline(boolean)
11019 * @see #getClipToOutline()
11020 * @see #getOutlineProvider()
11022 public void setOutlineProvider(ViewOutlineProvider provider) {
11023 mOutlineProvider = provider;
11024 invalidateOutline();
11028 * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
11029 * that defines the shape of the shadow it casts, and enables outline clipping.
11031 * @see #setOutlineProvider(ViewOutlineProvider)
11033 public ViewOutlineProvider getOutlineProvider() {
11034 return mOutlineProvider;
11038 * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
11040 * @see #setOutlineProvider(ViewOutlineProvider)
11042 public void invalidateOutline() {
11043 // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
11044 if (mAttachInfo == null) return;
11046 if (mOutlineProvider == null) {
11047 // no provider, remove outline
11048 mRenderNode.setOutline(null);
11050 final Outline outline = mAttachInfo.mTmpOutline;
11051 outline.setEmpty();
11052 outline.setAlpha(1.0f);
11054 mOutlineProvider.getOutline(this, outline);
11055 mRenderNode.setOutline(outline);
11058 notifySubtreeAccessibilityStateChangedIfNeeded();
11059 invalidateViewProperty(false, false);
11063 * HierarchyViewer only
11067 @ViewDebug.ExportedProperty(category = "drawing")
11068 public boolean hasShadow() {
11069 return mRenderNode.hasShadow();
11074 public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
11075 mRenderNode.setRevealClip(shouldClip, x, y, radius);
11076 invalidateViewProperty(false, false);
11080 * Hit rectangle in parent's coordinates
11082 * @param outRect The hit rectangle of the view.
11084 public void getHitRect(Rect outRect) {
11085 if (hasIdentityMatrix() || mAttachInfo == null) {
11086 outRect.set(mLeft, mTop, mRight, mBottom);
11088 final RectF tmpRect = mAttachInfo.mTmpTransformRect;
11089 tmpRect.set(0, 0, getWidth(), getHeight());
11090 getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
11091 outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
11092 (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
11097 * Determines whether the given point, in local coordinates is inside the view.
11099 /*package*/ final boolean pointInView(float localX, float localY) {
11100 return localX >= 0 && localX < (mRight - mLeft)
11101 && localY >= 0 && localY < (mBottom - mTop);
11105 * Utility method to determine whether the given point, in local coordinates,
11106 * is inside the view, where the area of the view is expanded by the slop factor.
11107 * This method is called while processing touch-move events to determine if the event
11108 * is still within the view.
11112 public boolean pointInView(float localX, float localY, float slop) {
11113 return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
11114 localY < ((mBottom - mTop) + slop);
11118 * When a view has focus and the user navigates away from it, the next view is searched for
11119 * starting from the rectangle filled in by this method.
11121 * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
11122 * of the view. However, if your view maintains some idea of internal selection,
11123 * such as a cursor, or a selected row or column, you should override this method and
11124 * fill in a more specific rectangle.
11126 * @param r The rectangle to fill in, in this view's coordinates.
11128 public void getFocusedRect(Rect r) {
11133 * If some part of this view is not clipped by any of its parents, then
11134 * return that area in r in global (root) coordinates. To convert r to local
11135 * coordinates (without taking possible View rotations into account), offset
11136 * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
11137 * If the view is completely clipped or translated out, return false.
11139 * @param r If true is returned, r holds the global coordinates of the
11140 * visible portion of this view.
11141 * @param globalOffset If true is returned, globalOffset holds the dx,dy
11142 * between this view and its root. globalOffet may be null.
11143 * @return true if r is non-empty (i.e. part of the view is visible at the
11146 public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
11147 int width = mRight - mLeft;
11148 int height = mBottom - mTop;
11149 if (width > 0 && height > 0) {
11150 r.set(0, 0, width, height);
11151 if (globalOffset != null) {
11152 globalOffset.set(-mScrollX, -mScrollY);
11154 return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
11159 public final boolean getGlobalVisibleRect(Rect r) {
11160 return getGlobalVisibleRect(r, null);
11163 public final boolean getLocalVisibleRect(Rect r) {
11164 final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
11165 if (getGlobalVisibleRect(r, offset)) {
11166 r.offset(-offset.x, -offset.y); // make r local
11173 * Offset this view's vertical location by the specified number of pixels.
11175 * @param offset the number of pixels to offset the view by
11177 public void offsetTopAndBottom(int offset) {
11179 final boolean matrixIsIdentity = hasIdentityMatrix();
11180 if (matrixIsIdentity) {
11181 if (isHardwareAccelerated()) {
11182 invalidateViewProperty(false, false);
11184 final ViewParent p = mParent;
11185 if (p != null && mAttachInfo != null) {
11186 final Rect r = mAttachInfo.mTmpInvalRect;
11191 minTop = mTop + offset;
11192 maxBottom = mBottom;
11196 maxBottom = mBottom + offset;
11199 r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
11200 p.invalidateChild(this, r);
11204 invalidateViewProperty(false, false);
11209 mRenderNode.offsetTopAndBottom(offset);
11210 if (isHardwareAccelerated()) {
11211 invalidateViewProperty(false, false);
11213 if (!matrixIsIdentity) {
11214 invalidateViewProperty(false, true);
11216 invalidateParentIfNeeded();
11218 notifySubtreeAccessibilityStateChangedIfNeeded();
11223 * Offset this view's horizontal location by the specified amount of pixels.
11225 * @param offset the number of pixels to offset the view by
11227 public void offsetLeftAndRight(int offset) {
11229 final boolean matrixIsIdentity = hasIdentityMatrix();
11230 if (matrixIsIdentity) {
11231 if (isHardwareAccelerated()) {
11232 invalidateViewProperty(false, false);
11234 final ViewParent p = mParent;
11235 if (p != null && mAttachInfo != null) {
11236 final Rect r = mAttachInfo.mTmpInvalRect;
11240 minLeft = mLeft + offset;
11244 maxRight = mRight + offset;
11246 r.set(0, 0, maxRight - minLeft, mBottom - mTop);
11247 p.invalidateChild(this, r);
11251 invalidateViewProperty(false, false);
11256 mRenderNode.offsetLeftAndRight(offset);
11257 if (isHardwareAccelerated()) {
11258 invalidateViewProperty(false, false);
11260 if (!matrixIsIdentity) {
11261 invalidateViewProperty(false, true);
11263 invalidateParentIfNeeded();
11265 notifySubtreeAccessibilityStateChangedIfNeeded();
11270 * Get the LayoutParams associated with this view. All views should have
11271 * layout parameters. These supply parameters to the <i>parent</i> of this
11272 * view specifying how it should be arranged. There are many subclasses of
11273 * ViewGroup.LayoutParams, and these correspond to the different subclasses
11274 * of ViewGroup that are responsible for arranging their children.
11276 * This method may return null if this View is not attached to a parent
11277 * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
11278 * was not invoked successfully. When a View is attached to a parent
11279 * ViewGroup, this method must not return null.
11281 * @return The LayoutParams associated with this view, or null if no
11282 * parameters have been set yet
11284 @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
11285 public ViewGroup.LayoutParams getLayoutParams() {
11286 return mLayoutParams;
11290 * Set the layout parameters associated with this view. These supply
11291 * parameters to the <i>parent</i> of this view specifying how it should be
11292 * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
11293 * correspond to the different subclasses of ViewGroup that are responsible
11294 * for arranging their children.
11296 * @param params The layout parameters for this view, cannot be null
11298 public void setLayoutParams(ViewGroup.LayoutParams params) {
11299 if (params == null) {
11300 throw new NullPointerException("Layout parameters cannot be null");
11302 mLayoutParams = params;
11303 resolveLayoutParams();
11304 if (mParent instanceof ViewGroup) {
11305 ((ViewGroup) mParent).onSetLayoutParams(this, params);
11311 * Resolve the layout parameters depending on the resolved layout direction
11315 public void resolveLayoutParams() {
11316 if (mLayoutParams != null) {
11317 mLayoutParams.resolveLayoutDirection(getLayoutDirection());
11322 * Set the scrolled position of your view. This will cause a call to
11323 * {@link #onScrollChanged(int, int, int, int)} and the view will be
11325 * @param x the x position to scroll to
11326 * @param y the y position to scroll to
11328 public void scrollTo(int x, int y) {
11329 if (mScrollX != x || mScrollY != y) {
11330 int oldX = mScrollX;
11331 int oldY = mScrollY;
11334 invalidateParentCaches();
11335 onScrollChanged(mScrollX, mScrollY, oldX, oldY);
11336 if (!awakenScrollBars()) {
11337 postInvalidateOnAnimation();
11343 * Move the scrolled position of your view. This will cause a call to
11344 * {@link #onScrollChanged(int, int, int, int)} and the view will be
11346 * @param x the amount of pixels to scroll by horizontally
11347 * @param y the amount of pixels to scroll by vertically
11349 public void scrollBy(int x, int y) {
11350 scrollTo(mScrollX + x, mScrollY + y);
11354 * <p>Trigger the scrollbars to draw. When invoked this method starts an
11355 * animation to fade the scrollbars out after a default delay. If a subclass
11356 * provides animated scrolling, the start delay should equal the duration
11357 * of the scrolling animation.</p>
11359 * <p>The animation starts only if at least one of the scrollbars is
11360 * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
11361 * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11362 * this method returns true, and false otherwise. If the animation is
11363 * started, this method calls {@link #invalidate()}; in that case the
11364 * caller should not call {@link #invalidate()}.</p>
11366 * <p>This method should be invoked every time a subclass directly updates
11367 * the scroll parameters.</p>
11369 * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
11370 * and {@link #scrollTo(int, int)}.</p>
11372 * @return true if the animation is played, false otherwise
11374 * @see #awakenScrollBars(int)
11375 * @see #scrollBy(int, int)
11376 * @see #scrollTo(int, int)
11377 * @see #isHorizontalScrollBarEnabled()
11378 * @see #isVerticalScrollBarEnabled()
11379 * @see #setHorizontalScrollBarEnabled(boolean)
11380 * @see #setVerticalScrollBarEnabled(boolean)
11382 protected boolean awakenScrollBars() {
11383 return mScrollCache != null &&
11384 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
11388 * Trigger the scrollbars to draw.
11389 * This method differs from awakenScrollBars() only in its default duration.
11390 * initialAwakenScrollBars() will show the scroll bars for longer than
11391 * usual to give the user more of a chance to notice them.
11393 * @return true if the animation is played, false otherwise.
11395 private boolean initialAwakenScrollBars() {
11396 return mScrollCache != null &&
11397 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
11402 * Trigger the scrollbars to draw. When invoked this method starts an
11403 * animation to fade the scrollbars out after a fixed delay. If a subclass
11404 * provides animated scrolling, the start delay should equal the duration of
11405 * the scrolling animation.
11409 * The animation starts only if at least one of the scrollbars is enabled,
11410 * as specified by {@link #isHorizontalScrollBarEnabled()} and
11411 * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11412 * this method returns true, and false otherwise. If the animation is
11413 * started, this method calls {@link #invalidate()}; in that case the caller
11414 * should not call {@link #invalidate()}.
11418 * This method should be invoked everytime a subclass directly updates the
11419 * scroll parameters.
11422 * @param startDelay the delay, in milliseconds, after which the animation
11423 * should start; when the delay is 0, the animation starts
11425 * @return true if the animation is played, false otherwise
11427 * @see #scrollBy(int, int)
11428 * @see #scrollTo(int, int)
11429 * @see #isHorizontalScrollBarEnabled()
11430 * @see #isVerticalScrollBarEnabled()
11431 * @see #setHorizontalScrollBarEnabled(boolean)
11432 * @see #setVerticalScrollBarEnabled(boolean)
11434 protected boolean awakenScrollBars(int startDelay) {
11435 return awakenScrollBars(startDelay, true);
11440 * Trigger the scrollbars to draw. When invoked this method starts an
11441 * animation to fade the scrollbars out after a fixed delay. If a subclass
11442 * provides animated scrolling, the start delay should equal the duration of
11443 * the scrolling animation.
11447 * The animation starts only if at least one of the scrollbars is enabled,
11448 * as specified by {@link #isHorizontalScrollBarEnabled()} and
11449 * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11450 * this method returns true, and false otherwise. If the animation is
11451 * started, this method calls {@link #invalidate()} if the invalidate parameter
11452 * is set to true; in that case the caller
11453 * should not call {@link #invalidate()}.
11457 * This method should be invoked everytime a subclass directly updates the
11458 * scroll parameters.
11461 * @param startDelay the delay, in milliseconds, after which the animation
11462 * should start; when the delay is 0, the animation starts
11465 * @param invalidate Wheter this method should call invalidate
11467 * @return true if the animation is played, false otherwise
11469 * @see #scrollBy(int, int)
11470 * @see #scrollTo(int, int)
11471 * @see #isHorizontalScrollBarEnabled()
11472 * @see #isVerticalScrollBarEnabled()
11473 * @see #setHorizontalScrollBarEnabled(boolean)
11474 * @see #setVerticalScrollBarEnabled(boolean)
11476 protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
11477 final ScrollabilityCache scrollCache = mScrollCache;
11479 if (scrollCache == null || !scrollCache.fadeScrollBars) {
11483 if (scrollCache.scrollBar == null) {
11484 scrollCache.scrollBar = new ScrollBarDrawable();
11487 if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
11490 // Invalidate to show the scrollbars
11491 postInvalidateOnAnimation();
11494 if (scrollCache.state == ScrollabilityCache.OFF) {
11495 // FIXME: this is copied from WindowManagerService.
11496 // We should get this value from the system when it
11497 // is possible to do so.
11498 final int KEY_REPEAT_FIRST_DELAY = 750;
11499 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
11502 // Tell mScrollCache when we should start fading. This may
11503 // extend the fade start time if one was already scheduled
11504 long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
11505 scrollCache.fadeStartTime = fadeStartTime;
11506 scrollCache.state = ScrollabilityCache.ON;
11508 // Schedule our fader to run, unscheduling any old ones first
11509 if (mAttachInfo != null) {
11510 mAttachInfo.mHandler.removeCallbacks(scrollCache);
11511 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
11521 * Do not invalidate views which are not visible and which are not running an animation. They
11522 * will not get drawn and they should not set dirty flags as if they will be drawn
11524 private boolean skipInvalidate() {
11525 return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
11526 (!(mParent instanceof ViewGroup) ||
11527 !((ViewGroup) mParent).isViewTransitioning(this));
11531 * Mark the area defined by dirty as needing to be drawn. If the view is
11532 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
11533 * point in the future.
11535 * This must be called from a UI thread. To call from a non-UI thread, call
11536 * {@link #postInvalidate()}.
11538 * <b>WARNING:</b> In API 19 and below, this method may be destructive to
11541 * @param dirty the rectangle representing the bounds of the dirty region
11543 public void invalidate(Rect dirty) {
11544 final int scrollX = mScrollX;
11545 final int scrollY = mScrollY;
11546 invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
11547 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
11551 * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
11552 * coordinates of the dirty rect are relative to the view. If the view is
11553 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
11554 * point in the future.
11556 * This must be called from a UI thread. To call from a non-UI thread, call
11557 * {@link #postInvalidate()}.
11559 * @param l the left position of the dirty region
11560 * @param t the top position of the dirty region
11561 * @param r the right position of the dirty region
11562 * @param b the bottom position of the dirty region
11564 public void invalidate(int l, int t, int r, int b) {
11565 final int scrollX = mScrollX;
11566 final int scrollY = mScrollY;
11567 invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
11571 * Invalidate the whole view. If the view is visible,
11572 * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
11575 * This must be called from a UI thread. To call from a non-UI thread, call
11576 * {@link #postInvalidate()}.
11578 public void invalidate() {
11583 * This is where the invalidate() work actually happens. A full invalidate()
11584 * causes the drawing cache to be invalidated, but this function can be
11585 * called with invalidateCache set to false to skip that invalidation step
11586 * for cases that do not need it (for example, a component that remains at
11587 * the same dimensions with the same content).
11589 * @param invalidateCache Whether the drawing cache for this view should be
11590 * invalidated as well. This is usually true for a full
11591 * invalidate, but may be set to false if the View's contents or
11592 * dimensions have not changed.
11594 void invalidate(boolean invalidateCache) {
11595 invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
11598 void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
11599 boolean fullInvalidate) {
11600 if (mGhostView != null) {
11601 mGhostView.invalidate(invalidateCache);
11605 if (skipInvalidate()) {
11609 if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
11610 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
11611 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
11612 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
11613 if (fullInvalidate) {
11614 mLastIsOpaque = isOpaque();
11615 mPrivateFlags &= ~PFLAG_DRAWN;
11618 mPrivateFlags |= PFLAG_DIRTY;
11620 if (invalidateCache) {
11621 mPrivateFlags |= PFLAG_INVALIDATED;
11622 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11625 // Propagate the damage rectangle to the parent view.
11626 final AttachInfo ai = mAttachInfo;
11627 final ViewParent p = mParent;
11628 if (p != null && ai != null && l < r && t < b) {
11629 final Rect damage = ai.mTmpInvalRect;
11630 damage.set(l, t, r, b);
11631 p.invalidateChild(this, damage);
11634 // Damage the entire projection receiver, if necessary.
11635 if (mBackground != null && mBackground.isProjected()) {
11636 final View receiver = getProjectionReceiver();
11637 if (receiver != null) {
11638 receiver.damageInParent();
11642 // Damage the entire IsolatedZVolume receiving this view's shadow.
11643 if (isHardwareAccelerated() && getZ() != 0) {
11644 damageShadowReceiver();
11650 * @return this view's projection receiver, or {@code null} if none exists
11652 private View getProjectionReceiver() {
11653 ViewParent p = getParent();
11654 while (p != null && p instanceof View) {
11655 final View v = (View) p;
11656 if (v.isProjectionReceiver()) {
11666 * @return whether the view is a projection receiver
11668 private boolean isProjectionReceiver() {
11669 return mBackground != null;
11673 * Damage area of the screen that can be covered by this View's shadow.
11675 * This method will guarantee that any changes to shadows cast by a View
11676 * are damaged on the screen for future redraw.
11678 private void damageShadowReceiver() {
11679 final AttachInfo ai = mAttachInfo;
11681 ViewParent p = getParent();
11682 if (p != null && p instanceof ViewGroup) {
11683 final ViewGroup vg = (ViewGroup) p;
11684 vg.damageInParent();
11690 * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
11691 * set any flags or handle all of the cases handled by the default invalidation methods.
11692 * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
11693 * dirty rect. This method calls into fast invalidation methods in ViewGroup that
11694 * walk up the hierarchy, transforming the dirty rect as necessary.
11696 * The method also handles normal invalidation logic if display list properties are not
11697 * being used in this view. The invalidateParent and forceRedraw flags are used by that
11698 * backup approach, to handle these cases used in the various property-setting methods.
11700 * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
11701 * are not being used in this view
11702 * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
11703 * list properties are not being used in this view
11705 void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
11706 if (!isHardwareAccelerated()
11707 || !mRenderNode.isValid()
11708 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
11709 if (invalidateParent) {
11710 invalidateParentCaches();
11713 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11719 if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
11720 damageShadowReceiver();
11725 * Tells the parent view to damage this view's bounds.
11729 protected void damageInParent() {
11730 final AttachInfo ai = mAttachInfo;
11731 final ViewParent p = mParent;
11732 if (p != null && ai != null) {
11733 final Rect r = ai.mTmpInvalRect;
11734 r.set(0, 0, mRight - mLeft, mBottom - mTop);
11735 if (mParent instanceof ViewGroup) {
11736 ((ViewGroup) mParent).damageChild(this, r);
11738 mParent.invalidateChild(this, r);
11744 * Utility method to transform a given Rect by the current matrix of this view.
11746 void transformRect(final Rect rect) {
11747 if (!getMatrix().isIdentity()) {
11748 RectF boundingRect = mAttachInfo.mTmpTransformRect;
11749 boundingRect.set(rect);
11750 getMatrix().mapRect(boundingRect);
11751 rect.set((int) Math.floor(boundingRect.left),
11752 (int) Math.floor(boundingRect.top),
11753 (int) Math.ceil(boundingRect.right),
11754 (int) Math.ceil(boundingRect.bottom));
11759 * Used to indicate that the parent of this view should clear its caches. This functionality
11760 * is used to force the parent to rebuild its display list (when hardware-accelerated),
11761 * which is necessary when various parent-managed properties of the view change, such as
11762 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
11763 * clears the parent caches and does not causes an invalidate event.
11767 protected void invalidateParentCaches() {
11768 if (mParent instanceof View) {
11769 ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
11774 * Used to indicate that the parent of this view should be invalidated. This functionality
11775 * is used to force the parent to rebuild its display list (when hardware-accelerated),
11776 * which is necessary when various parent-managed properties of the view change, such as
11777 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
11778 * an invalidation event to the parent.
11782 protected void invalidateParentIfNeeded() {
11783 if (isHardwareAccelerated() && mParent instanceof View) {
11784 ((View) mParent).invalidate(true);
11791 protected void invalidateParentIfNeededAndWasQuickRejected() {
11792 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
11793 // View was rejected last time it was drawn by its parent; this may have changed
11794 invalidateParentIfNeeded();
11799 * Indicates whether this View is opaque. An opaque View guarantees that it will
11800 * draw all the pixels overlapping its bounds using a fully opaque color.
11802 * Subclasses of View should override this method whenever possible to indicate
11803 * whether an instance is opaque. Opaque Views are treated in a special way by
11804 * the View hierarchy, possibly allowing it to perform optimizations during
11805 * invalidate/draw passes.
11807 * @return True if this View is guaranteed to be fully opaque, false otherwise.
11809 @ViewDebug.ExportedProperty(category = "drawing")
11810 public boolean isOpaque() {
11811 return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
11812 getFinalAlpha() >= 1.0f;
11818 protected void computeOpaqueFlags() {
11820 // - Has a background
11821 // - Background is opaque
11822 // - Doesn't have scrollbars or scrollbars overlay
11824 if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
11825 mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
11827 mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
11830 final int flags = mViewFlags;
11831 if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
11832 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
11833 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
11834 mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
11836 mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
11843 protected boolean hasOpaqueScrollbars() {
11844 return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
11848 * @return A handler associated with the thread running the View. This
11849 * handler can be used to pump events in the UI events queue.
11851 public Handler getHandler() {
11852 final AttachInfo attachInfo = mAttachInfo;
11853 if (attachInfo != null) {
11854 return attachInfo.mHandler;
11860 * Gets the view root associated with the View.
11861 * @return The view root, or null if none.
11864 public ViewRootImpl getViewRootImpl() {
11865 if (mAttachInfo != null) {
11866 return mAttachInfo.mViewRootImpl;
11874 public HardwareRenderer getHardwareRenderer() {
11875 return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
11879 * <p>Causes the Runnable to be added to the message queue.
11880 * The runnable will be run on the user interface thread.</p>
11882 * @param action The Runnable that will be executed.
11884 * @return Returns true if the Runnable was successfully placed in to the
11885 * message queue. Returns false on failure, usually because the
11886 * looper processing the message queue is exiting.
11888 * @see #postDelayed
11889 * @see #removeCallbacks
11891 public boolean post(Runnable action) {
11892 final AttachInfo attachInfo = mAttachInfo;
11893 if (attachInfo != null) {
11894 return attachInfo.mHandler.post(action);
11896 // Assume that post will succeed later
11897 ViewRootImpl.getRunQueue().post(action);
11902 * <p>Causes the Runnable to be added to the message queue, to be run
11903 * after the specified amount of time elapses.
11904 * The runnable will be run on the user interface thread.</p>
11906 * @param action The Runnable that will be executed.
11907 * @param delayMillis The delay (in milliseconds) until the Runnable
11908 * will be executed.
11910 * @return true if the Runnable was successfully placed in to the
11911 * message queue. Returns false on failure, usually because the
11912 * looper processing the message queue is exiting. Note that a
11913 * result of true does not mean the Runnable will be processed --
11914 * if the looper is quit before the delivery time of the message
11915 * occurs then the message will be dropped.
11918 * @see #removeCallbacks
11920 public boolean postDelayed(Runnable action, long delayMillis) {
11921 final AttachInfo attachInfo = mAttachInfo;
11922 if (attachInfo != null) {
11923 return attachInfo.mHandler.postDelayed(action, delayMillis);
11925 // Assume that post will succeed later
11926 ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
11931 * <p>Causes the Runnable to execute on the next animation time step.
11932 * The runnable will be run on the user interface thread.</p>
11934 * @param action The Runnable that will be executed.
11936 * @see #postOnAnimationDelayed
11937 * @see #removeCallbacks
11939 public void postOnAnimation(Runnable action) {
11940 final AttachInfo attachInfo = mAttachInfo;
11941 if (attachInfo != null) {
11942 attachInfo.mViewRootImpl.mChoreographer.postCallback(
11943 Choreographer.CALLBACK_ANIMATION, action, null);
11945 // Assume that post will succeed later
11946 ViewRootImpl.getRunQueue().post(action);
11951 * <p>Causes the Runnable to execute on the next animation time step,
11952 * after the specified amount of time elapses.
11953 * The runnable will be run on the user interface thread.</p>
11955 * @param action The Runnable that will be executed.
11956 * @param delayMillis The delay (in milliseconds) until the Runnable
11957 * will be executed.
11959 * @see #postOnAnimation
11960 * @see #removeCallbacks
11962 public void postOnAnimationDelayed(Runnable action, long delayMillis) {
11963 final AttachInfo attachInfo = mAttachInfo;
11964 if (attachInfo != null) {
11965 attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
11966 Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
11968 // Assume that post will succeed later
11969 ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
11974 * <p>Removes the specified Runnable from the message queue.</p>
11976 * @param action The Runnable to remove from the message handling queue
11978 * @return true if this view could ask the Handler to remove the Runnable,
11979 * false otherwise. When the returned value is true, the Runnable
11980 * may or may not have been actually removed from the message queue
11981 * (for instance, if the Runnable was not in the queue already.)
11984 * @see #postDelayed
11985 * @see #postOnAnimation
11986 * @see #postOnAnimationDelayed
11988 public boolean removeCallbacks(Runnable action) {
11989 if (action != null) {
11990 final AttachInfo attachInfo = mAttachInfo;
11991 if (attachInfo != null) {
11992 attachInfo.mHandler.removeCallbacks(action);
11993 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
11994 Choreographer.CALLBACK_ANIMATION, action, null);
11996 // Assume that post will succeed later
11997 ViewRootImpl.getRunQueue().removeCallbacks(action);
12003 * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
12004 * Use this to invalidate the View from a non-UI thread.</p>
12006 * <p>This method can be invoked from outside of the UI thread
12007 * only when this View is attached to a window.</p>
12009 * @see #invalidate()
12010 * @see #postInvalidateDelayed(long)
12012 public void postInvalidate() {
12013 postInvalidateDelayed(0);
12017 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
12018 * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
12020 * <p>This method can be invoked from outside of the UI thread
12021 * only when this View is attached to a window.</p>
12023 * @param left The left coordinate of the rectangle to invalidate.
12024 * @param top The top coordinate of the rectangle to invalidate.
12025 * @param right The right coordinate of the rectangle to invalidate.
12026 * @param bottom The bottom coordinate of the rectangle to invalidate.
12028 * @see #invalidate(int, int, int, int)
12029 * @see #invalidate(Rect)
12030 * @see #postInvalidateDelayed(long, int, int, int, int)
12032 public void postInvalidate(int left, int top, int right, int bottom) {
12033 postInvalidateDelayed(0, left, top, right, bottom);
12037 * <p>Cause an invalidate to happen on a subsequent cycle through the event
12038 * loop. Waits for the specified amount of time.</p>
12040 * <p>This method can be invoked from outside of the UI thread
12041 * only when this View is attached to a window.</p>
12043 * @param delayMilliseconds the duration in milliseconds to delay the
12046 * @see #invalidate()
12047 * @see #postInvalidate()
12049 public void postInvalidateDelayed(long delayMilliseconds) {
12050 // We try only with the AttachInfo because there's no point in invalidating
12051 // if we are not attached to our window
12052 final AttachInfo attachInfo = mAttachInfo;
12053 if (attachInfo != null) {
12054 attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
12059 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
12060 * through the event loop. Waits for the specified amount of time.</p>
12062 * <p>This method can be invoked from outside of the UI thread
12063 * only when this View is attached to a window.</p>
12065 * @param delayMilliseconds the duration in milliseconds to delay the
12067 * @param left The left coordinate of the rectangle to invalidate.
12068 * @param top The top coordinate of the rectangle to invalidate.
12069 * @param right The right coordinate of the rectangle to invalidate.
12070 * @param bottom The bottom coordinate of the rectangle to invalidate.
12072 * @see #invalidate(int, int, int, int)
12073 * @see #invalidate(Rect)
12074 * @see #postInvalidate(int, int, int, int)
12076 public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
12077 int right, int bottom) {
12079 // We try only with the AttachInfo because there's no point in invalidating
12080 // if we are not attached to our window
12081 final AttachInfo attachInfo = mAttachInfo;
12082 if (attachInfo != null) {
12083 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
12084 info.target = this;
12087 info.right = right;
12088 info.bottom = bottom;
12090 attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
12095 * <p>Cause an invalidate to happen on the next animation time step, typically the
12096 * next display frame.</p>
12098 * <p>This method can be invoked from outside of the UI thread
12099 * only when this View is attached to a window.</p>
12101 * @see #invalidate()
12103 public void postInvalidateOnAnimation() {
12104 // We try only with the AttachInfo because there's no point in invalidating
12105 // if we are not attached to our window
12106 final AttachInfo attachInfo = mAttachInfo;
12107 if (attachInfo != null) {
12108 attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
12113 * <p>Cause an invalidate of the specified area to happen on the next animation
12114 * time step, typically the next display frame.</p>
12116 * <p>This method can be invoked from outside of the UI thread
12117 * only when this View is attached to a window.</p>
12119 * @param left The left coordinate of the rectangle to invalidate.
12120 * @param top The top coordinate of the rectangle to invalidate.
12121 * @param right The right coordinate of the rectangle to invalidate.
12122 * @param bottom The bottom coordinate of the rectangle to invalidate.
12124 * @see #invalidate(int, int, int, int)
12125 * @see #invalidate(Rect)
12127 public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
12128 // We try only with the AttachInfo because there's no point in invalidating
12129 // if we are not attached to our window
12130 final AttachInfo attachInfo = mAttachInfo;
12131 if (attachInfo != null) {
12132 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
12133 info.target = this;
12136 info.right = right;
12137 info.bottom = bottom;
12139 attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
12144 * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
12145 * This event is sent at most once every
12146 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
12148 private void postSendViewScrolledAccessibilityEventCallback() {
12149 if (mSendViewScrolledAccessibilityEvent == null) {
12150 mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
12152 if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
12153 mSendViewScrolledAccessibilityEvent.mIsPending = true;
12154 postDelayed(mSendViewScrolledAccessibilityEvent,
12155 ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
12160 * Called by a parent to request that a child update its values for mScrollX
12161 * and mScrollY if necessary. This will typically be done if the child is
12162 * animating a scroll using a {@link android.widget.Scroller Scroller}
12165 public void computeScroll() {
12169 * <p>Indicate whether the horizontal edges are faded when the view is
12170 * scrolled horizontally.</p>
12172 * @return true if the horizontal edges should are faded on scroll, false
12175 * @see #setHorizontalFadingEdgeEnabled(boolean)
12177 * @attr ref android.R.styleable#View_requiresFadingEdge
12179 public boolean isHorizontalFadingEdgeEnabled() {
12180 return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
12184 * <p>Define whether the horizontal edges should be faded when this view
12185 * is scrolled horizontally.</p>
12187 * @param horizontalFadingEdgeEnabled true if the horizontal edges should
12188 * be faded when the view is scrolled
12191 * @see #isHorizontalFadingEdgeEnabled()
12193 * @attr ref android.R.styleable#View_requiresFadingEdge
12195 public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
12196 if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
12197 if (horizontalFadingEdgeEnabled) {
12201 mViewFlags ^= FADING_EDGE_HORIZONTAL;
12206 * <p>Indicate whether the vertical edges are faded when the view is
12207 * scrolled horizontally.</p>
12209 * @return true if the vertical edges should are faded on scroll, false
12212 * @see #setVerticalFadingEdgeEnabled(boolean)
12214 * @attr ref android.R.styleable#View_requiresFadingEdge
12216 public boolean isVerticalFadingEdgeEnabled() {
12217 return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
12221 * <p>Define whether the vertical edges should be faded when this view
12222 * is scrolled vertically.</p>
12224 * @param verticalFadingEdgeEnabled true if the vertical edges should
12225 * be faded when the view is scrolled
12228 * @see #isVerticalFadingEdgeEnabled()
12230 * @attr ref android.R.styleable#View_requiresFadingEdge
12232 public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
12233 if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
12234 if (verticalFadingEdgeEnabled) {
12238 mViewFlags ^= FADING_EDGE_VERTICAL;
12243 * Returns the strength, or intensity, of the top faded edge. The strength is
12244 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12245 * returns 0.0 or 1.0 but no value in between.
12247 * Subclasses should override this method to provide a smoother fade transition
12248 * when scrolling occurs.
12250 * @return the intensity of the top fade as a float between 0.0f and 1.0f
12252 protected float getTopFadingEdgeStrength() {
12253 return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
12257 * Returns the strength, or intensity, of the bottom faded edge. The strength is
12258 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12259 * returns 0.0 or 1.0 but no value in between.
12261 * Subclasses should override this method to provide a smoother fade transition
12262 * when scrolling occurs.
12264 * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
12266 protected float getBottomFadingEdgeStrength() {
12267 return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
12268 computeVerticalScrollRange() ? 1.0f : 0.0f;
12272 * Returns the strength, or intensity, of the left faded edge. The strength is
12273 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12274 * returns 0.0 or 1.0 but no value in between.
12276 * Subclasses should override this method to provide a smoother fade transition
12277 * when scrolling occurs.
12279 * @return the intensity of the left fade as a float between 0.0f and 1.0f
12281 protected float getLeftFadingEdgeStrength() {
12282 return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
12286 * Returns the strength, or intensity, of the right faded edge. The strength is
12287 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12288 * returns 0.0 or 1.0 but no value in between.
12290 * Subclasses should override this method to provide a smoother fade transition
12291 * when scrolling occurs.
12293 * @return the intensity of the right fade as a float between 0.0f and 1.0f
12295 protected float getRightFadingEdgeStrength() {
12296 return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
12297 computeHorizontalScrollRange() ? 1.0f : 0.0f;
12301 * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
12302 * scrollbar is not drawn by default.</p>
12304 * @return true if the horizontal scrollbar should be painted, false
12307 * @see #setHorizontalScrollBarEnabled(boolean)
12309 public boolean isHorizontalScrollBarEnabled() {
12310 return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
12314 * <p>Define whether the horizontal scrollbar should be drawn or not. The
12315 * scrollbar is not drawn by default.</p>
12317 * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
12320 * @see #isHorizontalScrollBarEnabled()
12322 public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
12323 if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
12324 mViewFlags ^= SCROLLBARS_HORIZONTAL;
12325 computeOpaqueFlags();
12331 * <p>Indicate whether the vertical scrollbar should be drawn or not. The
12332 * scrollbar is not drawn by default.</p>
12334 * @return true if the vertical scrollbar should be painted, false
12337 * @see #setVerticalScrollBarEnabled(boolean)
12339 public boolean isVerticalScrollBarEnabled() {
12340 return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
12344 * <p>Define whether the vertical scrollbar should be drawn or not. The
12345 * scrollbar is not drawn by default.</p>
12347 * @param verticalScrollBarEnabled true if the vertical scrollbar should
12350 * @see #isVerticalScrollBarEnabled()
12352 public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
12353 if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
12354 mViewFlags ^= SCROLLBARS_VERTICAL;
12355 computeOpaqueFlags();
12363 protected void recomputePadding() {
12364 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
12368 * Define whether scrollbars will fade when the view is not scrolling.
12370 * @param fadeScrollbars wheter to enable fading
12372 * @attr ref android.R.styleable#View_fadeScrollbars
12374 public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
12376 final ScrollabilityCache scrollabilityCache = mScrollCache;
12377 scrollabilityCache.fadeScrollBars = fadeScrollbars;
12378 if (fadeScrollbars) {
12379 scrollabilityCache.state = ScrollabilityCache.OFF;
12381 scrollabilityCache.state = ScrollabilityCache.ON;
12387 * Returns true if scrollbars will fade when this view is not scrolling
12389 * @return true if scrollbar fading is enabled
12391 * @attr ref android.R.styleable#View_fadeScrollbars
12393 public boolean isScrollbarFadingEnabled() {
12394 return mScrollCache != null && mScrollCache.fadeScrollBars;
12399 * Returns the delay before scrollbars fade.
12401 * @return the delay before scrollbars fade
12403 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
12405 public int getScrollBarDefaultDelayBeforeFade() {
12406 return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
12407 mScrollCache.scrollBarDefaultDelayBeforeFade;
12411 * Define the delay before scrollbars fade.
12413 * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
12415 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
12417 public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
12418 getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
12423 * Returns the scrollbar fade duration.
12425 * @return the scrollbar fade duration
12427 * @attr ref android.R.styleable#View_scrollbarFadeDuration
12429 public int getScrollBarFadeDuration() {
12430 return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
12431 mScrollCache.scrollBarFadeDuration;
12435 * Define the scrollbar fade duration.
12437 * @param scrollBarFadeDuration - the scrollbar fade duration
12439 * @attr ref android.R.styleable#View_scrollbarFadeDuration
12441 public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
12442 getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
12447 * Returns the scrollbar size.
12449 * @return the scrollbar size
12451 * @attr ref android.R.styleable#View_scrollbarSize
12453 public int getScrollBarSize() {
12454 return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
12455 mScrollCache.scrollBarSize;
12459 * Define the scrollbar size.
12461 * @param scrollBarSize - the scrollbar size
12463 * @attr ref android.R.styleable#View_scrollbarSize
12465 public void setScrollBarSize(int scrollBarSize) {
12466 getScrollCache().scrollBarSize = scrollBarSize;
12470 * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
12471 * inset. When inset, they add to the padding of the view. And the scrollbars
12472 * can be drawn inside the padding area or on the edge of the view. For example,
12473 * if a view has a background drawable and you want to draw the scrollbars
12474 * inside the padding specified by the drawable, you can use
12475 * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
12476 * appear at the edge of the view, ignoring the padding, then you can use
12477 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
12478 * @param style the style of the scrollbars. Should be one of
12479 * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
12480 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
12481 * @see #SCROLLBARS_INSIDE_OVERLAY
12482 * @see #SCROLLBARS_INSIDE_INSET
12483 * @see #SCROLLBARS_OUTSIDE_OVERLAY
12484 * @see #SCROLLBARS_OUTSIDE_INSET
12486 * @attr ref android.R.styleable#View_scrollbarStyle
12488 public void setScrollBarStyle(@ScrollBarStyle int style) {
12489 if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
12490 mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
12491 computeOpaqueFlags();
12497 * <p>Returns the current scrollbar style.</p>
12498 * @return the current scrollbar style
12499 * @see #SCROLLBARS_INSIDE_OVERLAY
12500 * @see #SCROLLBARS_INSIDE_INSET
12501 * @see #SCROLLBARS_OUTSIDE_OVERLAY
12502 * @see #SCROLLBARS_OUTSIDE_INSET
12504 * @attr ref android.R.styleable#View_scrollbarStyle
12506 @ViewDebug.ExportedProperty(mapping = {
12507 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
12508 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
12509 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
12510 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
12513 public int getScrollBarStyle() {
12514 return mViewFlags & SCROLLBARS_STYLE_MASK;
12518 * <p>Compute the horizontal range that the horizontal scrollbar
12521 * <p>The range is expressed in arbitrary units that must be the same as the
12522 * units used by {@link #computeHorizontalScrollExtent()} and
12523 * {@link #computeHorizontalScrollOffset()}.</p>
12525 * <p>The default range is the drawing width of this view.</p>
12527 * @return the total horizontal range represented by the horizontal
12530 * @see #computeHorizontalScrollExtent()
12531 * @see #computeHorizontalScrollOffset()
12532 * @see android.widget.ScrollBarDrawable
12534 protected int computeHorizontalScrollRange() {
12539 * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
12540 * within the horizontal range. This value is used to compute the position
12541 * of the thumb within the scrollbar's track.</p>
12543 * <p>The range is expressed in arbitrary units that must be the same as the
12544 * units used by {@link #computeHorizontalScrollRange()} and
12545 * {@link #computeHorizontalScrollExtent()}.</p>
12547 * <p>The default offset is the scroll offset of this view.</p>
12549 * @return the horizontal offset of the scrollbar's thumb
12551 * @see #computeHorizontalScrollRange()
12552 * @see #computeHorizontalScrollExtent()
12553 * @see android.widget.ScrollBarDrawable
12555 protected int computeHorizontalScrollOffset() {
12560 * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
12561 * within the horizontal range. This value is used to compute the length
12562 * of the thumb within the scrollbar's track.</p>
12564 * <p>The range is expressed in arbitrary units that must be the same as the
12565 * units used by {@link #computeHorizontalScrollRange()} and
12566 * {@link #computeHorizontalScrollOffset()}.</p>
12568 * <p>The default extent is the drawing width of this view.</p>
12570 * @return the horizontal extent of the scrollbar's thumb
12572 * @see #computeHorizontalScrollRange()
12573 * @see #computeHorizontalScrollOffset()
12574 * @see android.widget.ScrollBarDrawable
12576 protected int computeHorizontalScrollExtent() {
12581 * <p>Compute the vertical range that the vertical scrollbar represents.</p>
12583 * <p>The range is expressed in arbitrary units that must be the same as the
12584 * units used by {@link #computeVerticalScrollExtent()} and
12585 * {@link #computeVerticalScrollOffset()}.</p>
12587 * @return the total vertical range represented by the vertical scrollbar
12589 * <p>The default range is the drawing height of this view.</p>
12591 * @see #computeVerticalScrollExtent()
12592 * @see #computeVerticalScrollOffset()
12593 * @see android.widget.ScrollBarDrawable
12595 protected int computeVerticalScrollRange() {
12596 return getHeight();
12600 * <p>Compute the vertical offset of the vertical scrollbar's thumb
12601 * within the horizontal range. This value is used to compute the position
12602 * of the thumb within the scrollbar's track.</p>
12604 * <p>The range is expressed in arbitrary units that must be the same as the
12605 * units used by {@link #computeVerticalScrollRange()} and
12606 * {@link #computeVerticalScrollExtent()}.</p>
12608 * <p>The default offset is the scroll offset of this view.</p>
12610 * @return the vertical offset of the scrollbar's thumb
12612 * @see #computeVerticalScrollRange()
12613 * @see #computeVerticalScrollExtent()
12614 * @see android.widget.ScrollBarDrawable
12616 protected int computeVerticalScrollOffset() {
12621 * <p>Compute the vertical extent of the vertical scrollbar's thumb
12622 * within the vertical range. This value is used to compute the length
12623 * of the thumb within the scrollbar's track.</p>
12625 * <p>The range is expressed in arbitrary units that must be the same as the
12626 * units used by {@link #computeVerticalScrollRange()} and
12627 * {@link #computeVerticalScrollOffset()}.</p>
12629 * <p>The default extent is the drawing height of this view.</p>
12631 * @return the vertical extent of the scrollbar's thumb
12633 * @see #computeVerticalScrollRange()
12634 * @see #computeVerticalScrollOffset()
12635 * @see android.widget.ScrollBarDrawable
12637 protected int computeVerticalScrollExtent() {
12638 return getHeight();
12642 * Check if this view can be scrolled horizontally in a certain direction.
12644 * @param direction Negative to check scrolling left, positive to check scrolling right.
12645 * @return true if this view can be scrolled in the specified direction, false otherwise.
12647 public boolean canScrollHorizontally(int direction) {
12648 final int offset = computeHorizontalScrollOffset();
12649 final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
12650 if (range == 0) return false;
12651 if (direction < 0) {
12654 return offset < range - 1;
12659 * Check if this view can be scrolled vertically in a certain direction.
12661 * @param direction Negative to check scrolling up, positive to check scrolling down.
12662 * @return true if this view can be scrolled in the specified direction, false otherwise.
12664 public boolean canScrollVertically(int direction) {
12665 final int offset = computeVerticalScrollOffset();
12666 final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
12667 if (range == 0) return false;
12668 if (direction < 0) {
12671 return offset < range - 1;
12676 * <p>Request the drawing of the horizontal and the vertical scrollbar. The
12677 * scrollbars are painted only if they have been awakened first.</p>
12679 * @param canvas the canvas on which to draw the scrollbars
12681 * @see #awakenScrollBars(int)
12683 protected final void onDrawScrollBars(Canvas canvas) {
12684 // scrollbars are drawn only when the animation is running
12685 final ScrollabilityCache cache = mScrollCache;
12686 if (cache != null) {
12688 int state = cache.state;
12690 if (state == ScrollabilityCache.OFF) {
12694 boolean invalidate = false;
12696 if (state == ScrollabilityCache.FADING) {
12697 // We're fading -- get our fade interpolation
12698 if (cache.interpolatorValues == null) {
12699 cache.interpolatorValues = new float[1];
12702 float[] values = cache.interpolatorValues;
12704 // Stops the animation if we're done
12705 if (cache.scrollBarInterpolator.timeToValues(values) ==
12706 Interpolator.Result.FREEZE_END) {
12707 cache.state = ScrollabilityCache.OFF;
12709 cache.scrollBar.setAlpha(Math.round(values[0]));
12712 // This will make the scroll bars inval themselves after
12713 // drawing. We only want this when we're fading so that
12714 // we prevent excessive redraws
12717 // We're just on -- but we may have been fading before so
12719 cache.scrollBar.setAlpha(255);
12723 final int viewFlags = mViewFlags;
12725 final boolean drawHorizontalScrollBar =
12726 (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
12727 final boolean drawVerticalScrollBar =
12728 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
12729 && !isVerticalScrollBarHidden();
12731 if (drawVerticalScrollBar || drawHorizontalScrollBar) {
12732 final int width = mRight - mLeft;
12733 final int height = mBottom - mTop;
12735 final ScrollBarDrawable scrollBar = cache.scrollBar;
12737 final int scrollX = mScrollX;
12738 final int scrollY = mScrollY;
12739 final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
12746 if (drawHorizontalScrollBar) {
12747 int size = scrollBar.getSize(false);
12749 size = cache.scrollBarSize;
12752 scrollBar.setParameters(computeHorizontalScrollRange(),
12753 computeHorizontalScrollOffset(),
12754 computeHorizontalScrollExtent(), false);
12755 final int verticalScrollBarGap = drawVerticalScrollBar ?
12756 getVerticalScrollbarWidth() : 0;
12757 top = scrollY + height - size - (mUserPaddingBottom & inside);
12758 left = scrollX + (mPaddingLeft & inside);
12759 right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
12760 bottom = top + size;
12761 onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
12763 invalidate(left, top, right, bottom);
12767 if (drawVerticalScrollBar) {
12768 int size = scrollBar.getSize(true);
12770 size = cache.scrollBarSize;
12773 scrollBar.setParameters(computeVerticalScrollRange(),
12774 computeVerticalScrollOffset(),
12775 computeVerticalScrollExtent(), true);
12776 int verticalScrollbarPosition = mVerticalScrollbarPosition;
12777 if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
12778 verticalScrollbarPosition = isLayoutRtl() ?
12779 SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
12781 switch (verticalScrollbarPosition) {
12783 case SCROLLBAR_POSITION_RIGHT:
12784 left = scrollX + width - size - (mUserPaddingRight & inside);
12786 case SCROLLBAR_POSITION_LEFT:
12787 left = scrollX + (mUserPaddingLeft & inside);
12790 top = scrollY + (mPaddingTop & inside);
12791 right = left + size;
12792 bottom = scrollY + height - (mUserPaddingBottom & inside);
12793 onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
12795 invalidate(left, top, right, bottom);
12803 * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
12804 * FastScroller is visible.
12805 * @return whether to temporarily hide the vertical scrollbar
12808 protected boolean isVerticalScrollBarHidden() {
12813 * <p>Draw the horizontal scrollbar if
12814 * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
12816 * @param canvas the canvas on which to draw the scrollbar
12817 * @param scrollBar the scrollbar's drawable
12819 * @see #isHorizontalScrollBarEnabled()
12820 * @see #computeHorizontalScrollRange()
12821 * @see #computeHorizontalScrollExtent()
12822 * @see #computeHorizontalScrollOffset()
12823 * @see android.widget.ScrollBarDrawable
12826 protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
12827 int l, int t, int r, int b) {
12828 scrollBar.setBounds(l, t, r, b);
12829 scrollBar.draw(canvas);
12833 * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
12834 * returns true.</p>
12836 * @param canvas the canvas on which to draw the scrollbar
12837 * @param scrollBar the scrollbar's drawable
12839 * @see #isVerticalScrollBarEnabled()
12840 * @see #computeVerticalScrollRange()
12841 * @see #computeVerticalScrollExtent()
12842 * @see #computeVerticalScrollOffset()
12843 * @see android.widget.ScrollBarDrawable
12846 protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
12847 int l, int t, int r, int b) {
12848 scrollBar.setBounds(l, t, r, b);
12849 scrollBar.draw(canvas);
12853 * Implement this to do your drawing.
12855 * @param canvas the canvas on which the background will be drawn
12857 protected void onDraw(Canvas canvas) {
12861 * Caller is responsible for calling requestLayout if necessary.
12862 * (This allows addViewInLayout to not request a new layout.)
12864 void assignParent(ViewParent parent) {
12865 if (mParent == null) {
12867 } else if (parent == null) {
12870 throw new RuntimeException("view " + this + " being added, but"
12871 + " it already has a parent");
12876 * This is called when the view is attached to a window. At this point it
12877 * has a Surface and will start drawing. Note that this function is
12878 * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
12879 * however it may be called any time before the first onDraw -- including
12880 * before or after {@link #onMeasure(int, int)}.
12882 * @see #onDetachedFromWindow()
12884 protected void onAttachedToWindow() {
12885 if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
12886 mParent.requestTransparentRegion(this);
12889 if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
12890 initialAwakenScrollBars();
12891 mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
12894 mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
12896 jumpDrawablesToCurrentState();
12898 resetSubtreeAccessibilityStateChanged();
12900 invalidateOutline();
12903 InputMethodManager imm = InputMethodManager.peekInstance();
12909 * Resolve all RTL related properties.
12911 * @return true if resolution of RTL properties has been done
12915 public boolean resolveRtlPropertiesIfNeeded() {
12916 if (!needRtlPropertiesResolution()) return false;
12918 // Order is important here: LayoutDirection MUST be resolved first
12919 if (!isLayoutDirectionResolved()) {
12920 resolveLayoutDirection();
12921 resolveLayoutParams();
12923 // ... then we can resolve the others properties depending on the resolved LayoutDirection.
12924 if (!isTextDirectionResolved()) {
12925 resolveTextDirection();
12927 if (!isTextAlignmentResolved()) {
12928 resolveTextAlignment();
12930 // Should resolve Drawables before Padding because we need the layout direction of the
12931 // Drawable to correctly resolve Padding.
12932 if (!isDrawablesResolved()) {
12933 resolveDrawables();
12935 if (!isPaddingResolved()) {
12938 onRtlPropertiesChanged(getLayoutDirection());
12943 * Reset resolution of all RTL related properties.
12947 public void resetRtlProperties() {
12948 resetResolvedLayoutDirection();
12949 resetResolvedTextDirection();
12950 resetResolvedTextAlignment();
12951 resetResolvedPadding();
12952 resetResolvedDrawables();
12956 * @see #onScreenStateChanged(int)
12958 void dispatchScreenStateChanged(int screenState) {
12959 onScreenStateChanged(screenState);
12963 * This method is called whenever the state of the screen this view is
12964 * attached to changes. A state change will usually occurs when the screen
12965 * turns on or off (whether it happens automatically or the user does it
12968 * @param screenState The new state of the screen. Can be either
12969 * {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
12971 public void onScreenStateChanged(int screenState) {
12975 * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
12977 private boolean hasRtlSupport() {
12978 return mContext.getApplicationInfo().hasRtlSupport();
12982 * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
12983 * RTL not supported)
12985 private boolean isRtlCompatibilityMode() {
12986 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
12987 return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
12991 * @return true if RTL properties need resolution.
12994 private boolean needRtlPropertiesResolution() {
12995 return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
12999 * Called when any RTL property (layout direction or text direction or text alignment) has
13002 * Subclasses need to override this method to take care of cached information that depends on the
13003 * resolved layout direction, or to inform child views that inherit their layout direction.
13005 * The default implementation does nothing.
13007 * @param layoutDirection the direction of the layout
13009 * @see #LAYOUT_DIRECTION_LTR
13010 * @see #LAYOUT_DIRECTION_RTL
13012 public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
13016 * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
13017 * that the parent directionality can and will be resolved before its children.
13019 * @return true if resolution has been done, false otherwise.
13023 public boolean resolveLayoutDirection() {
13024 // Clear any previous layout direction resolution
13025 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
13027 if (hasRtlSupport()) {
13028 // Set resolved depending on layout direction
13029 switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
13030 PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
13031 case LAYOUT_DIRECTION_INHERIT:
13032 // We cannot resolve yet. LTR is by default and let the resolution happen again
13033 // later to get the correct resolved value
13034 if (!canResolveLayoutDirection()) return false;
13036 // Parent has not yet resolved, LTR is still the default
13038 if (!mParent.isLayoutDirectionResolved()) return false;
13040 if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
13041 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13043 } catch (AbstractMethodError e) {
13044 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13045 " does not fully implement ViewParent", e);
13048 case LAYOUT_DIRECTION_RTL:
13049 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13051 case LAYOUT_DIRECTION_LOCALE:
13052 if((LAYOUT_DIRECTION_RTL ==
13053 TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
13054 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13058 // Nothing to do, LTR by default
13063 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
13068 * Check if layout direction resolution can be done.
13070 * @return true if layout direction resolution can be done otherwise return false.
13072 public boolean canResolveLayoutDirection() {
13073 switch (getRawLayoutDirection()) {
13074 case LAYOUT_DIRECTION_INHERIT:
13075 if (mParent != null) {
13077 return mParent.canResolveLayoutDirection();
13078 } catch (AbstractMethodError e) {
13079 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13080 " does not fully implement ViewParent", e);
13091 * Reset the resolved layout direction. Layout direction will be resolved during a call to
13092 * {@link #onMeasure(int, int)}.
13096 public void resetResolvedLayoutDirection() {
13097 // Reset the current resolved bits
13098 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
13102 * @return true if the layout direction is inherited.
13106 public boolean isLayoutDirectionInherited() {
13107 return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
13111 * @return true if layout direction has been resolved.
13113 public boolean isLayoutDirectionResolved() {
13114 return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
13118 * Return if padding has been resolved
13122 boolean isPaddingResolved() {
13123 return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
13127 * Resolves padding depending on layout direction, if applicable, and
13128 * recomputes internal padding values to adjust for scroll bars.
13132 public void resolvePadding() {
13133 final int resolvedLayoutDirection = getLayoutDirection();
13135 if (!isRtlCompatibilityMode()) {
13136 // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
13137 // If start / end padding are defined, they will be resolved (hence overriding) to
13138 // left / right or right / left depending on the resolved layout direction.
13139 // If start / end padding are not defined, use the left / right ones.
13140 if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
13141 Rect padding = sThreadLocal.get();
13142 if (padding == null) {
13143 padding = new Rect();
13144 sThreadLocal.set(padding);
13146 mBackground.getPadding(padding);
13147 if (!mLeftPaddingDefined) {
13148 mUserPaddingLeftInitial = padding.left;
13150 if (!mRightPaddingDefined) {
13151 mUserPaddingRightInitial = padding.right;
13154 switch (resolvedLayoutDirection) {
13155 case LAYOUT_DIRECTION_RTL:
13156 if (mUserPaddingStart != UNDEFINED_PADDING) {
13157 mUserPaddingRight = mUserPaddingStart;
13159 mUserPaddingRight = mUserPaddingRightInitial;
13161 if (mUserPaddingEnd != UNDEFINED_PADDING) {
13162 mUserPaddingLeft = mUserPaddingEnd;
13164 mUserPaddingLeft = mUserPaddingLeftInitial;
13167 case LAYOUT_DIRECTION_LTR:
13169 if (mUserPaddingStart != UNDEFINED_PADDING) {
13170 mUserPaddingLeft = mUserPaddingStart;
13172 mUserPaddingLeft = mUserPaddingLeftInitial;
13174 if (mUserPaddingEnd != UNDEFINED_PADDING) {
13175 mUserPaddingRight = mUserPaddingEnd;
13177 mUserPaddingRight = mUserPaddingRightInitial;
13181 mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
13184 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
13185 onRtlPropertiesChanged(resolvedLayoutDirection);
13187 mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
13191 * Reset the resolved layout direction.
13195 public void resetResolvedPadding() {
13196 mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
13200 * This is called when the view is detached from a window. At this point it
13201 * no longer has a surface for drawing.
13203 * @see #onAttachedToWindow()
13205 protected void onDetachedFromWindow() {
13209 * This is a framework-internal mirror of onDetachedFromWindow() that's called
13210 * after onDetachedFromWindow().
13212 * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
13213 * The super method should be called at the end of the overriden method to ensure
13214 * subclasses are destroyed first
13218 protected void onDetachedFromWindowInternal() {
13219 mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
13220 mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
13222 removeUnsetPressCallback();
13223 removeLongPressCallback();
13224 removePerformClickCallback();
13225 removeSendViewScrolledAccessibilityEventCallback();
13226 stopNestedScroll();
13228 // Anything that started animating right before detach should already
13229 // be in its final state when re-attached.
13230 jumpDrawablesToCurrentState();
13232 destroyDrawingCache();
13235 mCurrentAnimation = null;
13238 private void cleanupDraw() {
13239 resetDisplayList();
13240 if (mAttachInfo != null) {
13241 mAttachInfo.mViewRootImpl.cancelInvalidate(this);
13245 void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
13249 * @return The number of times this view has been attached to a window
13251 protected int getWindowAttachCount() {
13252 return mWindowAttachCount;
13256 * Retrieve a unique token identifying the window this view is attached to.
13257 * @return Return the window's token for use in
13258 * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
13260 public IBinder getWindowToken() {
13261 return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
13265 * Retrieve the {@link WindowId} for the window this view is
13266 * currently attached to.
13268 public WindowId getWindowId() {
13269 if (mAttachInfo == null) {
13272 if (mAttachInfo.mWindowId == null) {
13274 mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
13275 mAttachInfo.mWindowToken);
13276 mAttachInfo.mWindowId = new WindowId(
13277 mAttachInfo.mIWindowId);
13278 } catch (RemoteException e) {
13281 return mAttachInfo.mWindowId;
13285 * Retrieve a unique token identifying the top-level "real" window of
13286 * the window that this view is attached to. That is, this is like
13287 * {@link #getWindowToken}, except if the window this view in is a panel
13288 * window (attached to another containing window), then the token of
13289 * the containing window is returned instead.
13291 * @return Returns the associated window token, either
13292 * {@link #getWindowToken()} or the containing window's token.
13294 public IBinder getApplicationWindowToken() {
13295 AttachInfo ai = mAttachInfo;
13297 IBinder appWindowToken = ai.mPanelParentWindowToken;
13298 if (appWindowToken == null) {
13299 appWindowToken = ai.mWindowToken;
13301 return appWindowToken;
13307 * Gets the logical display to which the view's window has been attached.
13309 * @return The logical display, or null if the view is not currently attached to a window.
13311 public Display getDisplay() {
13312 return mAttachInfo != null ? mAttachInfo.mDisplay : null;
13316 * Retrieve private session object this view hierarchy is using to
13317 * communicate with the window manager.
13318 * @return the session object to communicate with the window manager
13320 /*package*/ IWindowSession getWindowSession() {
13321 return mAttachInfo != null ? mAttachInfo.mSession : null;
13325 * @param info the {@link android.view.View.AttachInfo} to associated with
13328 void dispatchAttachedToWindow(AttachInfo info, int visibility) {
13329 //System.out.println("Attached! " + this);
13330 mAttachInfo = info;
13331 if (mOverlay != null) {
13332 mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
13334 mWindowAttachCount++;
13335 // We will need to evaluate the drawable state at least once.
13336 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
13337 if (mFloatingTreeObserver != null) {
13338 info.mTreeObserver.merge(mFloatingTreeObserver);
13339 mFloatingTreeObserver = null;
13341 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
13342 mAttachInfo.mScrollContainers.add(this);
13343 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
13345 performCollectViewAttributes(mAttachInfo, visibility);
13346 onAttachedToWindow();
13348 ListenerInfo li = mListenerInfo;
13349 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
13350 li != null ? li.mOnAttachStateChangeListeners : null;
13351 if (listeners != null && listeners.size() > 0) {
13352 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
13353 // perform the dispatching. The iterator is a safe guard against listeners that
13354 // could mutate the list by calling the various add/remove methods. This prevents
13355 // the array from being modified while we iterate it.
13356 for (OnAttachStateChangeListener listener : listeners) {
13357 listener.onViewAttachedToWindow(this);
13361 int vis = info.mWindowVisibility;
13363 onWindowVisibilityChanged(vis);
13365 if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
13366 // If nobody has evaluated the drawable state yet, then do it now.
13367 refreshDrawableState();
13369 needGlobalAttributesUpdate(false);
13372 void dispatchDetachedFromWindow() {
13373 AttachInfo info = mAttachInfo;
13374 if (info != null) {
13375 int vis = info.mWindowVisibility;
13377 onWindowVisibilityChanged(GONE);
13381 onDetachedFromWindow();
13382 onDetachedFromWindowInternal();
13384 ListenerInfo li = mListenerInfo;
13385 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
13386 li != null ? li.mOnAttachStateChangeListeners : null;
13387 if (listeners != null && listeners.size() > 0) {
13388 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
13389 // perform the dispatching. The iterator is a safe guard against listeners that
13390 // could mutate the list by calling the various add/remove methods. This prevents
13391 // the array from being modified while we iterate it.
13392 for (OnAttachStateChangeListener listener : listeners) {
13393 listener.onViewDetachedFromWindow(this);
13397 if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
13398 mAttachInfo.mScrollContainers.remove(this);
13399 mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
13402 mAttachInfo = null;
13403 if (mOverlay != null) {
13404 mOverlay.getOverlayView().dispatchDetachedFromWindow();
13409 * Cancel any deferred high-level input events that were previously posted to the event queue.
13411 * <p>Many views post high-level events such as click handlers to the event queue
13412 * to run deferred in order to preserve a desired user experience - clearing visible
13413 * pressed states before executing, etc. This method will abort any events of this nature
13414 * that are currently in flight.</p>
13416 * <p>Custom views that generate their own high-level deferred input events should override
13417 * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
13419 * <p>This will also cancel pending input events for any child views.</p>
13421 * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
13422 * This will not impact newer events posted after this call that may occur as a result of
13423 * lower-level input events still waiting in the queue. If you are trying to prevent
13424 * double-submitted events for the duration of some sort of asynchronous transaction
13425 * you should also take other steps to protect against unexpected double inputs e.g. calling
13426 * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
13427 * the transaction completes, tracking already submitted transaction IDs, etc.</p>
13429 public final void cancelPendingInputEvents() {
13430 dispatchCancelPendingInputEvents();
13434 * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
13435 * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
13437 void dispatchCancelPendingInputEvents() {
13438 mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
13439 onCancelPendingInputEvents();
13440 if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
13441 throw new SuperNotCalledException("View " + getClass().getSimpleName() +
13442 " did not call through to super.onCancelPendingInputEvents()");
13447 * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
13450 * <p>This method is responsible for removing any pending high-level input events that were
13451 * posted to the event queue to run later. Custom view classes that post their own deferred
13452 * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
13453 * {@link android.os.Handler} should override this method, call
13454 * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
13457 public void onCancelPendingInputEvents() {
13458 removePerformClickCallback();
13460 mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
13464 * Store this view hierarchy's frozen state into the given container.
13466 * @param container The SparseArray in which to save the view's state.
13468 * @see #restoreHierarchyState(android.util.SparseArray)
13469 * @see #dispatchSaveInstanceState(android.util.SparseArray)
13470 * @see #onSaveInstanceState()
13472 public void saveHierarchyState(SparseArray<Parcelable> container) {
13473 dispatchSaveInstanceState(container);
13477 * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
13478 * this view and its children. May be overridden to modify how freezing happens to a
13479 * view's children; for example, some views may want to not store state for their children.
13481 * @param container The SparseArray in which to save the view's state.
13483 * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13484 * @see #saveHierarchyState(android.util.SparseArray)
13485 * @see #onSaveInstanceState()
13487 protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
13488 if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
13489 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
13490 Parcelable state = onSaveInstanceState();
13491 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
13492 throw new IllegalStateException(
13493 "Derived class did not call super.onSaveInstanceState()");
13495 if (state != null) {
13496 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
13497 // + ": " + state);
13498 container.put(mID, state);
13504 * Hook allowing a view to generate a representation of its internal state
13505 * that can later be used to create a new instance with that same state.
13506 * This state should only contain information that is not persistent or can
13507 * not be reconstructed later. For example, you will never store your
13508 * current position on screen because that will be computed again when a
13509 * new instance of the view is placed in its view hierarchy.
13511 * Some examples of things you may store here: the current cursor position
13512 * in a text view (but usually not the text itself since that is stored in a
13513 * content provider or other persistent storage), the currently selected
13514 * item in a list view.
13516 * @return Returns a Parcelable object containing the view's current dynamic
13517 * state, or null if there is nothing interesting to save. The
13518 * default implementation returns null.
13519 * @see #onRestoreInstanceState(android.os.Parcelable)
13520 * @see #saveHierarchyState(android.util.SparseArray)
13521 * @see #dispatchSaveInstanceState(android.util.SparseArray)
13522 * @see #setSaveEnabled(boolean)
13524 protected Parcelable onSaveInstanceState() {
13525 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
13526 return BaseSavedState.EMPTY_STATE;
13530 * Restore this view hierarchy's frozen state from the given container.
13532 * @param container The SparseArray which holds previously frozen states.
13534 * @see #saveHierarchyState(android.util.SparseArray)
13535 * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13536 * @see #onRestoreInstanceState(android.os.Parcelable)
13538 public void restoreHierarchyState(SparseArray<Parcelable> container) {
13539 dispatchRestoreInstanceState(container);
13543 * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
13544 * state for this view and its children. May be overridden to modify how restoring
13545 * happens to a view's children; for example, some views may want to not store state
13546 * for their children.
13548 * @param container The SparseArray which holds previously saved state.
13550 * @see #dispatchSaveInstanceState(android.util.SparseArray)
13551 * @see #restoreHierarchyState(android.util.SparseArray)
13552 * @see #onRestoreInstanceState(android.os.Parcelable)
13554 protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
13555 if (mID != NO_ID) {
13556 Parcelable state = container.get(mID);
13557 if (state != null) {
13558 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
13559 // + ": " + state);
13560 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
13561 onRestoreInstanceState(state);
13562 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
13563 throw new IllegalStateException(
13564 "Derived class did not call super.onRestoreInstanceState()");
13571 * Hook allowing a view to re-apply a representation of its internal state that had previously
13572 * been generated by {@link #onSaveInstanceState}. This function will never be called with a
13575 * @param state The frozen state that had previously been returned by
13576 * {@link #onSaveInstanceState}.
13578 * @see #onSaveInstanceState()
13579 * @see #restoreHierarchyState(android.util.SparseArray)
13580 * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13582 protected void onRestoreInstanceState(Parcelable state) {
13583 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
13584 if (state != BaseSavedState.EMPTY_STATE && state != null) {
13585 throw new IllegalArgumentException("Wrong state class, expecting View State but "
13586 + "received " + state.getClass().toString() + " instead. This usually happens "
13587 + "when two views of different type have the same id in the same hierarchy. "
13588 + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
13589 + "other views do not use the same id.");
13594 * <p>Return the time at which the drawing of the view hierarchy started.</p>
13596 * @return the drawing start time in milliseconds
13598 public long getDrawingTime() {
13599 return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
13603 * <p>Enables or disables the duplication of the parent's state into this view. When
13604 * duplication is enabled, this view gets its drawable state from its parent rather
13605 * than from its own internal properties.</p>
13607 * <p>Note: in the current implementation, setting this property to true after the
13608 * view was added to a ViewGroup might have no effect at all. This property should
13609 * always be used from XML or set to true before adding this view to a ViewGroup.</p>
13611 * <p>Note: if this view's parent addStateFromChildren property is enabled and this
13612 * property is enabled, an exception will be thrown.</p>
13614 * <p>Note: if the child view uses and updates additionnal states which are unknown to the
13615 * parent, these states should not be affected by this method.</p>
13617 * @param enabled True to enable duplication of the parent's drawable state, false
13620 * @see #getDrawableState()
13621 * @see #isDuplicateParentStateEnabled()
13623 public void setDuplicateParentStateEnabled(boolean enabled) {
13624 setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
13628 * <p>Indicates whether this duplicates its drawable state from its parent.</p>
13630 * @return True if this view's drawable state is duplicated from the parent,
13633 * @see #getDrawableState()
13634 * @see #setDuplicateParentStateEnabled(boolean)
13636 public boolean isDuplicateParentStateEnabled() {
13637 return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
13641 * <p>Specifies the type of layer backing this view. The layer can be
13642 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
13643 * {@link #LAYER_TYPE_HARDWARE}.</p>
13645 * <p>A layer is associated with an optional {@link android.graphics.Paint}
13646 * instance that controls how the layer is composed on screen. The following
13647 * properties of the paint are taken into account when composing the layer:</p>
13649 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
13650 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
13651 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
13654 * <p>If this view has an alpha value set to < 1.0 by calling
13655 * {@link #setAlpha(float)}, the alpha value of the layer's paint is superceded
13656 * by this view's alpha value.</p>
13658 * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
13659 * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
13660 * for more information on when and how to use layers.</p>
13662 * @param layerType The type of layer to use with this view, must be one of
13663 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
13664 * {@link #LAYER_TYPE_HARDWARE}
13665 * @param paint The paint used to compose the layer. This argument is optional
13666 * and can be null. It is ignored when the layer type is
13667 * {@link #LAYER_TYPE_NONE}
13669 * @see #getLayerType()
13670 * @see #LAYER_TYPE_NONE
13671 * @see #LAYER_TYPE_SOFTWARE
13672 * @see #LAYER_TYPE_HARDWARE
13673 * @see #setAlpha(float)
13675 * @attr ref android.R.styleable#View_layerType
13677 public void setLayerType(int layerType, Paint paint) {
13678 if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
13679 throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
13680 + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
13683 boolean typeChanged = mRenderNode.setLayerType(layerType);
13685 if (!typeChanged) {
13686 setLayerPaint(paint);
13690 // Destroy any previous software drawing cache if needed
13691 if (mLayerType == LAYER_TYPE_SOFTWARE) {
13692 destroyDrawingCache();
13695 mLayerType = layerType;
13696 final boolean layerDisabled = (mLayerType == LAYER_TYPE_NONE);
13697 mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
13698 mRenderNode.setLayerPaint(mLayerPaint);
13700 // draw() behaves differently if we are on a layer, so we need to
13701 // invalidate() here
13702 invalidateParentCaches();
13707 * Updates the {@link Paint} object used with the current layer (used only if the current
13708 * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
13709 * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
13710 * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
13711 * ensure that the view gets redrawn immediately.
13713 * <p>A layer is associated with an optional {@link android.graphics.Paint}
13714 * instance that controls how the layer is composed on screen. The following
13715 * properties of the paint are taken into account when composing the layer:</p>
13717 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
13718 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
13719 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
13722 * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
13723 * alpha value of the layer's paint is superceded by this view's alpha value.</p>
13725 * @param paint The paint used to compose the layer. This argument is optional
13726 * and can be null. It is ignored when the layer type is
13727 * {@link #LAYER_TYPE_NONE}
13729 * @see #setLayerType(int, android.graphics.Paint)
13731 public void setLayerPaint(Paint paint) {
13732 int layerType = getLayerType();
13733 if (layerType != LAYER_TYPE_NONE) {
13734 mLayerPaint = paint == null ? new Paint() : paint;
13735 if (layerType == LAYER_TYPE_HARDWARE) {
13736 if (mRenderNode.setLayerPaint(mLayerPaint)) {
13737 invalidateViewProperty(false, false);
13746 * Indicates whether this view has a static layer. A view with layer type
13747 * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
13750 boolean hasStaticLayer() {
13755 * Indicates what type of layer is currently associated with this view. By default
13756 * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
13757 * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
13758 * for more information on the different types of layers.
13760 * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
13761 * {@link #LAYER_TYPE_HARDWARE}
13763 * @see #setLayerType(int, android.graphics.Paint)
13764 * @see #buildLayer()
13765 * @see #LAYER_TYPE_NONE
13766 * @see #LAYER_TYPE_SOFTWARE
13767 * @see #LAYER_TYPE_HARDWARE
13769 public int getLayerType() {
13774 * Forces this view's layer to be created and this view to be rendered
13775 * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
13776 * invoking this method will have no effect.
13778 * This method can for instance be used to render a view into its layer before
13779 * starting an animation. If this view is complex, rendering into the layer
13780 * before starting the animation will avoid skipping frames.
13782 * @throws IllegalStateException If this view is not attached to a window
13784 * @see #setLayerType(int, android.graphics.Paint)
13786 public void buildLayer() {
13787 if (mLayerType == LAYER_TYPE_NONE) return;
13789 final AttachInfo attachInfo = mAttachInfo;
13790 if (attachInfo == null) {
13791 throw new IllegalStateException("This view must be attached to a window first");
13794 if (getWidth() == 0 || getHeight() == 0) {
13798 switch (mLayerType) {
13799 case LAYER_TYPE_HARDWARE:
13800 updateDisplayListIfDirty();
13801 if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
13802 attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
13805 case LAYER_TYPE_SOFTWARE:
13806 buildDrawingCache(true);
13812 * If this View draws with a HardwareLayer, returns it.
13813 * Otherwise returns null
13815 * TODO: Only TextureView uses this, can we eliminate it?
13817 HardwareLayer getHardwareLayer() {
13822 * Destroys all hardware rendering resources. This method is invoked
13823 * when the system needs to reclaim resources. Upon execution of this
13824 * method, you should free any OpenGL resources created by the view.
13826 * Note: you <strong>must</strong> call
13827 * <code>super.destroyHardwareResources()</code> when overriding
13832 protected void destroyHardwareResources() {
13833 // Although the Layer will be destroyed by RenderNode, we want to release
13834 // the staging display list, which is also a signal to RenderNode that it's
13835 // safe to free its copy of the display list as it knows that we will
13836 // push an updated DisplayList if we try to draw again
13837 resetDisplayList();
13841 * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
13842 * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
13843 * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
13844 * the cache is enabled. To benefit from the cache, you must request the drawing cache by
13845 * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
13848 * <p>Enabling the drawing cache is similar to
13849 * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
13850 * acceleration is turned off. When hardware acceleration is turned on, enabling the
13851 * drawing cache has no effect on rendering because the system uses a different mechanism
13852 * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
13853 * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
13854 * for information on how to enable software and hardware layers.</p>
13856 * <p>This API can be used to manually generate
13857 * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
13858 * {@link #getDrawingCache()}.</p>
13860 * @param enabled true to enable the drawing cache, false otherwise
13862 * @see #isDrawingCacheEnabled()
13863 * @see #getDrawingCache()
13864 * @see #buildDrawingCache()
13865 * @see #setLayerType(int, android.graphics.Paint)
13867 public void setDrawingCacheEnabled(boolean enabled) {
13868 mCachingFailed = false;
13869 setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
13873 * <p>Indicates whether the drawing cache is enabled for this view.</p>
13875 * @return true if the drawing cache is enabled
13877 * @see #setDrawingCacheEnabled(boolean)
13878 * @see #getDrawingCache()
13880 @ViewDebug.ExportedProperty(category = "drawing")
13881 public boolean isDrawingCacheEnabled() {
13882 return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
13886 * Debugging utility which recursively outputs the dirty state of a view and its
13891 @SuppressWarnings({"UnusedDeclaration"})
13892 public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
13893 Log.d("View", indent + this + " DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
13894 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
13895 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
13896 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
13898 mPrivateFlags &= clearMask;
13900 if (this instanceof ViewGroup) {
13901 ViewGroup parent = (ViewGroup) this;
13902 final int count = parent.getChildCount();
13903 for (int i = 0; i < count; i++) {
13904 final View child = parent.getChildAt(i);
13905 child.outputDirtyFlags(indent + " ", clear, clearMask);
13911 * This method is used by ViewGroup to cause its children to restore or recreate their
13912 * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
13913 * to recreate its own display list, which would happen if it went through the normal
13914 * draw/dispatchDraw mechanisms.
13918 protected void dispatchGetDisplayList() {}
13921 * A view that is not attached or hardware accelerated cannot create a display list.
13922 * This method checks these conditions and returns the appropriate result.
13924 * @return true if view has the ability to create a display list, false otherwise.
13928 public boolean canHaveDisplayList() {
13929 return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
13932 private void updateDisplayListIfDirty() {
13933 final RenderNode renderNode = mRenderNode;
13934 if (!canHaveDisplayList()) {
13935 // can't populate RenderNode, don't try
13939 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
13940 || !renderNode.isValid()
13941 || (mRecreateDisplayList)) {
13942 // Don't need to recreate the display list, just need to tell our
13943 // children to restore/recreate theirs
13944 if (renderNode.isValid()
13945 && !mRecreateDisplayList) {
13946 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
13947 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13948 dispatchGetDisplayList();
13950 return; // no work needed
13953 // If we got here, we're recreating it. Mark it as such to ensure that
13954 // we copy in child display lists into ours in drawChild()
13955 mRecreateDisplayList = true;
13957 int width = mRight - mLeft;
13958 int height = mBottom - mTop;
13959 int layerType = getLayerType();
13961 final HardwareCanvas canvas = renderNode.start(width, height);
13962 canvas.setHighContrastText(mAttachInfo.mHighContrastText);
13965 final HardwareLayer layer = getHardwareLayer();
13966 if (layer != null && layer.isValid()) {
13967 canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
13968 } else if (layerType == LAYER_TYPE_SOFTWARE) {
13969 buildDrawingCache(true);
13970 Bitmap cache = getDrawingCache(true);
13971 if (cache != null) {
13972 canvas.drawBitmap(cache, 0, 0, mLayerPaint);
13977 canvas.translate(-mScrollX, -mScrollY);
13978 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
13979 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13981 // Fast path for layouts with no backgrounds
13982 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
13983 dispatchDraw(canvas);
13984 if (mOverlay != null && !mOverlay.isEmpty()) {
13985 mOverlay.getOverlayView().draw(canvas);
13990 drawAccessibilityFocus(canvas);
13993 renderNode.end(canvas);
13994 setDisplayListProperties(renderNode);
13997 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
13998 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14003 * Returns a RenderNode with View draw content recorded, which can be
14004 * used to draw this view again without executing its draw method.
14006 * @return A RenderNode ready to replay, or null if caching is not enabled.
14010 public RenderNode getDisplayList() {
14011 updateDisplayListIfDirty();
14012 return mRenderNode;
14015 private void resetDisplayList() {
14016 if (mRenderNode.isValid()) {
14017 mRenderNode.destroyDisplayListData();
14020 if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
14021 mBackgroundRenderNode.destroyDisplayListData();
14026 * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
14028 * @return A non-scaled bitmap representing this view or null if cache is disabled.
14030 * @see #getDrawingCache(boolean)
14032 public Bitmap getDrawingCache() {
14033 return getDrawingCache(false);
14037 * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
14038 * is null when caching is disabled. If caching is enabled and the cache is not ready,
14039 * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
14040 * draw from the cache when the cache is enabled. To benefit from the cache, you must
14041 * request the drawing cache by calling this method and draw it on screen if the
14042 * returned bitmap is not null.</p>
14044 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
14045 * this method will create a bitmap of the same size as this view. Because this bitmap
14046 * will be drawn scaled by the parent ViewGroup, the result on screen might show
14047 * scaling artifacts. To avoid such artifacts, you should call this method by setting
14048 * the auto scaling to true. Doing so, however, will generate a bitmap of a different
14049 * size than the view. This implies that your application must be able to handle this
14052 * @param autoScale Indicates whether the generated bitmap should be scaled based on
14053 * the current density of the screen when the application is in compatibility
14056 * @return A bitmap representing this view or null if cache is disabled.
14058 * @see #setDrawingCacheEnabled(boolean)
14059 * @see #isDrawingCacheEnabled()
14060 * @see #buildDrawingCache(boolean)
14061 * @see #destroyDrawingCache()
14063 public Bitmap getDrawingCache(boolean autoScale) {
14064 if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
14067 if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
14068 buildDrawingCache(autoScale);
14070 return autoScale ? mDrawingCache : mUnscaledDrawingCache;
14074 * <p>Frees the resources used by the drawing cache. If you call
14075 * {@link #buildDrawingCache()} manually without calling
14076 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
14077 * should cleanup the cache with this method afterwards.</p>
14079 * @see #setDrawingCacheEnabled(boolean)
14080 * @see #buildDrawingCache()
14081 * @see #getDrawingCache()
14083 public void destroyDrawingCache() {
14084 if (mDrawingCache != null) {
14085 mDrawingCache.recycle();
14086 mDrawingCache = null;
14088 if (mUnscaledDrawingCache != null) {
14089 mUnscaledDrawingCache.recycle();
14090 mUnscaledDrawingCache = null;
14095 * Setting a solid background color for the drawing cache's bitmaps will improve
14096 * performance and memory usage. Note, though that this should only be used if this
14097 * view will always be drawn on top of a solid color.
14099 * @param color The background color to use for the drawing cache's bitmap
14101 * @see #setDrawingCacheEnabled(boolean)
14102 * @see #buildDrawingCache()
14103 * @see #getDrawingCache()
14105 public void setDrawingCacheBackgroundColor(int color) {
14106 if (color != mDrawingCacheBackgroundColor) {
14107 mDrawingCacheBackgroundColor = color;
14108 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
14113 * @see #setDrawingCacheBackgroundColor(int)
14115 * @return The background color to used for the drawing cache's bitmap
14117 public int getDrawingCacheBackgroundColor() {
14118 return mDrawingCacheBackgroundColor;
14122 * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
14124 * @see #buildDrawingCache(boolean)
14126 public void buildDrawingCache() {
14127 buildDrawingCache(false);
14131 * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
14133 * <p>If you call {@link #buildDrawingCache()} manually without calling
14134 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
14135 * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
14137 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
14138 * this method will create a bitmap of the same size as this view. Because this bitmap
14139 * will be drawn scaled by the parent ViewGroup, the result on screen might show
14140 * scaling artifacts. To avoid such artifacts, you should call this method by setting
14141 * the auto scaling to true. Doing so, however, will generate a bitmap of a different
14142 * size than the view. This implies that your application must be able to handle this
14145 * <p>You should avoid calling this method when hardware acceleration is enabled. If
14146 * you do not need the drawing cache bitmap, calling this method will increase memory
14147 * usage and cause the view to be rendered in software once, thus negatively impacting
14150 * @see #getDrawingCache()
14151 * @see #destroyDrawingCache()
14153 public void buildDrawingCache(boolean autoScale) {
14154 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
14155 mDrawingCache == null : mUnscaledDrawingCache == null)) {
14156 mCachingFailed = false;
14158 int width = mRight - mLeft;
14159 int height = mBottom - mTop;
14161 final AttachInfo attachInfo = mAttachInfo;
14162 final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
14164 if (autoScale && scalingRequired) {
14165 width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
14166 height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
14169 final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
14170 final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
14171 final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
14173 final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
14174 final long drawingCacheSize =
14175 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
14176 if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
14177 if (width > 0 && height > 0) {
14178 Log.w(VIEW_LOG_TAG, "View too large to fit into drawing cache, needs "
14179 + projectedBitmapSize + " bytes, only "
14180 + drawingCacheSize + " available");
14182 destroyDrawingCache();
14183 mCachingFailed = true;
14187 boolean clear = true;
14188 Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
14190 if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
14191 Bitmap.Config quality;
14193 // Never pick ARGB_4444 because it looks awful
14194 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
14195 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
14196 case DRAWING_CACHE_QUALITY_AUTO:
14197 case DRAWING_CACHE_QUALITY_LOW:
14198 case DRAWING_CACHE_QUALITY_HIGH:
14200 quality = Bitmap.Config.ARGB_8888;
14204 // Optimization for translucent windows
14205 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
14206 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
14209 // Try to cleanup memory
14210 if (bitmap != null) bitmap.recycle();
14213 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
14214 width, height, quality);
14215 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
14217 mDrawingCache = bitmap;
14219 mUnscaledDrawingCache = bitmap;
14221 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
14222 } catch (OutOfMemoryError e) {
14223 // If there is not enough memory to create the bitmap cache, just
14224 // ignore the issue as bitmap caches are not required to draw the
14227 mDrawingCache = null;
14229 mUnscaledDrawingCache = null;
14231 mCachingFailed = true;
14235 clear = drawingCacheBackgroundColor != 0;
14239 if (attachInfo != null) {
14240 canvas = attachInfo.mCanvas;
14241 if (canvas == null) {
14242 canvas = new Canvas();
14244 canvas.setBitmap(bitmap);
14245 // Temporarily clobber the cached Canvas in case one of our children
14246 // is also using a drawing cache. Without this, the children would
14247 // steal the canvas by attaching their own bitmap to it and bad, bad
14248 // thing would happen (invisible views, corrupted drawings, etc.)
14249 attachInfo.mCanvas = null;
14251 // This case should hopefully never or seldom happen
14252 canvas = new Canvas(bitmap);
14256 bitmap.eraseColor(drawingCacheBackgroundColor);
14260 final int restoreCount = canvas.save();
14262 if (autoScale && scalingRequired) {
14263 final float scale = attachInfo.mApplicationScale;
14264 canvas.scale(scale, scale);
14267 canvas.translate(-mScrollX, -mScrollY);
14269 mPrivateFlags |= PFLAG_DRAWN;
14270 if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
14271 mLayerType != LAYER_TYPE_NONE) {
14272 mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
14275 // Fast path for layouts with no backgrounds
14276 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14277 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14278 dispatchDraw(canvas);
14279 if (mOverlay != null && !mOverlay.isEmpty()) {
14280 mOverlay.getOverlayView().draw(canvas);
14285 drawAccessibilityFocus(canvas);
14287 canvas.restoreToCount(restoreCount);
14288 canvas.setBitmap(null);
14290 if (attachInfo != null) {
14291 // Restore the cached Canvas for our siblings
14292 attachInfo.mCanvas = canvas;
14298 * Create a snapshot of the view into a bitmap. We should probably make
14299 * some form of this public, but should think about the API.
14301 Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
14302 int width = mRight - mLeft;
14303 int height = mBottom - mTop;
14305 final AttachInfo attachInfo = mAttachInfo;
14306 final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
14307 width = (int) ((width * scale) + 0.5f);
14308 height = (int) ((height * scale) + 0.5f);
14310 Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
14311 width > 0 ? width : 1, height > 0 ? height : 1, quality);
14312 if (bitmap == null) {
14313 throw new OutOfMemoryError();
14316 Resources resources = getResources();
14317 if (resources != null) {
14318 bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
14322 if (attachInfo != null) {
14323 canvas = attachInfo.mCanvas;
14324 if (canvas == null) {
14325 canvas = new Canvas();
14327 canvas.setBitmap(bitmap);
14328 // Temporarily clobber the cached Canvas in case one of our children
14329 // is also using a drawing cache. Without this, the children would
14330 // steal the canvas by attaching their own bitmap to it and bad, bad
14331 // things would happen (invisible views, corrupted drawings, etc.)
14332 attachInfo.mCanvas = null;
14334 // This case should hopefully never or seldom happen
14335 canvas = new Canvas(bitmap);
14338 if ((backgroundColor & 0xff000000) != 0) {
14339 bitmap.eraseColor(backgroundColor);
14343 final int restoreCount = canvas.save();
14344 canvas.scale(scale, scale);
14345 canvas.translate(-mScrollX, -mScrollY);
14347 // Temporarily remove the dirty mask
14348 int flags = mPrivateFlags;
14349 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14351 // Fast path for layouts with no backgrounds
14352 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14353 dispatchDraw(canvas);
14354 if (mOverlay != null && !mOverlay.isEmpty()) {
14355 mOverlay.getOverlayView().draw(canvas);
14360 drawAccessibilityFocus(canvas);
14362 mPrivateFlags = flags;
14364 canvas.restoreToCount(restoreCount);
14365 canvas.setBitmap(null);
14367 if (attachInfo != null) {
14368 // Restore the cached Canvas for our siblings
14369 attachInfo.mCanvas = canvas;
14376 * Indicates whether this View is currently in edit mode. A View is usually
14377 * in edit mode when displayed within a developer tool. For instance, if
14378 * this View is being drawn by a visual user interface builder, this method
14379 * should return true.
14381 * Subclasses should check the return value of this method to provide
14382 * different behaviors if their normal behavior might interfere with the
14383 * host environment. For instance: the class spawns a thread in its
14384 * constructor, the drawing code relies on device-specific features, etc.
14386 * This method is usually checked in the drawing code of custom widgets.
14388 * @return True if this View is in edit mode, false otherwise.
14390 public boolean isInEditMode() {
14395 * If the View draws content inside its padding and enables fading edges,
14396 * it needs to support padding offsets. Padding offsets are added to the
14397 * fading edges to extend the length of the fade so that it covers pixels
14398 * drawn inside the padding.
14400 * Subclasses of this class should override this method if they need
14401 * to draw content inside the padding.
14403 * @return True if padding offset must be applied, false otherwise.
14405 * @see #getLeftPaddingOffset()
14406 * @see #getRightPaddingOffset()
14407 * @see #getTopPaddingOffset()
14408 * @see #getBottomPaddingOffset()
14412 protected boolean isPaddingOffsetRequired() {
14417 * Amount by which to extend the left fading region. Called only when
14418 * {@link #isPaddingOffsetRequired()} returns true.
14420 * @return The left padding offset in pixels.
14422 * @see #isPaddingOffsetRequired()
14426 protected int getLeftPaddingOffset() {
14431 * Amount by which to extend the right fading region. Called only when
14432 * {@link #isPaddingOffsetRequired()} returns true.
14434 * @return The right padding offset in pixels.
14436 * @see #isPaddingOffsetRequired()
14440 protected int getRightPaddingOffset() {
14445 * Amount by which to extend the top fading region. Called only when
14446 * {@link #isPaddingOffsetRequired()} returns true.
14448 * @return The top padding offset in pixels.
14450 * @see #isPaddingOffsetRequired()
14454 protected int getTopPaddingOffset() {
14459 * Amount by which to extend the bottom fading region. Called only when
14460 * {@link #isPaddingOffsetRequired()} returns true.
14462 * @return The bottom padding offset in pixels.
14464 * @see #isPaddingOffsetRequired()
14468 protected int getBottomPaddingOffset() {
14474 * @param offsetRequired
14476 protected int getFadeTop(boolean offsetRequired) {
14477 int top = mPaddingTop;
14478 if (offsetRequired) top += getTopPaddingOffset();
14484 * @param offsetRequired
14486 protected int getFadeHeight(boolean offsetRequired) {
14487 int padding = mPaddingTop;
14488 if (offsetRequired) padding += getTopPaddingOffset();
14489 return mBottom - mTop - mPaddingBottom - padding;
14493 * <p>Indicates whether this view is attached to a hardware accelerated
14494 * window or not.</p>
14496 * <p>Even if this method returns true, it does not mean that every call
14497 * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
14498 * accelerated {@link android.graphics.Canvas}. For instance, if this view
14499 * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
14500 * window is hardware accelerated,
14501 * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
14502 * return false, and this method will return true.</p>
14504 * @return True if the view is attached to a window and the window is
14505 * hardware accelerated; false in any other case.
14507 @ViewDebug.ExportedProperty(category = "drawing")
14508 public boolean isHardwareAccelerated() {
14509 return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
14513 * Sets a rectangular area on this view to which the view will be clipped
14514 * when it is drawn. Setting the value to null will remove the clip bounds
14515 * and the view will draw normally, using its full bounds.
14517 * @param clipBounds The rectangular area, in the local coordinates of
14518 * this view, to which future drawing operations will be clipped.
14520 public void setClipBounds(Rect clipBounds) {
14521 if (clipBounds != null) {
14522 if (clipBounds.equals(mClipBounds)) {
14525 if (mClipBounds == null) {
14527 mClipBounds = new Rect(clipBounds);
14529 invalidate(Math.min(mClipBounds.left, clipBounds.left),
14530 Math.min(mClipBounds.top, clipBounds.top),
14531 Math.max(mClipBounds.right, clipBounds.right),
14532 Math.max(mClipBounds.bottom, clipBounds.bottom));
14533 mClipBounds.set(clipBounds);
14536 if (mClipBounds != null) {
14538 mClipBounds = null;
14541 mRenderNode.setClipBounds(mClipBounds);
14545 * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
14547 * @return A copy of the current clip bounds if clip bounds are set,
14550 public Rect getClipBounds() {
14551 return (mClipBounds != null) ? new Rect(mClipBounds) : null;
14555 * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
14556 * case of an active Animation being run on the view.
14558 private boolean drawAnimation(ViewGroup parent, long drawingTime,
14559 Animation a, boolean scalingRequired) {
14560 Transformation invalidationTransform;
14561 final int flags = parent.mGroupFlags;
14562 final boolean initialized = a.isInitialized();
14563 if (!initialized) {
14564 a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
14565 a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
14566 if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
14567 onAnimationStart();
14570 final Transformation t = parent.getChildTransformation();
14571 boolean more = a.getTransformation(drawingTime, t, 1f);
14572 if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
14573 if (parent.mInvalidationTransformation == null) {
14574 parent.mInvalidationTransformation = new Transformation();
14576 invalidationTransform = parent.mInvalidationTransformation;
14577 a.getTransformation(drawingTime, invalidationTransform, 1f);
14579 invalidationTransform = t;
14583 if (!a.willChangeBounds()) {
14584 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
14585 ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
14586 parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
14587 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
14588 // The child need to draw an animation, potentially offscreen, so
14589 // make sure we do not cancel invalidate requests
14590 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
14591 parent.invalidate(mLeft, mTop, mRight, mBottom);
14594 if (parent.mInvalidateRegion == null) {
14595 parent.mInvalidateRegion = new RectF();
14597 final RectF region = parent.mInvalidateRegion;
14598 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
14599 invalidationTransform);
14601 // The child need to draw an animation, potentially offscreen, so
14602 // make sure we do not cancel invalidate requests
14603 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
14605 final int left = mLeft + (int) region.left;
14606 final int top = mTop + (int) region.top;
14607 parent.invalidate(left, top, left + (int) (region.width() + .5f),
14608 top + (int) (region.height() + .5f));
14615 * This method is called by getDisplayList() when a display list is recorded for a View.
14616 * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
14618 void setDisplayListProperties(RenderNode renderNode) {
14619 if (renderNode != null) {
14620 renderNode.setHasOverlappingRendering(hasOverlappingRendering());
14621 if (mParent instanceof ViewGroup) {
14622 renderNode.setClipToBounds(
14623 (((ViewGroup) mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0);
14626 if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
14627 ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
14628 ViewGroup parentVG = (ViewGroup) mParent;
14629 final Transformation t = parentVG.getChildTransformation();
14630 if (parentVG.getChildStaticTransformation(this, t)) {
14631 final int transformType = t.getTransformationType();
14632 if (transformType != Transformation.TYPE_IDENTITY) {
14633 if ((transformType & Transformation.TYPE_ALPHA) != 0) {
14634 alpha = t.getAlpha();
14636 if ((transformType & Transformation.TYPE_MATRIX) != 0) {
14637 renderNode.setStaticMatrix(t.getMatrix());
14642 if (mTransformationInfo != null) {
14643 alpha *= getFinalAlpha();
14645 final int multipliedAlpha = (int) (255 * alpha);
14646 if (onSetAlpha(multipliedAlpha)) {
14650 renderNode.setAlpha(alpha);
14651 } else if (alpha < 1) {
14652 renderNode.setAlpha(alpha);
14658 * This method is called by ViewGroup.drawChild() to have each child view draw itself.
14659 * This draw() method is an implementation detail and is not intended to be overridden or
14660 * to be called from anywhere else other than ViewGroup.drawChild().
14662 boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
14663 boolean usingRenderNodeProperties = mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
14664 boolean more = false;
14665 final boolean childHasIdentityMatrix = hasIdentityMatrix();
14666 final int flags = parent.mGroupFlags;
14668 if ((flags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) == ViewGroup.FLAG_CLEAR_TRANSFORMATION) {
14669 parent.getChildTransformation().clear();
14670 parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
14673 Transformation transformToApply = null;
14674 boolean concatMatrix = false;
14676 boolean scalingRequired = false;
14678 int layerType = getLayerType();
14680 final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
14681 if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 ||
14682 (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) {
14684 // Auto-scaled apps are not hw-accelerated, no need to set scaling flag on DisplayList
14685 if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
14687 caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated;
14690 final Animation a = getAnimation();
14692 more = drawAnimation(parent, drawingTime, a, scalingRequired);
14693 concatMatrix = a.willChangeTransformationMatrix();
14694 if (concatMatrix) {
14695 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
14697 transformToApply = parent.getChildTransformation();
14699 if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
14700 // No longer animating: clear out old animation matrix
14701 mRenderNode.setAnimationMatrix(null);
14702 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
14704 if (!usingRenderNodeProperties &&
14705 (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
14706 final Transformation t = parent.getChildTransformation();
14707 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
14708 if (hasTransform) {
14709 final int transformType = t.getTransformationType();
14710 transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
14711 concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
14716 concatMatrix |= !childHasIdentityMatrix;
14718 // Sets the flag as early as possible to allow draw() implementations
14719 // to call invalidate() successfully when doing animations
14720 mPrivateFlags |= PFLAG_DRAWN;
14722 if (!concatMatrix &&
14723 (flags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
14724 ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
14725 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
14726 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
14727 mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
14730 mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
14732 if (hardwareAccelerated) {
14733 // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
14734 // retain the flag's value temporarily in the mRecreateDisplayList flag
14735 mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) == PFLAG_INVALIDATED;
14736 mPrivateFlags &= ~PFLAG_INVALIDATED;
14739 RenderNode renderNode = null;
14740 Bitmap cache = null;
14741 boolean hasDisplayList = false;
14743 if (!hardwareAccelerated) {
14744 if (layerType != LAYER_TYPE_NONE) {
14745 layerType = LAYER_TYPE_SOFTWARE;
14746 buildDrawingCache(true);
14748 cache = getDrawingCache(true);
14750 switch (layerType) {
14751 case LAYER_TYPE_SOFTWARE:
14752 if (usingRenderNodeProperties) {
14753 hasDisplayList = canHaveDisplayList();
14755 buildDrawingCache(true);
14756 cache = getDrawingCache(true);
14759 case LAYER_TYPE_HARDWARE:
14760 if (usingRenderNodeProperties) {
14761 hasDisplayList = canHaveDisplayList();
14764 case LAYER_TYPE_NONE:
14765 // Delay getting the display list until animation-driven alpha values are
14766 // set up and possibly passed on to the view
14767 hasDisplayList = canHaveDisplayList();
14772 usingRenderNodeProperties &= hasDisplayList;
14773 if (usingRenderNodeProperties) {
14774 renderNode = getDisplayList();
14775 if (!renderNode.isValid()) {
14776 // Uncommon, but possible. If a view is removed from the hierarchy during the call
14777 // to getDisplayList(), the display list will be marked invalid and we should not
14778 // try to use it again.
14780 hasDisplayList = false;
14781 usingRenderNodeProperties = false;
14787 if (!hasDisplayList) {
14793 final boolean hasNoCache = cache == null || hasDisplayList;
14794 final boolean offsetForScroll = cache == null && !hasDisplayList &&
14795 layerType != LAYER_TYPE_HARDWARE;
14797 int restoreTo = -1;
14798 if (!usingRenderNodeProperties || transformToApply != null) {
14799 restoreTo = canvas.save();
14801 if (offsetForScroll) {
14802 canvas.translate(mLeft - sx, mTop - sy);
14804 if (!usingRenderNodeProperties) {
14805 canvas.translate(mLeft, mTop);
14807 if (scalingRequired) {
14808 if (usingRenderNodeProperties) {
14809 // TODO: Might not need this if we put everything inside the DL
14810 restoreTo = canvas.save();
14812 // mAttachInfo cannot be null, otherwise scalingRequired == false
14813 final float scale = 1.0f / mAttachInfo.mApplicationScale;
14814 canvas.scale(scale, scale);
14818 float alpha = usingRenderNodeProperties ? 1 : (getAlpha() * getTransitionAlpha());
14819 if (transformToApply != null || alpha < 1 || !hasIdentityMatrix() ||
14820 (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
14821 if (transformToApply != null || !childHasIdentityMatrix) {
14825 if (offsetForScroll) {
14830 if (transformToApply != null) {
14831 if (concatMatrix) {
14832 if (usingRenderNodeProperties) {
14833 renderNode.setAnimationMatrix(transformToApply.getMatrix());
14835 // Undo the scroll translation, apply the transformation matrix,
14836 // then redo the scroll translate to get the correct result.
14837 canvas.translate(-transX, -transY);
14838 canvas.concat(transformToApply.getMatrix());
14839 canvas.translate(transX, transY);
14841 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
14844 float transformAlpha = transformToApply.getAlpha();
14845 if (transformAlpha < 1) {
14846 alpha *= transformAlpha;
14847 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
14851 if (!childHasIdentityMatrix && !usingRenderNodeProperties) {
14852 canvas.translate(-transX, -transY);
14853 canvas.concat(getMatrix());
14854 canvas.translate(transX, transY);
14858 // Deal with alpha if it is or used to be <1
14860 (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
14862 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
14864 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
14866 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
14868 final int multipliedAlpha = (int) (255 * alpha);
14869 if (!onSetAlpha(multipliedAlpha)) {
14870 int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
14871 if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 ||
14872 layerType != LAYER_TYPE_NONE) {
14873 layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
14875 if (usingRenderNodeProperties) {
14876 renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
14877 } else if (layerType == LAYER_TYPE_NONE) {
14878 final int scrollX = hasDisplayList ? 0 : sx;
14879 final int scrollY = hasDisplayList ? 0 : sy;
14880 canvas.saveLayerAlpha(scrollX, scrollY,
14881 scrollX + (mRight - mLeft), scrollY + (mBottom - mTop),
14882 multipliedAlpha, layerFlags);
14885 // Alpha is handled by the child directly, clobber the layer's alpha
14886 mPrivateFlags |= PFLAG_ALPHA_SET;
14890 } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
14892 mPrivateFlags &= ~PFLAG_ALPHA_SET;
14895 if (!usingRenderNodeProperties) {
14896 // apply clips directly, since RenderNode won't do it for this draw
14897 if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) == ViewGroup.FLAG_CLIP_CHILDREN
14898 && cache == null) {
14899 if (offsetForScroll) {
14900 canvas.clipRect(sx, sy, sx + (mRight - mLeft), sy + (mBottom - mTop));
14902 if (!scalingRequired || cache == null) {
14903 canvas.clipRect(0, 0, mRight - mLeft, mBottom - mTop);
14905 canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
14910 if (mClipBounds != null) {
14911 // clip bounds ignore scroll
14912 canvas.clipRect(mClipBounds);
14918 if (!usingRenderNodeProperties && hasDisplayList) {
14919 renderNode = getDisplayList();
14920 if (!renderNode.isValid()) {
14921 // Uncommon, but possible. If a view is removed from the hierarchy during the call
14922 // to getDisplayList(), the display list will be marked invalid and we should not
14923 // try to use it again.
14925 hasDisplayList = false;
14930 boolean layerRendered = false;
14931 if (layerType == LAYER_TYPE_HARDWARE && !usingRenderNodeProperties) {
14932 final HardwareLayer layer = getHardwareLayer();
14933 if (layer != null && layer.isValid()) {
14934 int restoreAlpha = mLayerPaint.getAlpha();
14935 mLayerPaint.setAlpha((int) (alpha * 255));
14936 ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint);
14937 mLayerPaint.setAlpha(restoreAlpha);
14938 layerRendered = true;
14940 final int scrollX = hasDisplayList ? 0 : sx;
14941 final int scrollY = hasDisplayList ? 0 : sy;
14942 canvas.saveLayer(scrollX, scrollY,
14943 scrollX + mRight - mLeft, scrollY + mBottom - mTop, mLayerPaint,
14944 Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
14948 if (!layerRendered) {
14949 if (!hasDisplayList) {
14950 // Fast path for layouts with no backgrounds
14951 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14952 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14953 dispatchDraw(canvas);
14954 if (mOverlay != null && !mOverlay.isEmpty()) {
14955 mOverlay.getOverlayView().draw(canvas);
14960 drawAccessibilityFocus(canvas);
14962 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14963 ((HardwareCanvas) canvas).drawRenderNode(renderNode, null, flags);
14966 } else if (cache != null) {
14967 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14969 int restoreAlpha = 0;
14971 if (layerType == LAYER_TYPE_NONE) {
14972 cachePaint = parent.mCachePaint;
14973 if (cachePaint == null) {
14974 cachePaint = new Paint();
14975 cachePaint.setDither(false);
14976 parent.mCachePaint = cachePaint;
14979 cachePaint = mLayerPaint;
14980 restoreAlpha = mLayerPaint.getAlpha();
14982 cachePaint.setAlpha((int) (alpha * 255));
14983 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
14984 cachePaint.setAlpha(restoreAlpha);
14987 if (restoreTo >= 0) {
14988 canvas.restoreToCount(restoreTo);
14991 if (a != null && !more) {
14992 if (!hardwareAccelerated && !a.getFillAfter()) {
14995 parent.finishAnimatingView(this, a);
14998 if (more && hardwareAccelerated) {
14999 if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
15000 // alpha animations should cause the child to recreate its display list
15005 mRecreateDisplayList = false;
15011 * Manually render this view (and all of its children) to the given Canvas.
15012 * The view must have already done a full layout before this function is
15013 * called. When implementing a view, implement
15014 * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
15015 * If you do need to override this method, call the superclass version.
15017 * @param canvas The Canvas to which the View is rendered.
15019 public void draw(Canvas canvas) {
15020 final int privateFlags = mPrivateFlags;
15021 final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
15022 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
15023 mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
15026 * Draw traversal performs several drawing steps which must be executed
15027 * in the appropriate order:
15029 * 1. Draw the background
15030 * 2. If necessary, save the canvas' layers to prepare for fading
15031 * 3. Draw view's content
15033 * 5. If necessary, draw the fading edges and restore layers
15034 * 6. Draw decorations (scrollbars for instance)
15037 // Step 1, draw the background, if needed
15040 if (!dirtyOpaque) {
15041 drawBackground(canvas);
15044 // skip step 2 & 5 if possible (common case)
15045 final int viewFlags = mViewFlags;
15046 boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
15047 boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
15048 if (!verticalEdges && !horizontalEdges) {
15049 // Step 3, draw the content
15050 if (!dirtyOpaque) onDraw(canvas);
15052 // Step 4, draw the children
15053 dispatchDraw(canvas);
15055 // Step 6, draw decorations (scrollbars)
15056 onDrawScrollBars(canvas);
15058 if (mOverlay != null && !mOverlay.isEmpty()) {
15059 mOverlay.getOverlayView().dispatchDraw(canvas);
15067 * Here we do the full fledged routine...
15068 * (this is an uncommon case where speed matters less,
15069 * this is why we repeat some of the tests that have been
15073 boolean drawTop = false;
15074 boolean drawBottom = false;
15075 boolean drawLeft = false;
15076 boolean drawRight = false;
15078 float topFadeStrength = 0.0f;
15079 float bottomFadeStrength = 0.0f;
15080 float leftFadeStrength = 0.0f;
15081 float rightFadeStrength = 0.0f;
15083 // Step 2, save the canvas' layers
15084 int paddingLeft = mPaddingLeft;
15086 final boolean offsetRequired = isPaddingOffsetRequired();
15087 if (offsetRequired) {
15088 paddingLeft += getLeftPaddingOffset();
15091 int left = mScrollX + paddingLeft;
15092 int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
15093 int top = mScrollY + getFadeTop(offsetRequired);
15094 int bottom = top + getFadeHeight(offsetRequired);
15096 if (offsetRequired) {
15097 right += getRightPaddingOffset();
15098 bottom += getBottomPaddingOffset();
15101 final ScrollabilityCache scrollabilityCache = mScrollCache;
15102 final float fadeHeight = scrollabilityCache.fadingEdgeLength;
15103 int length = (int) fadeHeight;
15105 // clip the fade length if top and bottom fades overlap
15106 // overlapping fades produce odd-looking artifacts
15107 if (verticalEdges && (top + length > bottom - length)) {
15108 length = (bottom - top) / 2;
15111 // also clip horizontal fades if necessary
15112 if (horizontalEdges && (left + length > right - length)) {
15113 length = (right - left) / 2;
15116 if (verticalEdges) {
15117 topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
15118 drawTop = topFadeStrength * fadeHeight > 1.0f;
15119 bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
15120 drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
15123 if (horizontalEdges) {
15124 leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
15125 drawLeft = leftFadeStrength * fadeHeight > 1.0f;
15126 rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
15127 drawRight = rightFadeStrength * fadeHeight > 1.0f;
15130 saveCount = canvas.getSaveCount();
15132 int solidColor = getSolidColor();
15133 if (solidColor == 0) {
15134 final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
15137 canvas.saveLayer(left, top, right, top + length, null, flags);
15141 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
15145 canvas.saveLayer(left, top, left + length, bottom, null, flags);
15149 canvas.saveLayer(right - length, top, right, bottom, null, flags);
15152 scrollabilityCache.setFadeColor(solidColor);
15155 // Step 3, draw the content
15156 if (!dirtyOpaque) onDraw(canvas);
15158 // Step 4, draw the children
15159 dispatchDraw(canvas);
15161 // Step 5, draw the fade effect and restore layers
15162 final Paint p = scrollabilityCache.paint;
15163 final Matrix matrix = scrollabilityCache.matrix;
15164 final Shader fade = scrollabilityCache.shader;
15167 matrix.setScale(1, fadeHeight * topFadeStrength);
15168 matrix.postTranslate(left, top);
15169 fade.setLocalMatrix(matrix);
15171 canvas.drawRect(left, top, right, top + length, p);
15175 matrix.setScale(1, fadeHeight * bottomFadeStrength);
15176 matrix.postRotate(180);
15177 matrix.postTranslate(left, bottom);
15178 fade.setLocalMatrix(matrix);
15180 canvas.drawRect(left, bottom - length, right, bottom, p);
15184 matrix.setScale(1, fadeHeight * leftFadeStrength);
15185 matrix.postRotate(-90);
15186 matrix.postTranslate(left, top);
15187 fade.setLocalMatrix(matrix);
15189 canvas.drawRect(left, top, left + length, bottom, p);
15193 matrix.setScale(1, fadeHeight * rightFadeStrength);
15194 matrix.postRotate(90);
15195 matrix.postTranslate(right, top);
15196 fade.setLocalMatrix(matrix);
15198 canvas.drawRect(right - length, top, right, bottom, p);
15201 canvas.restoreToCount(saveCount);
15203 // Step 6, draw decorations (scrollbars)
15204 onDrawScrollBars(canvas);
15206 if (mOverlay != null && !mOverlay.isEmpty()) {
15207 mOverlay.getOverlayView().dispatchDraw(canvas);
15212 * Draws the accessibility focus rect onto the specified canvas.
15214 * @param canvas Canvas on which to draw the focus rect
15216 private void drawAccessibilityFocus(Canvas canvas) {
15217 if (mAttachInfo == null) {
15221 final Rect bounds = mAttachInfo.mTmpInvalRect;
15222 final ViewRootImpl viewRoot = getViewRootImpl();
15223 if (viewRoot == null || viewRoot.getAccessibilityFocusedHost() != this) {
15227 final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
15228 if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
15232 final Drawable drawable = viewRoot.getAccessibilityFocusedDrawable();
15233 if (drawable == null) {
15237 final AccessibilityNodeInfo virtualView = viewRoot.getAccessibilityFocusedVirtualView();
15238 if (virtualView != null) {
15239 virtualView.getBoundsInScreen(bounds);
15240 final int[] offset = mAttachInfo.mTmpLocation;
15241 getLocationOnScreen(offset);
15242 bounds.offset(-offset[0], -offset[1]);
15244 bounds.set(0, 0, mRight - mLeft, mBottom - mTop);
15248 canvas.translate(mScrollX, mScrollY);
15249 canvas.clipRect(bounds, Region.Op.REPLACE);
15250 drawable.setBounds(bounds);
15251 drawable.draw(canvas);
15256 * Draws the background onto the specified canvas.
15258 * @param canvas Canvas on which to draw the background
15260 private void drawBackground(Canvas canvas) {
15261 final Drawable background = mBackground;
15262 if (background == null) {
15266 if (mBackgroundSizeChanged) {
15267 background.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
15268 mBackgroundSizeChanged = false;
15269 invalidateOutline();
15272 // Attempt to use a display list if requested.
15273 if (canvas.isHardwareAccelerated() && mAttachInfo != null
15274 && mAttachInfo.mHardwareRenderer != null) {
15275 mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
15277 final RenderNode displayList = mBackgroundRenderNode;
15278 if (displayList != null && displayList.isValid()) {
15279 setBackgroundDisplayListProperties(displayList);
15280 ((HardwareCanvas) canvas).drawRenderNode(displayList);
15285 final int scrollX = mScrollX;
15286 final int scrollY = mScrollY;
15287 if ((scrollX | scrollY) == 0) {
15288 background.draw(canvas);
15290 canvas.translate(scrollX, scrollY);
15291 background.draw(canvas);
15292 canvas.translate(-scrollX, -scrollY);
15297 * Set up background drawable display list properties.
15299 * @param displayList Valid display list for the background drawable
15301 private void setBackgroundDisplayListProperties(RenderNode displayList) {
15302 displayList.setTranslationX(mScrollX);
15303 displayList.setTranslationY(mScrollY);
15307 * Creates a new display list or updates the existing display list for the
15308 * specified Drawable.
15310 * @param drawable Drawable for which to create a display list
15311 * @param renderNode Existing RenderNode, or {@code null}
15312 * @return A valid display list for the specified drawable
15314 private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
15315 if (renderNode == null) {
15316 renderNode = RenderNode.create(drawable.getClass().getName(), this);
15319 final Rect bounds = drawable.getBounds();
15320 final int width = bounds.width();
15321 final int height = bounds.height();
15322 final HardwareCanvas canvas = renderNode.start(width, height);
15324 drawable.draw(canvas);
15326 renderNode.end(canvas);
15329 // Set up drawable properties that are view-independent.
15330 renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
15331 renderNode.setProjectBackwards(drawable.isProjected());
15332 renderNode.setProjectionReceiver(true);
15333 renderNode.setClipToBounds(false);
15338 * Returns the overlay for this view, creating it if it does not yet exist.
15339 * Adding drawables to the overlay will cause them to be displayed whenever
15340 * the view itself is redrawn. Objects in the overlay should be actively
15341 * managed: remove them when they should not be displayed anymore. The
15342 * overlay will always have the same size as its host view.
15344 * <p>Note: Overlays do not currently work correctly with {@link
15345 * SurfaceView} or {@link TextureView}; contents in overlays for these
15346 * types of views may not display correctly.</p>
15348 * @return The ViewOverlay object for this view.
15351 public ViewOverlay getOverlay() {
15352 if (mOverlay == null) {
15353 mOverlay = new ViewOverlay(mContext, this);
15359 * Override this if your view is known to always be drawn on top of a solid color background,
15360 * and needs to draw fading edges. Returning a non-zero color enables the view system to
15361 * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
15362 * should be set to 0xFF.
15364 * @see #setVerticalFadingEdgeEnabled(boolean)
15365 * @see #setHorizontalFadingEdgeEnabled(boolean)
15367 * @return The known solid color background for this view, or 0 if the color may vary
15369 @ViewDebug.ExportedProperty(category = "drawing")
15370 public int getSolidColor() {
15375 * Build a human readable string representation of the specified view flags.
15377 * @param flags the view flags to convert to a string
15378 * @return a String representing the supplied flags
15380 private static String printFlags(int flags) {
15381 String output = "";
15383 if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
15384 output += "TAKES_FOCUS";
15388 switch (flags & VISIBILITY_MASK) {
15390 if (numFlags > 0) {
15393 output += "INVISIBLE";
15394 // USELESS HERE numFlags++;
15397 if (numFlags > 0) {
15401 // USELESS HERE numFlags++;
15410 * Build a human readable string representation of the specified private
15413 * @param privateFlags the private view flags to convert to a string
15414 * @return a String representing the supplied flags
15416 private static String printPrivateFlags(int privateFlags) {
15417 String output = "";
15420 if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
15421 output += "WANTS_FOCUS";
15425 if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
15426 if (numFlags > 0) {
15429 output += "FOCUSED";
15433 if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
15434 if (numFlags > 0) {
15437 output += "SELECTED";
15441 if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
15442 if (numFlags > 0) {
15445 output += "IS_ROOT_NAMESPACE";
15449 if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
15450 if (numFlags > 0) {
15453 output += "HAS_BOUNDS";
15457 if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
15458 if (numFlags > 0) {
15462 // USELESS HERE numFlags++;
15468 * <p>Indicates whether or not this view's layout will be requested during
15469 * the next hierarchy layout pass.</p>
15471 * @return true if the layout will be forced during next layout pass
15473 public boolean isLayoutRequested() {
15474 return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
15478 * Return true if o is a ViewGroup that is laying out using optical bounds.
15481 public static boolean isLayoutModeOptical(Object o) {
15482 return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
15485 private boolean setOpticalFrame(int left, int top, int right, int bottom) {
15486 Insets parentInsets = mParent instanceof View ?
15487 ((View) mParent).getOpticalInsets() : Insets.NONE;
15488 Insets childInsets = getOpticalInsets();
15490 left + parentInsets.left - childInsets.left,
15491 top + parentInsets.top - childInsets.top,
15492 right + parentInsets.left + childInsets.right,
15493 bottom + parentInsets.top + childInsets.bottom);
15497 * Assign a size and position to a view and all of its
15500 * <p>This is the second phase of the layout mechanism.
15501 * (The first is measuring). In this phase, each parent calls
15502 * layout on all of its children to position them.
15503 * This is typically done using the child measurements
15504 * that were stored in the measure pass().</p>
15506 * <p>Derived classes should not override this method.
15507 * Derived classes with children should override
15508 * onLayout. In that method, they should
15509 * call layout on each of their children.</p>
15511 * @param l Left position, relative to parent
15512 * @param t Top position, relative to parent
15513 * @param r Right position, relative to parent
15514 * @param b Bottom position, relative to parent
15516 @SuppressWarnings({"unchecked"})
15517 public void layout(int l, int t, int r, int b) {
15518 if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
15519 onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
15520 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
15525 int oldB = mBottom;
15528 boolean changed = isLayoutModeOptical(mParent) ?
15529 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
15531 if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
15532 onLayout(changed, l, t, r, b);
15533 mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
15535 ListenerInfo li = mListenerInfo;
15536 if (li != null && li.mOnLayoutChangeListeners != null) {
15537 ArrayList<OnLayoutChangeListener> listenersCopy =
15538 (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
15539 int numListeners = listenersCopy.size();
15540 for (int i = 0; i < numListeners; ++i) {
15541 listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
15546 mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
15547 mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
15551 * Called from layout when this view should
15552 * assign a size and position to each of its children.
15554 * Derived classes with children should override
15555 * this method and call layout on each of
15557 * @param changed This is a new size or position for this view
15558 * @param left Left position, relative to parent
15559 * @param top Top position, relative to parent
15560 * @param right Right position, relative to parent
15561 * @param bottom Bottom position, relative to parent
15563 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
15567 * Assign a size and position to this view.
15569 * This is called from layout.
15571 * @param left Left position, relative to parent
15572 * @param top Top position, relative to parent
15573 * @param right Right position, relative to parent
15574 * @param bottom Bottom position, relative to parent
15575 * @return true if the new size and position are different than the
15579 protected boolean setFrame(int left, int top, int right, int bottom) {
15580 boolean changed = false;
15583 Log.d("View", this + " View.setFrame(" + left + "," + top + ","
15584 + right + "," + bottom + ")");
15587 if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
15590 // Remember our drawn bit
15591 int drawn = mPrivateFlags & PFLAG_DRAWN;
15593 int oldWidth = mRight - mLeft;
15594 int oldHeight = mBottom - mTop;
15595 int newWidth = right - left;
15596 int newHeight = bottom - top;
15597 boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
15599 // Invalidate our old position
15600 invalidate(sizeChanged);
15606 mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
15608 mPrivateFlags |= PFLAG_HAS_BOUNDS;
15612 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
15615 if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
15616 // If we are visible, force the DRAWN bit to on so that
15617 // this invalidate will go through (at least to our parent).
15618 // This is because someone may have invalidated this view
15619 // before this call to setFrame came in, thereby clearing
15621 mPrivateFlags |= PFLAG_DRAWN;
15622 invalidate(sizeChanged);
15623 // parent display list may need to be recreated based on a change in the bounds
15625 invalidateParentCaches();
15628 // Reset drawn bit to original value (invalidate turns it off)
15629 mPrivateFlags |= drawn;
15631 mBackgroundSizeChanged = true;
15633 notifySubtreeAccessibilityStateChangedIfNeeded();
15638 private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
15639 onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
15640 if (mOverlay != null) {
15641 mOverlay.getOverlayView().setRight(newWidth);
15642 mOverlay.getOverlayView().setBottom(newHeight);
15644 invalidateOutline();
15648 * Finalize inflating a view from XML. This is called as the last phase
15649 * of inflation, after all child views have been added.
15651 * <p>Even if the subclass overrides onFinishInflate, they should always be
15652 * sure to call the super method, so that we get called.
15654 protected void onFinishInflate() {
15658 * Returns the resources associated with this view.
15660 * @return Resources object.
15662 public Resources getResources() {
15667 * Invalidates the specified Drawable.
15669 * @param drawable the drawable to invalidate
15672 public void invalidateDrawable(@NonNull Drawable drawable) {
15673 if (verifyDrawable(drawable)) {
15674 final Rect dirty = drawable.getDirtyBounds();
15675 final int scrollX = mScrollX;
15676 final int scrollY = mScrollY;
15678 invalidate(dirty.left + scrollX, dirty.top + scrollY,
15679 dirty.right + scrollX, dirty.bottom + scrollY);
15681 invalidateOutline();
15686 * Schedules an action on a drawable to occur at a specified time.
15688 * @param who the recipient of the action
15689 * @param what the action to run on the drawable
15690 * @param when the time at which the action must occur. Uses the
15691 * {@link SystemClock#uptimeMillis} timebase.
15694 public void scheduleDrawable(Drawable who, Runnable what, long when) {
15695 if (verifyDrawable(who) && what != null) {
15696 final long delay = when - SystemClock.uptimeMillis();
15697 if (mAttachInfo != null) {
15698 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
15699 Choreographer.CALLBACK_ANIMATION, what, who,
15700 Choreographer.subtractFrameDelay(delay));
15702 ViewRootImpl.getRunQueue().postDelayed(what, delay);
15708 * Cancels a scheduled action on a drawable.
15710 * @param who the recipient of the action
15711 * @param what the action to cancel
15714 public void unscheduleDrawable(Drawable who, Runnable what) {
15715 if (verifyDrawable(who) && what != null) {
15716 if (mAttachInfo != null) {
15717 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15718 Choreographer.CALLBACK_ANIMATION, what, who);
15720 ViewRootImpl.getRunQueue().removeCallbacks(what);
15725 * Unschedule any events associated with the given Drawable. This can be
15726 * used when selecting a new Drawable into a view, so that the previous
15727 * one is completely unscheduled.
15729 * @param who The Drawable to unschedule.
15731 * @see #drawableStateChanged
15733 public void unscheduleDrawable(Drawable who) {
15734 if (mAttachInfo != null && who != null) {
15735 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15736 Choreographer.CALLBACK_ANIMATION, null, who);
15741 * Resolve the Drawables depending on the layout direction. This is implicitly supposing
15742 * that the View directionality can and will be resolved before its Drawables.
15744 * Will call {@link View#onResolveDrawables} when resolution is done.
15748 protected void resolveDrawables() {
15749 // Drawables resolution may need to happen before resolving the layout direction (which is
15750 // done only during the measure() call).
15751 // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
15752 // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
15753 // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
15754 // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
15755 // direction to be resolved as its resolved value will be the same as its raw value.
15756 if (!isLayoutDirectionResolved() &&
15757 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
15761 final int layoutDirection = isLayoutDirectionResolved() ?
15762 getLayoutDirection() : getRawLayoutDirection();
15764 if (mBackground != null) {
15765 mBackground.setLayoutDirection(layoutDirection);
15767 mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
15768 onResolveDrawables(layoutDirection);
15772 * Called when layout direction has been resolved.
15774 * The default implementation does nothing.
15776 * @param layoutDirection The resolved layout direction.
15778 * @see #LAYOUT_DIRECTION_LTR
15779 * @see #LAYOUT_DIRECTION_RTL
15783 public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
15789 protected void resetResolvedDrawables() {
15790 mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
15793 private boolean isDrawablesResolved() {
15794 return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
15798 * If your view subclass is displaying its own Drawable objects, it should
15799 * override this function and return true for any Drawable it is
15800 * displaying. This allows animations for those drawables to be
15803 * <p>Be sure to call through to the super class when overriding this
15806 * @param who The Drawable to verify. Return true if it is one you are
15807 * displaying, else return the result of calling through to the
15810 * @return boolean If true than the Drawable is being displayed in the
15811 * view; else false and it is not allowed to animate.
15813 * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
15814 * @see #drawableStateChanged()
15816 protected boolean verifyDrawable(Drawable who) {
15817 return who == mBackground;
15821 * This function is called whenever the state of the view changes in such
15822 * a way that it impacts the state of drawables being shown.
15824 * If the View has a StateListAnimator, it will also be called to run necessary state
15825 * change animations.
15827 * Be sure to call through to the superclass when overriding this function.
15829 * @see Drawable#setState(int[])
15831 protected void drawableStateChanged() {
15832 final Drawable d = mBackground;
15833 if (d != null && d.isStateful()) {
15834 d.setState(getDrawableState());
15837 if (mStateListAnimator != null) {
15838 mStateListAnimator.setState(getDrawableState());
15843 * This function is called whenever the view hotspot changes and needs to
15844 * be propagated to drawables managed by the view.
15846 * Be sure to call through to the superclass when overriding this function.
15848 * @param x hotspot x coordinate
15849 * @param y hotspot y coordinate
15851 public void drawableHotspotChanged(float x, float y) {
15852 if (mBackground != null) {
15853 mBackground.setHotspot(x, y);
15858 * Call this to force a view to update its drawable state. This will cause
15859 * drawableStateChanged to be called on this view. Views that are interested
15860 * in the new state should call getDrawableState.
15862 * @see #drawableStateChanged
15863 * @see #getDrawableState
15865 public void refreshDrawableState() {
15866 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
15867 drawableStateChanged();
15869 ViewParent parent = mParent;
15870 if (parent != null) {
15871 parent.childDrawableStateChanged(this);
15876 * Return an array of resource IDs of the drawable states representing the
15877 * current state of the view.
15879 * @return The current drawable state
15881 * @see Drawable#setState(int[])
15882 * @see #drawableStateChanged()
15883 * @see #onCreateDrawableState(int)
15885 public final int[] getDrawableState() {
15886 if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
15887 return mDrawableState;
15889 mDrawableState = onCreateDrawableState(0);
15890 mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
15891 return mDrawableState;
15896 * Generate the new {@link android.graphics.drawable.Drawable} state for
15897 * this view. This is called by the view
15898 * system when the cached Drawable state is determined to be invalid. To
15899 * retrieve the current state, you should use {@link #getDrawableState}.
15901 * @param extraSpace if non-zero, this is the number of extra entries you
15902 * would like in the returned array in which you can place your own
15905 * @return Returns an array holding the current {@link Drawable} state of
15908 * @see #mergeDrawableStates(int[], int[])
15910 protected int[] onCreateDrawableState(int extraSpace) {
15911 if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
15912 mParent instanceof View) {
15913 return ((View) mParent).onCreateDrawableState(extraSpace);
15916 int[] drawableState;
15918 int privateFlags = mPrivateFlags;
15920 int viewStateIndex = 0;
15921 if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
15922 if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED;
15923 if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED;
15924 if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
15925 if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED;
15926 if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
15927 if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
15928 HardwareRenderer.isAvailable()) {
15929 // This is set if HW acceleration is requested, even if the current
15930 // process doesn't allow it. This is just to allow app preview
15931 // windows to better match their app.
15932 viewStateIndex |= VIEW_STATE_ACCELERATED;
15934 if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
15936 final int privateFlags2 = mPrivateFlags2;
15937 if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
15938 if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
15940 drawableState = VIEW_STATE_SETS[viewStateIndex];
15942 //noinspection ConstantIfStatement
15944 Log.i("View", "drawableStateIndex=" + viewStateIndex);
15945 Log.i("View", toString()
15946 + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
15947 + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
15948 + " fo=" + hasFocus()
15949 + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
15950 + " wf=" + hasWindowFocus()
15951 + ": " + Arrays.toString(drawableState));
15954 if (extraSpace == 0) {
15955 return drawableState;
15958 final int[] fullState;
15959 if (drawableState != null) {
15960 fullState = new int[drawableState.length + extraSpace];
15961 System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
15963 fullState = new int[extraSpace];
15970 * Merge your own state values in <var>additionalState</var> into the base
15971 * state values <var>baseState</var> that were returned by
15972 * {@link #onCreateDrawableState(int)}.
15974 * @param baseState The base state values returned by
15975 * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
15976 * own additional state values.
15978 * @param additionalState The additional state values you would like
15979 * added to <var>baseState</var>; this array is not modified.
15981 * @return As a convenience, the <var>baseState</var> array you originally
15982 * passed into the function is returned.
15984 * @see #onCreateDrawableState(int)
15986 protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
15987 final int N = baseState.length;
15989 while (i >= 0 && baseState[i] == 0) {
15992 System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
15997 * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
15998 * on all Drawable objects associated with this view.
16000 * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
16001 * attached to this view.
16003 public void jumpDrawablesToCurrentState() {
16004 if (mBackground != null) {
16005 mBackground.jumpToCurrentState();
16007 if (mStateListAnimator != null) {
16008 mStateListAnimator.jumpToCurrentState();
16013 * Sets the background color for this view.
16014 * @param color the color of the background
16016 @RemotableViewMethod
16017 public void setBackgroundColor(int color) {
16018 if (mBackground instanceof ColorDrawable) {
16019 ((ColorDrawable) mBackground.mutate()).setColor(color);
16020 computeOpaqueFlags();
16021 mBackgroundResource = 0;
16023 setBackground(new ColorDrawable(color));
16028 * Set the background to a given resource. The resource should refer to
16029 * a Drawable object or 0 to remove the background.
16030 * @param resid The identifier of the resource.
16032 * @attr ref android.R.styleable#View_background
16034 @RemotableViewMethod
16035 public void setBackgroundResource(int resid) {
16036 if (resid != 0 && resid == mBackgroundResource) {
16042 d = mContext.getDrawable(resid);
16046 mBackgroundResource = resid;
16050 * Set the background to a given Drawable, or remove the background. If the
16051 * background has padding, this View's padding is set to the background's
16052 * padding. However, when a background is removed, this View's padding isn't
16053 * touched. If setting the padding is desired, please use
16054 * {@link #setPadding(int, int, int, int)}.
16056 * @param background The Drawable to use as the background, or null to remove the
16059 public void setBackground(Drawable background) {
16060 //noinspection deprecation
16061 setBackgroundDrawable(background);
16065 * @deprecated use {@link #setBackground(Drawable)} instead
16068 public void setBackgroundDrawable(Drawable background) {
16069 computeOpaqueFlags();
16071 if (background == mBackground) {
16075 boolean requestLayout = false;
16077 mBackgroundResource = 0;
16080 * Regardless of whether we're setting a new background or not, we want
16081 * to clear the previous drawable.
16083 if (mBackground != null) {
16084 mBackground.setCallback(null);
16085 unscheduleDrawable(mBackground);
16088 if (background != null) {
16089 Rect padding = sThreadLocal.get();
16090 if (padding == null) {
16091 padding = new Rect();
16092 sThreadLocal.set(padding);
16094 resetResolvedDrawables();
16095 background.setLayoutDirection(getLayoutDirection());
16096 if (background.getPadding(padding)) {
16097 resetResolvedPadding();
16098 switch (background.getLayoutDirection()) {
16099 case LAYOUT_DIRECTION_RTL:
16100 mUserPaddingLeftInitial = padding.right;
16101 mUserPaddingRightInitial = padding.left;
16102 internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
16104 case LAYOUT_DIRECTION_LTR:
16106 mUserPaddingLeftInitial = padding.left;
16107 mUserPaddingRightInitial = padding.right;
16108 internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
16110 mLeftPaddingDefined = false;
16111 mRightPaddingDefined = false;
16114 // Compare the minimum sizes of the old Drawable and the new. If there isn't an old or
16115 // if it has a different minimum size, we should layout again
16116 if (mBackground == null
16117 || mBackground.getMinimumHeight() != background.getMinimumHeight()
16118 || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
16119 requestLayout = true;
16122 background.setCallback(this);
16123 if (background.isStateful()) {
16124 background.setState(getDrawableState());
16126 background.setVisible(getVisibility() == VISIBLE, false);
16127 mBackground = background;
16129 applyBackgroundTint();
16131 if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
16132 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
16133 mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
16134 requestLayout = true;
16137 /* Remove the background */
16138 mBackground = null;
16140 if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) {
16142 * This view ONLY drew the background before and we're removing
16143 * the background, so now it won't draw anything
16144 * (hence we SKIP_DRAW)
16146 mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND;
16147 mPrivateFlags |= PFLAG_SKIP_DRAW;
16151 * When the background is set, we try to apply its padding to this
16152 * View. When the background is removed, we don't touch this View's
16153 * padding. This is noted in the Javadocs. Hence, we don't need to
16154 * requestLayout(), the invalidate() below is sufficient.
16157 // The old background's minimum size could have affected this
16158 // View's layout, so let's requestLayout
16159 requestLayout = true;
16162 computeOpaqueFlags();
16164 if (requestLayout) {
16168 mBackgroundSizeChanged = true;
16173 * Gets the background drawable
16175 * @return The drawable used as the background for this view, if any.
16177 * @see #setBackground(Drawable)
16179 * @attr ref android.R.styleable#View_background
16181 public Drawable getBackground() {
16182 return mBackground;
16186 * Applies a tint to the background drawable. Does not modify the current tint
16187 * mode, which is {@link PorterDuff.Mode#SRC_ATOP} by default.
16189 * Subsequent calls to {@link #setBackground(Drawable)} will automatically
16190 * mutate the drawable and apply the specified tint and tint mode using
16191 * {@link Drawable#setTintList(ColorStateList)}.
16193 * @param tint the tint to apply, may be {@code null} to clear tint
16195 * @attr ref android.R.styleable#View_backgroundTint
16196 * @see #getBackgroundTintList()
16197 * @see Drawable#setTintList(ColorStateList)
16199 public void setBackgroundTintList(@Nullable ColorStateList tint) {
16200 mBackgroundTintList = tint;
16201 mHasBackgroundTint = true;
16203 applyBackgroundTint();
16207 * @return the tint applied to the background drawable
16208 * @attr ref android.R.styleable#View_backgroundTint
16209 * @see #setBackgroundTintList(ColorStateList)
16212 public ColorStateList getBackgroundTintList() {
16213 return mBackgroundTintList;
16217 * Specifies the blending mode used to apply the tint specified by
16218 * {@link #setBackgroundTintList(ColorStateList)}} to the background drawable.
16219 * The default mode is {@link PorterDuff.Mode#SRC_ATOP}.
16221 * @param tintMode the blending mode used to apply the tint, may be
16222 * {@code null} to clear tint
16223 * @attr ref android.R.styleable#View_backgroundTintMode
16224 * @see #getBackgroundTintMode()
16225 * @see Drawable#setTintMode(PorterDuff.Mode)
16227 public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
16228 mBackgroundTintMode = tintMode;
16230 applyBackgroundTint();
16234 * @return the blending mode used to apply the tint to the background drawable
16235 * @attr ref android.R.styleable#View_backgroundTintMode
16236 * @see #setBackgroundTintMode(PorterDuff.Mode)
16239 public PorterDuff.Mode getBackgroundTintMode() {
16240 return mBackgroundTintMode;
16243 private void applyBackgroundTint() {
16244 if (mBackground != null && mHasBackgroundTint) {
16245 mBackground = mBackground.mutate();
16246 mBackground.setTintList(mBackgroundTintList);
16247 mBackground.setTintMode(mBackgroundTintMode);
16252 * Sets the padding. The view may add on the space required to display
16253 * the scrollbars, depending on the style and visibility of the scrollbars.
16254 * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
16255 * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
16256 * from the values set in this call.
16258 * @attr ref android.R.styleable#View_padding
16259 * @attr ref android.R.styleable#View_paddingBottom
16260 * @attr ref android.R.styleable#View_paddingLeft
16261 * @attr ref android.R.styleable#View_paddingRight
16262 * @attr ref android.R.styleable#View_paddingTop
16263 * @param left the left padding in pixels
16264 * @param top the top padding in pixels
16265 * @param right the right padding in pixels
16266 * @param bottom the bottom padding in pixels
16268 public void setPadding(int left, int top, int right, int bottom) {
16269 resetResolvedPadding();
16271 mUserPaddingStart = UNDEFINED_PADDING;
16272 mUserPaddingEnd = UNDEFINED_PADDING;
16274 mUserPaddingLeftInitial = left;
16275 mUserPaddingRightInitial = right;
16277 mLeftPaddingDefined = true;
16278 mRightPaddingDefined = true;
16280 internalSetPadding(left, top, right, bottom);
16286 protected void internalSetPadding(int left, int top, int right, int bottom) {
16287 mUserPaddingLeft = left;
16288 mUserPaddingRight = right;
16289 mUserPaddingBottom = bottom;
16291 final int viewFlags = mViewFlags;
16292 boolean changed = false;
16294 // Common case is there are no scroll bars.
16295 if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
16296 if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
16297 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
16298 ? 0 : getVerticalScrollbarWidth();
16299 switch (mVerticalScrollbarPosition) {
16300 case SCROLLBAR_POSITION_DEFAULT:
16301 if (isLayoutRtl()) {
16307 case SCROLLBAR_POSITION_RIGHT:
16310 case SCROLLBAR_POSITION_LEFT:
16315 if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
16316 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
16317 ? 0 : getHorizontalScrollbarHeight();
16321 if (mPaddingLeft != left) {
16323 mPaddingLeft = left;
16325 if (mPaddingTop != top) {
16329 if (mPaddingRight != right) {
16331 mPaddingRight = right;
16333 if (mPaddingBottom != bottom) {
16335 mPaddingBottom = bottom;
16344 * Sets the relative padding. The view may add on the space required to display
16345 * the scrollbars, depending on the style and visibility of the scrollbars.
16346 * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
16347 * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
16348 * from the values set in this call.
16350 * @attr ref android.R.styleable#View_padding
16351 * @attr ref android.R.styleable#View_paddingBottom
16352 * @attr ref android.R.styleable#View_paddingStart
16353 * @attr ref android.R.styleable#View_paddingEnd
16354 * @attr ref android.R.styleable#View_paddingTop
16355 * @param start the start padding in pixels
16356 * @param top the top padding in pixels
16357 * @param end the end padding in pixels
16358 * @param bottom the bottom padding in pixels
16360 public void setPaddingRelative(int start, int top, int end, int bottom) {
16361 resetResolvedPadding();
16363 mUserPaddingStart = start;
16364 mUserPaddingEnd = end;
16365 mLeftPaddingDefined = true;
16366 mRightPaddingDefined = true;
16368 switch(getLayoutDirection()) {
16369 case LAYOUT_DIRECTION_RTL:
16370 mUserPaddingLeftInitial = end;
16371 mUserPaddingRightInitial = start;
16372 internalSetPadding(end, top, start, bottom);
16374 case LAYOUT_DIRECTION_LTR:
16376 mUserPaddingLeftInitial = start;
16377 mUserPaddingRightInitial = end;
16378 internalSetPadding(start, top, end, bottom);
16383 * Returns the top padding of this view.
16385 * @return the top padding in pixels
16387 public int getPaddingTop() {
16388 return mPaddingTop;
16392 * Returns the bottom padding of this view. If there are inset and enabled
16393 * scrollbars, this value may include the space required to display the
16394 * scrollbars as well.
16396 * @return the bottom padding in pixels
16398 public int getPaddingBottom() {
16399 return mPaddingBottom;
16403 * Returns the left padding of this view. If there are inset and enabled
16404 * scrollbars, this value may include the space required to display the
16405 * scrollbars as well.
16407 * @return the left padding in pixels
16409 public int getPaddingLeft() {
16410 if (!isPaddingResolved()) {
16413 return mPaddingLeft;
16417 * Returns the start padding of this view depending on its resolved layout direction.
16418 * If there are inset and enabled scrollbars, this value may include the space
16419 * required to display the scrollbars as well.
16421 * @return the start padding in pixels
16423 public int getPaddingStart() {
16424 if (!isPaddingResolved()) {
16427 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
16428 mPaddingRight : mPaddingLeft;
16432 * Returns the right padding of this view. If there are inset and enabled
16433 * scrollbars, this value may include the space required to display the
16434 * scrollbars as well.
16436 * @return the right padding in pixels
16438 public int getPaddingRight() {
16439 if (!isPaddingResolved()) {
16442 return mPaddingRight;
16446 * Returns the end padding of this view depending on its resolved layout direction.
16447 * If there are inset and enabled scrollbars, this value may include the space
16448 * required to display the scrollbars as well.
16450 * @return the end padding in pixels
16452 public int getPaddingEnd() {
16453 if (!isPaddingResolved()) {
16456 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
16457 mPaddingLeft : mPaddingRight;
16461 * Return if the padding as been set thru relative values
16462 * {@link #setPaddingRelative(int, int, int, int)} or thru
16463 * @attr ref android.R.styleable#View_paddingStart or
16464 * @attr ref android.R.styleable#View_paddingEnd
16466 * @return true if the padding is relative or false if it is not.
16468 public boolean isPaddingRelative() {
16469 return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
16472 Insets computeOpticalInsets() {
16473 return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
16479 public void resetPaddingToInitialValues() {
16480 if (isRtlCompatibilityMode()) {
16481 mPaddingLeft = mUserPaddingLeftInitial;
16482 mPaddingRight = mUserPaddingRightInitial;
16485 if (isLayoutRtl()) {
16486 mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
16487 mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
16489 mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
16490 mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
16497 public Insets getOpticalInsets() {
16498 if (mLayoutInsets == null) {
16499 mLayoutInsets = computeOpticalInsets();
16501 return mLayoutInsets;
16505 * Set this view's optical insets.
16507 * <p>This method should be treated similarly to setMeasuredDimension and not as a general
16508 * property. Views that compute their own optical insets should call it as part of measurement.
16509 * This method does not request layout. If you are setting optical insets outside of
16510 * measure/layout itself you will want to call requestLayout() yourself.
16514 public void setOpticalInsets(Insets insets) {
16515 mLayoutInsets = insets;
16519 * Changes the selection state of this view. A view can be selected or not.
16520 * Note that selection is not the same as focus. Views are typically
16521 * selected in the context of an AdapterView like ListView or GridView;
16522 * the selected view is the view that is highlighted.
16524 * @param selected true if the view must be selected, false otherwise
16526 public void setSelected(boolean selected) {
16527 //noinspection DoubleNegation
16528 if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
16529 mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
16530 if (!selected) resetPressedState();
16532 refreshDrawableState();
16533 dispatchSetSelected(selected);
16534 notifyViewAccessibilityStateChangedIfNeeded(
16535 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
16540 * Dispatch setSelected to all of this View's children.
16542 * @see #setSelected(boolean)
16544 * @param selected The new selected state
16546 protected void dispatchSetSelected(boolean selected) {
16550 * Indicates the selection state of this view.
16552 * @return true if the view is selected, false otherwise
16554 @ViewDebug.ExportedProperty
16555 public boolean isSelected() {
16556 return (mPrivateFlags & PFLAG_SELECTED) != 0;
16560 * Changes the activated state of this view. A view can be activated or not.
16561 * Note that activation is not the same as selection. Selection is
16562 * a transient property, representing the view (hierarchy) the user is
16563 * currently interacting with. Activation is a longer-term state that the
16564 * user can move views in and out of. For example, in a list view with
16565 * single or multiple selection enabled, the views in the current selection
16566 * set are activated. (Um, yeah, we are deeply sorry about the terminology
16567 * here.) The activated state is propagated down to children of the view it
16570 * @param activated true if the view must be activated, false otherwise
16572 public void setActivated(boolean activated) {
16573 //noinspection DoubleNegation
16574 if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
16575 mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
16577 refreshDrawableState();
16578 dispatchSetActivated(activated);
16583 * Dispatch setActivated to all of this View's children.
16585 * @see #setActivated(boolean)
16587 * @param activated The new activated state
16589 protected void dispatchSetActivated(boolean activated) {
16593 * Indicates the activation state of this view.
16595 * @return true if the view is activated, false otherwise
16597 @ViewDebug.ExportedProperty
16598 public boolean isActivated() {
16599 return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
16603 * Returns the ViewTreeObserver for this view's hierarchy. The view tree
16604 * observer can be used to get notifications when global events, like
16607 * The returned ViewTreeObserver observer is not guaranteed to remain
16608 * valid for the lifetime of this View. If the caller of this method keeps
16609 * a long-lived reference to ViewTreeObserver, it should always check for
16610 * the return value of {@link ViewTreeObserver#isAlive()}.
16612 * @return The ViewTreeObserver for this view's hierarchy.
16614 public ViewTreeObserver getViewTreeObserver() {
16615 if (mAttachInfo != null) {
16616 return mAttachInfo.mTreeObserver;
16618 if (mFloatingTreeObserver == null) {
16619 mFloatingTreeObserver = new ViewTreeObserver();
16621 return mFloatingTreeObserver;
16625 * <p>Finds the topmost view in the current view hierarchy.</p>
16627 * @return the topmost view containing this view
16629 public View getRootView() {
16630 if (mAttachInfo != null) {
16631 final View v = mAttachInfo.mRootView;
16637 View parent = this;
16639 while (parent.mParent != null && parent.mParent instanceof View) {
16640 parent = (View) parent.mParent;
16647 * Transforms a motion event from view-local coordinates to on-screen
16650 * @param ev the view-local motion event
16651 * @return false if the transformation could not be applied
16654 public boolean toGlobalMotionEvent(MotionEvent ev) {
16655 final AttachInfo info = mAttachInfo;
16656 if (info == null) {
16660 final Matrix m = info.mTmpMatrix;
16661 m.set(Matrix.IDENTITY_MATRIX);
16662 transformMatrixToGlobal(m);
16668 * Transforms a motion event from on-screen coordinates to view-local
16671 * @param ev the on-screen motion event
16672 * @return false if the transformation could not be applied
16675 public boolean toLocalMotionEvent(MotionEvent ev) {
16676 final AttachInfo info = mAttachInfo;
16677 if (info == null) {
16681 final Matrix m = info.mTmpMatrix;
16682 m.set(Matrix.IDENTITY_MATRIX);
16683 transformMatrixToLocal(m);
16689 * Modifies the input matrix such that it maps view-local coordinates to
16690 * on-screen coordinates.
16692 * @param m input matrix to modify
16695 public void transformMatrixToGlobal(Matrix m) {
16696 final ViewParent parent = mParent;
16697 if (parent instanceof View) {
16698 final View vp = (View) parent;
16699 vp.transformMatrixToGlobal(m);
16700 m.preTranslate(-vp.mScrollX, -vp.mScrollY);
16701 } else if (parent instanceof ViewRootImpl) {
16702 final ViewRootImpl vr = (ViewRootImpl) parent;
16703 vr.transformMatrixToGlobal(m);
16704 m.preTranslate(0, -vr.mCurScrollY);
16707 m.preTranslate(mLeft, mTop);
16709 if (!hasIdentityMatrix()) {
16710 m.preConcat(getMatrix());
16715 * Modifies the input matrix such that it maps on-screen coordinates to
16716 * view-local coordinates.
16718 * @param m input matrix to modify
16721 public void transformMatrixToLocal(Matrix m) {
16722 final ViewParent parent = mParent;
16723 if (parent instanceof View) {
16724 final View vp = (View) parent;
16725 vp.transformMatrixToLocal(m);
16726 m.postTranslate(vp.mScrollX, vp.mScrollY);
16727 } else if (parent instanceof ViewRootImpl) {
16728 final ViewRootImpl vr = (ViewRootImpl) parent;
16729 vr.transformMatrixToLocal(m);
16730 m.postTranslate(0, vr.mCurScrollY);
16733 m.postTranslate(-mLeft, -mTop);
16735 if (!hasIdentityMatrix()) {
16736 m.postConcat(getInverseMatrix());
16743 @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
16744 @ViewDebug.IntToString(from = 0, to = "x"),
16745 @ViewDebug.IntToString(from = 1, to = "y")
16747 public int[] getLocationOnScreen() {
16748 int[] location = new int[2];
16749 getLocationOnScreen(location);
16754 * <p>Computes the coordinates of this view on the screen. The argument
16755 * must be an array of two integers. After the method returns, the array
16756 * contains the x and y location in that order.</p>
16758 * @param location an array of two integers in which to hold the coordinates
16760 public void getLocationOnScreen(int[] location) {
16761 getLocationInWindow(location);
16763 final AttachInfo info = mAttachInfo;
16764 if (info != null) {
16765 location[0] += info.mWindowLeft;
16766 location[1] += info.mWindowTop;
16771 * <p>Computes the coordinates of this view in its window. The argument
16772 * must be an array of two integers. After the method returns, the array
16773 * contains the x and y location in that order.</p>
16775 * @param location an array of two integers in which to hold the coordinates
16777 public void getLocationInWindow(int[] location) {
16778 if (location == null || location.length < 2) {
16779 throw new IllegalArgumentException("location must be an array of two integers");
16782 if (mAttachInfo == null) {
16783 // When the view is not attached to a window, this method does not make sense
16784 location[0] = location[1] = 0;
16788 float[] position = mAttachInfo.mTmpTransformLocation;
16789 position[0] = position[1] = 0.0f;
16791 if (!hasIdentityMatrix()) {
16792 getMatrix().mapPoints(position);
16795 position[0] += mLeft;
16796 position[1] += mTop;
16798 ViewParent viewParent = mParent;
16799 while (viewParent instanceof View) {
16800 final View view = (View) viewParent;
16802 position[0] -= view.mScrollX;
16803 position[1] -= view.mScrollY;
16805 if (!view.hasIdentityMatrix()) {
16806 view.getMatrix().mapPoints(position);
16809 position[0] += view.mLeft;
16810 position[1] += view.mTop;
16812 viewParent = view.mParent;
16815 if (viewParent instanceof ViewRootImpl) {
16817 final ViewRootImpl vr = (ViewRootImpl) viewParent;
16818 position[1] -= vr.mCurScrollY;
16821 location[0] = (int) (position[0] + 0.5f);
16822 location[1] = (int) (position[1] + 0.5f);
16827 * @param id the id of the view to be found
16828 * @return the view of the specified id, null if cannot be found
16830 protected View findViewTraversal(int id) {
16839 * @param tag the tag of the view to be found
16840 * @return the view of specified tag, null if cannot be found
16842 protected View findViewWithTagTraversal(Object tag) {
16843 if (tag != null && tag.equals(mTag)) {
16851 * @param predicate The predicate to evaluate.
16852 * @param childToSkip If not null, ignores this child during the recursive traversal.
16853 * @return The first view that matches the predicate or null.
16855 protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
16856 if (predicate.apply(this)) {
16863 * Look for a child view with the given id. If this view has the given
16864 * id, return this view.
16866 * @param id The id to search for.
16867 * @return The view that has the given id in the hierarchy or null
16869 public final View findViewById(int id) {
16873 return findViewTraversal(id);
16877 * Finds a view by its unuque and stable accessibility id.
16879 * @param accessibilityId The searched accessibility id.
16880 * @return The found view.
16882 final View findViewByAccessibilityId(int accessibilityId) {
16883 if (accessibilityId < 0) {
16886 return findViewByAccessibilityIdTraversal(accessibilityId);
16890 * Performs the traversal to find a view by its unuque and stable accessibility id.
16892 * <strong>Note:</strong>This method does not stop at the root namespace
16893 * boundary since the user can touch the screen at an arbitrary location
16894 * potentially crossing the root namespace bounday which will send an
16895 * accessibility event to accessibility services and they should be able
16896 * to obtain the event source. Also accessibility ids are guaranteed to be
16897 * unique in the window.
16899 * @param accessibilityId The accessibility id.
16900 * @return The found view.
16904 public View findViewByAccessibilityIdTraversal(int accessibilityId) {
16905 if (getAccessibilityViewId() == accessibilityId) {
16912 * Look for a child view with the given tag. If this view has the given
16913 * tag, return this view.
16915 * @param tag The tag to search for, using "tag.equals(getTag())".
16916 * @return The View that has the given tag in the hierarchy or null
16918 public final View findViewWithTag(Object tag) {
16922 return findViewWithTagTraversal(tag);
16927 * Look for a child view that matches the specified predicate.
16928 * If this view matches the predicate, return this view.
16930 * @param predicate The predicate to evaluate.
16931 * @return The first view that matches the predicate or null.
16933 public final View findViewByPredicate(Predicate<View> predicate) {
16934 return findViewByPredicateTraversal(predicate, null);
16939 * Look for a child view that matches the specified predicate,
16940 * starting with the specified view and its descendents and then
16941 * recusively searching the ancestors and siblings of that view
16942 * until this view is reached.
16944 * This method is useful in cases where the predicate does not match
16945 * a single unique view (perhaps multiple views use the same id)
16946 * and we are trying to find the view that is "closest" in scope to the
16949 * @param start The view to start from.
16950 * @param predicate The predicate to evaluate.
16951 * @return The first view that matches the predicate or null.
16953 public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
16954 View childToSkip = null;
16956 View view = start.findViewByPredicateTraversal(predicate, childToSkip);
16957 if (view != null || start == this) {
16961 ViewParent parent = start.getParent();
16962 if (parent == null || !(parent instanceof View)) {
16966 childToSkip = start;
16967 start = (View) parent;
16972 * Sets the identifier for this view. The identifier does not have to be
16973 * unique in this view's hierarchy. The identifier should be a positive
16978 * @see #findViewById(int)
16980 * @param id a number used to identify the view
16982 * @attr ref android.R.styleable#View_id
16984 public void setId(int id) {
16986 if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
16987 mID = generateViewId();
16994 * @param isRoot true if the view belongs to the root namespace, false
16997 public void setIsRootNamespace(boolean isRoot) {
16999 mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
17001 mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
17008 * @return true if the view belongs to the root namespace, false otherwise
17010 public boolean isRootNamespace() {
17011 return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
17015 * Returns this view's identifier.
17017 * @return a positive integer used to identify the view or {@link #NO_ID}
17018 * if the view has no ID
17021 * @see #findViewById(int)
17022 * @attr ref android.R.styleable#View_id
17024 @ViewDebug.CapturedViewProperty
17025 public int getId() {
17030 * Returns this view's tag.
17032 * @return the Object stored in this view as a tag, or {@code null} if not
17035 * @see #setTag(Object)
17036 * @see #getTag(int)
17038 @ViewDebug.ExportedProperty
17039 public Object getTag() {
17044 * Sets the tag associated with this view. A tag can be used to mark
17045 * a view in its hierarchy and does not have to be unique within the
17046 * hierarchy. Tags can also be used to store data within a view without
17047 * resorting to another data structure.
17049 * @param tag an Object to tag the view with
17052 * @see #setTag(int, Object)
17054 public void setTag(final Object tag) {
17059 * Returns the tag associated with this view and the specified key.
17061 * @param key The key identifying the tag
17063 * @return the Object stored in this view as a tag, or {@code null} if not
17066 * @see #setTag(int, Object)
17069 public Object getTag(int key) {
17070 if (mKeyedTags != null) return mKeyedTags.get(key);
17075 * Sets a tag associated with this view and a key. A tag can be used
17076 * to mark a view in its hierarchy and does not have to be unique within
17077 * the hierarchy. Tags can also be used to store data within a view
17078 * without resorting to another data structure.
17080 * The specified key should be an id declared in the resources of the
17081 * application to ensure it is unique (see the <a
17082 * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
17083 * Keys identified as belonging to
17084 * the Android framework or not associated with any package will cause
17085 * an {@link IllegalArgumentException} to be thrown.
17087 * @param key The key identifying the tag
17088 * @param tag An Object to tag the view with
17090 * @throws IllegalArgumentException If they specified key is not valid
17092 * @see #setTag(Object)
17093 * @see #getTag(int)
17095 public void setTag(int key, final Object tag) {
17096 // If the package id is 0x00 or 0x01, it's either an undefined package
17097 // or a framework id
17098 if ((key >>> 24) < 2) {
17099 throw new IllegalArgumentException("The key must be an application-specific "
17103 setKeyedTag(key, tag);
17107 * Variation of {@link #setTag(int, Object)} that enforces the key to be a
17112 public void setTagInternal(int key, Object tag) {
17113 if ((key >>> 24) != 0x1) {
17114 throw new IllegalArgumentException("The key must be a framework-specific "
17118 setKeyedTag(key, tag);
17121 private void setKeyedTag(int key, Object tag) {
17122 if (mKeyedTags == null) {
17123 mKeyedTags = new SparseArray<Object>(2);
17126 mKeyedTags.put(key, tag);
17130 * Prints information about this view in the log output, with the tag
17131 * {@link #VIEW_LOG_TAG}.
17135 public void debug() {
17140 * Prints information about this view in the log output, with the tag
17141 * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
17142 * indentation defined by the <code>depth</code>.
17144 * @param depth the indentation level
17148 protected void debug(int depth) {
17149 String output = debugIndent(depth - 1);
17151 output += "+ " + this;
17154 output += " (id=" + id + ")";
17156 Object tag = getTag();
17158 output += " (tag=" + tag + ")";
17160 Log.d(VIEW_LOG_TAG, output);
17162 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
17163 output = debugIndent(depth) + " FOCUSED";
17164 Log.d(VIEW_LOG_TAG, output);
17167 output = debugIndent(depth);
17168 output += "frame={" + mLeft + ", " + mTop + ", " + mRight
17169 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
17171 Log.d(VIEW_LOG_TAG, output);
17173 if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
17174 || mPaddingBottom != 0) {
17175 output = debugIndent(depth);
17176 output += "padding={" + mPaddingLeft + ", " + mPaddingTop
17177 + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
17178 Log.d(VIEW_LOG_TAG, output);
17181 output = debugIndent(depth);
17182 output += "mMeasureWidth=" + mMeasuredWidth +
17183 " mMeasureHeight=" + mMeasuredHeight;
17184 Log.d(VIEW_LOG_TAG, output);
17186 output = debugIndent(depth);
17187 if (mLayoutParams == null) {
17188 output += "BAD! no layout params";
17190 output = mLayoutParams.debug(output);
17192 Log.d(VIEW_LOG_TAG, output);
17194 output = debugIndent(depth);
17195 output += "flags={";
17196 output += View.printFlags(mViewFlags);
17198 Log.d(VIEW_LOG_TAG, output);
17200 output = debugIndent(depth);
17201 output += "privateFlags={";
17202 output += View.printPrivateFlags(mPrivateFlags);
17204 Log.d(VIEW_LOG_TAG, output);
17208 * Creates a string of whitespaces used for indentation.
17210 * @param depth the indentation level
17211 * @return a String containing (depth * 2 + 3) * 2 white spaces
17215 protected static String debugIndent(int depth) {
17216 StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
17217 for (int i = 0; i < (depth * 2) + 3; i++) {
17218 spaces.append(' ').append(' ');
17220 return spaces.toString();
17224 * <p>Return the offset of the widget's text baseline from the widget's top
17225 * boundary. If this widget does not support baseline alignment, this
17226 * method returns -1. </p>
17228 * @return the offset of the baseline within the widget's bounds or -1
17229 * if baseline alignment is not supported
17231 @ViewDebug.ExportedProperty(category = "layout")
17232 public int getBaseline() {
17237 * Returns whether the view hierarchy is currently undergoing a layout pass. This
17238 * information is useful to avoid situations such as calling {@link #requestLayout()} during
17241 * @return whether the view hierarchy is currently undergoing a layout pass
17243 public boolean isInLayout() {
17244 ViewRootImpl viewRoot = getViewRootImpl();
17245 return (viewRoot != null && viewRoot.isInLayout());
17249 * Call this when something has changed which has invalidated the
17250 * layout of this view. This will schedule a layout pass of the view
17251 * tree. This should not be called while the view hierarchy is currently in a layout
17252 * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
17253 * end of the current layout pass (and then layout will run again) or after the current
17254 * frame is drawn and the next layout occurs.
17256 * <p>Subclasses which override this method should call the superclass method to
17257 * handle possible request-during-layout errors correctly.</p>
17259 public void requestLayout() {
17260 if (mMeasureCache != null) mMeasureCache.clear();
17262 if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
17263 // Only trigger request-during-layout logic if this is the view requesting it,
17264 // not the views in its parent hierarchy
17265 ViewRootImpl viewRoot = getViewRootImpl();
17266 if (viewRoot != null && viewRoot.isInLayout()) {
17267 if (!viewRoot.requestLayoutDuringLayout(this)) {
17271 mAttachInfo.mViewRequestingLayout = this;
17274 mPrivateFlags |= PFLAG_FORCE_LAYOUT;
17275 mPrivateFlags |= PFLAG_INVALIDATED;
17277 if (mParent != null && !mParent.isLayoutRequested()) {
17278 mParent.requestLayout();
17280 if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
17281 mAttachInfo.mViewRequestingLayout = null;
17286 * Forces this view to be laid out during the next layout pass.
17287 * This method does not call requestLayout() or forceLayout()
17290 public void forceLayout() {
17291 if (mMeasureCache != null) mMeasureCache.clear();
17293 mPrivateFlags |= PFLAG_FORCE_LAYOUT;
17294 mPrivateFlags |= PFLAG_INVALIDATED;
17299 * This is called to find out how big a view should be. The parent
17300 * supplies constraint information in the width and height parameters.
17304 * The actual measurement work of a view is performed in
17305 * {@link #onMeasure(int, int)}, called by this method. Therefore, only
17306 * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
17310 * @param widthMeasureSpec Horizontal space requirements as imposed by the
17312 * @param heightMeasureSpec Vertical space requirements as imposed by the
17315 * @see #onMeasure(int, int)
17317 public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
17318 boolean optical = isLayoutModeOptical(this);
17319 if (optical != isLayoutModeOptical(mParent)) {
17320 Insets insets = getOpticalInsets();
17321 int oWidth = insets.left + insets.right;
17322 int oHeight = insets.top + insets.bottom;
17323 widthMeasureSpec = MeasureSpec.adjust(widthMeasureSpec, optical ? -oWidth : oWidth);
17324 heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
17327 // Suppress sign extension for the low bytes
17328 long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
17329 if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
17331 if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
17332 widthMeasureSpec != mOldWidthMeasureSpec ||
17333 heightMeasureSpec != mOldHeightMeasureSpec) {
17335 // first clears the measured dimension flag
17336 mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
17338 resolveRtlPropertiesIfNeeded();
17340 int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ? -1 :
17341 mMeasureCache.indexOfKey(key);
17342 if (cacheIndex < 0 || sIgnoreMeasureCache) {
17343 // measure ourselves, this should set the measured dimension flag back
17344 onMeasure(widthMeasureSpec, heightMeasureSpec);
17345 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
17347 long value = mMeasureCache.valueAt(cacheIndex);
17348 // Casting a long to int drops the high 32 bits, no mask needed
17349 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
17350 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
17353 // flag not set, setMeasuredDimension() was not invoked, we raise
17354 // an exception to warn the developer
17355 if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
17356 throw new IllegalStateException("onMeasure() did not set the"
17357 + " measured dimension by calling"
17358 + " setMeasuredDimension()");
17361 mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
17364 mOldWidthMeasureSpec = widthMeasureSpec;
17365 mOldHeightMeasureSpec = heightMeasureSpec;
17367 mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
17368 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
17373 * Measure the view and its content to determine the measured width and the
17374 * measured height. This method is invoked by {@link #measure(int, int)} and
17375 * should be overriden by subclasses to provide accurate and efficient
17376 * measurement of their contents.
17380 * <strong>CONTRACT:</strong> When overriding this method, you
17381 * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
17382 * measured width and height of this view. Failure to do so will trigger an
17383 * <code>IllegalStateException</code>, thrown by
17384 * {@link #measure(int, int)}. Calling the superclass'
17385 * {@link #onMeasure(int, int)} is a valid use.
17389 * The base class implementation of measure defaults to the background size,
17390 * unless a larger size is allowed by the MeasureSpec. Subclasses should
17391 * override {@link #onMeasure(int, int)} to provide better measurements of
17396 * If this method is overridden, it is the subclass's responsibility to make
17397 * sure the measured height and width are at least the view's minimum height
17398 * and width ({@link #getSuggestedMinimumHeight()} and
17399 * {@link #getSuggestedMinimumWidth()}).
17402 * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
17403 * The requirements are encoded with
17404 * {@link android.view.View.MeasureSpec}.
17405 * @param heightMeasureSpec vertical space requirements as imposed by the parent.
17406 * The requirements are encoded with
17407 * {@link android.view.View.MeasureSpec}.
17409 * @see #getMeasuredWidth()
17410 * @see #getMeasuredHeight()
17411 * @see #setMeasuredDimension(int, int)
17412 * @see #getSuggestedMinimumHeight()
17413 * @see #getSuggestedMinimumWidth()
17414 * @see android.view.View.MeasureSpec#getMode(int)
17415 * @see android.view.View.MeasureSpec#getSize(int)
17417 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
17418 setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
17419 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
17423 * <p>This method must be called by {@link #onMeasure(int, int)} to store the
17424 * measured width and measured height. Failing to do so will trigger an
17425 * exception at measurement time.</p>
17427 * @param measuredWidth The measured width of this view. May be a complex
17428 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17429 * {@link #MEASURED_STATE_TOO_SMALL}.
17430 * @param measuredHeight The measured height of this view. May be a complex
17431 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17432 * {@link #MEASURED_STATE_TOO_SMALL}.
17434 protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
17435 boolean optical = isLayoutModeOptical(this);
17436 if (optical != isLayoutModeOptical(mParent)) {
17437 Insets insets = getOpticalInsets();
17438 int opticalWidth = insets.left + insets.right;
17439 int opticalHeight = insets.top + insets.bottom;
17441 measuredWidth += optical ? opticalWidth : -opticalWidth;
17442 measuredHeight += optical ? opticalHeight : -opticalHeight;
17444 setMeasuredDimensionRaw(measuredWidth, measuredHeight);
17448 * Sets the measured dimension without extra processing for things like optical bounds.
17449 * Useful for reapplying consistent values that have already been cooked with adjustments
17450 * for optical bounds, etc. such as those from the measurement cache.
17452 * @param measuredWidth The measured width of this view. May be a complex
17453 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17454 * {@link #MEASURED_STATE_TOO_SMALL}.
17455 * @param measuredHeight The measured height of this view. May be a complex
17456 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17457 * {@link #MEASURED_STATE_TOO_SMALL}.
17459 private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
17460 mMeasuredWidth = measuredWidth;
17461 mMeasuredHeight = measuredHeight;
17463 mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
17467 * Merge two states as returned by {@link #getMeasuredState()}.
17468 * @param curState The current state as returned from a view or the result
17469 * of combining multiple views.
17470 * @param newState The new view state to combine.
17471 * @return Returns a new integer reflecting the combination of the two
17474 public static int combineMeasuredStates(int curState, int newState) {
17475 return curState | newState;
17479 * Version of {@link #resolveSizeAndState(int, int, int)}
17480 * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
17482 public static int resolveSize(int size, int measureSpec) {
17483 return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
17487 * Utility to reconcile a desired size and state, with constraints imposed
17488 * by a MeasureSpec. Will take the desired size, unless a different size
17489 * is imposed by the constraints. The returned value is a compound integer,
17490 * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
17491 * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting
17492 * size is smaller than the size the view wants to be.
17494 * @param size How big the view wants to be
17495 * @param measureSpec Constraints imposed by the parent
17496 * @return Size information bit mask as defined by
17497 * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
17499 public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
17501 int specMode = MeasureSpec.getMode(measureSpec);
17502 int specSize = MeasureSpec.getSize(measureSpec);
17503 switch (specMode) {
17504 case MeasureSpec.UNSPECIFIED:
17507 case MeasureSpec.AT_MOST:
17508 if (specSize < size) {
17509 result = specSize | MEASURED_STATE_TOO_SMALL;
17514 case MeasureSpec.EXACTLY:
17518 return result | (childMeasuredState&MEASURED_STATE_MASK);
17522 * Utility to return a default size. Uses the supplied size if the
17523 * MeasureSpec imposed no constraints. Will get larger if allowed
17524 * by the MeasureSpec.
17526 * @param size Default size for this view
17527 * @param measureSpec Constraints imposed by the parent
17528 * @return The size this view should be.
17530 public static int getDefaultSize(int size, int measureSpec) {
17532 int specMode = MeasureSpec.getMode(measureSpec);
17533 int specSize = MeasureSpec.getSize(measureSpec);
17535 switch (specMode) {
17536 case MeasureSpec.UNSPECIFIED:
17539 case MeasureSpec.AT_MOST:
17540 case MeasureSpec.EXACTLY:
17548 * Returns the suggested minimum height that the view should use. This
17549 * returns the maximum of the view's minimum height
17550 * and the background's minimum height
17551 * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
17553 * When being used in {@link #onMeasure(int, int)}, the caller should still
17554 * ensure the returned height is within the requirements of the parent.
17556 * @return The suggested minimum height of the view.
17558 protected int getSuggestedMinimumHeight() {
17559 return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
17564 * Returns the suggested minimum width that the view should use. This
17565 * returns the maximum of the view's minimum width)
17566 * and the background's minimum width
17567 * ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
17569 * When being used in {@link #onMeasure(int, int)}, the caller should still
17570 * ensure the returned width is within the requirements of the parent.
17572 * @return The suggested minimum width of the view.
17574 protected int getSuggestedMinimumWidth() {
17575 return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
17579 * Returns the minimum height of the view.
17581 * @return the minimum height the view will try to be.
17583 * @see #setMinimumHeight(int)
17585 * @attr ref android.R.styleable#View_minHeight
17587 public int getMinimumHeight() {
17592 * Sets the minimum height of the view. It is not guaranteed the view will
17593 * be able to achieve this minimum height (for example, if its parent layout
17594 * constrains it with less available height).
17596 * @param minHeight The minimum height the view will try to be.
17598 * @see #getMinimumHeight()
17600 * @attr ref android.R.styleable#View_minHeight
17602 public void setMinimumHeight(int minHeight) {
17603 mMinHeight = minHeight;
17608 * Returns the minimum width of the view.
17610 * @return the minimum width the view will try to be.
17612 * @see #setMinimumWidth(int)
17614 * @attr ref android.R.styleable#View_minWidth
17616 public int getMinimumWidth() {
17621 * Sets the minimum width of the view. It is not guaranteed the view will
17622 * be able to achieve this minimum width (for example, if its parent layout
17623 * constrains it with less available width).
17625 * @param minWidth The minimum width the view will try to be.
17627 * @see #getMinimumWidth()
17629 * @attr ref android.R.styleable#View_minWidth
17631 public void setMinimumWidth(int minWidth) {
17632 mMinWidth = minWidth;
17638 * Get the animation currently associated with this view.
17640 * @return The animation that is currently playing or
17641 * scheduled to play for this view.
17643 public Animation getAnimation() {
17644 return mCurrentAnimation;
17648 * Start the specified animation now.
17650 * @param animation the animation to start now
17652 public void startAnimation(Animation animation) {
17653 animation.setStartTime(Animation.START_ON_FIRST_FRAME);
17654 setAnimation(animation);
17655 invalidateParentCaches();
17660 * Cancels any animations for this view.
17662 public void clearAnimation() {
17663 if (mCurrentAnimation != null) {
17664 mCurrentAnimation.detach();
17666 mCurrentAnimation = null;
17667 invalidateParentIfNeeded();
17671 * Sets the next animation to play for this view.
17672 * If you want the animation to play immediately, use
17673 * {@link #startAnimation(android.view.animation.Animation)} instead.
17674 * This method provides allows fine-grained
17675 * control over the start time and invalidation, but you
17676 * must make sure that 1) the animation has a start time set, and
17677 * 2) the view's parent (which controls animations on its children)
17678 * will be invalidated when the animation is supposed to
17681 * @param animation The next animation, or null.
17683 public void setAnimation(Animation animation) {
17684 mCurrentAnimation = animation;
17686 if (animation != null) {
17687 // If the screen is off assume the animation start time is now instead of
17688 // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
17689 // would cause the animation to start when the screen turns back on
17690 if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
17691 && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
17692 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
17699 * Invoked by a parent ViewGroup to notify the start of the animation
17700 * currently associated with this view. If you override this method,
17701 * always call super.onAnimationStart();
17703 * @see #setAnimation(android.view.animation.Animation)
17704 * @see #getAnimation()
17706 protected void onAnimationStart() {
17707 mPrivateFlags |= PFLAG_ANIMATION_STARTED;
17711 * Invoked by a parent ViewGroup to notify the end of the animation
17712 * currently associated with this view. If you override this method,
17713 * always call super.onAnimationEnd();
17715 * @see #setAnimation(android.view.animation.Animation)
17716 * @see #getAnimation()
17718 protected void onAnimationEnd() {
17719 mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
17723 * Invoked if there is a Transform that involves alpha. Subclass that can
17724 * draw themselves with the specified alpha should return true, and then
17725 * respect that alpha when their onDraw() is called. If this returns false
17726 * then the view may be redirected to draw into an offscreen buffer to
17727 * fulfill the request, which will look fine, but may be slower than if the
17728 * subclass handles it internally. The default implementation returns false.
17730 * @param alpha The alpha (0..255) to apply to the view's drawing
17731 * @return true if the view can draw with the specified alpha.
17733 protected boolean onSetAlpha(int alpha) {
17738 * This is used by the RootView to perform an optimization when
17739 * the view hierarchy contains one or several SurfaceView.
17740 * SurfaceView is always considered transparent, but its children are not,
17741 * therefore all View objects remove themselves from the global transparent
17742 * region (passed as a parameter to this function).
17744 * @param region The transparent region for this ViewAncestor (window).
17746 * @return Returns true if the effective visibility of the view at this
17747 * point is opaque, regardless of the transparent region; returns false
17748 * if it is possible for underlying windows to be seen behind the view.
17752 public boolean gatherTransparentRegion(Region region) {
17753 final AttachInfo attachInfo = mAttachInfo;
17754 if (region != null && attachInfo != null) {
17755 final int pflags = mPrivateFlags;
17756 if ((pflags & PFLAG_SKIP_DRAW) == 0) {
17757 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
17758 // remove it from the transparent region.
17759 final int[] location = attachInfo.mTransparentLocation;
17760 getLocationInWindow(location);
17761 region.op(location[0], location[1], location[0] + mRight - mLeft,
17762 location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
17763 } else if ((pflags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null &&
17764 mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
17765 // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
17766 // exists, so we remove the background drawable's non-transparent
17767 // parts from this transparent region.
17768 applyDrawableToTransparentRegion(mBackground, region);
17775 * Play a sound effect for this view.
17777 * <p>The framework will play sound effects for some built in actions, such as
17778 * clicking, but you may wish to play these effects in your widget,
17779 * for instance, for internal navigation.
17781 * <p>The sound effect will only be played if sound effects are enabled by the user, and
17782 * {@link #isSoundEffectsEnabled()} is true.
17784 * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
17786 public void playSoundEffect(int soundConstant) {
17787 if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
17790 mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
17796 * <p>Provide haptic feedback to the user for this view.
17798 * <p>The framework will provide haptic feedback for some built in actions,
17799 * such as long presses, but you may wish to provide feedback for your
17802 * <p>The feedback will only be performed if
17803 * {@link #isHapticFeedbackEnabled()} is true.
17805 * @param feedbackConstant One of the constants defined in
17806 * {@link HapticFeedbackConstants}
17808 public boolean performHapticFeedback(int feedbackConstant) {
17809 return performHapticFeedback(feedbackConstant, 0);
17815 * <p>Like {@link #performHapticFeedback(int)}, with additional options.
17817 * @param feedbackConstant One of the constants defined in
17818 * {@link HapticFeedbackConstants}
17819 * @param flags Additional flags as per {@link HapticFeedbackConstants}.
17821 public boolean performHapticFeedback(int feedbackConstant, int flags) {
17822 if (mAttachInfo == null) {
17825 //noinspection SimplifiableIfStatement
17826 if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
17827 && !isHapticFeedbackEnabled()) {
17830 return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
17831 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
17835 * Request that the visibility of the status bar or other screen/window
17836 * decorations be changed.
17838 * <p>This method is used to put the over device UI into temporary modes
17839 * where the user's attention is focused more on the application content,
17840 * by dimming or hiding surrounding system affordances. This is typically
17841 * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
17842 * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
17843 * to be placed behind the action bar (and with these flags other system
17844 * affordances) so that smooth transitions between hiding and showing them
17847 * <p>Two representative examples of the use of system UI visibility is
17848 * implementing a content browsing application (like a magazine reader)
17849 * and a video playing application.
17851 * <p>The first code shows a typical implementation of a View in a content
17852 * browsing application. In this implementation, the application goes
17853 * into a content-oriented mode by hiding the status bar and action bar,
17854 * and putting the navigation elements into lights out mode. The user can
17855 * then interact with content while in this mode. Such an application should
17856 * provide an easy way for the user to toggle out of the mode (such as to
17857 * check information in the status bar or access notifications). In the
17858 * implementation here, this is done simply by tapping on the content.
17860 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
17863 * <p>This second code sample shows a typical implementation of a View
17864 * in a video playing application. In this situation, while the video is
17865 * playing the application would like to go into a complete full-screen mode,
17866 * to use as much of the display as possible for the video. When in this state
17867 * the user can not interact with the application; the system intercepts
17868 * touching on the screen to pop the UI out of full screen mode. See
17869 * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
17871 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
17874 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
17875 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
17876 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
17877 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
17878 * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
17880 public void setSystemUiVisibility(int visibility) {
17881 if (visibility != mSystemUiVisibility) {
17882 mSystemUiVisibility = visibility;
17883 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
17884 mParent.recomputeViewAttributes(this);
17890 * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
17891 * @return Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
17892 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
17893 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
17894 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
17895 * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
17897 public int getSystemUiVisibility() {
17898 return mSystemUiVisibility;
17902 * Returns the current system UI visibility that is currently set for
17903 * the entire window. This is the combination of the
17904 * {@link #setSystemUiVisibility(int)} values supplied by all of the
17905 * views in the window.
17907 public int getWindowSystemUiVisibility() {
17908 return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
17912 * Override to find out when the window's requested system UI visibility
17913 * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
17914 * This is different from the callbacks received through
17915 * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
17916 * in that this is only telling you about the local request of the window,
17917 * not the actual values applied by the system.
17919 public void onWindowSystemUiVisibilityChanged(int visible) {
17923 * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
17924 * the view hierarchy.
17926 public void dispatchWindowSystemUiVisiblityChanged(int visible) {
17927 onWindowSystemUiVisibilityChanged(visible);
17931 * Set a listener to receive callbacks when the visibility of the system bar changes.
17932 * @param l The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
17934 public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
17935 getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
17936 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
17937 mParent.recomputeViewAttributes(this);
17942 * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
17943 * the view hierarchy.
17945 public void dispatchSystemUiVisibilityChanged(int visibility) {
17946 ListenerInfo li = mListenerInfo;
17947 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
17948 li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
17949 visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
17953 boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
17954 int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
17955 if (val != mSystemUiVisibility) {
17956 setSystemUiVisibility(val);
17963 public void setDisabledSystemUiVisibility(int flags) {
17964 if (mAttachInfo != null) {
17965 if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
17966 mAttachInfo.mDisabledSystemUiVisibility = flags;
17967 if (mParent != null) {
17968 mParent.recomputeViewAttributes(this);
17975 * Creates an image that the system displays during the drag and drop
17976 * operation. This is called a "drag shadow". The default implementation
17977 * for a DragShadowBuilder based on a View returns an image that has exactly the same
17978 * appearance as the given View. The default also positions the center of the drag shadow
17979 * directly under the touch point. If no View is provided (the constructor with no parameters
17980 * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
17981 * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overriden, then the
17982 * default is an invisible drag shadow.
17984 * You are not required to use the View you provide to the constructor as the basis of the
17985 * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
17986 * anything you want as the drag shadow.
17989 * You pass a DragShadowBuilder object to the system when you start the drag. The system
17990 * calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
17991 * size and position of the drag shadow. It uses this data to construct a
17992 * {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
17993 * so that your application can draw the shadow image in the Canvas.
17996 * <div class="special reference">
17997 * <h3>Developer Guides</h3>
17998 * <p>For a guide to implementing drag and drop features, read the
17999 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
18002 public static class DragShadowBuilder {
18003 private final WeakReference<View> mView;
18006 * Constructs a shadow image builder based on a View. By default, the resulting drag
18007 * shadow will have the same appearance and dimensions as the View, with the touch point
18008 * over the center of the View.
18009 * @param view A View. Any View in scope can be used.
18011 public DragShadowBuilder(View view) {
18012 mView = new WeakReference<View>(view);
18016 * Construct a shadow builder object with no associated View. This
18017 * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
18018 * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
18019 * to supply the drag shadow's dimensions and appearance without
18020 * reference to any View object. If they are not overridden, then the result is an
18021 * invisible drag shadow.
18023 public DragShadowBuilder() {
18024 mView = new WeakReference<View>(null);
18028 * Returns the View object that had been passed to the
18029 * {@link #View.DragShadowBuilder(View)}
18030 * constructor. If that View parameter was {@code null} or if the
18031 * {@link #View.DragShadowBuilder()}
18032 * constructor was used to instantiate the builder object, this method will return
18035 * @return The View object associate with this builder object.
18037 @SuppressWarnings({"JavadocReference"})
18038 final public View getView() {
18039 return mView.get();
18043 * Provides the metrics for the shadow image. These include the dimensions of
18044 * the shadow image, and the point within that shadow that should
18045 * be centered under the touch location while dragging.
18047 * The default implementation sets the dimensions of the shadow to be the
18048 * same as the dimensions of the View itself and centers the shadow under
18052 * @param shadowSize A {@link android.graphics.Point} containing the width and height
18053 * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
18054 * desired width and must set {@link android.graphics.Point#y} to the desired height of the
18057 * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
18058 * shadow image that should be underneath the touch point during the drag and drop
18059 * operation. Your application must set {@link android.graphics.Point#x} to the
18060 * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
18062 public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
18063 final View view = mView.get();
18064 if (view != null) {
18065 shadowSize.set(view.getWidth(), view.getHeight());
18066 shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
18068 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
18073 * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
18074 * based on the dimensions it received from the
18075 * {@link #onProvideShadowMetrics(Point, Point)} callback.
18077 * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
18079 public void onDrawShadow(Canvas canvas) {
18080 final View view = mView.get();
18081 if (view != null) {
18084 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
18090 * Starts a drag and drop operation. When your application calls this method, it passes a
18091 * {@link android.view.View.DragShadowBuilder} object to the system. The
18092 * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
18093 * to get metrics for the drag shadow, and then calls the object's
18094 * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
18096 * Once the system has the drag shadow, it begins the drag and drop operation by sending
18097 * drag events to all the View objects in your application that are currently visible. It does
18098 * this either by calling the View object's drag listener (an implementation of
18099 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
18100 * View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
18101 * Both are passed a {@link android.view.DragEvent} object that has a
18102 * {@link android.view.DragEvent#getAction()} value of
18103 * {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
18106 * Your application can invoke startDrag() on any attached View object. The View object does not
18107 * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
18108 * be related to the View the user selected for dragging.
18110 * @param data A {@link android.content.ClipData} object pointing to the data to be
18111 * transferred by the drag and drop operation.
18112 * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
18114 * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
18115 * drop operation. This Object is put into every DragEvent object sent by the system during the
18118 * myLocalState is a lightweight mechanism for the sending information from the dragged View
18119 * to the target Views. For example, it can contain flags that differentiate between a
18120 * a copy operation and a move operation.
18122 * @param flags Flags that control the drag and drop operation. No flags are currently defined,
18123 * so the parameter should be set to 0.
18124 * @return {@code true} if the method completes successfully, or
18125 * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
18126 * do a drag, and so no drag operation is in progress.
18128 public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
18129 Object myLocalState, int flags) {
18130 if (ViewDebug.DEBUG_DRAG) {
18131 Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
18133 boolean okay = false;
18135 Point shadowSize = new Point();
18136 Point shadowTouchPoint = new Point();
18137 shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
18139 if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
18140 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
18141 throw new IllegalStateException("Drag shadow dimensions must not be negative");
18144 if (ViewDebug.DEBUG_DRAG) {
18145 Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
18146 + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
18148 Surface surface = new Surface();
18150 IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
18151 flags, shadowSize.x, shadowSize.y, surface);
18152 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
18153 + " surface=" + surface);
18154 if (token != null) {
18155 Canvas canvas = surface.lockCanvas(null);
18157 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
18158 shadowBuilder.onDrawShadow(canvas);
18160 surface.unlockCanvasAndPost(canvas);
18163 final ViewRootImpl root = getViewRootImpl();
18165 // Cache the local state object for delivery with DragEvents
18166 root.setLocalDragState(myLocalState);
18168 // repurpose 'shadowSize' for the last touch point
18169 root.getLastTouchPoint(shadowSize);
18171 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
18172 shadowSize.x, shadowSize.y,
18173 shadowTouchPoint.x, shadowTouchPoint.y, data);
18174 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
18176 // Off and running! Release our local surface instance; the drag
18177 // shadow surface is now managed by the system process.
18180 } catch (Exception e) {
18181 Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
18189 * Handles drag events sent by the system following a call to
18190 * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
18192 * When the system calls this method, it passes a
18193 * {@link android.view.DragEvent} object. A call to
18194 * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
18195 * in DragEvent. The method uses these to determine what is happening in the drag and drop
18197 * @param event The {@link android.view.DragEvent} sent by the system.
18198 * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
18199 * in DragEvent, indicating the type of drag event represented by this object.
18200 * @return {@code true} if the method was successful, otherwise {@code false}.
18202 * The method should return {@code true} in response to an action type of
18203 * {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
18207 * The method should also return {@code true} in response to an action type of
18208 * {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
18209 * {@code false} if it didn't.
18212 public boolean onDragEvent(DragEvent event) {
18217 * Detects if this View is enabled and has a drag event listener.
18218 * If both are true, then it calls the drag event listener with the
18219 * {@link android.view.DragEvent} it received. If the drag event listener returns
18220 * {@code true}, then dispatchDragEvent() returns {@code true}.
18222 * For all other cases, the method calls the
18223 * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
18224 * method and returns its result.
18227 * This ensures that a drag event is always consumed, even if the View does not have a drag
18228 * event listener. However, if the View has a listener and the listener returns true, then
18229 * onDragEvent() is not called.
18232 public boolean dispatchDragEvent(DragEvent event) {
18233 ListenerInfo li = mListenerInfo;
18234 //noinspection SimplifiableIfStatement
18235 if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
18236 && li.mOnDragListener.onDrag(this, event)) {
18239 return onDragEvent(event);
18242 boolean canAcceptDrag() {
18243 return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
18247 * This needs to be a better API (NOT ON VIEW) before it is exposed. If
18248 * it is ever exposed at all.
18251 public void onCloseSystemDialogs(String reason) {
18255 * Given a Drawable whose bounds have been set to draw into this view,
18256 * update a Region being computed for
18257 * {@link #gatherTransparentRegion(android.graphics.Region)} so
18258 * that any non-transparent parts of the Drawable are removed from the
18259 * given transparent region.
18261 * @param dr The Drawable whose transparency is to be applied to the region.
18262 * @param region A Region holding the current transparency information,
18263 * where any parts of the region that are set are considered to be
18264 * transparent. On return, this region will be modified to have the
18265 * transparency information reduced by the corresponding parts of the
18266 * Drawable that are not transparent.
18269 public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
18271 Log.i("View", "Getting transparent region for: " + this);
18273 final Region r = dr.getTransparentRegion();
18274 final Rect db = dr.getBounds();
18275 final AttachInfo attachInfo = mAttachInfo;
18276 if (r != null && attachInfo != null) {
18277 final int w = getRight()-getLeft();
18278 final int h = getBottom()-getTop();
18280 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
18281 r.op(0, 0, db.left, h, Region.Op.UNION);
18283 if (db.right < w) {
18284 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
18285 r.op(db.right, 0, w, h, Region.Op.UNION);
18288 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
18289 r.op(0, 0, w, db.top, Region.Op.UNION);
18291 if (db.bottom < h) {
18292 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
18293 r.op(0, db.bottom, w, h, Region.Op.UNION);
18295 final int[] location = attachInfo.mTransparentLocation;
18296 getLocationInWindow(location);
18297 r.translate(location[0], location[1]);
18298 region.op(r, Region.Op.INTERSECT);
18300 region.op(db, Region.Op.DIFFERENCE);
18304 private void checkForLongClick(int delayOffset) {
18305 if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
18306 mHasPerformedLongPress = false;
18308 if (mPendingCheckForLongPress == null) {
18309 mPendingCheckForLongPress = new CheckForLongPress();
18311 mPendingCheckForLongPress.rememberWindowAttachCount();
18312 postDelayed(mPendingCheckForLongPress,
18313 ViewConfiguration.getLongPressTimeout() - delayOffset);
18318 * Inflate a view from an XML resource. This convenience method wraps the {@link
18319 * LayoutInflater} class, which provides a full range of options for view inflation.
18321 * @param context The Context object for your activity or application.
18322 * @param resource The resource ID to inflate
18323 * @param root A view group that will be the parent. Used to properly inflate the
18324 * layout_* parameters.
18325 * @see LayoutInflater
18327 public static View inflate(Context context, int resource, ViewGroup root) {
18328 LayoutInflater factory = LayoutInflater.from(context);
18329 return factory.inflate(resource, root);
18333 * Scroll the view with standard behavior for scrolling beyond the normal
18334 * content boundaries. Views that call this method should override
18335 * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
18336 * results of an over-scroll operation.
18338 * Views can use this method to handle any touch or fling-based scrolling.
18340 * @param deltaX Change in X in pixels
18341 * @param deltaY Change in Y in pixels
18342 * @param scrollX Current X scroll value in pixels before applying deltaX
18343 * @param scrollY Current Y scroll value in pixels before applying deltaY
18344 * @param scrollRangeX Maximum content scroll range along the X axis
18345 * @param scrollRangeY Maximum content scroll range along the Y axis
18346 * @param maxOverScrollX Number of pixels to overscroll by in either direction
18347 * along the X axis.
18348 * @param maxOverScrollY Number of pixels to overscroll by in either direction
18349 * along the Y axis.
18350 * @param isTouchEvent true if this scroll operation is the result of a touch event.
18351 * @return true if scrolling was clamped to an over-scroll boundary along either
18352 * axis, false otherwise.
18354 @SuppressWarnings({"UnusedParameters"})
18355 protected boolean overScrollBy(int deltaX, int deltaY,
18356 int scrollX, int scrollY,
18357 int scrollRangeX, int scrollRangeY,
18358 int maxOverScrollX, int maxOverScrollY,
18359 boolean isTouchEvent) {
18360 final int overScrollMode = mOverScrollMode;
18361 final boolean canScrollHorizontal =
18362 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
18363 final boolean canScrollVertical =
18364 computeVerticalScrollRange() > computeVerticalScrollExtent();
18365 final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
18366 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
18367 final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
18368 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
18370 int newScrollX = scrollX + deltaX;
18371 if (!overScrollHorizontal) {
18372 maxOverScrollX = 0;
18375 int newScrollY = scrollY + deltaY;
18376 if (!overScrollVertical) {
18377 maxOverScrollY = 0;
18380 // Clamp values if at the limits and record
18381 final int left = -maxOverScrollX;
18382 final int right = maxOverScrollX + scrollRangeX;
18383 final int top = -maxOverScrollY;
18384 final int bottom = maxOverScrollY + scrollRangeY;
18386 boolean clampedX = false;
18387 if (newScrollX > right) {
18388 newScrollX = right;
18390 } else if (newScrollX < left) {
18395 boolean clampedY = false;
18396 if (newScrollY > bottom) {
18397 newScrollY = bottom;
18399 } else if (newScrollY < top) {
18404 onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
18406 return clampedX || clampedY;
18410 * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
18411 * respond to the results of an over-scroll operation.
18413 * @param scrollX New X scroll value in pixels
18414 * @param scrollY New Y scroll value in pixels
18415 * @param clampedX True if scrollX was clamped to an over-scroll boundary
18416 * @param clampedY True if scrollY was clamped to an over-scroll boundary
18418 protected void onOverScrolled(int scrollX, int scrollY,
18419 boolean clampedX, boolean clampedY) {
18420 // Intentionally empty.
18424 * Returns the over-scroll mode for this view. The result will be
18425 * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
18426 * (allow over-scrolling only if the view content is larger than the container),
18427 * or {@link #OVER_SCROLL_NEVER}.
18429 * @return This view's over-scroll mode.
18431 public int getOverScrollMode() {
18432 return mOverScrollMode;
18436 * Set the over-scroll mode for this view. Valid over-scroll modes are
18437 * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
18438 * (allow over-scrolling only if the view content is larger than the container),
18439 * or {@link #OVER_SCROLL_NEVER}.
18441 * Setting the over-scroll mode of a view will have an effect only if the
18442 * view is capable of scrolling.
18444 * @param overScrollMode The new over-scroll mode for this view.
18446 public void setOverScrollMode(int overScrollMode) {
18447 if (overScrollMode != OVER_SCROLL_ALWAYS &&
18448 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
18449 overScrollMode != OVER_SCROLL_NEVER) {
18450 throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
18452 mOverScrollMode = overScrollMode;
18456 * Enable or disable nested scrolling for this view.
18458 * <p>If this property is set to true the view will be permitted to initiate nested
18459 * scrolling operations with a compatible parent view in the current hierarchy. If this
18460 * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
18461 * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
18462 * the nested scroll.</p>
18464 * @param enabled true to enable nested scrolling, false to disable
18466 * @see #isNestedScrollingEnabled()
18468 public void setNestedScrollingEnabled(boolean enabled) {
18470 mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
18472 stopNestedScroll();
18473 mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
18478 * Returns true if nested scrolling is enabled for this view.
18480 * <p>If nested scrolling is enabled and this View class implementation supports it,
18481 * this view will act as a nested scrolling child view when applicable, forwarding data
18482 * about the scroll operation in progress to a compatible and cooperating nested scrolling
18485 * @return true if nested scrolling is enabled
18487 * @see #setNestedScrollingEnabled(boolean)
18489 public boolean isNestedScrollingEnabled() {
18490 return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
18491 PFLAG3_NESTED_SCROLLING_ENABLED;
18495 * Begin a nestable scroll operation along the given axes.
18497 * <p>A view starting a nested scroll promises to abide by the following contract:</p>
18499 * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
18500 * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
18501 * In the case of touch scrolling the nested scroll will be terminated automatically in
18502 * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
18503 * In the event of programmatic scrolling the caller must explicitly call
18504 * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
18506 * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
18507 * If it returns false the caller may ignore the rest of this contract until the next scroll.
18508 * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
18510 * <p>At each incremental step of the scroll the caller should invoke
18511 * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
18512 * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
18513 * parent at least partially consumed the scroll and the caller should adjust the amount it
18516 * <p>After applying the remainder of the scroll delta the caller should invoke
18517 * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
18518 * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
18519 * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
18522 * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
18523 * {@link #SCROLL_AXIS_VERTICAL}.
18524 * @return true if a cooperative parent was found and nested scrolling has been enabled for
18525 * the current gesture.
18527 * @see #stopNestedScroll()
18528 * @see #dispatchNestedPreScroll(int, int, int[], int[])
18529 * @see #dispatchNestedScroll(int, int, int, int, int[])
18531 public boolean startNestedScroll(int axes) {
18532 if (hasNestedScrollingParent()) {
18533 // Already in progress
18536 if (isNestedScrollingEnabled()) {
18537 ViewParent p = getParent();
18539 while (p != null) {
18541 if (p.onStartNestedScroll(child, this, axes)) {
18542 mNestedScrollingParent = p;
18543 p.onNestedScrollAccepted(child, this, axes);
18546 } catch (AbstractMethodError e) {
18547 Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
18548 "method onStartNestedScroll", e);
18549 // Allow the search upward to continue
18551 if (p instanceof View) {
18561 * Stop a nested scroll in progress.
18563 * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
18565 * @see #startNestedScroll(int)
18567 public void stopNestedScroll() {
18568 if (mNestedScrollingParent != null) {
18569 mNestedScrollingParent.onStopNestedScroll(this);
18570 mNestedScrollingParent = null;
18575 * Returns true if this view has a nested scrolling parent.
18577 * <p>The presence of a nested scrolling parent indicates that this view has initiated
18578 * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
18580 * @return whether this view has a nested scrolling parent
18582 public boolean hasNestedScrollingParent() {
18583 return mNestedScrollingParent != null;
18587 * Dispatch one step of a nested scroll in progress.
18589 * <p>Implementations of views that support nested scrolling should call this to report
18590 * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
18591 * is not currently in progress or nested scrolling is not
18592 * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
18594 * <p>Compatible View implementations should also call
18595 * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
18596 * consuming a component of the scroll event themselves.</p>
18598 * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
18599 * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
18600 * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
18601 * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
18602 * @param offsetInWindow Optional. If not null, on return this will contain the offset
18603 * in local view coordinates of this view from before this operation
18604 * to after it completes. View implementations may use this to adjust
18605 * expected input coordinate tracking.
18606 * @return true if the event was dispatched, false if it could not be dispatched.
18607 * @see #dispatchNestedPreScroll(int, int, int[], int[])
18609 public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
18610 int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
18611 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18612 if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
18615 if (offsetInWindow != null) {
18616 getLocationInWindow(offsetInWindow);
18617 startX = offsetInWindow[0];
18618 startY = offsetInWindow[1];
18621 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
18622 dxUnconsumed, dyUnconsumed);
18624 if (offsetInWindow != null) {
18625 getLocationInWindow(offsetInWindow);
18626 offsetInWindow[0] -= startX;
18627 offsetInWindow[1] -= startY;
18630 } else if (offsetInWindow != null) {
18631 // No motion, no dispatch. Keep offsetInWindow up to date.
18632 offsetInWindow[0] = 0;
18633 offsetInWindow[1] = 0;
18640 * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
18642 * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
18643 * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
18644 * scrolling operation to consume some or all of the scroll operation before the child view
18647 * @param dx Horizontal scroll distance in pixels
18648 * @param dy Vertical scroll distance in pixels
18649 * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
18650 * and consumed[1] the consumed dy.
18651 * @param offsetInWindow Optional. If not null, on return this will contain the offset
18652 * in local view coordinates of this view from before this operation
18653 * to after it completes. View implementations may use this to adjust
18654 * expected input coordinate tracking.
18655 * @return true if the parent consumed some or all of the scroll delta
18656 * @see #dispatchNestedScroll(int, int, int, int, int[])
18658 public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
18659 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18660 if (dx != 0 || dy != 0) {
18663 if (offsetInWindow != null) {
18664 getLocationInWindow(offsetInWindow);
18665 startX = offsetInWindow[0];
18666 startY = offsetInWindow[1];
18669 if (consumed == null) {
18670 if (mTempNestedScrollConsumed == null) {
18671 mTempNestedScrollConsumed = new int[2];
18673 consumed = mTempNestedScrollConsumed;
18677 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
18679 if (offsetInWindow != null) {
18680 getLocationInWindow(offsetInWindow);
18681 offsetInWindow[0] -= startX;
18682 offsetInWindow[1] -= startY;
18684 return consumed[0] != 0 || consumed[1] != 0;
18685 } else if (offsetInWindow != null) {
18686 offsetInWindow[0] = 0;
18687 offsetInWindow[1] = 0;
18694 * Dispatch a fling to a nested scrolling parent.
18696 * <p>This method should be used to indicate that a nested scrolling child has detected
18697 * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
18698 * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
18699 * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
18700 * along a scrollable axis.</p>
18702 * <p>If a nested scrolling child view would normally fling but it is at the edge of
18703 * its own content, it can use this method to delegate the fling to its nested scrolling
18704 * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
18706 * @param velocityX Horizontal fling velocity in pixels per second
18707 * @param velocityY Vertical fling velocity in pixels per second
18708 * @param consumed true if the child consumed the fling, false otherwise
18709 * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
18711 public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
18712 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18713 return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
18719 * Dispatch a fling to a nested scrolling parent before it is processed by this view.
18721 * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
18722 * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
18723 * offsets an opportunity for the parent view in a nested fling to fully consume the fling
18724 * before the child view consumes it. If this method returns <code>true</code>, a nested
18725 * parent view consumed the fling and this view should not scroll as a result.</p>
18727 * <p>For a better user experience, only one view in a nested scrolling chain should consume
18728 * the fling at a time. If a parent view consumed the fling this method will return false.
18729 * Custom view implementations should account for this in two ways:</p>
18732 * <li>If a custom view is paged and needs to settle to a fixed page-point, do not
18733 * call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
18734 * position regardless.</li>
18735 * <li>If a nested parent does consume the fling, this view should not scroll at all,
18736 * even to settle back to a valid idle position.</li>
18739 * <p>Views should also not offer fling velocities to nested parent views along an axis
18740 * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
18741 * should not offer a horizontal fling velocity to its parents since scrolling along that
18742 * axis is not permitted and carrying velocity along that motion does not make sense.</p>
18744 * @param velocityX Horizontal fling velocity in pixels per second
18745 * @param velocityY Vertical fling velocity in pixels per second
18746 * @return true if a nested scrolling parent consumed the fling
18748 public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
18749 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18750 return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
18756 * Gets a scale factor that determines the distance the view should scroll
18757 * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
18758 * @return The vertical scroll scale factor.
18761 protected float getVerticalScrollFactor() {
18762 if (mVerticalScrollFactor == 0) {
18763 TypedValue outValue = new TypedValue();
18764 if (!mContext.getTheme().resolveAttribute(
18765 com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
18766 throw new IllegalStateException(
18767 "Expected theme to define listPreferredItemHeight.");
18769 mVerticalScrollFactor = outValue.getDimension(
18770 mContext.getResources().getDisplayMetrics());
18772 return mVerticalScrollFactor;
18776 * Gets a scale factor that determines the distance the view should scroll
18777 * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
18778 * @return The horizontal scroll scale factor.
18781 protected float getHorizontalScrollFactor() {
18782 // TODO: Should use something else.
18783 return getVerticalScrollFactor();
18787 * Return the value specifying the text direction or policy that was set with
18788 * {@link #setTextDirection(int)}.
18790 * @return the defined text direction. It can be one of:
18792 * {@link #TEXT_DIRECTION_INHERIT},
18793 * {@link #TEXT_DIRECTION_FIRST_STRONG}
18794 * {@link #TEXT_DIRECTION_ANY_RTL},
18795 * {@link #TEXT_DIRECTION_LTR},
18796 * {@link #TEXT_DIRECTION_RTL},
18797 * {@link #TEXT_DIRECTION_LOCALE}
18799 * @attr ref android.R.styleable#View_textDirection
18803 @ViewDebug.ExportedProperty(category = "text", mapping = {
18804 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
18805 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
18806 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
18807 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
18808 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
18809 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
18811 public int getRawTextDirection() {
18812 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
18816 * Set the text direction.
18818 * @param textDirection the direction to set. Should be one of:
18820 * {@link #TEXT_DIRECTION_INHERIT},
18821 * {@link #TEXT_DIRECTION_FIRST_STRONG}
18822 * {@link #TEXT_DIRECTION_ANY_RTL},
18823 * {@link #TEXT_DIRECTION_LTR},
18824 * {@link #TEXT_DIRECTION_RTL},
18825 * {@link #TEXT_DIRECTION_LOCALE}
18827 * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
18828 * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
18829 * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
18831 * @attr ref android.R.styleable#View_textDirection
18833 public void setTextDirection(int textDirection) {
18834 if (getRawTextDirection() != textDirection) {
18835 // Reset the current text direction and the resolved one
18836 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
18837 resetResolvedTextDirection();
18838 // Set the new text direction
18839 mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
18841 resolveTextDirection();
18843 onRtlPropertiesChanged(getLayoutDirection());
18851 * Return the resolved text direction.
18853 * @return the resolved text direction. Returns one of:
18855 * {@link #TEXT_DIRECTION_FIRST_STRONG}
18856 * {@link #TEXT_DIRECTION_ANY_RTL},
18857 * {@link #TEXT_DIRECTION_LTR},
18858 * {@link #TEXT_DIRECTION_RTL},
18859 * {@link #TEXT_DIRECTION_LOCALE}
18861 * @attr ref android.R.styleable#View_textDirection
18863 @ViewDebug.ExportedProperty(category = "text", mapping = {
18864 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
18865 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
18866 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
18867 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
18868 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
18869 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
18871 public int getTextDirection() {
18872 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
18876 * Resolve the text direction.
18878 * @return true if resolution has been done, false otherwise.
18882 public boolean resolveTextDirection() {
18883 // Reset any previous text direction resolution
18884 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
18886 if (hasRtlSupport()) {
18887 // Set resolved text direction flag depending on text direction flag
18888 final int textDirection = getRawTextDirection();
18889 switch(textDirection) {
18890 case TEXT_DIRECTION_INHERIT:
18891 if (!canResolveTextDirection()) {
18892 // We cannot do the resolution if there is no parent, so use the default one
18893 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
18894 // Resolution will need to happen again later
18898 // Parent has not yet resolved, so we still return the default
18900 if (!mParent.isTextDirectionResolved()) {
18901 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
18902 // Resolution will need to happen again later
18905 } catch (AbstractMethodError e) {
18906 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
18907 " does not fully implement ViewParent", e);
18908 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
18909 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
18913 // Set current resolved direction to the same value as the parent's one
18914 int parentResolvedDirection;
18916 parentResolvedDirection = mParent.getTextDirection();
18917 } catch (AbstractMethodError e) {
18918 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
18919 " does not fully implement ViewParent", e);
18920 parentResolvedDirection = TEXT_DIRECTION_LTR;
18922 switch (parentResolvedDirection) {
18923 case TEXT_DIRECTION_FIRST_STRONG:
18924 case TEXT_DIRECTION_ANY_RTL:
18925 case TEXT_DIRECTION_LTR:
18926 case TEXT_DIRECTION_RTL:
18927 case TEXT_DIRECTION_LOCALE:
18929 (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
18932 // Default resolved direction is "first strong" heuristic
18933 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
18936 case TEXT_DIRECTION_FIRST_STRONG:
18937 case TEXT_DIRECTION_ANY_RTL:
18938 case TEXT_DIRECTION_LTR:
18939 case TEXT_DIRECTION_RTL:
18940 case TEXT_DIRECTION_LOCALE:
18941 // Resolved direction is the same as text direction
18942 mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
18945 // Default resolved direction is "first strong" heuristic
18946 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
18949 // Default resolved direction is "first strong" heuristic
18950 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
18954 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
18959 * Check if text direction resolution can be done.
18961 * @return true if text direction resolution can be done otherwise return false.
18963 public boolean canResolveTextDirection() {
18964 switch (getRawTextDirection()) {
18965 case TEXT_DIRECTION_INHERIT:
18966 if (mParent != null) {
18968 return mParent.canResolveTextDirection();
18969 } catch (AbstractMethodError e) {
18970 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
18971 " does not fully implement ViewParent", e);
18982 * Reset resolved text direction. Text direction will be resolved during a call to
18983 * {@link #onMeasure(int, int)}.
18987 public void resetResolvedTextDirection() {
18988 // Reset any previous text direction resolution
18989 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
18990 // Set to default value
18991 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
18995 * @return true if text direction is inherited.
18999 public boolean isTextDirectionInherited() {
19000 return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
19004 * @return true if text direction is resolved.
19006 public boolean isTextDirectionResolved() {
19007 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
19011 * Return the value specifying the text alignment or policy that was set with
19012 * {@link #setTextAlignment(int)}.
19014 * @return the defined text alignment. It can be one of:
19016 * {@link #TEXT_ALIGNMENT_INHERIT},
19017 * {@link #TEXT_ALIGNMENT_GRAVITY},
19018 * {@link #TEXT_ALIGNMENT_CENTER},
19019 * {@link #TEXT_ALIGNMENT_TEXT_START},
19020 * {@link #TEXT_ALIGNMENT_TEXT_END},
19021 * {@link #TEXT_ALIGNMENT_VIEW_START},
19022 * {@link #TEXT_ALIGNMENT_VIEW_END}
19024 * @attr ref android.R.styleable#View_textAlignment
19028 @ViewDebug.ExportedProperty(category = "text", mapping = {
19029 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
19030 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
19031 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
19032 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
19033 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
19034 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
19035 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
19038 public int getRawTextAlignment() {
19039 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
19043 * Set the text alignment.
19045 * @param textAlignment The text alignment to set. Should be one of
19047 * {@link #TEXT_ALIGNMENT_INHERIT},
19048 * {@link #TEXT_ALIGNMENT_GRAVITY},
19049 * {@link #TEXT_ALIGNMENT_CENTER},
19050 * {@link #TEXT_ALIGNMENT_TEXT_START},
19051 * {@link #TEXT_ALIGNMENT_TEXT_END},
19052 * {@link #TEXT_ALIGNMENT_VIEW_START},
19053 * {@link #TEXT_ALIGNMENT_VIEW_END}
19055 * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
19056 * proceeds up the parent chain of the view to get the value. If there is no parent, then it
19057 * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
19059 * @attr ref android.R.styleable#View_textAlignment
19061 public void setTextAlignment(@TextAlignment int textAlignment) {
19062 if (textAlignment != getRawTextAlignment()) {
19063 // Reset the current and resolved text alignment
19064 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
19065 resetResolvedTextAlignment();
19066 // Set the new text alignment
19068 ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
19070 resolveTextAlignment();
19072 onRtlPropertiesChanged(getLayoutDirection());
19080 * Return the resolved text alignment.
19082 * @return the resolved text alignment. Returns one of:
19084 * {@link #TEXT_ALIGNMENT_GRAVITY},
19085 * {@link #TEXT_ALIGNMENT_CENTER},
19086 * {@link #TEXT_ALIGNMENT_TEXT_START},
19087 * {@link #TEXT_ALIGNMENT_TEXT_END},
19088 * {@link #TEXT_ALIGNMENT_VIEW_START},
19089 * {@link #TEXT_ALIGNMENT_VIEW_END}
19091 * @attr ref android.R.styleable#View_textAlignment
19093 @ViewDebug.ExportedProperty(category = "text", mapping = {
19094 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
19095 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
19096 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
19097 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
19098 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
19099 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
19100 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
19103 public int getTextAlignment() {
19104 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
19105 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
19109 * Resolve the text alignment.
19111 * @return true if resolution has been done, false otherwise.
19115 public boolean resolveTextAlignment() {
19116 // Reset any previous text alignment resolution
19117 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
19119 if (hasRtlSupport()) {
19120 // Set resolved text alignment flag depending on text alignment flag
19121 final int textAlignment = getRawTextAlignment();
19122 switch (textAlignment) {
19123 case TEXT_ALIGNMENT_INHERIT:
19124 // Check if we can resolve the text alignment
19125 if (!canResolveTextAlignment()) {
19126 // We cannot do the resolution if there is no parent so use the default
19127 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19128 // Resolution will need to happen again later
19132 // Parent has not yet resolved, so we still return the default
19134 if (!mParent.isTextAlignmentResolved()) {
19135 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19136 // Resolution will need to happen again later
19139 } catch (AbstractMethodError e) {
19140 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19141 " does not fully implement ViewParent", e);
19142 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
19143 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19147 int parentResolvedTextAlignment;
19149 parentResolvedTextAlignment = mParent.getTextAlignment();
19150 } catch (AbstractMethodError e) {
19151 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19152 " does not fully implement ViewParent", e);
19153 parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
19155 switch (parentResolvedTextAlignment) {
19156 case TEXT_ALIGNMENT_GRAVITY:
19157 case TEXT_ALIGNMENT_TEXT_START:
19158 case TEXT_ALIGNMENT_TEXT_END:
19159 case TEXT_ALIGNMENT_CENTER:
19160 case TEXT_ALIGNMENT_VIEW_START:
19161 case TEXT_ALIGNMENT_VIEW_END:
19162 // Resolved text alignment is the same as the parent resolved
19165 (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
19168 // Use default resolved text alignment
19169 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19172 case TEXT_ALIGNMENT_GRAVITY:
19173 case TEXT_ALIGNMENT_TEXT_START:
19174 case TEXT_ALIGNMENT_TEXT_END:
19175 case TEXT_ALIGNMENT_CENTER:
19176 case TEXT_ALIGNMENT_VIEW_START:
19177 case TEXT_ALIGNMENT_VIEW_END:
19178 // Resolved text alignment is the same as text alignment
19179 mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
19182 // Use default resolved text alignment
19183 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19186 // Use default resolved text alignment
19187 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19190 // Set the resolved
19191 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
19196 * Check if text alignment resolution can be done.
19198 * @return true if text alignment resolution can be done otherwise return false.
19200 public boolean canResolveTextAlignment() {
19201 switch (getRawTextAlignment()) {
19202 case TEXT_DIRECTION_INHERIT:
19203 if (mParent != null) {
19205 return mParent.canResolveTextAlignment();
19206 } catch (AbstractMethodError e) {
19207 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19208 " does not fully implement ViewParent", e);
19219 * Reset resolved text alignment. Text alignment will be resolved during a call to
19220 * {@link #onMeasure(int, int)}.
19224 public void resetResolvedTextAlignment() {
19225 // Reset any previous text alignment resolution
19226 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
19228 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19232 * @return true if text alignment is inherited.
19236 public boolean isTextAlignmentInherited() {
19237 return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
19241 * @return true if text alignment is resolved.
19243 public boolean isTextAlignmentResolved() {
19244 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
19248 * Generate a value suitable for use in {@link #setId(int)}.
19249 * This value will not collide with ID values generated at build time by aapt for R.id.
19251 * @return a generated ID value
19253 public static int generateViewId() {
19255 final int result = sNextGeneratedId.get();
19256 // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
19257 int newValue = result + 1;
19258 if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
19259 if (sNextGeneratedId.compareAndSet(result, newValue)) {
19266 * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
19267 * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
19268 * a normal View or a ViewGroup with
19269 * {@link android.view.ViewGroup#isTransitionGroup()} true.
19272 public void captureTransitioningViews(List<View> transitioningViews) {
19273 if (getVisibility() == View.VISIBLE) {
19274 transitioningViews.add(this);
19279 * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
19280 * @param namedElements Will contain all Views in the hierarchy having a transitionName.
19283 public void findNamedViews(Map<String, View> namedElements) {
19284 if (getVisibility() == VISIBLE || mGhostView != null) {
19285 String transitionName = getTransitionName();
19286 if (transitionName != null) {
19287 namedElements.put(transitionName, this);
19296 * A Property wrapper around the <code>alpha</code> functionality handled by the
19297 * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
19299 public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
19301 public void setValue(View object, float value) {
19302 object.setAlpha(value);
19306 public Float get(View object) {
19307 return object.getAlpha();
19312 * A Property wrapper around the <code>translationX</code> functionality handled by the
19313 * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
19315 public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
19317 public void setValue(View object, float value) {
19318 object.setTranslationX(value);
19322 public Float get(View object) {
19323 return object.getTranslationX();
19328 * A Property wrapper around the <code>translationY</code> functionality handled by the
19329 * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
19331 public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
19333 public void setValue(View object, float value) {
19334 object.setTranslationY(value);
19338 public Float get(View object) {
19339 return object.getTranslationY();
19344 * A Property wrapper around the <code>translationZ</code> functionality handled by the
19345 * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
19347 public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
19349 public void setValue(View object, float value) {
19350 object.setTranslationZ(value);
19354 public Float get(View object) {
19355 return object.getTranslationZ();
19360 * A Property wrapper around the <code>x</code> functionality handled by the
19361 * {@link View#setX(float)} and {@link View#getX()} methods.
19363 public static final Property<View, Float> X = new FloatProperty<View>("x") {
19365 public void setValue(View object, float value) {
19366 object.setX(value);
19370 public Float get(View object) {
19371 return object.getX();
19376 * A Property wrapper around the <code>y</code> functionality handled by the
19377 * {@link View#setY(float)} and {@link View#getY()} methods.
19379 public static final Property<View, Float> Y = new FloatProperty<View>("y") {
19381 public void setValue(View object, float value) {
19382 object.setY(value);
19386 public Float get(View object) {
19387 return object.getY();
19392 * A Property wrapper around the <code>z</code> functionality handled by the
19393 * {@link View#setZ(float)} and {@link View#getZ()} methods.
19395 public static final Property<View, Float> Z = new FloatProperty<View>("z") {
19397 public void setValue(View object, float value) {
19398 object.setZ(value);
19402 public Float get(View object) {
19403 return object.getZ();
19408 * A Property wrapper around the <code>rotation</code> functionality handled by the
19409 * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
19411 public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
19413 public void setValue(View object, float value) {
19414 object.setRotation(value);
19418 public Float get(View object) {
19419 return object.getRotation();
19424 * A Property wrapper around the <code>rotationX</code> functionality handled by the
19425 * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
19427 public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
19429 public void setValue(View object, float value) {
19430 object.setRotationX(value);
19434 public Float get(View object) {
19435 return object.getRotationX();
19440 * A Property wrapper around the <code>rotationY</code> functionality handled by the
19441 * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
19443 public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
19445 public void setValue(View object, float value) {
19446 object.setRotationY(value);
19450 public Float get(View object) {
19451 return object.getRotationY();
19456 * A Property wrapper around the <code>scaleX</code> functionality handled by the
19457 * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
19459 public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
19461 public void setValue(View object, float value) {
19462 object.setScaleX(value);
19466 public Float get(View object) {
19467 return object.getScaleX();
19472 * A Property wrapper around the <code>scaleY</code> functionality handled by the
19473 * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
19475 public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
19477 public void setValue(View object, float value) {
19478 object.setScaleY(value);
19482 public Float get(View object) {
19483 return object.getScaleY();
19488 * A MeasureSpec encapsulates the layout requirements passed from parent to child.
19489 * Each MeasureSpec represents a requirement for either the width or the height.
19490 * A MeasureSpec is comprised of a size and a mode. There are three possible
19493 * <dt>UNSPECIFIED</dt>
19495 * The parent has not imposed any constraint on the child. It can be whatever size
19501 * The parent has determined an exact size for the child. The child is going to be
19502 * given those bounds regardless of how big it wants to be.
19507 * The child can be as large as it wants up to the specified size.
19511 * MeasureSpecs are implemented as ints to reduce object allocation. This class
19512 * is provided to pack and unpack the <size, mode> tuple into the int.
19514 public static class MeasureSpec {
19515 private static final int MODE_SHIFT = 30;
19516 private static final int MODE_MASK = 0x3 << MODE_SHIFT;
19519 * Measure specification mode: The parent has not imposed any constraint
19520 * on the child. It can be whatever size it wants.
19522 public static final int UNSPECIFIED = 0 << MODE_SHIFT;
19525 * Measure specification mode: The parent has determined an exact size
19526 * for the child. The child is going to be given those bounds regardless
19527 * of how big it wants to be.
19529 public static final int EXACTLY = 1 << MODE_SHIFT;
19532 * Measure specification mode: The child can be as large as it wants up
19533 * to the specified size.
19535 public static final int AT_MOST = 2 << MODE_SHIFT;
19538 * Creates a measure specification based on the supplied size and mode.
19540 * The mode must always be one of the following:
19542 * <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
19543 * <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
19544 * <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
19547 * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
19548 * implementation was such that the order of arguments did not matter
19549 * and overflow in either value could impact the resulting MeasureSpec.
19550 * {@link android.widget.RelativeLayout} was affected by this bug.
19551 * Apps targeting API levels greater than 17 will get the fixed, more strict
19554 * @param size the size of the measure specification
19555 * @param mode the mode of the measure specification
19556 * @return the measure specification based on size and mode
19558 public static int makeMeasureSpec(int size, int mode) {
19559 if (sUseBrokenMakeMeasureSpec) {
19560 return size + mode;
19562 return (size & ~MODE_MASK) | (mode & MODE_MASK);
19567 * Extracts the mode from the supplied measure specification.
19569 * @param measureSpec the measure specification to extract the mode from
19570 * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
19571 * {@link android.view.View.MeasureSpec#AT_MOST} or
19572 * {@link android.view.View.MeasureSpec#EXACTLY}
19574 public static int getMode(int measureSpec) {
19575 return (measureSpec & MODE_MASK);
19579 * Extracts the size from the supplied measure specification.
19581 * @param measureSpec the measure specification to extract the size from
19582 * @return the size in pixels defined in the supplied measure specification
19584 public static int getSize(int measureSpec) {
19585 return (measureSpec & ~MODE_MASK);
19588 static int adjust(int measureSpec, int delta) {
19589 final int mode = getMode(measureSpec);
19590 if (mode == UNSPECIFIED) {
19591 // No need to adjust size for UNSPECIFIED mode.
19592 return makeMeasureSpec(0, UNSPECIFIED);
19594 int size = getSize(measureSpec) + delta;
19596 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
19597 ") spec: " + toString(measureSpec) + " delta: " + delta);
19600 return makeMeasureSpec(size, mode);
19604 * Returns a String representation of the specified measure
19607 * @param measureSpec the measure specification to convert to a String
19608 * @return a String with the following format: "MeasureSpec: MODE SIZE"
19610 public static String toString(int measureSpec) {
19611 int mode = getMode(measureSpec);
19612 int size = getSize(measureSpec);
19614 StringBuilder sb = new StringBuilder("MeasureSpec: ");
19616 if (mode == UNSPECIFIED)
19617 sb.append("UNSPECIFIED ");
19618 else if (mode == EXACTLY)
19619 sb.append("EXACTLY ");
19620 else if (mode == AT_MOST)
19621 sb.append("AT_MOST ");
19623 sb.append(mode).append(" ");
19626 return sb.toString();
19630 private final class CheckForLongPress implements Runnable {
19631 private int mOriginalWindowAttachCount;
19634 public void run() {
19635 if (isPressed() && (mParent != null)
19636 && mOriginalWindowAttachCount == mWindowAttachCount) {
19637 if (performLongClick()) {
19638 mHasPerformedLongPress = true;
19643 public void rememberWindowAttachCount() {
19644 mOriginalWindowAttachCount = mWindowAttachCount;
19648 private final class CheckForTap implements Runnable {
19653 public void run() {
19654 mPrivateFlags &= ~PFLAG_PREPRESSED;
19655 setPressed(true, x, y);
19656 checkForLongClick(ViewConfiguration.getTapTimeout());
19660 private final class PerformClick implements Runnable {
19662 public void run() {
19668 public void hackTurnOffWindowResizeAnim(boolean off) {
19669 mAttachInfo.mTurnOffWindowResizeAnim = off;
19673 * This method returns a ViewPropertyAnimator object, which can be used to animate
19674 * specific properties on this View.
19676 * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
19678 public ViewPropertyAnimator animate() {
19679 if (mAnimator == null) {
19680 mAnimator = new ViewPropertyAnimator(this);
19686 * Sets the name of the View to be used to identify Views in Transitions.
19687 * Names should be unique in the View hierarchy.
19689 * @param transitionName The name of the View to uniquely identify it for Transitions.
19691 public final void setTransitionName(String transitionName) {
19692 mTransitionName = transitionName;
19696 * Returns the name of the View to be used to identify Views in Transitions.
19697 * Names should be unique in the View hierarchy.
19699 * <p>This returns null if the View has not been given a name.</p>
19701 * @return The name used of the View to be used to identify Views in Transitions or null
19702 * if no name has been given.
19704 @ViewDebug.ExportedProperty
19705 public String getTransitionName() {
19706 return mTransitionName;
19710 * Interface definition for a callback to be invoked when a hardware key event is
19711 * dispatched to this view. The callback will be invoked before the key event is
19712 * given to the view. This is only useful for hardware keyboards; a software input
19713 * method has no obligation to trigger this listener.
19715 public interface OnKeyListener {
19717 * Called when a hardware key is dispatched to a view. This allows listeners to
19718 * get a chance to respond before the target view.
19719 * <p>Key presses in software keyboards will generally NOT trigger this method,
19720 * although some may elect to do so in some situations. Do not assume a
19721 * software input method has to be key-based; even if it is, it may use key presses
19722 * in a different way than you expect, so there is no way to reliably catch soft
19723 * input key presses.
19725 * @param v The view the key has been dispatched to.
19726 * @param keyCode The code for the physical key that was pressed
19727 * @param event The KeyEvent object containing full information about
19729 * @return True if the listener has consumed the event, false otherwise.
19731 boolean onKey(View v, int keyCode, KeyEvent event);
19735 * Interface definition for a callback to be invoked when a touch event is
19736 * dispatched to this view. The callback will be invoked before the touch
19737 * event is given to the view.
19739 public interface OnTouchListener {
19741 * Called when a touch event is dispatched to a view. This allows listeners to
19742 * get a chance to respond before the target view.
19744 * @param v The view the touch event has been dispatched to.
19745 * @param event The MotionEvent object containing full information about
19747 * @return True if the listener has consumed the event, false otherwise.
19749 boolean onTouch(View v, MotionEvent event);
19753 * Interface definition for a callback to be invoked when a hover event is
19754 * dispatched to this view. The callback will be invoked before the hover
19755 * event is given to the view.
19757 public interface OnHoverListener {
19759 * Called when a hover event is dispatched to a view. This allows listeners to
19760 * get a chance to respond before the target view.
19762 * @param v The view the hover event has been dispatched to.
19763 * @param event The MotionEvent object containing full information about
19765 * @return True if the listener has consumed the event, false otherwise.
19767 boolean onHover(View v, MotionEvent event);
19771 * Interface definition for a callback to be invoked when a generic motion event is
19772 * dispatched to this view. The callback will be invoked before the generic motion
19773 * event is given to the view.
19775 public interface OnGenericMotionListener {
19777 * Called when a generic motion event is dispatched to a view. This allows listeners to
19778 * get a chance to respond before the target view.
19780 * @param v The view the generic motion event has been dispatched to.
19781 * @param event The MotionEvent object containing full information about
19783 * @return True if the listener has consumed the event, false otherwise.
19785 boolean onGenericMotion(View v, MotionEvent event);
19789 * Interface definition for a callback to be invoked when a view has been clicked and held.
19791 public interface OnLongClickListener {
19793 * Called when a view has been clicked and held.
19795 * @param v The view that was clicked and held.
19797 * @return true if the callback consumed the long click, false otherwise.
19799 boolean onLongClick(View v);
19803 * Interface definition for a callback to be invoked when a drag is being dispatched
19804 * to this view. The callback will be invoked before the hosting view's own
19805 * onDrag(event) method. If the listener wants to fall back to the hosting view's
19806 * onDrag(event) behavior, it should return 'false' from this callback.
19808 * <div class="special reference">
19809 * <h3>Developer Guides</h3>
19810 * <p>For a guide to implementing drag and drop features, read the
19811 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
19814 public interface OnDragListener {
19816 * Called when a drag event is dispatched to a view. This allows listeners
19817 * to get a chance to override base View behavior.
19819 * @param v The View that received the drag event.
19820 * @param event The {@link android.view.DragEvent} object for the drag event.
19821 * @return {@code true} if the drag event was handled successfully, or {@code false}
19822 * if the drag event was not handled. Note that {@code false} will trigger the View
19823 * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
19825 boolean onDrag(View v, DragEvent event);
19829 * Interface definition for a callback to be invoked when the focus state of
19832 public interface OnFocusChangeListener {
19834 * Called when the focus state of a view has changed.
19836 * @param v The view whose state has changed.
19837 * @param hasFocus The new focus state of v.
19839 void onFocusChange(View v, boolean hasFocus);
19843 * Interface definition for a callback to be invoked when a view is clicked.
19845 public interface OnClickListener {
19847 * Called when a view has been clicked.
19849 * @param v The view that was clicked.
19851 void onClick(View v);
19855 * Interface definition for a callback to be invoked when the context menu
19856 * for this view is being built.
19858 public interface OnCreateContextMenuListener {
19860 * Called when the context menu for this view is being built. It is not
19861 * safe to hold onto the menu after this method returns.
19863 * @param menu The context menu that is being built
19864 * @param v The view for which the context menu is being built
19865 * @param menuInfo Extra information about the item for which the
19866 * context menu should be shown. This information will vary
19867 * depending on the class of v.
19869 void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
19873 * Interface definition for a callback to be invoked when the status bar changes
19874 * visibility. This reports <strong>global</strong> changes to the system UI
19875 * state, not what the application is requesting.
19877 * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
19879 public interface OnSystemUiVisibilityChangeListener {
19881 * Called when the status bar changes visibility because of a call to
19882 * {@link View#setSystemUiVisibility(int)}.
19884 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19885 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
19886 * This tells you the <strong>global</strong> state of these UI visibility
19887 * flags, not what your app is currently applying.
19889 public void onSystemUiVisibilityChange(int visibility);
19893 * Interface definition for a callback to be invoked when this view is attached
19894 * or detached from its window.
19896 public interface OnAttachStateChangeListener {
19898 * Called when the view is attached to a window.
19899 * @param v The view that was attached
19901 public void onViewAttachedToWindow(View v);
19903 * Called when the view is detached from a window.
19904 * @param v The view that was detached
19906 public void onViewDetachedFromWindow(View v);
19910 * Listener for applying window insets on a view in a custom way.
19912 * <p>Apps may choose to implement this interface if they want to apply custom policy
19913 * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
19915 * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
19916 * method will be called instead of the View's own
19917 * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
19918 * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
19919 * the View's normal behavior as part of its own.</p>
19921 public interface OnApplyWindowInsetsListener {
19923 * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
19924 * on a View, this listener method will be called instead of the view's own
19925 * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
19927 * @param v The view applying window insets
19928 * @param insets The insets to apply
19929 * @return The insets supplied, minus any insets that were consumed
19931 public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
19934 private final class UnsetPressedState implements Runnable {
19936 public void run() {
19942 * Base class for derived classes that want to save and restore their own
19943 * state in {@link android.view.View#onSaveInstanceState()}.
19945 public static class BaseSavedState extends AbsSavedState {
19947 * Constructor used when reading from a parcel. Reads the state of the superclass.
19951 public BaseSavedState(Parcel source) {
19956 * Constructor called by derived classes when creating their SavedState objects
19958 * @param superState The state of the superclass of this view
19960 public BaseSavedState(Parcelable superState) {
19964 public static final Parcelable.Creator<BaseSavedState> CREATOR =
19965 new Parcelable.Creator<BaseSavedState>() {
19966 public BaseSavedState createFromParcel(Parcel in) {
19967 return new BaseSavedState(in);
19970 public BaseSavedState[] newArray(int size) {
19971 return new BaseSavedState[size];
19977 * A set of information given to a view when it is attached to its parent
19980 final static class AttachInfo {
19981 interface Callbacks {
19982 void playSoundEffect(int effectId);
19983 boolean performHapticFeedback(int effectId, boolean always);
19987 * InvalidateInfo is used to post invalidate(int, int, int, int) messages
19988 * to a Handler. This class contains the target (View) to invalidate and
19989 * the coordinates of the dirty rectangle.
19991 * For performance purposes, this class also implements a pool of up to
19992 * POOL_LIMIT objects that get reused. This reduces memory allocations
19993 * whenever possible.
19995 static class InvalidateInfo {
19996 private static final int POOL_LIMIT = 10;
19998 private static final SynchronizedPool<InvalidateInfo> sPool =
19999 new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
20008 public static InvalidateInfo obtain() {
20009 InvalidateInfo instance = sPool.acquire();
20010 return (instance != null) ? instance : new InvalidateInfo();
20013 public void recycle() {
20015 sPool.release(this);
20019 final IWindowSession mSession;
20021 final IWindow mWindow;
20023 final IBinder mWindowToken;
20025 final Display mDisplay;
20027 final Callbacks mRootCallbacks;
20029 IWindowId mIWindowId;
20030 WindowId mWindowId;
20033 * The top view of the hierarchy.
20037 IBinder mPanelParentWindowToken;
20039 boolean mHardwareAccelerated;
20040 boolean mHardwareAccelerationRequested;
20041 HardwareRenderer mHardwareRenderer;
20042 List<RenderNode> mPendingAnimatingRenderNodes;
20045 * The state of the display to which the window is attached, as reported
20046 * by {@link Display#getState()}. Note that the display state constants
20047 * declared by {@link Display} do not exactly line up with the screen state
20048 * constants declared by {@link View} (there are more display states than
20051 int mDisplayState = Display.STATE_UNKNOWN;
20054 * Scale factor used by the compatibility mode
20056 float mApplicationScale;
20059 * Indicates whether the application is in compatibility mode
20061 boolean mScalingRequired;
20064 * If set, ViewRootImpl doesn't use its lame animation for when the window resizes.
20066 boolean mTurnOffWindowResizeAnim;
20069 * Left position of this view's window
20074 * Top position of this view's window
20079 * Indicates whether views need to use 32-bit drawing caches
20081 boolean mUse32BitDrawingCache;
20084 * For windows that are full-screen but using insets to layout inside
20085 * of the screen areas, these are the current insets to appear inside
20086 * the overscan area of the display.
20088 final Rect mOverscanInsets = new Rect();
20091 * For windows that are full-screen but using insets to layout inside
20092 * of the screen decorations, these are the current insets for the
20093 * content of the window.
20095 final Rect mContentInsets = new Rect();
20098 * For windows that are full-screen but using insets to layout inside
20099 * of the screen decorations, these are the current insets for the
20100 * actual visible parts of the window.
20102 final Rect mVisibleInsets = new Rect();
20105 * For windows that are full-screen but using insets to layout inside
20106 * of the screen decorations, these are the current insets for the
20107 * stable system windows.
20109 final Rect mStableInsets = new Rect();
20112 * The internal insets given by this window. This value is
20113 * supplied by the client (through
20114 * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
20115 * be given to the window manager when changed to be used in laying
20116 * out windows behind it.
20118 final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
20119 = new ViewTreeObserver.InternalInsetsInfo();
20122 * Set to true when mGivenInternalInsets is non-empty.
20124 boolean mHasNonEmptyGivenInternalInsets;
20127 * All views in the window's hierarchy that serve as scroll containers,
20128 * used to determine if the window can be resized or must be panned
20129 * to adjust for a soft input area.
20131 final ArrayList<View> mScrollContainers = new ArrayList<View>();
20133 final KeyEvent.DispatcherState mKeyDispatchState
20134 = new KeyEvent.DispatcherState();
20137 * Indicates whether the view's window currently has the focus.
20139 boolean mHasWindowFocus;
20142 * The current visibility of the window.
20144 int mWindowVisibility;
20147 * Indicates the time at which drawing started to occur.
20152 * Indicates whether or not ignoring the DIRTY_MASK flags.
20154 boolean mIgnoreDirtyState;
20157 * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
20158 * to avoid clearing that flag prematurely.
20160 boolean mSetIgnoreDirtyState = false;
20163 * Indicates whether the view's window is currently in touch mode.
20165 boolean mInTouchMode;
20168 * Indicates whether the view has requested unbuffered input dispatching for the current
20171 boolean mUnbufferedDispatchRequested;
20174 * Indicates that ViewAncestor should trigger a global layout change
20175 * the next time it performs a traversal
20177 boolean mRecomputeGlobalAttributes;
20180 * Always report new attributes at next traversal.
20182 boolean mForceReportNewAttributes;
20185 * Set during a traveral if any views want to keep the screen on.
20187 boolean mKeepScreenOn;
20190 * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
20192 int mSystemUiVisibility;
20195 * Hack to force certain system UI visibility flags to be cleared.
20197 int mDisabledSystemUiVisibility;
20200 * Last global system UI visibility reported by the window manager.
20202 int mGlobalSystemUiVisibility;
20205 * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
20208 boolean mHasSystemUiListeners;
20211 * Set if the window has requested to extend into the overscan region
20212 * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
20214 boolean mOverscanRequested;
20217 * Set if the visibility of any views has changed.
20219 boolean mViewVisibilityChanged;
20222 * Set to true if a view has been scrolled.
20224 boolean mViewScrollChanged;
20227 * Set to true if high contrast mode enabled
20229 boolean mHighContrastText;
20232 * Global to the view hierarchy used as a temporary for dealing with
20233 * x/y points in the transparent region computations.
20235 final int[] mTransparentLocation = new int[2];
20238 * Global to the view hierarchy used as a temporary for dealing with
20239 * x/y points in the ViewGroup.invalidateChild implementation.
20241 final int[] mInvalidateChildLocation = new int[2];
20244 * Global to the view hierarchy used as a temporary for dealng with
20245 * computing absolute on-screen location.
20247 final int[] mTmpLocation = new int[2];
20250 * Global to the view hierarchy used as a temporary for dealing with
20251 * x/y location when view is transformed.
20253 final float[] mTmpTransformLocation = new float[2];
20256 * The view tree observer used to dispatch global events like
20257 * layout, pre-draw, touch mode change, etc.
20259 final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
20262 * A Canvas used by the view hierarchy to perform bitmap caching.
20267 * The view root impl.
20269 final ViewRootImpl mViewRootImpl;
20272 * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
20273 * handler can be used to pump events in the UI events queue.
20275 final Handler mHandler;
20278 * Temporary for use in computing invalidate rectangles while
20279 * calling up the hierarchy.
20281 final Rect mTmpInvalRect = new Rect();
20284 * Temporary for use in computing hit areas with transformed views
20286 final RectF mTmpTransformRect = new RectF();
20289 * Temporary for use in computing hit areas with transformed views
20291 final RectF mTmpTransformRect1 = new RectF();
20294 * Temporary list of rectanges.
20296 final List<RectF> mTmpRectList = new ArrayList<>();
20299 * Temporary for use in transforming invalidation rect
20301 final Matrix mTmpMatrix = new Matrix();
20304 * Temporary for use in transforming invalidation rect
20306 final Transformation mTmpTransformation = new Transformation();
20309 * Temporary for use in querying outlines from OutlineProviders
20311 final Outline mTmpOutline = new Outline();
20314 * Temporary list for use in collecting focusable descendents of a view.
20316 final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
20319 * The id of the window for accessibility purposes.
20321 int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
20324 * Flags related to accessibility processing.
20326 * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
20327 * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
20329 int mAccessibilityFetchFlags;
20332 * The drawable for highlighting accessibility focus.
20334 Drawable mAccessibilityFocusDrawable;
20337 * Show where the margins, bounds and layout bounds are for each view.
20339 boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
20342 * Point used to compute visible regions.
20344 final Point mPoint = new Point();
20347 * Used to track which View originated a requestLayout() call, used when
20348 * requestLayout() is called during layout.
20350 View mViewRequestingLayout;
20353 * Creates a new set of attachment information with the specified
20354 * events handler and thread.
20356 * @param handler the events handler the view must use
20358 AttachInfo(IWindowSession session, IWindow window, Display display,
20359 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
20360 mSession = session;
20362 mWindowToken = window.asBinder();
20363 mDisplay = display;
20364 mViewRootImpl = viewRootImpl;
20365 mHandler = handler;
20366 mRootCallbacks = effectPlayer;
20371 * <p>ScrollabilityCache holds various fields used by a View when scrolling
20372 * is supported. This avoids keeping too many unused fields in most
20373 * instances of View.</p>
20375 private static class ScrollabilityCache implements Runnable {
20378 * Scrollbars are not visible
20380 public static final int OFF = 0;
20383 * Scrollbars are visible
20385 public static final int ON = 1;
20388 * Scrollbars are fading away
20390 public static final int FADING = 2;
20392 public boolean fadeScrollBars;
20394 public int fadingEdgeLength;
20395 public int scrollBarDefaultDelayBeforeFade;
20396 public int scrollBarFadeDuration;
20398 public int scrollBarSize;
20399 public ScrollBarDrawable scrollBar;
20400 public float[] interpolatorValues;
20403 public final Paint paint;
20404 public final Matrix matrix;
20405 public Shader shader;
20407 public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
20409 private static final float[] OPAQUE = { 255 };
20410 private static final float[] TRANSPARENT = { 0.0f };
20413 * When fading should start. This time moves into the future every time
20414 * a new scroll happens. Measured based on SystemClock.uptimeMillis()
20416 public long fadeStartTime;
20420 * The current state of the scrollbars: ON, OFF, or FADING
20422 public int state = OFF;
20424 private int mLastColor;
20426 public ScrollabilityCache(ViewConfiguration configuration, View host) {
20427 fadingEdgeLength = configuration.getScaledFadingEdgeLength();
20428 scrollBarSize = configuration.getScaledScrollBarSize();
20429 scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
20430 scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
20432 paint = new Paint();
20433 matrix = new Matrix();
20434 // use use a height of 1, and then wack the matrix each time we
20435 // actually use it.
20436 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
20437 paint.setShader(shader);
20438 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
20443 public void setFadeColor(int color) {
20444 if (color != mLastColor) {
20445 mLastColor = color;
20448 shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
20449 color & 0x00FFFFFF, Shader.TileMode.CLAMP);
20450 paint.setShader(shader);
20451 // Restore the default transfer mode (src_over)
20452 paint.setXfermode(null);
20454 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
20455 paint.setShader(shader);
20456 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
20461 public void run() {
20462 long now = AnimationUtils.currentAnimationTimeMillis();
20463 if (now >= fadeStartTime) {
20465 // the animation fades the scrollbars out by changing
20466 // the opacity (alpha) from fully opaque to fully
20468 int nextFrame = (int) now;
20469 int framesCount = 0;
20471 Interpolator interpolator = scrollBarInterpolator;
20474 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
20477 nextFrame += scrollBarFadeDuration;
20478 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
20482 // Kick off the fade animation
20483 host.invalidate(true);
20489 * Resuable callback for sending
20490 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
20492 private class SendViewScrolledAccessibilityEvent implements Runnable {
20493 public volatile boolean mIsPending;
20495 public void run() {
20496 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
20497 mIsPending = false;
20503 * This class represents a delegate that can be registered in a {@link View}
20504 * to enhance accessibility support via composition rather via inheritance.
20505 * It is specifically targeted to widget developers that extend basic View
20506 * classes i.e. classes in package android.view, that would like their
20507 * applications to be backwards compatible.
20509 * <div class="special reference">
20510 * <h3>Developer Guides</h3>
20511 * <p>For more information about making applications accessible, read the
20512 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
20513 * developer guide.</p>
20516 * A scenario in which a developer would like to use an accessibility delegate
20517 * is overriding a method introduced in a later API version then the minimal API
20518 * version supported by the application. For example, the method
20519 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
20520 * in API version 4 when the accessibility APIs were first introduced. If a
20521 * developer would like his application to run on API version 4 devices (assuming
20522 * all other APIs used by the application are version 4 or lower) and take advantage
20523 * of this method, instead of overriding the method which would break the application's
20524 * backwards compatibility, he can override the corresponding method in this
20525 * delegate and register the delegate in the target View if the API version of
20526 * the system is high enough i.e. the API version is same or higher to the API
20527 * version that introduced
20528 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
20531 * Here is an example implementation:
20534 * if (Build.VERSION.SDK_INT >= 14) {
20535 * // If the API version is equal of higher than the version in
20536 * // which onInitializeAccessibilityNodeInfo was introduced we
20537 * // register a delegate with a customized implementation.
20538 * View view = findViewById(R.id.view_id);
20539 * view.setAccessibilityDelegate(new AccessibilityDelegate() {
20540 * public void onInitializeAccessibilityNodeInfo(View host,
20541 * AccessibilityNodeInfo info) {
20542 * // Let the default implementation populate the info.
20543 * super.onInitializeAccessibilityNodeInfo(host, info);
20544 * // Set some other information.
20545 * info.setEnabled(host.isEnabled());
20549 * </code></pre></p>
20551 * This delegate contains methods that correspond to the accessibility methods
20552 * in View. If a delegate has been specified the implementation in View hands
20553 * off handling to the corresponding method in this delegate. The default
20554 * implementation the delegate methods behaves exactly as the corresponding
20555 * method in View for the case of no accessibility delegate been set. Hence,
20556 * to customize the behavior of a View method, clients can override only the
20557 * corresponding delegate method without altering the behavior of the rest
20558 * accessibility related methods of the host view.
20561 public static class AccessibilityDelegate {
20564 * Sends an accessibility event of the given type. If accessibility is not
20565 * enabled this method has no effect.
20567 * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
20568 * View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
20572 * @param host The View hosting the delegate.
20573 * @param eventType The type of the event to send.
20575 * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
20577 public void sendAccessibilityEvent(View host, int eventType) {
20578 host.sendAccessibilityEventInternal(eventType);
20582 * Performs the specified accessibility action on the view. For
20583 * possible accessibility actions look at {@link AccessibilityNodeInfo}.
20585 * The default implementation behaves as
20586 * {@link View#performAccessibilityAction(int, Bundle)
20587 * View#performAccessibilityAction(int, Bundle)} for the case of
20588 * no accessibility delegate been set.
20591 * @param action The action to perform.
20592 * @return Whether the action was performed.
20594 * @see View#performAccessibilityAction(int, Bundle)
20595 * View#performAccessibilityAction(int, Bundle)
20597 public boolean performAccessibilityAction(View host, int action, Bundle args) {
20598 return host.performAccessibilityActionInternal(action, args);
20602 * Sends an accessibility event. This method behaves exactly as
20603 * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
20604 * empty {@link AccessibilityEvent} and does not perform a check whether
20605 * accessibility is enabled.
20607 * The default implementation behaves as
20608 * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
20609 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
20610 * the case of no accessibility delegate been set.
20613 * @param host The View hosting the delegate.
20614 * @param event The event to send.
20616 * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
20617 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)
20619 public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
20620 host.sendAccessibilityEventUncheckedInternal(event);
20624 * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
20625 * to its children for adding their text content to the event.
20627 * The default implementation behaves as
20628 * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
20629 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
20630 * the case of no accessibility delegate been set.
20633 * @param host The View hosting the delegate.
20634 * @param event The event.
20635 * @return True if the event population was completed.
20637 * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
20638 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
20640 public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
20641 return host.dispatchPopulateAccessibilityEventInternal(event);
20645 * Gives a chance to the host View to populate the accessibility event with its
20648 * The default implementation behaves as
20649 * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
20650 * View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
20651 * the case of no accessibility delegate been set.
20654 * @param host The View hosting the delegate.
20655 * @param event The accessibility event which to populate.
20657 * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
20658 * View#onPopulateAccessibilityEvent(AccessibilityEvent)
20660 public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
20661 host.onPopulateAccessibilityEventInternal(event);
20665 * Initializes an {@link AccessibilityEvent} with information about the
20666 * the host View which is the event source.
20668 * The default implementation behaves as
20669 * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
20670 * View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
20671 * the case of no accessibility delegate been set.
20674 * @param host The View hosting the delegate.
20675 * @param event The event to initialize.
20677 * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
20678 * View#onInitializeAccessibilityEvent(AccessibilityEvent)
20680 public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
20681 host.onInitializeAccessibilityEventInternal(event);
20685 * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
20687 * The default implementation behaves as
20688 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
20689 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
20690 * the case of no accessibility delegate been set.
20693 * @param host The View hosting the delegate.
20694 * @param info The instance to initialize.
20696 * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
20697 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
20699 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
20700 host.onInitializeAccessibilityNodeInfoInternal(info);
20704 * Called when a child of the host View has requested sending an
20705 * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
20706 * to augment the event.
20708 * The default implementation behaves as
20709 * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
20710 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
20711 * the case of no accessibility delegate been set.
20714 * @param host The View hosting the delegate.
20715 * @param child The child which requests sending the event.
20716 * @param event The event to be sent.
20717 * @return True if the event should be sent
20719 * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
20720 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
20722 public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
20723 AccessibilityEvent event) {
20724 return host.onRequestSendAccessibilityEventInternal(child, event);
20728 * Gets the provider for managing a virtual view hierarchy rooted at this View
20729 * and reported to {@link android.accessibilityservice.AccessibilityService}s
20730 * that explore the window content.
20732 * The default implementation behaves as
20733 * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
20734 * the case of no accessibility delegate been set.
20737 * @return The provider.
20739 * @see AccessibilityNodeProvider
20741 public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
20746 * Returns an {@link AccessibilityNodeInfo} representing the host view from the
20747 * point of view of an {@link android.accessibilityservice.AccessibilityService}.
20748 * This method is responsible for obtaining an accessibility node info from a
20749 * pool of reusable instances and calling
20750 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
20751 * view to initialize the former.
20753 * <strong>Note:</strong> The client is responsible for recycling the obtained
20754 * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
20758 * The default implementation behaves as
20759 * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
20760 * the case of no accessibility delegate been set.
20762 * @return A populated {@link AccessibilityNodeInfo}.
20764 * @see AccessibilityNodeInfo
20768 public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
20769 return host.createAccessibilityNodeInfoInternal();
20773 private class MatchIdPredicate implements Predicate<View> {
20777 public boolean apply(View view) {
20778 return (view.mID == mId);
20782 private class MatchLabelForPredicate implements Predicate<View> {
20783 private int mLabeledId;
20786 public boolean apply(View view) {
20787 return (view.mLabelForId == mLabeledId);
20791 private class SendViewStateChangedAccessibilityEvent implements Runnable {
20792 private int mChangeTypes = 0;
20793 private boolean mPosted;
20794 private boolean mPostedWithDelay;
20795 private long mLastEventTimeMillis;
20798 public void run() {
20800 mPostedWithDelay = false;
20801 mLastEventTimeMillis = SystemClock.uptimeMillis();
20802 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
20803 final AccessibilityEvent event = AccessibilityEvent.obtain();
20804 event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
20805 event.setContentChangeTypes(mChangeTypes);
20806 sendAccessibilityEventUnchecked(event);
20811 public void runOrPost(int changeType) {
20812 mChangeTypes |= changeType;
20814 // If this is a live region or the child of a live region, collect
20815 // all events from this frame and send them on the next frame.
20816 if (inLiveRegion()) {
20817 // If we're already posted with a delay, remove that.
20818 if (mPostedWithDelay) {
20819 removeCallbacks(this);
20820 mPostedWithDelay = false;
20822 // Only post if we're not already posted.
20834 final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
20835 final long minEventIntevalMillis =
20836 ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
20837 if (timeSinceLastMillis >= minEventIntevalMillis) {
20838 removeCallbacks(this);
20841 postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
20842 mPostedWithDelay = true;
20847 private boolean inLiveRegion() {
20848 if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
20852 ViewParent parent = getParent();
20853 while (parent instanceof View) {
20854 if (((View) parent).getAccessibilityLiveRegion()
20855 != View.ACCESSIBILITY_LIVE_REGION_NONE) {
20858 parent = parent.getParent();
20865 * Dump all private flags in readable format, useful for documentation and
20868 private static void dumpFlags() {
20869 final HashMap<String, String> found = Maps.newHashMap();
20871 for (Field field : View.class.getDeclaredFields()) {
20872 final int modifiers = field.getModifiers();
20873 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
20874 if (field.getType().equals(int.class)) {
20875 final int value = field.getInt(null);
20876 dumpFlag(found, field.getName(), value);
20877 } else if (field.getType().equals(int[].class)) {
20878 final int[] values = (int[]) field.get(null);
20879 for (int i = 0; i < values.length; i++) {
20880 dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
20885 } catch (IllegalAccessException e) {
20886 throw new RuntimeException(e);
20889 final ArrayList<String> keys = Lists.newArrayList();
20890 keys.addAll(found.keySet());
20891 Collections.sort(keys);
20892 for (String key : keys) {
20893 Log.d(VIEW_LOG_TAG, found.get(key));
20897 private static void dumpFlag(HashMap<String, String> found, String name, int value) {
20898 // Sort flags by prefix, then by bits, always keeping unique keys
20899 final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
20900 final int prefix = name.indexOf('_');
20901 final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
20902 final String output = bits + " " + name;
20903 found.put(key, output);