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.CallSuper;
22 import android.annotation.ColorInt;
23 import android.annotation.DrawableRes;
24 import android.annotation.FloatRange;
25 import android.annotation.IdRes;
26 import android.annotation.IntDef;
27 import android.annotation.LayoutRes;
28 import android.annotation.NonNull;
29 import android.annotation.Nullable;
30 import android.annotation.Size;
31 import android.content.ClipData;
32 import android.content.Context;
33 import android.content.ContextWrapper;
34 import android.content.Intent;
35 import android.content.res.ColorStateList;
36 import android.content.res.Configuration;
37 import android.content.res.Resources;
38 import android.content.res.TypedArray;
39 import android.graphics.Bitmap;
40 import android.graphics.Canvas;
41 import android.graphics.Insets;
42 import android.graphics.Interpolator;
43 import android.graphics.LinearGradient;
44 import android.graphics.Matrix;
45 import android.graphics.Outline;
46 import android.graphics.Paint;
47 import android.graphics.PixelFormat;
48 import android.graphics.Point;
49 import android.graphics.PorterDuff;
50 import android.graphics.PorterDuffXfermode;
51 import android.graphics.Rect;
52 import android.graphics.RectF;
53 import android.graphics.Region;
54 import android.graphics.Shader;
55 import android.graphics.drawable.ColorDrawable;
56 import android.graphics.drawable.Drawable;
57 import android.hardware.display.DisplayManagerGlobal;
58 import android.os.Bundle;
59 import android.os.Handler;
60 import android.os.IBinder;
61 import android.os.Parcel;
62 import android.os.Parcelable;
63 import android.os.RemoteException;
64 import android.os.SystemClock;
65 import android.os.SystemProperties;
66 import android.os.Trace;
67 import android.text.TextUtils;
68 import android.util.AttributeSet;
69 import android.util.FloatProperty;
70 import android.util.LayoutDirection;
71 import android.util.Log;
72 import android.util.LongSparseLongArray;
73 import android.util.Pools.SynchronizedPool;
74 import android.util.Property;
75 import android.util.SparseArray;
76 import android.util.StateSet;
77 import android.util.SuperNotCalledException;
78 import android.util.TypedValue;
79 import android.view.ContextMenu.ContextMenuInfo;
80 import android.view.AccessibilityIterators.TextSegmentIterator;
81 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
82 import android.view.AccessibilityIterators.WordTextSegmentIterator;
83 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
84 import android.view.accessibility.AccessibilityEvent;
85 import android.view.accessibility.AccessibilityEventSource;
86 import android.view.accessibility.AccessibilityManager;
87 import android.view.accessibility.AccessibilityNodeInfo;
88 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
89 import android.view.accessibility.AccessibilityNodeProvider;
90 import android.view.animation.Animation;
91 import android.view.animation.AnimationUtils;
92 import android.view.animation.Transformation;
93 import android.view.inputmethod.EditorInfo;
94 import android.view.inputmethod.InputConnection;
95 import android.view.inputmethod.InputMethodManager;
96 import android.widget.Checkable;
97 import android.widget.ScrollBarDrawable;
99 import static android.os.Build.VERSION_CODES.*;
100 import static java.lang.Math.max;
102 import com.android.internal.R;
103 import com.android.internal.util.Predicate;
104 import com.android.internal.view.menu.MenuBuilder;
105 import com.google.android.collect.Lists;
106 import com.google.android.collect.Maps;
108 import java.lang.annotation.Retention;
109 import java.lang.annotation.RetentionPolicy;
110 import java.lang.ref.WeakReference;
111 import java.lang.reflect.Field;
112 import java.lang.reflect.InvocationTargetException;
113 import java.lang.reflect.Method;
114 import java.lang.reflect.Modifier;
115 import java.util.ArrayList;
116 import java.util.Arrays;
117 import java.util.Collections;
118 import java.util.HashMap;
119 import java.util.List;
120 import java.util.Locale;
121 import java.util.Map;
122 import java.util.concurrent.CopyOnWriteArrayList;
123 import java.util.concurrent.atomic.AtomicInteger;
127 * This class represents the basic building block for user interface components. A View
128 * occupies a rectangular area on the screen and is responsible for drawing and
129 * event handling. View is the base class for <em>widgets</em>, which are
130 * used to create interactive UI components (buttons, text fields, etc.). The
131 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
132 * are invisible containers that hold other Views (or other ViewGroups) and define
133 * their layout properties.
136 * <div class="special reference">
137 * <h3>Developer Guides</h3>
138 * <p>For information about using this class to develop your application's user interface,
139 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
142 * <a name="Using"></a>
143 * <h3>Using Views</h3>
145 * All of the views in a window are arranged in a single tree. You can add views
146 * either from code or by specifying a tree of views in one or more XML layout
147 * files. There are many specialized subclasses of views that act as controls or
148 * are capable of displaying text, images, or other content.
151 * Once you have created a tree of views, there are typically a few types of
152 * common operations you may wish to perform:
154 * <li><strong>Set properties:</strong> for example setting the text of a
155 * {@link android.widget.TextView}. The available properties and the methods
156 * that set them will vary among the different subclasses of views. Note that
157 * properties that are known at build time can be set in the XML layout
159 * <li><strong>Set focus:</strong> The framework will handled moving focus in
160 * response to user input. To force focus to a specific view, call
161 * {@link #requestFocus}.</li>
162 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
163 * that will be notified when something interesting happens to the view. For
164 * example, all views will let you set a listener to be notified when the view
165 * gains or loses focus. You can register such a listener using
166 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
167 * Other view subclasses offer more specialized listeners. For example, a Button
168 * exposes a listener to notify clients when the button is clicked.</li>
169 * <li><strong>Set visibility:</strong> You can hide or show views using
170 * {@link #setVisibility(int)}.</li>
174 * Note: The Android framework is responsible for measuring, laying out and
175 * drawing views. You should not call methods that perform these actions on
176 * views yourself unless you are actually implementing a
177 * {@link android.view.ViewGroup}.
180 * <a name="Lifecycle"></a>
181 * <h3>Implementing a Custom View</h3>
184 * To implement a custom view, you will usually begin by providing overrides for
185 * some of the standard methods that the framework calls on all views. You do
186 * not need to override all of these methods. In fact, you can start by just
187 * overriding {@link #onDraw(android.graphics.Canvas)}.
188 * <table border="2" width="85%" align="center" cellpadding="5">
190 * <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
195 * <td rowspan="2">Creation</td>
196 * <td>Constructors</td>
197 * <td>There is a form of the constructor that are called when the view
198 * is created from code and a form that is called when the view is
199 * inflated from a layout file. The second form should parse and apply
200 * any attributes defined in the layout file.
204 * <td><code>{@link #onFinishInflate()}</code></td>
205 * <td>Called after a view and all of its children has been inflated
210 * <td rowspan="3">Layout</td>
211 * <td><code>{@link #onMeasure(int, int)}</code></td>
212 * <td>Called to determine the size requirements for this view and all
217 * <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
218 * <td>Called when this view should assign a size and position to all
223 * <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
224 * <td>Called when the size of this view has changed.
230 * <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
231 * <td>Called when the view should render its content.
236 * <td rowspan="4">Event processing</td>
237 * <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
238 * <td>Called when a new hardware key event occurs.
242 * <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
243 * <td>Called when a hardware key up event occurs.
247 * <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
248 * <td>Called when a trackball motion event occurs.
252 * <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
253 * <td>Called when a touch screen motion event occurs.
258 * <td rowspan="2">Focus</td>
259 * <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
260 * <td>Called when the view gains or loses focus.
265 * <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
266 * <td>Called when the window containing the view gains or loses focus.
271 * <td rowspan="3">Attaching</td>
272 * <td><code>{@link #onAttachedToWindow()}</code></td>
273 * <td>Called when the view is attached to a window.
278 * <td><code>{@link #onDetachedFromWindow}</code></td>
279 * <td>Called when the view is detached from its window.
284 * <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
285 * <td>Called when the visibility of the window containing the view
296 * Views may have an integer id associated with them. These ids are typically
297 * assigned in the layout XML files, and are used to find specific views within
298 * the view tree. A common pattern is to:
300 * <li>Define a Button in the layout file and assign it a unique ID.
303 * android:id="@+id/my_button"
304 * android:layout_width="wrap_content"
305 * android:layout_height="wrap_content"
306 * android:text="@string/my_button_text"/>
308 * <li>From the onCreate method of an Activity, find the Button
309 * <pre class="prettyprint">
310 * Button myButton = (Button) findViewById(R.id.my_button);
314 * View IDs need not be unique throughout the tree, but it is good practice to
315 * ensure that they are at least unique within the part of the tree you are
319 * <a name="Position"></a>
322 * The geometry of a view is that of a rectangle. A view has a location,
323 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
324 * two dimensions, expressed as a width and a height. The unit for location
325 * and dimensions is the pixel.
329 * It is possible to retrieve the location of a view by invoking the methods
330 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
331 * coordinate of the rectangle representing the view. The latter returns the
332 * top, or Y, coordinate of the rectangle representing the view. These methods
333 * both return the location of the view relative to its parent. For instance,
334 * when getLeft() returns 20, that means the view is located 20 pixels to the
335 * right of the left edge of its direct parent.
339 * In addition, several convenience methods are offered to avoid unnecessary
340 * computations, namely {@link #getRight()} and {@link #getBottom()}.
341 * These methods return the coordinates of the right and bottom edges of the
342 * rectangle representing the view. For instance, calling {@link #getRight()}
343 * is similar to the following computation: <code>getLeft() + getWidth()</code>
344 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
347 * <a name="SizePaddingMargins"></a>
348 * <h3>Size, padding and margins</h3>
350 * The size of a view is expressed with a width and a height. A view actually
351 * possess two pairs of width and height values.
355 * The first pair is known as <em>measured width</em> and
356 * <em>measured height</em>. These dimensions define how big a view wants to be
357 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
358 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
359 * and {@link #getMeasuredHeight()}.
363 * The second pair is simply known as <em>width</em> and <em>height</em>, or
364 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
365 * dimensions define the actual size of the view on screen, at drawing time and
366 * after layout. These values may, but do not have to, be different from the
367 * measured width and height. The width and height can be obtained by calling
368 * {@link #getWidth()} and {@link #getHeight()}.
372 * To measure its dimensions, a view takes into account its padding. The padding
373 * is expressed in pixels for the left, top, right and bottom parts of the view.
374 * Padding can be used to offset the content of the view by a specific amount of
375 * pixels. For instance, a left padding of 2 will push the view's content by
376 * 2 pixels to the right of the left edge. Padding can be set using the
377 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
378 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
379 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
380 * {@link #getPaddingEnd()}.
384 * Even though a view can define a padding, it does not provide any support for
385 * margins. However, view groups provide such a support. Refer to
386 * {@link android.view.ViewGroup} and
387 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
390 * <a name="Layout"></a>
393 * Layout is a two pass process: a measure pass and a layout pass. The measuring
394 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
395 * of the view tree. Each view pushes dimension specifications down the tree
396 * during the recursion. At the end of the measure pass, every view has stored
397 * its measurements. The second pass happens in
398 * {@link #layout(int,int,int,int)} and is also top-down. During
399 * this pass each parent is responsible for positioning all of its children
400 * using the sizes computed in the measure pass.
404 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
405 * {@link #getMeasuredHeight()} values must be set, along with those for all of
406 * that view's descendants. A view's measured width and measured height values
407 * must respect the constraints imposed by the view's parents. This guarantees
408 * that at the end of the measure pass, all parents accept all of their
409 * children's measurements. A parent view may call measure() more than once on
410 * its children. For example, the parent may measure each child once with
411 * unspecified dimensions to find out how big they want to be, then call
412 * measure() on them again with actual numbers if the sum of all the children's
413 * unconstrained sizes is too big or too small.
417 * The measure pass uses two classes to communicate dimensions. The
418 * {@link MeasureSpec} class is used by views to tell their parents how they
419 * want to be measured and positioned. The base LayoutParams class just
420 * describes how big the view wants to be for both width and height. For each
421 * dimension, it can specify one of:
423 * <li> an exact number
424 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
426 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
427 * enclose its content (plus padding).
429 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
430 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
435 * MeasureSpecs are used to push requirements down the tree from parent to
436 * child. A MeasureSpec can be in one of three modes:
438 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
439 * of a child view. For example, a LinearLayout may call measure() on its child
440 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
441 * tall the child view wants to be given a width of 240 pixels.
442 * <li>EXACTLY: This is used by the parent to impose an exact size on the
443 * child. The child must use this size, and guarantee that all of its
444 * descendants will fit within this size.
445 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
446 * child. The child must guarantee that it and all of its descendants will fit
452 * To initiate a layout, call {@link #requestLayout}. This method is typically
453 * called by a view on itself when it believes that is can no longer fit within
454 * its current bounds.
457 * <a name="Drawing"></a>
460 * Drawing is handled by walking the tree and recording the drawing commands of
461 * any View that needs to update. After this, the drawing commands of the
462 * entire tree are issued to screen, clipped to the newly damaged area.
466 * The tree is largely recorded and drawn in order, with parents drawn before
467 * (i.e., behind) their children, with siblings drawn in the order they appear
468 * in the tree. If you set a background drawable for a View, then the View will
469 * draw it before calling back to its <code>onDraw()</code> method. The child
470 * drawing order can be overridden with
471 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
472 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
476 * To force a view to draw, call {@link #invalidate()}.
479 * <a name="EventHandlingThreading"></a>
480 * <h3>Event Handling and Threading</h3>
482 * The basic cycle of a view is as follows:
484 * <li>An event comes in and is dispatched to the appropriate view. The view
485 * handles the event and notifies any listeners.</li>
486 * <li>If in the course of processing the event, the view's bounds may need
487 * to be changed, the view will call {@link #requestLayout()}.</li>
488 * <li>Similarly, if in the course of processing the event the view's appearance
489 * may need to be changed, the view will call {@link #invalidate()}.</li>
490 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
491 * the framework will take care of measuring, laying out, and drawing the tree
492 * as appropriate.</li>
496 * <p><em>Note: The entire view tree is single threaded. You must always be on
497 * the UI thread when calling any method on any view.</em>
498 * If you are doing work on other threads and want to update the state of a view
499 * from that thread, you should use a {@link Handler}.
502 * <a name="FocusHandling"></a>
503 * <h3>Focus Handling</h3>
505 * The framework will handle routine focus movement in response to user input.
506 * This includes changing the focus as views are removed or hidden, or as new
507 * views become available. Views indicate their willingness to take focus
508 * through the {@link #isFocusable} method. To change whether a view can take
509 * focus, call {@link #setFocusable(boolean)}. When in touch mode (see notes below)
510 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
511 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
514 * Focus movement is based on an algorithm which finds the nearest neighbor in a
515 * given direction. In rare cases, the default algorithm may not match the
516 * intended behavior of the developer. In these situations, you can provide
517 * explicit overrides by using these XML attributes in the layout file:
528 * To get a particular view to take focus, call {@link #requestFocus()}.
531 * <a name="TouchMode"></a>
532 * <h3>Touch Mode</h3>
534 * When a user is navigating a user interface via directional keys such as a D-pad, it is
535 * necessary to give focus to actionable items such as buttons so the user can see
536 * what will take input. If the device has touch capabilities, however, and the user
537 * begins interacting with the interface by touching it, it is no longer necessary to
538 * always highlight, or give focus to, a particular view. This motivates a mode
539 * for interaction named 'touch mode'.
542 * For a touch capable device, once the user touches the screen, the device
543 * will enter touch mode. From this point onward, only views for which
544 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
545 * Other views that are touchable, like buttons, will not take focus when touched; they will
546 * only fire the on click listeners.
549 * Any time a user hits a directional key, such as a D-pad direction, the view device will
550 * exit touch mode, and find a view to take focus, so that the user may resume interacting
551 * with the user interface without touching the screen again.
554 * The touch mode state is maintained across {@link android.app.Activity}s. Call
555 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
558 * <a name="Scrolling"></a>
561 * The framework provides basic support for views that wish to internally
562 * scroll their content. This includes keeping track of the X and Y scroll
563 * offset as well as mechanisms for drawing scrollbars. See
564 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
565 * {@link #awakenScrollBars()} for more details.
568 * <a name="Tags"></a>
571 * Unlike IDs, tags are not used to identify views. Tags are essentially an
572 * extra piece of information that can be associated with a view. They are most
573 * often used as a convenience to store data related to views in the views
574 * themselves rather than by putting them in a separate structure.
577 * <a name="Properties"></a>
578 * <h3>Properties</h3>
580 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
581 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
582 * available both in the {@link Property} form as well as in similarly-named setter/getter
583 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
584 * be used to set persistent state associated with these rendering-related properties on the view.
585 * The properties and methods can also be used in conjunction with
586 * {@link android.animation.Animator Animator}-based animations, described more in the
587 * <a href="#Animation">Animation</a> section.
590 * <a name="Animation"></a>
593 * Starting with Android 3.0, the preferred way of animating views is to use the
594 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
595 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
596 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
597 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
598 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
599 * makes animating these View properties particularly easy and efficient.
602 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
603 * You can attach an {@link Animation} object to a view using
604 * {@link #setAnimation(Animation)} or
605 * {@link #startAnimation(Animation)}. The animation can alter the scale,
606 * rotation, translation and alpha of a view over time. If the animation is
607 * attached to a view that has children, the animation will affect the entire
608 * subtree rooted by that node. When an animation is started, the framework will
609 * take care of redrawing the appropriate views until the animation completes.
612 * <a name="Security"></a>
615 * Sometimes it is essential that an application be able to verify that an action
616 * is being performed with the full knowledge and consent of the user, such as
617 * granting a permission request, making a purchase or clicking on an advertisement.
618 * Unfortunately, a malicious application could try to spoof the user into
619 * performing these actions, unaware, by concealing the intended purpose of the view.
620 * As a remedy, the framework offers a touch filtering mechanism that can be used to
621 * improve the security of views that provide access to sensitive functionality.
623 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
624 * android:filterTouchesWhenObscured layout attribute to true. When enabled, the framework
625 * will discard touches that are received whenever the view's window is obscured by
626 * another visible window. As a result, the view will not receive touches whenever a
627 * toast, dialog or other window appears above the view's window.
629 * For more fine-grained control over security, consider overriding the
630 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
631 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
634 * @attr ref android.R.styleable#View_alpha
635 * @attr ref android.R.styleable#View_assistBlocked
636 * @attr ref android.R.styleable#View_background
637 * @attr ref android.R.styleable#View_clickable
638 * @attr ref android.R.styleable#View_contentDescription
639 * @attr ref android.R.styleable#View_drawingCacheQuality
640 * @attr ref android.R.styleable#View_duplicateParentState
641 * @attr ref android.R.styleable#View_id
642 * @attr ref android.R.styleable#View_requiresFadingEdge
643 * @attr ref android.R.styleable#View_fadeScrollbars
644 * @attr ref android.R.styleable#View_fadingEdgeLength
645 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
646 * @attr ref android.R.styleable#View_fitsSystemWindows
647 * @attr ref android.R.styleable#View_isScrollContainer
648 * @attr ref android.R.styleable#View_focusable
649 * @attr ref android.R.styleable#View_focusableInTouchMode
650 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
651 * @attr ref android.R.styleable#View_keepScreenOn
652 * @attr ref android.R.styleable#View_layerType
653 * @attr ref android.R.styleable#View_layoutDirection
654 * @attr ref android.R.styleable#View_longClickable
655 * @attr ref android.R.styleable#View_minHeight
656 * @attr ref android.R.styleable#View_minWidth
657 * @attr ref android.R.styleable#View_nextFocusDown
658 * @attr ref android.R.styleable#View_nextFocusLeft
659 * @attr ref android.R.styleable#View_nextFocusRight
660 * @attr ref android.R.styleable#View_nextFocusUp
661 * @attr ref android.R.styleable#View_onClick
662 * @attr ref android.R.styleable#View_padding
663 * @attr ref android.R.styleable#View_paddingBottom
664 * @attr ref android.R.styleable#View_paddingLeft
665 * @attr ref android.R.styleable#View_paddingRight
666 * @attr ref android.R.styleable#View_paddingTop
667 * @attr ref android.R.styleable#View_paddingStart
668 * @attr ref android.R.styleable#View_paddingEnd
669 * @attr ref android.R.styleable#View_saveEnabled
670 * @attr ref android.R.styleable#View_rotation
671 * @attr ref android.R.styleable#View_rotationX
672 * @attr ref android.R.styleable#View_rotationY
673 * @attr ref android.R.styleable#View_scaleX
674 * @attr ref android.R.styleable#View_scaleY
675 * @attr ref android.R.styleable#View_scrollX
676 * @attr ref android.R.styleable#View_scrollY
677 * @attr ref android.R.styleable#View_scrollbarSize
678 * @attr ref android.R.styleable#View_scrollbarStyle
679 * @attr ref android.R.styleable#View_scrollbars
680 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
681 * @attr ref android.R.styleable#View_scrollbarFadeDuration
682 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
683 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
684 * @attr ref android.R.styleable#View_scrollbarThumbVertical
685 * @attr ref android.R.styleable#View_scrollbarTrackVertical
686 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
687 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
688 * @attr ref android.R.styleable#View_stateListAnimator
689 * @attr ref android.R.styleable#View_transitionName
690 * @attr ref android.R.styleable#View_soundEffectsEnabled
691 * @attr ref android.R.styleable#View_tag
692 * @attr ref android.R.styleable#View_textAlignment
693 * @attr ref android.R.styleable#View_textDirection
694 * @attr ref android.R.styleable#View_transformPivotX
695 * @attr ref android.R.styleable#View_transformPivotY
696 * @attr ref android.R.styleable#View_translationX
697 * @attr ref android.R.styleable#View_translationY
698 * @attr ref android.R.styleable#View_translationZ
699 * @attr ref android.R.styleable#View_visibility
701 * @see android.view.ViewGroup
703 public class View implements Drawable.Callback, KeyEvent.Callback,
704 AccessibilityEventSource {
705 private static final boolean DBG = false;
708 * The logging tag used by this class with android.util.Log.
710 protected static final String VIEW_LOG_TAG = "View";
713 * When set to true, apps will draw debugging information about their layouts.
717 public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
720 * When set to true, this view will save its attribute data.
724 public static boolean mDebugViewAttributes = false;
727 * Used to mark a View that has no ID.
729 public static final int NO_ID = -1;
732 * Signals that compatibility booleans have been initialized according to
733 * target SDK versions.
735 private static boolean sCompatibilityDone = false;
738 * Use the old (broken) way of building MeasureSpecs.
740 private static boolean sUseBrokenMakeMeasureSpec = false;
743 * Ignore any optimizations using the measure cache.
745 private static boolean sIgnoreMeasureCache = false;
748 * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
751 private static final int NOT_FOCUSABLE = 0x00000000;
754 * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
757 private static final int FOCUSABLE = 0x00000001;
760 * Mask for use with setFlags indicating bits used for focus.
762 private static final int FOCUSABLE_MASK = 0x00000001;
765 * This view will adjust its padding to fit sytem windows (e.g. status bar)
767 private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
770 @IntDef({VISIBLE, INVISIBLE, GONE})
771 @Retention(RetentionPolicy.SOURCE)
772 public @interface Visibility {}
775 * This view is visible.
776 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
777 * android:visibility}.
779 public static final int VISIBLE = 0x00000000;
782 * This view is invisible, but it still takes up space for layout purposes.
783 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
784 * android:visibility}.
786 public static final int INVISIBLE = 0x00000004;
789 * This view is invisible, and it doesn't take any space for layout
790 * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
791 * android:visibility}.
793 public static final int GONE = 0x00000008;
796 * Mask for use with setFlags indicating bits used for visibility.
799 static final int VISIBILITY_MASK = 0x0000000C;
801 private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
804 * This view is enabled. Interpretation varies by subclass.
805 * Use with ENABLED_MASK when calling setFlags.
808 static final int ENABLED = 0x00000000;
811 * This view is disabled. Interpretation varies by subclass.
812 * Use with ENABLED_MASK when calling setFlags.
815 static final int DISABLED = 0x00000020;
818 * Mask for use with setFlags indicating bits used for indicating whether
819 * this view is enabled
822 static final int ENABLED_MASK = 0x00000020;
825 * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
826 * called and further optimizations will be performed. It is okay to have
827 * this flag set and a background. Use with DRAW_MASK when calling setFlags.
830 static final int WILL_NOT_DRAW = 0x00000080;
833 * Mask for use with setFlags indicating bits used for indicating whether
834 * this view is will draw
837 static final int DRAW_MASK = 0x00000080;
840 * <p>This view doesn't show scrollbars.</p>
843 static final int SCROLLBARS_NONE = 0x00000000;
846 * <p>This view shows horizontal scrollbars.</p>
849 static final int SCROLLBARS_HORIZONTAL = 0x00000100;
852 * <p>This view shows vertical scrollbars.</p>
855 static final int SCROLLBARS_VERTICAL = 0x00000200;
858 * <p>Mask for use with setFlags indicating bits used for indicating which
859 * scrollbars are enabled.</p>
862 static final int SCROLLBARS_MASK = 0x00000300;
865 * Indicates that the view should filter touches when its window is obscured.
866 * Refer to the class comments for more information about this security feature.
869 static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
872 * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
873 * that they are optional and should be skipped if the window has
874 * requested system UI flags that ignore those insets for layout.
876 static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
879 * <p>This view doesn't show fading edges.</p>
882 static final int FADING_EDGE_NONE = 0x00000000;
885 * <p>This view shows horizontal fading edges.</p>
888 static final int FADING_EDGE_HORIZONTAL = 0x00001000;
891 * <p>This view shows vertical fading edges.</p>
894 static final int FADING_EDGE_VERTICAL = 0x00002000;
897 * <p>Mask for use with setFlags indicating bits used for indicating which
898 * fading edges are enabled.</p>
901 static final int FADING_EDGE_MASK = 0x00003000;
904 * <p>Indicates this view can be clicked. When clickable, a View reacts
905 * to clicks by notifying the OnClickListener.<p>
908 static final int CLICKABLE = 0x00004000;
911 * <p>Indicates this view is caching its drawing into a bitmap.</p>
914 static final int DRAWING_CACHE_ENABLED = 0x00008000;
917 * <p>Indicates that no icicle should be saved for this view.<p>
920 static final int SAVE_DISABLED = 0x000010000;
923 * <p>Mask for use with setFlags indicating bits used for the saveEnabled
927 static final int SAVE_DISABLED_MASK = 0x000010000;
930 * <p>Indicates that no drawing cache should ever be created for this view.<p>
933 static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
936 * <p>Indicates this view can take / keep focus when int touch mode.</p>
939 static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
942 @Retention(RetentionPolicy.SOURCE)
943 @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
944 public @interface DrawingCacheQuality {}
947 * <p>Enables low quality mode for the drawing cache.</p>
949 public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
952 * <p>Enables high quality mode for the drawing cache.</p>
954 public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
957 * <p>Enables automatic quality mode for the drawing cache.</p>
959 public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
961 private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
962 DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
966 * <p>Mask for use with setFlags indicating bits used for the cache
967 * quality property.</p>
970 static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
974 * Indicates this view can be long clicked. When long clickable, a View
975 * reacts to long clicks by notifying the OnLongClickListener or showing a
980 static final int LONG_CLICKABLE = 0x00200000;
983 * <p>Indicates that this view gets its drawable states from its direct parent
984 * and ignores its original internal states.</p>
988 static final int DUPLICATE_PARENT_STATE = 0x00400000;
992 SCROLLBARS_INSIDE_OVERLAY,
993 SCROLLBARS_INSIDE_INSET,
994 SCROLLBARS_OUTSIDE_OVERLAY,
995 SCROLLBARS_OUTSIDE_INSET
997 @Retention(RetentionPolicy.SOURCE)
998 public @interface ScrollBarStyle {}
1001 * The scrollbar style to display the scrollbars inside the content area,
1002 * without increasing the padding. The scrollbars will be overlaid with
1003 * translucency on the view's content.
1005 public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1008 * The scrollbar style to display the scrollbars inside the padded area,
1009 * increasing the padding of the view. The scrollbars will not overlap the
1010 * content area of the view.
1012 public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1015 * The scrollbar style to display the scrollbars at the edge of the view,
1016 * without increasing the padding. The scrollbars will be overlaid with
1019 public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1022 * The scrollbar style to display the scrollbars at the edge of the view,
1023 * increasing the padding of the view. The scrollbars will only overlap the
1024 * background, if any.
1026 public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1029 * Mask to check if the scrollbar style is overlay or inset.
1032 static final int SCROLLBARS_INSET_MASK = 0x01000000;
1035 * Mask to check if the scrollbar style is inside or outside.
1038 static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1041 * Mask for scrollbar style.
1044 static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1047 * View flag indicating that the screen should remain on while the
1048 * window containing this view is visible to the user. This effectively
1049 * takes care of automatically setting the WindowManager's
1050 * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1052 public static final int KEEP_SCREEN_ON = 0x04000000;
1055 * View flag indicating whether this view should have sound effects enabled
1056 * for events such as clicking and touching.
1058 public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1061 * View flag indicating whether this view should have haptic feedback
1062 * enabled for events such as long presses.
1064 public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1067 * <p>Indicates that the view hierarchy should stop saving state when
1068 * it reaches this view. If state saving is initiated immediately at
1069 * the view, it will be allowed.
1072 static final int PARENT_SAVE_DISABLED = 0x20000000;
1075 * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1078 static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1081 @IntDef(flag = true,
1084 FOCUSABLES_TOUCH_MODE
1086 @Retention(RetentionPolicy.SOURCE)
1087 public @interface FocusableMode {}
1090 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1091 * should add all focusable Views regardless if they are focusable in touch mode.
1093 public static final int FOCUSABLES_ALL = 0x00000000;
1096 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1097 * should add only Views focusable in touch mode.
1099 public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1110 @Retention(RetentionPolicy.SOURCE)
1111 public @interface FocusDirection {}
1120 @Retention(RetentionPolicy.SOURCE)
1121 public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1124 * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1127 public static final int FOCUS_BACKWARD = 0x00000001;
1130 * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1133 public static final int FOCUS_FORWARD = 0x00000002;
1136 * Use with {@link #focusSearch(int)}. Move focus to the left.
1138 public static final int FOCUS_LEFT = 0x00000011;
1141 * Use with {@link #focusSearch(int)}. Move focus up.
1143 public static final int FOCUS_UP = 0x00000021;
1146 * Use with {@link #focusSearch(int)}. Move focus to the right.
1148 public static final int FOCUS_RIGHT = 0x00000042;
1151 * Use with {@link #focusSearch(int)}. Move focus down.
1153 public static final int FOCUS_DOWN = 0x00000082;
1156 * Bits of {@link #getMeasuredWidthAndState()} and
1157 * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1159 public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1162 * Bits of {@link #getMeasuredWidthAndState()} and
1163 * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1165 public static final int MEASURED_STATE_MASK = 0xff000000;
1168 * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1169 * for functions that combine both width and height into a single int,
1170 * such as {@link #getMeasuredState()} and the childState argument of
1171 * {@link #resolveSizeAndState(int, int, int)}.
1173 public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1176 * Bit of {@link #getMeasuredWidthAndState()} and
1177 * {@link #getMeasuredWidthAndState()} that indicates the measured size
1178 * is smaller that the space the view would like to have.
1180 public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1183 * Base View state sets
1187 * Indicates the view has no states set. States are used with
1188 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1189 * view depending on its state.
1191 * @see android.graphics.drawable.Drawable
1192 * @see #getDrawableState()
1194 protected static final int[] EMPTY_STATE_SET;
1196 * Indicates the view is enabled. States are used with
1197 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1198 * view depending on its state.
1200 * @see android.graphics.drawable.Drawable
1201 * @see #getDrawableState()
1203 protected static final int[] ENABLED_STATE_SET;
1205 * Indicates the view is focused. States are used with
1206 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1207 * view depending on its state.
1209 * @see android.graphics.drawable.Drawable
1210 * @see #getDrawableState()
1212 protected static final int[] FOCUSED_STATE_SET;
1214 * Indicates the view is selected. States are used with
1215 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1216 * view depending on its state.
1218 * @see android.graphics.drawable.Drawable
1219 * @see #getDrawableState()
1221 protected static final int[] SELECTED_STATE_SET;
1223 * Indicates the view is pressed. States are used with
1224 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1225 * view depending on its state.
1227 * @see android.graphics.drawable.Drawable
1228 * @see #getDrawableState()
1230 protected static final int[] PRESSED_STATE_SET;
1232 * Indicates the view's window has focus. States are used with
1233 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1234 * view depending on its state.
1236 * @see android.graphics.drawable.Drawable
1237 * @see #getDrawableState()
1239 protected static final int[] WINDOW_FOCUSED_STATE_SET;
1242 * Indicates the view is enabled and has the focus.
1244 * @see #ENABLED_STATE_SET
1245 * @see #FOCUSED_STATE_SET
1247 protected static final int[] ENABLED_FOCUSED_STATE_SET;
1249 * Indicates the view is enabled and selected.
1251 * @see #ENABLED_STATE_SET
1252 * @see #SELECTED_STATE_SET
1254 protected static final int[] ENABLED_SELECTED_STATE_SET;
1256 * Indicates the view is enabled and that its window has focus.
1258 * @see #ENABLED_STATE_SET
1259 * @see #WINDOW_FOCUSED_STATE_SET
1261 protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1263 * Indicates the view is focused and selected.
1265 * @see #FOCUSED_STATE_SET
1266 * @see #SELECTED_STATE_SET
1268 protected static final int[] FOCUSED_SELECTED_STATE_SET;
1270 * Indicates the view has the focus and that its window has the focus.
1272 * @see #FOCUSED_STATE_SET
1273 * @see #WINDOW_FOCUSED_STATE_SET
1275 protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1277 * Indicates the view is selected and that its window has the focus.
1279 * @see #SELECTED_STATE_SET
1280 * @see #WINDOW_FOCUSED_STATE_SET
1282 protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1285 * Indicates the view is enabled, focused and selected.
1287 * @see #ENABLED_STATE_SET
1288 * @see #FOCUSED_STATE_SET
1289 * @see #SELECTED_STATE_SET
1291 protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1293 * Indicates the view is enabled, focused and its window has the focus.
1295 * @see #ENABLED_STATE_SET
1296 * @see #FOCUSED_STATE_SET
1297 * @see #WINDOW_FOCUSED_STATE_SET
1299 protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1301 * Indicates the view is enabled, selected and its window has the focus.
1303 * @see #ENABLED_STATE_SET
1304 * @see #SELECTED_STATE_SET
1305 * @see #WINDOW_FOCUSED_STATE_SET
1307 protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1309 * Indicates the view is focused, selected and its window has the focus.
1311 * @see #FOCUSED_STATE_SET
1312 * @see #SELECTED_STATE_SET
1313 * @see #WINDOW_FOCUSED_STATE_SET
1315 protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1317 * Indicates the view is enabled, focused, selected and its window
1320 * @see #ENABLED_STATE_SET
1321 * @see #FOCUSED_STATE_SET
1322 * @see #SELECTED_STATE_SET
1323 * @see #WINDOW_FOCUSED_STATE_SET
1325 protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1327 * Indicates the view is pressed and its window has the focus.
1329 * @see #PRESSED_STATE_SET
1330 * @see #WINDOW_FOCUSED_STATE_SET
1332 protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1334 * Indicates the view is pressed and selected.
1336 * @see #PRESSED_STATE_SET
1337 * @see #SELECTED_STATE_SET
1339 protected static final int[] PRESSED_SELECTED_STATE_SET;
1341 * Indicates the view is pressed, selected and its window has the focus.
1343 * @see #PRESSED_STATE_SET
1344 * @see #SELECTED_STATE_SET
1345 * @see #WINDOW_FOCUSED_STATE_SET
1347 protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1349 * Indicates the view is pressed and focused.
1351 * @see #PRESSED_STATE_SET
1352 * @see #FOCUSED_STATE_SET
1354 protected static final int[] PRESSED_FOCUSED_STATE_SET;
1356 * Indicates the view is pressed, focused and its window has the focus.
1358 * @see #PRESSED_STATE_SET
1359 * @see #FOCUSED_STATE_SET
1360 * @see #WINDOW_FOCUSED_STATE_SET
1362 protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1364 * Indicates the view is pressed, focused and selected.
1366 * @see #PRESSED_STATE_SET
1367 * @see #SELECTED_STATE_SET
1368 * @see #FOCUSED_STATE_SET
1370 protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1372 * Indicates the view is pressed, focused, selected and its window has the focus.
1374 * @see #PRESSED_STATE_SET
1375 * @see #FOCUSED_STATE_SET
1376 * @see #SELECTED_STATE_SET
1377 * @see #WINDOW_FOCUSED_STATE_SET
1379 protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1381 * Indicates the view is pressed and enabled.
1383 * @see #PRESSED_STATE_SET
1384 * @see #ENABLED_STATE_SET
1386 protected static final int[] PRESSED_ENABLED_STATE_SET;
1388 * Indicates the view is pressed, enabled and its window has the focus.
1390 * @see #PRESSED_STATE_SET
1391 * @see #ENABLED_STATE_SET
1392 * @see #WINDOW_FOCUSED_STATE_SET
1394 protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1396 * Indicates the view is pressed, enabled and selected.
1398 * @see #PRESSED_STATE_SET
1399 * @see #ENABLED_STATE_SET
1400 * @see #SELECTED_STATE_SET
1402 protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1404 * Indicates the view is pressed, enabled, selected and its window has the
1407 * @see #PRESSED_STATE_SET
1408 * @see #ENABLED_STATE_SET
1409 * @see #SELECTED_STATE_SET
1410 * @see #WINDOW_FOCUSED_STATE_SET
1412 protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1414 * Indicates the view is pressed, enabled and focused.
1416 * @see #PRESSED_STATE_SET
1417 * @see #ENABLED_STATE_SET
1418 * @see #FOCUSED_STATE_SET
1420 protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1422 * Indicates the view is pressed, enabled, focused and its window has the
1425 * @see #PRESSED_STATE_SET
1426 * @see #ENABLED_STATE_SET
1427 * @see #FOCUSED_STATE_SET
1428 * @see #WINDOW_FOCUSED_STATE_SET
1430 protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1432 * Indicates the view is pressed, enabled, focused and selected.
1434 * @see #PRESSED_STATE_SET
1435 * @see #ENABLED_STATE_SET
1436 * @see #SELECTED_STATE_SET
1437 * @see #FOCUSED_STATE_SET
1439 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1441 * Indicates the view is pressed, enabled, focused, selected and its window
1444 * @see #PRESSED_STATE_SET
1445 * @see #ENABLED_STATE_SET
1446 * @see #SELECTED_STATE_SET
1447 * @see #FOCUSED_STATE_SET
1448 * @see #WINDOW_FOCUSED_STATE_SET
1450 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1453 EMPTY_STATE_SET = StateSet.get(0);
1455 WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1457 SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1458 SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1459 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1461 FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1462 FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1463 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1464 FOCUSED_SELECTED_STATE_SET = StateSet.get(
1465 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1466 FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1467 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1468 | StateSet.VIEW_STATE_FOCUSED);
1470 ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1471 ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1472 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1473 ENABLED_SELECTED_STATE_SET = StateSet.get(
1474 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1475 ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1476 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1477 | StateSet.VIEW_STATE_ENABLED);
1478 ENABLED_FOCUSED_STATE_SET = StateSet.get(
1479 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1480 ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1481 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1482 | StateSet.VIEW_STATE_ENABLED);
1483 ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1484 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1485 | StateSet.VIEW_STATE_ENABLED);
1486 ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1487 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1488 | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1490 PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1491 PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1492 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1493 PRESSED_SELECTED_STATE_SET = StateSet.get(
1494 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1495 PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1496 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1497 | StateSet.VIEW_STATE_PRESSED);
1498 PRESSED_FOCUSED_STATE_SET = StateSet.get(
1499 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1500 PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1501 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1502 | StateSet.VIEW_STATE_PRESSED);
1503 PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1504 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1505 | StateSet.VIEW_STATE_PRESSED);
1506 PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1507 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1508 | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1509 PRESSED_ENABLED_STATE_SET = StateSet.get(
1510 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1511 PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1512 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1513 | StateSet.VIEW_STATE_PRESSED);
1514 PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1515 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1516 | StateSet.VIEW_STATE_PRESSED);
1517 PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1518 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1519 | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1520 PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1521 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1522 | StateSet.VIEW_STATE_PRESSED);
1523 PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1524 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1525 | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1526 PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1527 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1528 | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1529 PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1530 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1531 | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1532 | StateSet.VIEW_STATE_PRESSED);
1536 * Accessibility event types that are dispatched for text population.
1538 private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1539 AccessibilityEvent.TYPE_VIEW_CLICKED
1540 | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1541 | AccessibilityEvent.TYPE_VIEW_SELECTED
1542 | AccessibilityEvent.TYPE_VIEW_FOCUSED
1543 | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1544 | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1545 | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1546 | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1547 | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1548 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1549 | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1552 * Temporary Rect currently for use in setBackground(). This will probably
1553 * be extended in the future to hold our own class with more than just
1556 static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1559 * Map used to store views' tags.
1561 private SparseArray<Object> mKeyedTags;
1564 * The next available accessibility id.
1566 private static int sNextAccessibilityViewId;
1569 * The animation currently associated with this view.
1572 protected Animation mCurrentAnimation = null;
1575 * Width as measured during measure pass.
1578 @ViewDebug.ExportedProperty(category = "measurement")
1582 * Height as measured during measure pass.
1585 @ViewDebug.ExportedProperty(category = "measurement")
1586 int mMeasuredHeight;
1589 * Flag to indicate that this view was marked INVALIDATED, or had its display list
1590 * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1591 * its display list. This flag, used only when hw accelerated, allows us to clear the
1592 * flag while retaining this information until it's needed (at getDisplayList() time and
1593 * in drawChild(), when we decide to draw a view's children's display lists into our own).
1597 boolean mRecreateDisplayList = false;
1600 * The view's identifier.
1607 @ViewDebug.ExportedProperty(resolveId = true)
1611 * The stable ID of this view for accessibility purposes.
1613 int mAccessibilityViewId = NO_ID;
1615 private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1617 SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1623 * @see #setTag(Object)
1626 protected Object mTag = null;
1628 // for mPrivateFlags:
1630 static final int PFLAG_WANTS_FOCUS = 0x00000001;
1632 static final int PFLAG_FOCUSED = 0x00000002;
1634 static final int PFLAG_SELECTED = 0x00000004;
1636 static final int PFLAG_IS_ROOT_NAMESPACE = 0x00000008;
1638 static final int PFLAG_HAS_BOUNDS = 0x00000010;
1640 static final int PFLAG_DRAWN = 0x00000020;
1642 * When this flag is set, this view is running an animation on behalf of its
1643 * children and should therefore not cancel invalidate requests, even if they
1644 * lie outside of this view's bounds.
1648 static final int PFLAG_DRAW_ANIMATION = 0x00000040;
1650 static final int PFLAG_SKIP_DRAW = 0x00000080;
1652 static final int PFLAG_ONLY_DRAWS_BACKGROUND = 0x00000100;
1654 static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1656 static final int PFLAG_DRAWABLE_STATE_DIRTY = 0x00000400;
1658 static final int PFLAG_MEASURED_DIMENSION_SET = 0x00000800;
1660 static final int PFLAG_FORCE_LAYOUT = 0x00001000;
1662 static final int PFLAG_LAYOUT_REQUIRED = 0x00002000;
1664 private static final int PFLAG_PRESSED = 0x00004000;
1667 static final int PFLAG_DRAWING_CACHE_VALID = 0x00008000;
1669 * Flag used to indicate that this view should be drawn once more (and only once
1670 * more) after its animation has completed.
1673 static final int PFLAG_ANIMATION_STARTED = 0x00010000;
1675 private static final int PFLAG_SAVE_STATE_CALLED = 0x00020000;
1678 * Indicates that the View returned true when onSetAlpha() was called and that
1679 * the alpha must be restored.
1682 static final int PFLAG_ALPHA_SET = 0x00040000;
1685 * Set by {@link #setScrollContainer(boolean)}.
1687 static final int PFLAG_SCROLL_CONTAINER = 0x00080000;
1690 * Set by {@link #setScrollContainer(boolean)}.
1692 static final int PFLAG_SCROLL_CONTAINER_ADDED = 0x00100000;
1695 * View flag indicating whether this view was invalidated (fully or partially.)
1699 static final int PFLAG_DIRTY = 0x00200000;
1702 * View flag indicating whether this view was invalidated by an opaque
1703 * invalidate request.
1707 static final int PFLAG_DIRTY_OPAQUE = 0x00400000;
1710 * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1714 static final int PFLAG_DIRTY_MASK = 0x00600000;
1717 * Indicates whether the background is opaque.
1721 static final int PFLAG_OPAQUE_BACKGROUND = 0x00800000;
1724 * Indicates whether the scrollbars are opaque.
1728 static final int PFLAG_OPAQUE_SCROLLBARS = 0x01000000;
1731 * Indicates whether the view is opaque.
1735 static final int PFLAG_OPAQUE_MASK = 0x01800000;
1738 * Indicates a prepressed state;
1739 * the short time between ACTION_DOWN and recognizing
1740 * a 'real' press. Prepressed is used to recognize quick taps
1741 * even when they are shorter than ViewConfiguration.getTapTimeout().
1745 private static final int PFLAG_PREPRESSED = 0x02000000;
1748 * Indicates whether the view is temporarily detached.
1752 static final int PFLAG_CANCEL_NEXT_UP_EVENT = 0x04000000;
1755 * Indicates that we should awaken scroll bars once attached
1759 private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1762 * Indicates that the view has received HOVER_ENTER. Cleared on HOVER_EXIT.
1765 private static final int PFLAG_HOVERED = 0x10000000;
1768 * no longer needed, should be reused
1770 private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1773 static final int PFLAG_ACTIVATED = 0x40000000;
1776 * Indicates that this view was specifically invalidated, not just dirtied because some
1777 * child view was invalidated. The flag is used to determine when we need to recreate
1778 * a view's display list (as opposed to just returning a reference to its existing
1783 static final int PFLAG_INVALIDATED = 0x80000000;
1786 * Masks for mPrivateFlags2, as generated by dumpFlags():
1788 * |-------|-------|-------|-------|
1789 * 1 PFLAG2_DRAG_CAN_ACCEPT
1790 * 1 PFLAG2_DRAG_HOVERED
1791 * 11 PFLAG2_LAYOUT_DIRECTION_MASK
1792 * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1793 * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED
1794 * 11 PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1795 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[1]
1796 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[2]
1797 * 11 PFLAG2_TEXT_DIRECTION_FLAGS[3]
1798 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[4]
1799 * 1 1 PFLAG2_TEXT_DIRECTION_FLAGS[5]
1800 * 11 PFLAG2_TEXT_DIRECTION_FLAGS[6]
1801 * 111 PFLAG2_TEXT_DIRECTION_FLAGS[7]
1802 * 111 PFLAG2_TEXT_DIRECTION_MASK
1803 * 1 PFLAG2_TEXT_DIRECTION_RESOLVED
1804 * 1 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1805 * 111 PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1806 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1807 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1808 * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1809 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1810 * 1 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1811 * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1812 * 111 PFLAG2_TEXT_ALIGNMENT_MASK
1813 * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1814 * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1815 * 111 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1816 * 111 PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1817 * 11 PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1818 * 1 PFLAG2_ACCESSIBILITY_FOCUSED
1819 * 1 PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1820 * 1 PFLAG2_VIEW_QUICK_REJECTED
1821 * 1 PFLAG2_PADDING_RESOLVED
1822 * 1 PFLAG2_DRAWABLE_RESOLVED
1823 * 1 PFLAG2_HAS_TRANSIENT_STATE
1824 * |-------|-------|-------|-------|
1828 * Indicates that this view has reported that it can accept the current drag's content.
1829 * Cleared when the drag operation concludes.
1832 static final int PFLAG2_DRAG_CAN_ACCEPT = 0x00000001;
1835 * Indicates that this view is currently directly under the drag location in a
1836 * drag-and-drop operation involving content that it can accept. Cleared when
1837 * the drag exits the view, or when the drag operation concludes.
1840 static final int PFLAG2_DRAG_HOVERED = 0x00000002;
1844 LAYOUT_DIRECTION_LTR,
1845 LAYOUT_DIRECTION_RTL,
1846 LAYOUT_DIRECTION_INHERIT,
1847 LAYOUT_DIRECTION_LOCALE
1849 @Retention(RetentionPolicy.SOURCE)
1850 // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1851 public @interface LayoutDir {}
1855 LAYOUT_DIRECTION_LTR,
1856 LAYOUT_DIRECTION_RTL
1858 @Retention(RetentionPolicy.SOURCE)
1859 public @interface ResolvedLayoutDir {}
1862 * Horizontal layout direction of this view is from Left to Right.
1863 * Use with {@link #setLayoutDirection}.
1865 public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1868 * Horizontal layout direction of this view is from Right to Left.
1869 * Use with {@link #setLayoutDirection}.
1871 public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1874 * Horizontal layout direction of this view is inherited from its parent.
1875 * Use with {@link #setLayoutDirection}.
1877 public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1880 * Horizontal layout direction of this view is from deduced from the default language
1881 * script for the locale. Use with {@link #setLayoutDirection}.
1883 public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1886 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1889 static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1892 * Mask for use with private flags indicating bits used for horizontal layout direction.
1895 static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1898 * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1899 * right-to-left direction.
1902 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1905 * Indicates whether the view horizontal layout direction has been resolved.
1908 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1911 * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1914 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1915 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1918 * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1922 private static final int[] LAYOUT_DIRECTION_FLAGS = {
1923 LAYOUT_DIRECTION_LTR,
1924 LAYOUT_DIRECTION_RTL,
1925 LAYOUT_DIRECTION_INHERIT,
1926 LAYOUT_DIRECTION_LOCALE
1930 * Default horizontal layout direction.
1932 private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
1935 * Default horizontal layout direction.
1938 static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
1941 * Text direction is inherited through {@link ViewGroup}
1943 public static final int TEXT_DIRECTION_INHERIT = 0;
1946 * Text direction is using "first strong algorithm". The first strong directional character
1947 * determines the paragraph direction. If there is no strong directional character, the
1948 * paragraph direction is the view's resolved layout direction.
1950 public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
1953 * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
1954 * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
1955 * If there are neither, the paragraph direction is the view's resolved layout direction.
1957 public static final int TEXT_DIRECTION_ANY_RTL = 2;
1960 * Text direction is forced to LTR.
1962 public static final int TEXT_DIRECTION_LTR = 3;
1965 * Text direction is forced to RTL.
1967 public static final int TEXT_DIRECTION_RTL = 4;
1970 * Text direction is coming from the system Locale.
1972 public static final int TEXT_DIRECTION_LOCALE = 5;
1975 * Text direction is using "first strong algorithm". The first strong directional character
1976 * determines the paragraph direction. If there is no strong directional character, the
1977 * paragraph direction is LTR.
1979 public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
1982 * Text direction is using "first strong algorithm". The first strong directional character
1983 * determines the paragraph direction. If there is no strong directional character, the
1984 * paragraph direction is RTL.
1986 public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
1989 * Default text direction is inherited
1991 private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
1994 * Default resolved text direction
1997 static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2000 * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2003 static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2006 * Mask for use with private flags indicating bits used for text direction.
2009 static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2010 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2013 * Array of text direction flags for mapping attribute "textDirection" to correct
2017 private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2018 TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2019 TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2020 TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2021 TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2022 TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2023 TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2024 TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2025 TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2029 * Indicates whether the view text direction has been resolved.
2032 static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2033 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2036 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2039 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2042 * Mask for use with private flags indicating bits used for resolved text direction.
2045 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2046 << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2049 * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2052 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2053 TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2057 TEXT_ALIGNMENT_INHERIT,
2058 TEXT_ALIGNMENT_GRAVITY,
2059 TEXT_ALIGNMENT_CENTER,
2060 TEXT_ALIGNMENT_TEXT_START,
2061 TEXT_ALIGNMENT_TEXT_END,
2062 TEXT_ALIGNMENT_VIEW_START,
2063 TEXT_ALIGNMENT_VIEW_END
2065 @Retention(RetentionPolicy.SOURCE)
2066 public @interface TextAlignment {}
2069 * Default text alignment. The text alignment of this View is inherited from its parent.
2070 * Use with {@link #setTextAlignment(int)}
2072 public static final int TEXT_ALIGNMENT_INHERIT = 0;
2075 * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2076 * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2078 * Use with {@link #setTextAlignment(int)}
2080 public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2083 * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2085 * Use with {@link #setTextAlignment(int)}
2087 public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2090 * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2092 * Use with {@link #setTextAlignment(int)}
2094 public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2097 * Center the paragraph, e.g. ALIGN_CENTER.
2099 * Use with {@link #setTextAlignment(int)}
2101 public static final int TEXT_ALIGNMENT_CENTER = 4;
2104 * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2105 * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2107 * Use with {@link #setTextAlignment(int)}
2109 public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2112 * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2113 * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2115 * Use with {@link #setTextAlignment(int)}
2117 public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2120 * Default text alignment is inherited
2122 private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2125 * Default resolved text alignment
2128 static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2131 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2134 static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2137 * Mask for use with private flags indicating bits used for text alignment.
2140 static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2143 * Array of text direction flags for mapping attribute "textAlignment" to correct
2147 private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2148 TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2149 TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2150 TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2151 TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2152 TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2153 TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2154 TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2158 * Indicates whether the view text alignment has been resolved.
2161 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2164 * Bit shift to get the resolved text alignment.
2167 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2170 * Mask for use with private flags indicating bits used for text alignment.
2173 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2174 << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2177 * Indicates whether if the view text alignment has been resolved to gravity
2179 private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2180 TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2182 // Accessiblity constants for mPrivateFlags2
2185 * Shift for the bits in {@link #mPrivateFlags2} related to the
2186 * "importantForAccessibility" attribute.
2188 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2191 * Automatically determine whether a view is important for accessibility.
2193 public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2196 * The view is important for accessibility.
2198 public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2201 * The view is not important for accessibility.
2203 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2206 * The view is not important for accessibility, nor are any of its
2209 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2212 * The default whether the view is important for accessibility.
2214 static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2217 * Mask for obtainig the bits which specify how to determine
2218 * whether a view is important for accessibility.
2220 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2221 | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2222 | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2223 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2226 * Shift for the bits in {@link #mPrivateFlags2} related to the
2227 * "accessibilityLiveRegion" attribute.
2229 static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2232 * Live region mode specifying that accessibility services should not
2233 * automatically announce changes to this view. This is the default live
2234 * region mode for most views.
2236 * Use with {@link #setAccessibilityLiveRegion(int)}.
2238 public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2241 * Live region mode specifying that accessibility services should announce
2242 * changes to this view.
2244 * Use with {@link #setAccessibilityLiveRegion(int)}.
2246 public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2249 * Live region mode specifying that accessibility services should interrupt
2250 * ongoing speech to immediately announce changes to this view.
2252 * Use with {@link #setAccessibilityLiveRegion(int)}.
2254 public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2257 * The default whether the view is important for accessibility.
2259 static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2262 * Mask for obtaining the bits which specify a view's accessibility live
2265 static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2266 | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2267 << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2270 * Flag indicating whether a view has accessibility focus.
2272 static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2275 * Flag whether the accessibility state of the subtree rooted at this view changed.
2277 static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2280 * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2281 * is used to check whether later changes to the view's transform should invalidate the
2282 * view to force the quickReject test to run again.
2284 static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2287 * Flag indicating that start/end padding has been resolved into left/right padding
2288 * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2289 * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2290 * during measurement. In some special cases this is required such as when an adapter-based
2291 * view measures prospective children without attaching them to a window.
2293 static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2296 * Flag indicating that the start/end drawables has been resolved into left/right ones.
2298 static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2301 * Indicates that the view is tracking some sort of transient state
2302 * that the app should not need to be aware of, but that the framework
2303 * should take special care to preserve.
2305 static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2308 * Group of bits indicating that RTL properties resolution is done.
2310 static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2311 PFLAG2_TEXT_DIRECTION_RESOLVED |
2312 PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2313 PFLAG2_PADDING_RESOLVED |
2314 PFLAG2_DRAWABLE_RESOLVED;
2316 // There are a couple of flags left in mPrivateFlags2
2318 /* End of masks for mPrivateFlags2 */
2321 * Masks for mPrivateFlags3, as generated by dumpFlags():
2323 * |-------|-------|-------|-------|
2324 * 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2325 * 1 PFLAG3_VIEW_IS_ANIMATING_ALPHA
2326 * 1 PFLAG3_IS_LAID_OUT
2327 * 1 PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2328 * 1 PFLAG3_CALLED_SUPER
2329 * 1 PFLAG3_APPLYING_INSETS
2330 * 1 PFLAG3_FITTING_SYSTEM_WINDOWS
2331 * 1 PFLAG3_NESTED_SCROLLING_ENABLED
2332 * 1 PFLAG3_ASSIST_BLOCKED
2333 * |-------|-------|-------|-------|
2337 * Flag indicating that view has a transform animation set on it. This is used to track whether
2338 * an animation is cleared between successive frames, in order to tell the associated
2339 * DisplayList to clear its animation matrix.
2341 static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2344 * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2345 * animation is cleared between successive frames, in order to tell the associated
2346 * DisplayList to restore its alpha value.
2348 static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2351 * Flag indicating that the view has been through at least one layout since it
2352 * was last attached to a window.
2354 static final int PFLAG3_IS_LAID_OUT = 0x4;
2357 * Flag indicating that a call to measure() was skipped and should be done
2358 * instead when layout() is invoked.
2360 static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2363 * Flag indicating that an overridden method correctly called down to
2364 * the superclass implementation as required by the API spec.
2366 static final int PFLAG3_CALLED_SUPER = 0x10;
2369 * Flag indicating that we're in the process of applying window insets.
2371 static final int PFLAG3_APPLYING_INSETS = 0x20;
2374 * Flag indicating that we're in the process of fitting system windows using the old method.
2376 static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2379 * Flag indicating that nested scrolling is enabled for this view.
2380 * The view will optionally cooperate with views up its parent chain to allow for
2381 * integrated nested scrolling along the same axis.
2383 static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2385 /* End of masks for mPrivateFlags3 */
2387 static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2390 * <p>Indicates that we are allowing {@link android.view.ViewAssistStructure} to traverse
2391 * into this view.<p>
2393 static final int PFLAG3_ASSIST_BLOCKED = 0x100;
2396 * Always allow a user to over-scroll this view, provided it is a
2397 * view that can scroll.
2399 * @see #getOverScrollMode()
2400 * @see #setOverScrollMode(int)
2402 public static final int OVER_SCROLL_ALWAYS = 0;
2405 * Allow a user to over-scroll this view only if the content is large
2406 * enough to meaningfully scroll, provided it is a view that can scroll.
2408 * @see #getOverScrollMode()
2409 * @see #setOverScrollMode(int)
2411 public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2414 * Never allow a user to over-scroll this view.
2416 * @see #getOverScrollMode()
2417 * @see #setOverScrollMode(int)
2419 public static final int OVER_SCROLL_NEVER = 2;
2422 * Special constant for {@link #setSystemUiVisibility(int)}: View has
2423 * requested the system UI (status bar) to be visible (the default).
2425 * @see #setSystemUiVisibility(int)
2427 public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2430 * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2431 * system UI to enter an unobtrusive "low profile" mode.
2433 * <p>This is for use in games, book readers, video players, or any other
2434 * "immersive" application where the usual system chrome is deemed too distracting.
2436 * <p>In low profile mode, the status bar and/or navigation icons may dim.
2438 * @see #setSystemUiVisibility(int)
2440 public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2443 * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2444 * system navigation be temporarily hidden.
2446 * <p>This is an even less obtrusive state than that called for by
2447 * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2448 * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2449 * those to disappear. This is useful (in conjunction with the
2450 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2451 * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2452 * window flags) for displaying content using every last pixel on the display.
2454 * <p>There is a limitation: because navigation controls are so important, the least user
2455 * interaction will cause them to reappear immediately. When this happens, both
2456 * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2457 * so that both elements reappear at the same time.
2459 * @see #setSystemUiVisibility(int)
2461 public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2464 * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2465 * into the normal fullscreen mode so that its content can take over the screen
2466 * while still allowing the user to interact with the application.
2468 * <p>This has the same visual effect as
2469 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2470 * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2471 * meaning that non-critical screen decorations (such as the status bar) will be
2472 * hidden while the user is in the View's window, focusing the experience on
2473 * that content. Unlike the window flag, if you are using ActionBar in
2474 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2475 * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2476 * hide the action bar.
2478 * <p>This approach to going fullscreen is best used over the window flag when
2479 * it is a transient state -- that is, the application does this at certain
2480 * points in its user interaction where it wants to allow the user to focus
2481 * on content, but not as a continuous state. For situations where the application
2482 * would like to simply stay full screen the entire time (such as a game that
2483 * wants to take over the screen), the
2484 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2485 * is usually a better approach. The state set here will be removed by the system
2486 * in various situations (such as the user moving to another application) like
2487 * the other system UI states.
2489 * <p>When using this flag, the application should provide some easy facility
2490 * for the user to go out of it. A common example would be in an e-book
2491 * reader, where tapping on the screen brings back whatever screen and UI
2492 * decorations that had been hidden while the user was immersed in reading
2495 * @see #setSystemUiVisibility(int)
2497 public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2500 * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2501 * flags, we would like a stable view of the content insets given to
2502 * {@link #fitSystemWindows(Rect)}. This means that the insets seen there
2503 * will always represent the worst case that the application can expect
2504 * as a continuous state. In the stock Android UI this is the space for
2505 * the system bar, nav bar, and status bar, but not more transient elements
2506 * such as an input method.
2508 * The stable layout your UI sees is based on the system UI modes you can
2509 * switch to. That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2510 * then you will get a stable layout for changes of the
2511 * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2512 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2513 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2514 * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2515 * with a stable layout. (Note that you should avoid using
2516 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2518 * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2519 * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2520 * then a hidden status bar will be considered a "stable" state for purposes
2521 * here. This allows your UI to continually hide the status bar, while still
2522 * using the system UI flags to hide the action bar while still retaining
2523 * a stable layout. Note that changing the window fullscreen flag will never
2524 * provide a stable layout for a clean transition.
2526 * <p>If you are using ActionBar in
2527 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2528 * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2529 * insets it adds to those given to the application.
2531 public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2534 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2535 * to be laid out as if it has requested
2536 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't. This
2537 * allows it to avoid artifacts when switching in and out of that mode, at
2538 * the expense that some of its user interface may be covered by screen
2539 * decorations when they are shown. You can perform layout of your inner
2540 * UI elements to account for the navigation system UI through the
2541 * {@link #fitSystemWindows(Rect)} method.
2543 public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2546 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2547 * to be laid out as if it has requested
2548 * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, 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 non-fullscreen system UI through the
2553 * {@link #fitSystemWindows(Rect)} method.
2555 public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2558 * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2559 * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. If this flag is
2560 * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2562 * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2563 * has an effect when used in combination with that flag.</p>
2565 public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2568 * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2569 * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2570 * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. Use this flag to create an immersive
2571 * experience while also hiding the system bars. If this flag is not set,
2572 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2573 * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2574 * if the user swipes from the top of the screen.
2575 * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2576 * system gestures, such as swiping from the top of the screen. These transient system bars
2577 * will overlay app’s content, may have some degree of transparency, and will automatically
2578 * hide after a short timeout.
2579 * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2580 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2581 * with one or both of those flags.</p>
2583 public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2586 * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2587 * is compatible with light status bar backgrounds.
2589 * <p>For this to take effect, the window must request
2590 * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2591 * FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2592 * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2593 * FLAG_TRANSLUCENT_STATUS}.
2595 * @see android.R.attr#windowLightStatusBar
2597 public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2600 * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2602 public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2605 * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2607 public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2612 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2613 * out of the public fields to keep the undefined bits out of the developer's way.
2615 * Flag to make the status bar not expandable. Unless you also
2616 * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2618 public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2623 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2624 * out of the public fields to keep the undefined bits out of the developer's way.
2626 * Flag to hide notification icons and scrolling ticker text.
2628 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2633 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2634 * out of the public fields to keep the undefined bits out of the developer's way.
2636 * Flag to disable incoming notification alerts. This will not block
2637 * icons, but it will block sound, vibrating and other visual or aural notifications.
2639 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2644 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2645 * out of the public fields to keep the undefined bits out of the developer's way.
2647 * Flag to hide only the scrolling ticker. Note that
2648 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2649 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2651 public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2656 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2657 * out of the public fields to keep the undefined bits out of the developer's way.
2659 * Flag to hide the center system info area.
2661 public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2666 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2667 * out of the public fields to keep the undefined bits out of the developer's way.
2669 * Flag to hide only the home button. Don't use this
2670 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2672 public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2677 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2678 * out of the public fields to keep the undefined bits out of the developer's way.
2680 * Flag to hide only the back button. Don't use this
2681 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2683 public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2688 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2689 * out of the public fields to keep the undefined bits out of the developer's way.
2691 * Flag to hide only the clock. You might use this if your activity has
2692 * its own clock making the status bar's clock redundant.
2694 public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2699 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2700 * out of the public fields to keep the undefined bits out of the developer's way.
2702 * Flag to hide only the recent apps button. Don't use this
2703 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2705 public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2710 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2711 * out of the public fields to keep the undefined bits out of the developer's way.
2713 * Flag to disable the global search gesture. Don't use this
2714 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2716 public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2721 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2722 * out of the public fields to keep the undefined bits out of the developer's way.
2724 * Flag to specify that the status bar is displayed in transient mode.
2726 public static final int STATUS_BAR_TRANSIENT = 0x04000000;
2731 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2732 * out of the public fields to keep the undefined bits out of the developer's way.
2734 * Flag to specify that the navigation bar is displayed in transient mode.
2736 public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
2741 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2742 * out of the public fields to keep the undefined bits out of the developer's way.
2744 * Flag to specify that the hidden status bar would like to be shown.
2746 public static final int STATUS_BAR_UNHIDE = 0x10000000;
2751 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2752 * out of the public fields to keep the undefined bits out of the developer's way.
2754 * Flag to specify that the hidden navigation bar would like to be shown.
2756 public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
2761 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2762 * out of the public fields to keep the undefined bits out of the developer's way.
2764 * Flag to specify that the status bar is displayed in translucent mode.
2766 public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
2771 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2772 * out of the public fields to keep the undefined bits out of the developer's way.
2774 * Flag to specify that the navigation bar is displayed in translucent mode.
2776 public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
2781 * Whether Recents is visible or not.
2783 public static final int RECENT_APPS_VISIBLE = 0x00004000;
2788 * Makes system ui transparent.
2790 public static final int SYSTEM_UI_TRANSPARENT = 0x00008000;
2795 public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FFF;
2798 * These are the system UI flags that can be cleared by events outside
2799 * of an application. Currently this is just the ability to tap on the
2800 * screen while hiding the navigation bar to have it return.
2803 public static final int SYSTEM_UI_CLEARABLE_FLAGS =
2804 SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2805 | SYSTEM_UI_FLAG_FULLSCREEN;
2808 * Flags that can impact the layout in relation to system UI.
2810 public static final int SYSTEM_UI_LAYOUT_FLAGS =
2811 SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2812 | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2815 @IntDef(flag = true,
2816 value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
2817 @Retention(RetentionPolicy.SOURCE)
2818 public @interface FindViewFlags {}
2821 * Find views that render the specified text.
2823 * @see #findViewsWithText(ArrayList, CharSequence, int)
2825 public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2828 * Find find views that contain the specified content description.
2830 * @see #findViewsWithText(ArrayList, CharSequence, int)
2832 public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2835 * Find views that contain {@link AccessibilityNodeProvider}. Such
2836 * a View is a root of virtual view hierarchy and may contain the searched
2837 * text. If this flag is set Views with providers are automatically
2838 * added and it is a responsibility of the client to call the APIs of
2839 * the provider to determine whether the virtual tree rooted at this View
2840 * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
2841 * representing the virtual views with this text.
2843 * @see #findViewsWithText(ArrayList, CharSequence, int)
2847 public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
2850 * The undefined cursor position.
2854 public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
2857 * Indicates that the screen has changed state and is now off.
2859 * @see #onScreenStateChanged(int)
2861 public static final int SCREEN_STATE_OFF = 0x0;
2864 * Indicates that the screen has changed state and is now on.
2866 * @see #onScreenStateChanged(int)
2868 public static final int SCREEN_STATE_ON = 0x1;
2871 * Indicates no axis of view scrolling.
2873 public static final int SCROLL_AXIS_NONE = 0;
2876 * Indicates scrolling along the horizontal axis.
2878 public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
2881 * Indicates scrolling along the vertical axis.
2883 public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
2886 * Controls the over-scroll mode for this view.
2887 * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
2888 * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
2889 * and {@link #OVER_SCROLL_NEVER}.
2891 private int mOverScrollMode;
2894 * The parent this view is attached to.
2899 protected ViewParent mParent;
2904 AttachInfo mAttachInfo;
2909 @ViewDebug.ExportedProperty(flagMapping = {
2910 @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
2911 name = "FORCE_LAYOUT"),
2912 @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
2913 name = "LAYOUT_REQUIRED"),
2914 @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
2915 name = "DRAWING_CACHE_INVALID", outputIf = false),
2916 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
2917 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
2918 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
2919 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
2920 }, formatToHexString = true)
2926 * This view's request for the visibility of the status bar.
2929 @ViewDebug.ExportedProperty(flagMapping = {
2930 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
2931 equals = SYSTEM_UI_FLAG_LOW_PROFILE,
2932 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
2933 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2934 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2935 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
2936 @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
2937 equals = SYSTEM_UI_FLAG_VISIBLE,
2938 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
2939 }, formatToHexString = true)
2940 int mSystemUiVisibility;
2943 * Reference count for transient state.
2944 * @see #setHasTransientState(boolean)
2946 int mTransientStateCount = 0;
2949 * Count of how many windows this view has been attached to.
2951 int mWindowAttachCount;
2954 * The layout parameters associated with this view and used by the parent
2955 * {@link android.view.ViewGroup} to determine how this view should be
2959 protected ViewGroup.LayoutParams mLayoutParams;
2962 * The view flags hold various views states.
2965 @ViewDebug.ExportedProperty(formatToHexString = true)
2968 static class TransformationInfo {
2970 * The transform matrix for the View. This transform is calculated internally
2971 * based on the translation, rotation, and scale properties.
2973 * Do *not* use this variable directly; instead call getMatrix(), which will
2974 * load the value from the View's RenderNode.
2976 private final Matrix mMatrix = new Matrix();
2979 * The inverse transform matrix for the View. This transform is calculated
2980 * internally based on the translation, rotation, and scale properties.
2982 * Do *not* use this variable directly; instead call getInverseMatrix(),
2983 * which will load the value from the View's RenderNode.
2985 private Matrix mInverseMatrix;
2988 * The opacity of the View. This is a value from 0 to 1, where 0 means
2989 * completely transparent and 1 means completely opaque.
2991 @ViewDebug.ExportedProperty
2995 * The opacity of the view as manipulated by the Fade transition. This is a hidden
2996 * property only used by transitions, which is composited with the other alpha
2997 * values to calculate the final visual alpha value.
2999 float mTransitionAlpha = 1f;
3002 TransformationInfo mTransformationInfo;
3005 * Current clip bounds. to which all drawing of this view are constrained.
3007 Rect mClipBounds = null;
3009 private boolean mLastIsOpaque;
3012 * The distance in pixels from the left edge of this view's parent
3013 * to the left edge of this view.
3016 @ViewDebug.ExportedProperty(category = "layout")
3017 protected int mLeft;
3019 * The distance in pixels from the left edge of this view's parent
3020 * to the right edge of this view.
3023 @ViewDebug.ExportedProperty(category = "layout")
3024 protected int mRight;
3026 * The distance in pixels from the top edge of this view's parent
3027 * to the top edge of this view.
3030 @ViewDebug.ExportedProperty(category = "layout")
3033 * The distance in pixels from the top edge of this view's parent
3034 * to the bottom edge of this view.
3037 @ViewDebug.ExportedProperty(category = "layout")
3038 protected int mBottom;
3041 * The offset, in pixels, by which the content of this view is scrolled
3045 @ViewDebug.ExportedProperty(category = "scrolling")
3046 protected int mScrollX;
3048 * The offset, in pixels, by which the content of this view is scrolled
3052 @ViewDebug.ExportedProperty(category = "scrolling")
3053 protected int mScrollY;
3056 * The left padding in pixels, that is the distance in pixels between the
3057 * left edge of this view and the left edge of its content.
3060 @ViewDebug.ExportedProperty(category = "padding")
3061 protected int mPaddingLeft = 0;
3063 * The right padding in pixels, that is the distance in pixels between the
3064 * right edge of this view and the right edge of its content.
3067 @ViewDebug.ExportedProperty(category = "padding")
3068 protected int mPaddingRight = 0;
3070 * The top padding in pixels, that is the distance in pixels between the
3071 * top edge of this view and the top edge of its content.
3074 @ViewDebug.ExportedProperty(category = "padding")
3075 protected int mPaddingTop;
3077 * The bottom padding in pixels, that is the distance in pixels between the
3078 * bottom edge of this view and the bottom edge of its content.
3081 @ViewDebug.ExportedProperty(category = "padding")
3082 protected int mPaddingBottom;
3085 * The layout insets in pixels, that is the distance in pixels between the
3086 * visible edges of this view its bounds.
3088 private Insets mLayoutInsets;
3091 * Briefly describes the view and is primarily used for accessibility support.
3093 private CharSequence mContentDescription;
3096 * Specifies the id of a view for which this view serves as a label for
3097 * accessibility purposes.
3099 private int mLabelForId = View.NO_ID;
3102 * Predicate for matching labeled view id with its label for
3103 * accessibility purposes.
3105 private MatchLabelForPredicate mMatchLabelForPredicate;
3108 * Specifies a view before which this one is visited in accessibility traversal.
3110 private int mAccessibilityTraversalBeforeId = NO_ID;
3113 * Specifies a view after which this one is visited in accessibility traversal.
3115 private int mAccessibilityTraversalAfterId = NO_ID;
3118 * Predicate for matching a view by its id.
3120 private MatchIdPredicate mMatchIdPredicate;
3123 * Cache the paddingRight set by the user to append to the scrollbar's size.
3127 @ViewDebug.ExportedProperty(category = "padding")
3128 protected int mUserPaddingRight;
3131 * Cache the paddingBottom set by the user to append to the scrollbar's size.
3135 @ViewDebug.ExportedProperty(category = "padding")
3136 protected int mUserPaddingBottom;
3139 * Cache the paddingLeft set by the user to append to the scrollbar's size.
3143 @ViewDebug.ExportedProperty(category = "padding")
3144 protected int mUserPaddingLeft;
3147 * Cache the paddingStart set by the user to append to the scrollbar's size.
3150 @ViewDebug.ExportedProperty(category = "padding")
3151 int mUserPaddingStart;
3154 * Cache the paddingEnd set by the user to append to the scrollbar's size.
3157 @ViewDebug.ExportedProperty(category = "padding")
3158 int mUserPaddingEnd;
3161 * Cache initial left padding.
3165 int mUserPaddingLeftInitial;
3168 * Cache initial right padding.
3172 int mUserPaddingRightInitial;
3175 * Default undefined padding
3177 private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3180 * Cache if a left padding has been defined
3182 private boolean mLeftPaddingDefined = false;
3185 * Cache if a right padding has been defined
3187 private boolean mRightPaddingDefined = false;
3192 int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3196 int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3198 private LongSparseLongArray mMeasureCache;
3200 @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3201 private Drawable mBackground;
3202 private TintInfo mBackgroundTint;
3204 @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3205 private ForegroundInfo mForegroundInfo;
3208 * RenderNode used for backgrounds.
3210 * When non-null and valid, this is expected to contain an up-to-date copy
3211 * of the background drawable. It is cleared on temporary detach, and reset
3214 private RenderNode mBackgroundRenderNode;
3216 private int mBackgroundResource;
3217 private boolean mBackgroundSizeChanged;
3219 private String mTransitionName;
3221 static class TintInfo {
3222 ColorStateList mTintList;
3223 PorterDuff.Mode mTintMode;
3224 boolean mHasTintMode;
3225 boolean mHasTintList;
3228 private static class ForegroundInfo {
3229 private Drawable mDrawable;
3230 private TintInfo mTintInfo;
3231 private int mGravity = Gravity.FILL;
3232 private boolean mInsidePadding = true;
3233 private boolean mBoundsChanged = true;
3234 private final Rect mSelfBounds = new Rect();
3235 private final Rect mOverlayBounds = new Rect();
3238 static class ListenerInfo {
3240 * Listener used to dispatch focus change events.
3241 * This field should be made private, so it is hidden from the SDK.
3244 protected OnFocusChangeListener mOnFocusChangeListener;
3247 * Listeners for layout change events.
3249 private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3251 protected OnScrollChangeListener mOnScrollChangeListener;
3254 * Listeners for attach events.
3256 private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3259 * Listener used to dispatch click events.
3260 * This field should be made private, so it is hidden from the SDK.
3263 public OnClickListener mOnClickListener;
3266 * Listener used to dispatch long click events.
3267 * This field should be made private, so it is hidden from the SDK.
3270 protected OnLongClickListener mOnLongClickListener;
3273 * Listener used to build the context menu.
3274 * This field should be made private, so it is hidden from the SDK.
3277 protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3279 private OnKeyListener mOnKeyListener;
3281 private OnTouchListener mOnTouchListener;
3283 private OnHoverListener mOnHoverListener;
3285 private OnGenericMotionListener mOnGenericMotionListener;
3287 private OnDragListener mOnDragListener;
3289 private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3291 OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3294 ListenerInfo mListenerInfo;
3297 * The application environment this view lives in.
3298 * This field should be made private, so it is hidden from the SDK.
3301 @ViewDebug.ExportedProperty(deepExport = true)
3302 protected Context mContext;
3304 private final Resources mResources;
3306 private ScrollabilityCache mScrollCache;
3308 private int[] mDrawableState = null;
3310 ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3313 * Animator that automatically runs based on state changes.
3315 private StateListAnimator mStateListAnimator;
3318 * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3319 * the user may specify which view to go to next.
3321 private int mNextFocusLeftId = View.NO_ID;
3324 * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3325 * the user may specify which view to go to next.
3327 private int mNextFocusRightId = View.NO_ID;
3330 * When this view has focus and the next focus is {@link #FOCUS_UP},
3331 * the user may specify which view to go to next.
3333 private int mNextFocusUpId = View.NO_ID;
3336 * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3337 * the user may specify which view to go to next.
3339 private int mNextFocusDownId = View.NO_ID;
3342 * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3343 * the user may specify which view to go to next.
3345 int mNextFocusForwardId = View.NO_ID;
3347 private CheckForLongPress mPendingCheckForLongPress;
3348 private CheckForTap mPendingCheckForTap = null;
3349 private PerformClick mPerformClick;
3350 private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3352 private UnsetPressedState mUnsetPressedState;
3355 * Whether the long press's action has been invoked. The tap's action is invoked on the
3356 * up event while a long press is invoked as soon as the long press duration is reached, so
3357 * a long press could be performed before the tap is checked, in which case the tap's action
3358 * should not be invoked.
3360 private boolean mHasPerformedLongPress;
3363 * The minimum height of the view. We'll try our best to have the height
3364 * of this view to at least this amount.
3366 @ViewDebug.ExportedProperty(category = "measurement")
3367 private int mMinHeight;
3370 * The minimum width of the view. We'll try our best to have the width
3371 * of this view to at least this amount.
3373 @ViewDebug.ExportedProperty(category = "measurement")
3374 private int mMinWidth;
3377 * The delegate to handle touch events that are physically in this view
3378 * but should be handled by another view.
3380 private TouchDelegate mTouchDelegate = null;
3383 * Solid color to use as a background when creating the drawing cache. Enables
3384 * the cache to use 16 bit bitmaps instead of 32 bit.
3386 private int mDrawingCacheBackgroundColor = 0;
3389 * Special tree observer used when mAttachInfo is null.
3391 private ViewTreeObserver mFloatingTreeObserver;
3394 * Cache the touch slop from the context that created the view.
3396 private int mTouchSlop;
3399 * Object that handles automatic animation of view properties.
3401 private ViewPropertyAnimator mAnimator = null;
3404 * Flag indicating that a drag can cross window boundaries. When
3405 * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3406 * with this flag set, all visible applications will be able to participate
3407 * in the drag operation and receive the dragged content.
3411 public static final int DRAG_FLAG_GLOBAL = 1;
3414 * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3416 private float mVerticalScrollFactor;
3419 * Position of the vertical scroll bar.
3421 private int mVerticalScrollbarPosition;
3424 * Position the scroll bar at the default position as determined by the system.
3426 public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3429 * Position the scroll bar along the left edge.
3431 public static final int SCROLLBAR_POSITION_LEFT = 1;
3434 * Position the scroll bar along the right edge.
3436 public static final int SCROLLBAR_POSITION_RIGHT = 2;
3439 * Indicates that the view does not have a layer.
3441 * @see #getLayerType()
3442 * @see #setLayerType(int, android.graphics.Paint)
3443 * @see #LAYER_TYPE_SOFTWARE
3444 * @see #LAYER_TYPE_HARDWARE
3446 public static final int LAYER_TYPE_NONE = 0;
3449 * <p>Indicates that the view has a software layer. A software layer is backed
3450 * by a bitmap and causes the view to be rendered using Android's software
3451 * rendering pipeline, even if hardware acceleration is enabled.</p>
3453 * <p>Software layers have various usages:</p>
3454 * <p>When the application is not using hardware acceleration, a software layer
3455 * is useful to apply a specific color filter and/or blending mode and/or
3456 * translucency to a view and all its children.</p>
3457 * <p>When the application is using hardware acceleration, a software layer
3458 * is useful to render drawing primitives not supported by the hardware
3459 * accelerated pipeline. It can also be used to cache a complex view tree
3460 * into a texture and reduce the complexity of drawing operations. For instance,
3461 * when animating a complex view tree with a translation, a software layer can
3462 * be used to render the view tree only once.</p>
3463 * <p>Software layers should be avoided when the affected view tree updates
3464 * often. Every update will require to re-render the software layer, which can
3465 * potentially be slow (particularly when hardware acceleration is turned on
3466 * since the layer will have to be uploaded into a hardware texture after every
3469 * @see #getLayerType()
3470 * @see #setLayerType(int, android.graphics.Paint)
3471 * @see #LAYER_TYPE_NONE
3472 * @see #LAYER_TYPE_HARDWARE
3474 public static final int LAYER_TYPE_SOFTWARE = 1;
3477 * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3478 * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3479 * OpenGL hardware) and causes the view to be rendered using Android's hardware
3480 * rendering pipeline, but only if hardware acceleration is turned on for the
3481 * view hierarchy. When hardware acceleration is turned off, hardware layers
3482 * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3484 * <p>A hardware layer is useful to apply a specific color filter and/or
3485 * blending mode and/or translucency to a view and all its children.</p>
3486 * <p>A hardware layer can be used to cache a complex view tree into a
3487 * texture and reduce the complexity of drawing operations. For instance,
3488 * when animating a complex view tree with a translation, a hardware layer can
3489 * be used to render the view tree only once.</p>
3490 * <p>A hardware layer can also be used to increase the rendering quality when
3491 * rotation transformations are applied on a view. It can also be used to
3492 * prevent potential clipping issues when applying 3D transforms on a view.</p>
3494 * @see #getLayerType()
3495 * @see #setLayerType(int, android.graphics.Paint)
3496 * @see #LAYER_TYPE_NONE
3497 * @see #LAYER_TYPE_SOFTWARE
3499 public static final int LAYER_TYPE_HARDWARE = 2;
3501 @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3502 @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3503 @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3504 @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3506 int mLayerType = LAYER_TYPE_NONE;
3510 * Set to true when drawing cache is enabled and cannot be created.
3514 public boolean mCachingFailed;
3515 private Bitmap mDrawingCache;
3516 private Bitmap mUnscaledDrawingCache;
3519 * RenderNode holding View properties, potentially holding a DisplayList of View content.
3521 * When non-null and valid, this is expected to contain an up-to-date copy
3522 * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3525 final RenderNode mRenderNode;
3528 * Set to true when the view is sending hover accessibility events because it
3529 * is the innermost hovered view.
3531 private boolean mSendingHoverAccessibilityEvents;
3534 * Delegate for injecting accessibility functionality.
3536 AccessibilityDelegate mAccessibilityDelegate;
3539 * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3540 * and add/remove objects to/from the overlay directly through the Overlay methods.
3542 ViewOverlay mOverlay;
3545 * The currently active parent view for receiving delegated nested scrolling events.
3546 * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3547 * by {@link #stopNestedScroll()} at the same point where we clear
3548 * requestDisallowInterceptTouchEvent.
3550 private ViewParent mNestedScrollingParent;
3553 * Consistency verifier for debugging purposes.
3556 protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3557 InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3558 new InputEventConsistencyVerifier(this, 0) : null;
3560 private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3562 private int[] mTempNestedScrollConsumed;
3565 * An overlay is going to draw this View instead of being drawn as part of this
3566 * View's parent. mGhostView is the View in the Overlay that must be invalidated
3567 * when this view is invalidated.
3569 GhostView mGhostView;
3572 * Holds pairs of adjacent attribute data: attribute name followed by its value.
3575 @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3576 public String[] mAttributes;
3579 * Maps a Resource id to its name.
3581 private static SparseArray<String> mAttributeMap;
3586 String mStartActivityRequestWho;
3589 * Simple constructor to use when creating a view from code.
3591 * @param context The Context the view is running in, through which it can
3592 * access the current theme, resources, etc.
3594 public View(Context context) {
3596 mResources = context != null ? context.getResources() : null;
3597 mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3598 // Set some flags defaults
3600 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3601 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3602 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3603 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3604 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3605 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3606 mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3607 setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3608 mUserPaddingStart = UNDEFINED_PADDING;
3609 mUserPaddingEnd = UNDEFINED_PADDING;
3610 mRenderNode = RenderNode.create(getClass().getName(), this);
3612 if (!sCompatibilityDone && context != null) {
3613 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3615 // Older apps may need this compatibility hack for measurement.
3616 sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
3618 // Older apps expect onMeasure() to always be called on a layout pass, regardless
3619 // of whether a layout was requested on that View.
3620 sIgnoreMeasureCache = targetSdkVersion < KITKAT;
3622 Canvas.sCompatibilityRestore = targetSdkVersion < MNC;
3624 sCompatibilityDone = true;
3629 * Constructor that is called when inflating a view from XML. This is called
3630 * when a view is being constructed from an XML file, supplying attributes
3631 * that were specified in the XML file. This version uses a default style of
3632 * 0, so the only attribute values applied are those in the Context's Theme
3633 * and the given AttributeSet.
3636 * The method onFinishInflate() will be called after all children have been
3639 * @param context The Context the view is running in, through which it can
3640 * access the current theme, resources, etc.
3641 * @param attrs The attributes of the XML tag that is inflating the view.
3642 * @see #View(Context, AttributeSet, int)
3644 public View(Context context, @Nullable AttributeSet attrs) {
3645 this(context, attrs, 0);
3649 * Perform inflation from XML and apply a class-specific base style from a
3650 * theme attribute. This constructor of View allows subclasses to use their
3651 * own base style when they are inflating. For example, a Button class's
3652 * constructor would call this version of the super class constructor and
3653 * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
3654 * allows the theme's button style to modify all of the base view attributes
3655 * (in particular its background) as well as the Button class's attributes.
3657 * @param context The Context the view is running in, through which it can
3658 * access the current theme, resources, etc.
3659 * @param attrs The attributes of the XML tag that is inflating the view.
3660 * @param defStyleAttr An attribute in the current theme that contains a
3661 * reference to a style resource that supplies default values for
3662 * the view. Can be 0 to not look for defaults.
3663 * @see #View(Context, AttributeSet)
3665 public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
3666 this(context, attrs, defStyleAttr, 0);
3670 * Perform inflation from XML and apply a class-specific base style from a
3671 * theme attribute or style resource. This constructor of View allows
3672 * subclasses to use their own base style when they are inflating.
3674 * When determining the final value of a particular attribute, there are
3675 * four inputs that come into play:
3677 * <li>Any attribute values in the given AttributeSet.
3678 * <li>The style resource specified in the AttributeSet (named "style").
3679 * <li>The default style specified by <var>defStyleAttr</var>.
3680 * <li>The default style specified by <var>defStyleRes</var>.
3681 * <li>The base values in this theme.
3684 * Each of these inputs is considered in-order, with the first listed taking
3685 * precedence over the following ones. In other words, if in the
3686 * AttributeSet you have supplied <code><Button * textColor="#ff000000"></code>
3687 * , then the button's text will <em>always</em> be black, regardless of
3688 * what is specified in any of the styles.
3690 * @param context The Context the view is running in, through which it can
3691 * access the current theme, resources, etc.
3692 * @param attrs The attributes of the XML tag that is inflating the view.
3693 * @param defStyleAttr An attribute in the current theme that contains a
3694 * reference to a style resource that supplies default values for
3695 * the view. Can be 0 to not look for defaults.
3696 * @param defStyleRes A resource identifier of a style resource that
3697 * supplies default values for the view, used only if
3698 * defStyleAttr is 0 or can not be found in the theme. Can be 0
3699 * to not look for defaults.
3700 * @see #View(Context, AttributeSet, int)
3702 public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
3705 final TypedArray a = context.obtainStyledAttributes(
3706 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
3708 if (mDebugViewAttributes) {
3709 saveAttributeData(attrs, a);
3712 Drawable background = null;
3714 int leftPadding = -1;
3715 int topPadding = -1;
3716 int rightPadding = -1;
3717 int bottomPadding = -1;
3718 int startPadding = UNDEFINED_PADDING;
3719 int endPadding = UNDEFINED_PADDING;
3723 int viewFlagValues = 0;
3724 int viewFlagMasks = 0;
3726 boolean setScrollContainer = false;
3734 float elevation = 0;
3736 float rotationX = 0;
3737 float rotationY = 0;
3740 boolean transformSet = false;
3742 int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
3743 int overScrollMode = mOverScrollMode;
3744 boolean initializeScrollbars = false;
3746 boolean startPaddingDefined = false;
3747 boolean endPaddingDefined = false;
3748 boolean leftPaddingDefined = false;
3749 boolean rightPaddingDefined = false;
3751 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3753 final int N = a.getIndexCount();
3754 for (int i = 0; i < N; i++) {
3755 int attr = a.getIndex(i);
3757 case com.android.internal.R.styleable.View_background:
3758 background = a.getDrawable(attr);
3760 case com.android.internal.R.styleable.View_padding:
3761 padding = a.getDimensionPixelSize(attr, -1);
3762 mUserPaddingLeftInitial = padding;
3763 mUserPaddingRightInitial = padding;
3764 leftPaddingDefined = true;
3765 rightPaddingDefined = true;
3767 case com.android.internal.R.styleable.View_paddingLeft:
3768 leftPadding = a.getDimensionPixelSize(attr, -1);
3769 mUserPaddingLeftInitial = leftPadding;
3770 leftPaddingDefined = true;
3772 case com.android.internal.R.styleable.View_paddingTop:
3773 topPadding = a.getDimensionPixelSize(attr, -1);
3775 case com.android.internal.R.styleable.View_paddingRight:
3776 rightPadding = a.getDimensionPixelSize(attr, -1);
3777 mUserPaddingRightInitial = rightPadding;
3778 rightPaddingDefined = true;
3780 case com.android.internal.R.styleable.View_paddingBottom:
3781 bottomPadding = a.getDimensionPixelSize(attr, -1);
3783 case com.android.internal.R.styleable.View_paddingStart:
3784 startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3785 startPaddingDefined = (startPadding != UNDEFINED_PADDING);
3787 case com.android.internal.R.styleable.View_paddingEnd:
3788 endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3789 endPaddingDefined = (endPadding != UNDEFINED_PADDING);
3791 case com.android.internal.R.styleable.View_scrollX:
3792 x = a.getDimensionPixelOffset(attr, 0);
3794 case com.android.internal.R.styleable.View_scrollY:
3795 y = a.getDimensionPixelOffset(attr, 0);
3797 case com.android.internal.R.styleable.View_alpha:
3798 setAlpha(a.getFloat(attr, 1f));
3800 case com.android.internal.R.styleable.View_transformPivotX:
3801 setPivotX(a.getDimensionPixelOffset(attr, 0));
3803 case com.android.internal.R.styleable.View_transformPivotY:
3804 setPivotY(a.getDimensionPixelOffset(attr, 0));
3806 case com.android.internal.R.styleable.View_translationX:
3807 tx = a.getDimensionPixelOffset(attr, 0);
3808 transformSet = true;
3810 case com.android.internal.R.styleable.View_translationY:
3811 ty = a.getDimensionPixelOffset(attr, 0);
3812 transformSet = true;
3814 case com.android.internal.R.styleable.View_translationZ:
3815 tz = a.getDimensionPixelOffset(attr, 0);
3816 transformSet = true;
3818 case com.android.internal.R.styleable.View_elevation:
3819 elevation = a.getDimensionPixelOffset(attr, 0);
3820 transformSet = true;
3822 case com.android.internal.R.styleable.View_rotation:
3823 rotation = a.getFloat(attr, 0);
3824 transformSet = true;
3826 case com.android.internal.R.styleable.View_rotationX:
3827 rotationX = a.getFloat(attr, 0);
3828 transformSet = true;
3830 case com.android.internal.R.styleable.View_rotationY:
3831 rotationY = a.getFloat(attr, 0);
3832 transformSet = true;
3834 case com.android.internal.R.styleable.View_scaleX:
3835 sx = a.getFloat(attr, 1f);
3836 transformSet = true;
3838 case com.android.internal.R.styleable.View_scaleY:
3839 sy = a.getFloat(attr, 1f);
3840 transformSet = true;
3842 case com.android.internal.R.styleable.View_id:
3843 mID = a.getResourceId(attr, NO_ID);
3845 case com.android.internal.R.styleable.View_tag:
3846 mTag = a.getText(attr);
3848 case com.android.internal.R.styleable.View_fitsSystemWindows:
3849 if (a.getBoolean(attr, false)) {
3850 viewFlagValues |= FITS_SYSTEM_WINDOWS;
3851 viewFlagMasks |= FITS_SYSTEM_WINDOWS;
3854 case com.android.internal.R.styleable.View_focusable:
3855 if (a.getBoolean(attr, false)) {
3856 viewFlagValues |= FOCUSABLE;
3857 viewFlagMasks |= FOCUSABLE_MASK;
3860 case com.android.internal.R.styleable.View_focusableInTouchMode:
3861 if (a.getBoolean(attr, false)) {
3862 viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
3863 viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
3866 case com.android.internal.R.styleable.View_clickable:
3867 if (a.getBoolean(attr, false)) {
3868 viewFlagValues |= CLICKABLE;
3869 viewFlagMasks |= CLICKABLE;
3872 case com.android.internal.R.styleable.View_longClickable:
3873 if (a.getBoolean(attr, false)) {
3874 viewFlagValues |= LONG_CLICKABLE;
3875 viewFlagMasks |= LONG_CLICKABLE;
3878 case com.android.internal.R.styleable.View_saveEnabled:
3879 if (!a.getBoolean(attr, true)) {
3880 viewFlagValues |= SAVE_DISABLED;
3881 viewFlagMasks |= SAVE_DISABLED_MASK;
3884 case com.android.internal.R.styleable.View_assistBlocked:
3885 if (a.getBoolean(attr, false)) {
3886 mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
3889 case com.android.internal.R.styleable.View_duplicateParentState:
3890 if (a.getBoolean(attr, false)) {
3891 viewFlagValues |= DUPLICATE_PARENT_STATE;
3892 viewFlagMasks |= DUPLICATE_PARENT_STATE;
3895 case com.android.internal.R.styleable.View_visibility:
3896 final int visibility = a.getInt(attr, 0);
3897 if (visibility != 0) {
3898 viewFlagValues |= VISIBILITY_FLAGS[visibility];
3899 viewFlagMasks |= VISIBILITY_MASK;
3902 case com.android.internal.R.styleable.View_layoutDirection:
3903 // Clear any layout direction flags (included resolved bits) already set
3905 ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
3906 // Set the layout direction flags depending on the value of the attribute
3907 final int layoutDirection = a.getInt(attr, -1);
3908 final int value = (layoutDirection != -1) ?
3909 LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
3910 mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
3912 case com.android.internal.R.styleable.View_drawingCacheQuality:
3913 final int cacheQuality = a.getInt(attr, 0);
3914 if (cacheQuality != 0) {
3915 viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
3916 viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
3919 case com.android.internal.R.styleable.View_contentDescription:
3920 setContentDescription(a.getString(attr));
3922 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
3923 setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
3925 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
3926 setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
3928 case com.android.internal.R.styleable.View_labelFor:
3929 setLabelFor(a.getResourceId(attr, NO_ID));
3931 case com.android.internal.R.styleable.View_soundEffectsEnabled:
3932 if (!a.getBoolean(attr, true)) {
3933 viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
3934 viewFlagMasks |= SOUND_EFFECTS_ENABLED;
3937 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
3938 if (!a.getBoolean(attr, true)) {
3939 viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
3940 viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
3943 case R.styleable.View_scrollbars:
3944 final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
3945 if (scrollbars != SCROLLBARS_NONE) {
3946 viewFlagValues |= scrollbars;
3947 viewFlagMasks |= SCROLLBARS_MASK;
3948 initializeScrollbars = true;
3951 //noinspection deprecation
3952 case R.styleable.View_fadingEdge:
3953 if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
3954 // Ignore the attribute starting with ICS
3957 // With builds < ICS, fall through and apply fading edges
3958 case R.styleable.View_requiresFadingEdge:
3959 final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
3960 if (fadingEdge != FADING_EDGE_NONE) {
3961 viewFlagValues |= fadingEdge;
3962 viewFlagMasks |= FADING_EDGE_MASK;
3963 initializeFadingEdgeInternal(a);
3966 case R.styleable.View_scrollbarStyle:
3967 scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
3968 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3969 viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
3970 viewFlagMasks |= SCROLLBARS_STYLE_MASK;
3973 case R.styleable.View_isScrollContainer:
3974 setScrollContainer = true;
3975 if (a.getBoolean(attr, false)) {
3976 setScrollContainer(true);
3979 case com.android.internal.R.styleable.View_keepScreenOn:
3980 if (a.getBoolean(attr, false)) {
3981 viewFlagValues |= KEEP_SCREEN_ON;
3982 viewFlagMasks |= KEEP_SCREEN_ON;
3985 case R.styleable.View_filterTouchesWhenObscured:
3986 if (a.getBoolean(attr, false)) {
3987 viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
3988 viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
3991 case R.styleable.View_nextFocusLeft:
3992 mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
3994 case R.styleable.View_nextFocusRight:
3995 mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
3997 case R.styleable.View_nextFocusUp:
3998 mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4000 case R.styleable.View_nextFocusDown:
4001 mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4003 case R.styleable.View_nextFocusForward:
4004 mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4006 case R.styleable.View_minWidth:
4007 mMinWidth = a.getDimensionPixelSize(attr, 0);
4009 case R.styleable.View_minHeight:
4010 mMinHeight = a.getDimensionPixelSize(attr, 0);
4012 case R.styleable.View_onClick:
4013 if (context.isRestricted()) {
4014 throw new IllegalStateException("The android:onClick attribute cannot "
4015 + "be used within a restricted context");
4018 final String handlerName = a.getString(attr);
4019 if (handlerName != null) {
4020 setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4023 case R.styleable.View_overScrollMode:
4024 overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4026 case R.styleable.View_verticalScrollbarPosition:
4027 mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4029 case R.styleable.View_layerType:
4030 setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4032 case R.styleable.View_textDirection:
4033 // Clear any text direction flag already set
4034 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4035 // Set the text direction flags depending on the value of the attribute
4036 final int textDirection = a.getInt(attr, -1);
4037 if (textDirection != -1) {
4038 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4041 case R.styleable.View_textAlignment:
4042 // Clear any text alignment flag already set
4043 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4044 // Set the text alignment flag depending on the value of the attribute
4045 final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4046 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4048 case R.styleable.View_importantForAccessibility:
4049 setImportantForAccessibility(a.getInt(attr,
4050 IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4052 case R.styleable.View_accessibilityLiveRegion:
4053 setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4055 case R.styleable.View_transitionName:
4056 setTransitionName(a.getString(attr));
4058 case R.styleable.View_nestedScrollingEnabled:
4059 setNestedScrollingEnabled(a.getBoolean(attr, false));
4061 case R.styleable.View_stateListAnimator:
4062 setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4063 a.getResourceId(attr, 0)));
4065 case R.styleable.View_backgroundTint:
4066 // This will get applied later during setBackground().
4067 if (mBackgroundTint == null) {
4068 mBackgroundTint = new TintInfo();
4070 mBackgroundTint.mTintList = a.getColorStateList(
4071 R.styleable.View_backgroundTint);
4072 mBackgroundTint.mHasTintList = true;
4074 case R.styleable.View_backgroundTintMode:
4075 // This will get applied later during setBackground().
4076 if (mBackgroundTint == null) {
4077 mBackgroundTint = new TintInfo();
4079 mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4080 R.styleable.View_backgroundTintMode, -1), null);
4081 mBackgroundTint.mHasTintMode = true;
4083 case R.styleable.View_outlineProvider:
4084 setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4085 PROVIDER_BACKGROUND));
4087 case R.styleable.View_foreground:
4088 setForeground(a.getDrawable(attr));
4090 case R.styleable.View_foregroundGravity:
4091 setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4093 case R.styleable.View_foregroundTintMode:
4094 setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4096 case R.styleable.View_foregroundTint:
4097 setForegroundTintList(a.getColorStateList(attr));
4099 case R.styleable.View_foregroundInsidePadding:
4100 if (mForegroundInfo == null) {
4101 mForegroundInfo = new ForegroundInfo();
4103 mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4104 mForegroundInfo.mInsidePadding);
4109 setOverScrollMode(overScrollMode);
4111 // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4112 // the resolved layout direction). Those cached values will be used later during padding
4114 mUserPaddingStart = startPadding;
4115 mUserPaddingEnd = endPadding;
4117 if (background != null) {
4118 setBackground(background);
4121 // setBackground above will record that padding is currently provided by the background.
4122 // If we have padding specified via xml, record that here instead and use it.
4123 mLeftPaddingDefined = leftPaddingDefined;
4124 mRightPaddingDefined = rightPaddingDefined;
4127 leftPadding = padding;
4128 topPadding = padding;
4129 rightPadding = padding;
4130 bottomPadding = padding;
4131 mUserPaddingLeftInitial = padding;
4132 mUserPaddingRightInitial = padding;
4135 if (isRtlCompatibilityMode()) {
4136 // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4137 // left / right padding are used if defined (meaning here nothing to do). If they are not
4138 // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4139 // start / end and resolve them as left / right (layout direction is not taken into account).
4140 // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4141 // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4143 if (!mLeftPaddingDefined && startPaddingDefined) {
4144 leftPadding = startPadding;
4146 mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4147 if (!mRightPaddingDefined && endPaddingDefined) {
4148 rightPadding = endPadding;
4150 mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4152 // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4153 // values defined. Otherwise, left /right values are used.
4154 // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4155 // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4157 final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4159 if (mLeftPaddingDefined && !hasRelativePadding) {
4160 mUserPaddingLeftInitial = leftPadding;
4162 if (mRightPaddingDefined && !hasRelativePadding) {
4163 mUserPaddingRightInitial = rightPadding;
4168 mUserPaddingLeftInitial,
4169 topPadding >= 0 ? topPadding : mPaddingTop,
4170 mUserPaddingRightInitial,
4171 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4173 if (viewFlagMasks != 0) {
4174 setFlags(viewFlagValues, viewFlagMasks);
4177 if (initializeScrollbars) {
4178 initializeScrollbarsInternal(a);
4183 // Needs to be called after mViewFlags is set
4184 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4188 if (x != 0 || y != 0) {
4193 setTranslationX(tx);
4194 setTranslationY(ty);
4195 setTranslationZ(tz);
4196 setElevation(elevation);
4197 setRotation(rotation);
4198 setRotationX(rotationX);
4199 setRotationY(rotationY);
4204 if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4205 setScrollContainer(true);
4208 computeOpaqueFlags();
4212 * An implementation of OnClickListener that attempts to lazily load a
4213 * named click handling method from a parent or ancestor context.
4215 private static class DeclaredOnClickListener implements OnClickListener {
4216 private final View mHostView;
4217 private final String mMethodName;
4219 private Method mMethod;
4221 public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4222 mHostView = hostView;
4223 mMethodName = methodName;
4227 public void onClick(@NonNull View v) {
4228 if (mMethod == null) {
4229 mMethod = resolveMethod(mHostView.getContext(), mMethodName);
4233 mMethod.invoke(mHostView.getContext(), v);
4234 } catch (IllegalAccessException e) {
4235 throw new IllegalStateException(
4236 "Could not execute non-public method for android:onClick", e);
4237 } catch (InvocationTargetException e) {
4238 throw new IllegalStateException(
4239 "Could not execute method for android:onClick", e);
4244 private Method resolveMethod(@Nullable Context context, @NonNull String name) {
4245 while (context != null) {
4247 if (!context.isRestricted()) {
4248 return context.getClass().getMethod(mMethodName, View.class);
4250 } catch (NoSuchMethodException e) {
4251 // Failed to find method, keep searching up the hierarchy.
4254 if (context instanceof ContextWrapper) {
4255 context = ((ContextWrapper) context).getBaseContext();
4257 // Can't search up the hierarchy, null out and fail.
4262 final int id = mHostView.getId();
4263 final String idText = id == NO_ID ? "" : " with id '"
4264 + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4265 throw new IllegalStateException("Could not find method " + mMethodName
4266 + "(View) in a parent or ancestor Context for android:onClick "
4267 + "attribute defined on view " + mHostView.getClass() + idText);
4272 * Non-public constructor for use in testing
4276 mRenderNode = RenderNode.create(getClass().getName(), this);
4279 private static SparseArray<String> getAttributeMap() {
4280 if (mAttributeMap == null) {
4281 mAttributeMap = new SparseArray<String>();
4283 return mAttributeMap;
4286 private void saveAttributeData(AttributeSet attrs, TypedArray a) {
4287 int length = ((attrs == null ? 0 : attrs.getAttributeCount()) + a.getIndexCount()) * 2;
4288 mAttributes = new String[length];
4291 if (attrs != null) {
4292 for (i = 0; i < attrs.getAttributeCount(); i += 2) {
4293 mAttributes[i] = attrs.getAttributeName(i);
4294 mAttributes[i + 1] = attrs.getAttributeValue(i);
4299 SparseArray<String> attributeMap = getAttributeMap();
4300 for (int j = 0; j < a.length(); ++j) {
4301 if (a.hasValue(j)) {
4303 int resourceId = a.getResourceId(j, 0);
4304 if (resourceId == 0) {
4308 String resourceName = attributeMap.get(resourceId);
4309 if (resourceName == null) {
4310 resourceName = a.getResources().getResourceName(resourceId);
4311 attributeMap.put(resourceId, resourceName);
4314 mAttributes[i] = resourceName;
4315 mAttributes[i + 1] = a.getText(j).toString();
4317 } catch (Resources.NotFoundException e) {
4318 // if we can't get the resource name, we just ignore it
4324 public String toString() {
4325 StringBuilder out = new StringBuilder(128);
4326 out.append(getClass().getName());
4328 out.append(Integer.toHexString(System.identityHashCode(this)));
4330 switch (mViewFlags&VISIBILITY_MASK) {
4331 case VISIBLE: out.append('V'); break;
4332 case INVISIBLE: out.append('I'); break;
4333 case GONE: out.append('G'); break;
4334 default: out.append('.'); break;
4336 out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4337 out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4338 out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4339 out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4340 out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4341 out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4342 out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4344 out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4345 out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4346 out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4347 if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4350 out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4352 out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4353 out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4354 out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4355 out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4363 out.append(mBottom);
4364 final int id = getId();
4367 out.append(Integer.toHexString(id));
4368 final Resources r = mResources;
4369 if (Resources.resourceHasPackage(id) && r != null) {
4372 switch (id&0xff000000) {
4380 pkgname = r.getResourcePackageName(id);
4383 String typename = r.getResourceTypeName(id);
4384 String entryname = r.getResourceEntryName(id);
4386 out.append(pkgname);
4388 out.append(typename);
4390 out.append(entryname);
4391 } catch (Resources.NotFoundException e) {
4396 return out.toString();
4401 * Initializes the fading edges from a given set of styled attributes. This
4402 * method should be called by subclasses that need fading edges and when an
4403 * instance of these subclasses is created programmatically rather than
4404 * being inflated from XML. This method is automatically called when the XML
4408 * @param a the styled attributes set to initialize the fading edges from
4412 protected void initializeFadingEdge(TypedArray a) {
4413 // This method probably shouldn't have been included in the SDK to begin with.
4414 // It relies on 'a' having been initialized using an attribute filter array that is
4415 // not publicly available to the SDK. The old method has been renamed
4416 // to initializeFadingEdgeInternal and hidden for framework use only;
4417 // this one initializes using defaults to make it safe to call for apps.
4419 TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4421 initializeFadingEdgeInternal(arr);
4428 * Initializes the fading edges from a given set of styled attributes. This
4429 * method should be called by subclasses that need fading edges and when an
4430 * instance of these subclasses is created programmatically rather than
4431 * being inflated from XML. This method is automatically called when the XML
4435 * @param a the styled attributes set to initialize the fading edges from
4436 * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4438 protected void initializeFadingEdgeInternal(TypedArray a) {
4441 mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4442 R.styleable.View_fadingEdgeLength,
4443 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4447 * Returns the size of the vertical faded edges used to indicate that more
4448 * content in this view is visible.
4450 * @return The size in pixels of the vertical faded edge or 0 if vertical
4451 * faded edges are not enabled for this view.
4452 * @attr ref android.R.styleable#View_fadingEdgeLength
4454 public int getVerticalFadingEdgeLength() {
4455 if (isVerticalFadingEdgeEnabled()) {
4456 ScrollabilityCache cache = mScrollCache;
4457 if (cache != null) {
4458 return cache.fadingEdgeLength;
4465 * Set the size of the faded edge used to indicate that more content in this
4466 * view is available. Will not change whether the fading edge is enabled; use
4467 * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4468 * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4469 * for the vertical or horizontal fading edges.
4471 * @param length The size in pixels of the faded edge used to indicate that more
4472 * content in this view is visible.
4474 public void setFadingEdgeLength(int length) {
4476 mScrollCache.fadingEdgeLength = length;
4480 * Returns the size of the horizontal faded edges used to indicate that more
4481 * content in this view is visible.
4483 * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4484 * faded edges are not enabled for this view.
4485 * @attr ref android.R.styleable#View_fadingEdgeLength
4487 public int getHorizontalFadingEdgeLength() {
4488 if (isHorizontalFadingEdgeEnabled()) {
4489 ScrollabilityCache cache = mScrollCache;
4490 if (cache != null) {
4491 return cache.fadingEdgeLength;
4498 * Returns the width of the vertical scrollbar.
4500 * @return The width in pixels of the vertical scrollbar or 0 if there
4501 * is no vertical scrollbar.
4503 public int getVerticalScrollbarWidth() {
4504 ScrollabilityCache cache = mScrollCache;
4505 if (cache != null) {
4506 ScrollBarDrawable scrollBar = cache.scrollBar;
4507 if (scrollBar != null) {
4508 int size = scrollBar.getSize(true);
4510 size = cache.scrollBarSize;
4520 * Returns the height of the horizontal scrollbar.
4522 * @return The height in pixels of the horizontal scrollbar or 0 if
4523 * there is no horizontal scrollbar.
4525 protected int getHorizontalScrollbarHeight() {
4526 ScrollabilityCache cache = mScrollCache;
4527 if (cache != null) {
4528 ScrollBarDrawable scrollBar = cache.scrollBar;
4529 if (scrollBar != null) {
4530 int size = scrollBar.getSize(false);
4532 size = cache.scrollBarSize;
4543 * Initializes the scrollbars from a given set of styled attributes. This
4544 * method should be called by subclasses that need scrollbars and when an
4545 * instance of these subclasses is created programmatically rather than
4546 * being inflated from XML. This method is automatically called when the XML
4550 * @param a the styled attributes set to initialize the scrollbars from
4554 protected void initializeScrollbars(TypedArray a) {
4555 // It's not safe to use this method from apps. The parameter 'a' must have been obtained
4556 // using the View filter array which is not available to the SDK. As such, internal
4557 // framework usage now uses initializeScrollbarsInternal and we grab a default
4558 // TypedArray with the right filter instead here.
4559 TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4561 initializeScrollbarsInternal(arr);
4563 // We ignored the method parameter. Recycle the one we actually did use.
4569 * Initializes the scrollbars from a given set of styled attributes. This
4570 * method should be called by subclasses that need scrollbars and when an
4571 * instance of these subclasses is created programmatically rather than
4572 * being inflated from XML. This method is automatically called when the XML
4576 * @param a the styled attributes set to initialize the scrollbars from
4579 protected void initializeScrollbarsInternal(TypedArray a) {
4582 final ScrollabilityCache scrollabilityCache = mScrollCache;
4584 if (scrollabilityCache.scrollBar == null) {
4585 scrollabilityCache.scrollBar = new ScrollBarDrawable();
4586 scrollabilityCache.scrollBar.setCallback(this);
4587 scrollabilityCache.scrollBar.setState(getDrawableState());
4590 final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
4592 if (!fadeScrollbars) {
4593 scrollabilityCache.state = ScrollabilityCache.ON;
4595 scrollabilityCache.fadeScrollBars = fadeScrollbars;
4598 scrollabilityCache.scrollBarFadeDuration = a.getInt(
4599 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
4600 .getScrollBarFadeDuration());
4601 scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
4602 R.styleable.View_scrollbarDefaultDelayBeforeFade,
4603 ViewConfiguration.getScrollDefaultDelay());
4606 scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
4607 com.android.internal.R.styleable.View_scrollbarSize,
4608 ViewConfiguration.get(mContext).getScaledScrollBarSize());
4610 Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
4611 scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
4613 Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
4614 if (thumb != null) {
4615 scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
4618 boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
4621 scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
4624 track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
4625 scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
4627 thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
4628 if (thumb != null) {
4629 scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
4632 alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
4635 scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
4638 // Apply layout direction to the new Drawables if needed
4639 final int layoutDirection = getLayoutDirection();
4640 if (track != null) {
4641 track.setLayoutDirection(layoutDirection);
4643 if (thumb != null) {
4644 thumb.setLayoutDirection(layoutDirection);
4647 // Re-apply user/background padding so that scrollbar(s) get added
4653 * Initalizes the scrollability cache if necessary.
4656 private void initScrollCache() {
4657 if (mScrollCache == null) {
4658 mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
4662 private ScrollabilityCache getScrollCache() {
4664 return mScrollCache;
4668 * Set the position of the vertical scroll bar. Should be one of
4669 * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
4670 * {@link #SCROLLBAR_POSITION_RIGHT}.
4672 * @param position Where the vertical scroll bar should be positioned.
4674 public void setVerticalScrollbarPosition(int position) {
4675 if (mVerticalScrollbarPosition != position) {
4676 mVerticalScrollbarPosition = position;
4677 computeOpaqueFlags();
4683 * @return The position where the vertical scroll bar will show, if applicable.
4684 * @see #setVerticalScrollbarPosition(int)
4686 public int getVerticalScrollbarPosition() {
4687 return mVerticalScrollbarPosition;
4690 ListenerInfo getListenerInfo() {
4691 if (mListenerInfo != null) {
4692 return mListenerInfo;
4694 mListenerInfo = new ListenerInfo();
4695 return mListenerInfo;
4699 * Register a callback to be invoked when the scroll X or Y positions of
4702 * <b>Note:</b> Some views handle scrolling independently from View and may
4703 * have their own separate listeners for scroll-type events. For example,
4704 * {@link android.widget.ListView ListView} allows clients to register an
4705 * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
4706 * to listen for changes in list scroll position.
4708 * @param l The listener to notify when the scroll X or Y position changes.
4709 * @see android.view.View#getScrollX()
4710 * @see android.view.View#getScrollY()
4712 public void setOnScrollChangeListener(OnScrollChangeListener l) {
4713 getListenerInfo().mOnScrollChangeListener = l;
4717 * Register a callback to be invoked when focus of this view changed.
4719 * @param l The callback that will run.
4721 public void setOnFocusChangeListener(OnFocusChangeListener l) {
4722 getListenerInfo().mOnFocusChangeListener = l;
4726 * Add a listener that will be called when the bounds of the view change due to
4727 * layout processing.
4729 * @param listener The listener that will be called when layout bounds change.
4731 public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
4732 ListenerInfo li = getListenerInfo();
4733 if (li.mOnLayoutChangeListeners == null) {
4734 li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
4736 if (!li.mOnLayoutChangeListeners.contains(listener)) {
4737 li.mOnLayoutChangeListeners.add(listener);
4742 * Remove a listener for layout changes.
4744 * @param listener The listener for layout bounds change.
4746 public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
4747 ListenerInfo li = mListenerInfo;
4748 if (li == null || li.mOnLayoutChangeListeners == null) {
4751 li.mOnLayoutChangeListeners.remove(listener);
4755 * Add a listener for attach state changes.
4757 * This listener will be called whenever this view is attached or detached
4758 * from a window. Remove the listener using
4759 * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
4761 * @param listener Listener to attach
4762 * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
4764 public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4765 ListenerInfo li = getListenerInfo();
4766 if (li.mOnAttachStateChangeListeners == null) {
4767 li.mOnAttachStateChangeListeners
4768 = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
4770 li.mOnAttachStateChangeListeners.add(listener);
4774 * Remove a listener for attach state changes. The listener will receive no further
4775 * notification of window attach/detach events.
4777 * @param listener Listener to remove
4778 * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
4780 public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4781 ListenerInfo li = mListenerInfo;
4782 if (li == null || li.mOnAttachStateChangeListeners == null) {
4785 li.mOnAttachStateChangeListeners.remove(listener);
4789 * Returns the focus-change callback registered for this view.
4791 * @return The callback, or null if one is not registered.
4793 public OnFocusChangeListener getOnFocusChangeListener() {
4794 ListenerInfo li = mListenerInfo;
4795 return li != null ? li.mOnFocusChangeListener : null;
4799 * Register a callback to be invoked when this view is clicked. If this view is not
4800 * clickable, it becomes clickable.
4802 * @param l The callback that will run
4804 * @see #setClickable(boolean)
4806 public void setOnClickListener(@Nullable OnClickListener l) {
4807 if (!isClickable()) {
4810 getListenerInfo().mOnClickListener = l;
4814 * Return whether this view has an attached OnClickListener. Returns
4815 * true if there is a listener, false if there is none.
4817 public boolean hasOnClickListeners() {
4818 ListenerInfo li = mListenerInfo;
4819 return (li != null && li.mOnClickListener != null);
4823 * Register a callback to be invoked when this view is clicked and held. If this view is not
4824 * long clickable, it becomes long clickable.
4826 * @param l The callback that will run
4828 * @see #setLongClickable(boolean)
4830 public void setOnLongClickListener(@Nullable OnLongClickListener l) {
4831 if (!isLongClickable()) {
4832 setLongClickable(true);
4834 getListenerInfo().mOnLongClickListener = l;
4838 * Register a callback to be invoked when the context menu for this view is
4839 * being built. If this view is not long clickable, it becomes long clickable.
4841 * @param l The callback that will run
4844 public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
4845 if (!isLongClickable()) {
4846 setLongClickable(true);
4848 getListenerInfo().mOnCreateContextMenuListener = l;
4852 * Call this view's OnClickListener, if it is defined. Performs all normal
4853 * actions associated with clicking: reporting accessibility event, playing
4856 * @return True there was an assigned OnClickListener that was called, false
4857 * otherwise is returned.
4859 public boolean performClick() {
4860 final boolean result;
4861 final ListenerInfo li = mListenerInfo;
4862 if (li != null && li.mOnClickListener != null) {
4863 playSoundEffect(SoundEffectConstants.CLICK);
4864 li.mOnClickListener.onClick(this);
4870 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
4875 * Directly call any attached OnClickListener. Unlike {@link #performClick()},
4876 * this only calls the listener, and does not do any associated clicking
4877 * actions like reporting an accessibility event.
4879 * @return True there was an assigned OnClickListener that was called, false
4880 * otherwise is returned.
4882 public boolean callOnClick() {
4883 ListenerInfo li = mListenerInfo;
4884 if (li != null && li.mOnClickListener != null) {
4885 li.mOnClickListener.onClick(this);
4892 * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
4893 * OnLongClickListener did not consume the event.
4895 * @return True if one of the above receivers consumed the event, false otherwise.
4897 public boolean performLongClick() {
4898 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
4900 boolean handled = false;
4901 ListenerInfo li = mListenerInfo;
4902 if (li != null && li.mOnLongClickListener != null) {
4903 handled = li.mOnLongClickListener.onLongClick(View.this);
4906 handled = showContextMenu();
4909 performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
4915 * Performs button-related actions during a touch down event.
4917 * @param event The event.
4918 * @return True if the down was consumed.
4922 protected boolean performButtonActionOnTouchDown(MotionEvent event) {
4923 if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE &&
4924 (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
4925 showContextMenu(event.getX(), event.getY(), event.getMetaState());
4926 mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
4933 * Bring up the context menu for this view.
4935 * @return Whether a context menu was displayed.
4937 public boolean showContextMenu() {
4938 return getParent().showContextMenuForChild(this);
4942 * Bring up the context menu for this view, referring to the item under the specified point.
4944 * @param x The referenced x coordinate.
4945 * @param y The referenced y coordinate.
4946 * @param metaState The keyboard modifiers that were pressed.
4947 * @return Whether a context menu was displayed.
4951 public boolean showContextMenu(float x, float y, int metaState) {
4952 return showContextMenu();
4956 * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
4958 * @param callback Callback that will control the lifecycle of the action mode
4959 * @return The new action mode if it is started, null otherwise
4962 * @see #startActionMode(android.view.ActionMode.Callback, int)
4964 public ActionMode startActionMode(ActionMode.Callback callback) {
4965 return startActionMode(callback, ActionMode.TYPE_PRIMARY);
4969 * Start an action mode with the given type.
4971 * @param callback Callback that will control the lifecycle of the action mode
4972 * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
4973 * @return The new action mode if it is started, null otherwise
4977 public ActionMode startActionMode(ActionMode.Callback callback, int type) {
4978 ViewParent parent = getParent();
4979 if (parent == null) return null;
4981 return parent.startActionModeForChild(this, callback, type);
4982 } catch (AbstractMethodError ame) {
4983 // Older implementations of custom views might not implement this.
4984 return parent.startActionModeForChild(this, callback);
4989 * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
4990 * Context, creating a unique View identifier to retrieve the result.
4992 * @param intent The Intent to be started.
4993 * @param requestCode The request code to use.
4996 public void startActivityForResult(Intent intent, int requestCode) {
4997 mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
4998 getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
5002 * If this View corresponds to the calling who, dispatches the activity result.
5003 * @param who The identifier for the targeted View to receive the result.
5004 * @param requestCode The integer request code originally supplied to
5005 * startActivityForResult(), allowing you to identify who this
5007 * @param resultCode The integer result code returned by the child activity
5008 * through its setResult().
5009 * @param data An Intent, which can return result data to the caller
5010 * (various data can be attached to Intent "extras").
5011 * @return {@code true} if the activity result was dispatched.
5014 public boolean dispatchActivityResult(
5015 String who, int requestCode, int resultCode, Intent data) {
5016 if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
5017 onActivityResult(requestCode, resultCode, data);
5018 mStartActivityRequestWho = null;
5025 * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
5027 * @param requestCode The integer request code originally supplied to
5028 * startActivityForResult(), allowing you to identify who this
5030 * @param resultCode The integer result code returned by the child activity
5031 * through its setResult().
5032 * @param data An Intent, which can return result data to the caller
5033 * (various data can be attached to Intent "extras").
5036 public void onActivityResult(int requestCode, int resultCode, Intent data) {
5041 * Register a callback to be invoked when a hardware key is pressed in this view.
5042 * Key presses in software input methods will generally not trigger the methods of
5044 * @param l the key listener to attach to this view
5046 public void setOnKeyListener(OnKeyListener l) {
5047 getListenerInfo().mOnKeyListener = l;
5051 * Register a callback to be invoked when a touch event is sent to this view.
5052 * @param l the touch listener to attach to this view
5054 public void setOnTouchListener(OnTouchListener l) {
5055 getListenerInfo().mOnTouchListener = l;
5059 * Register a callback to be invoked when a generic motion event is sent to this view.
5060 * @param l the generic motion listener to attach to this view
5062 public void setOnGenericMotionListener(OnGenericMotionListener l) {
5063 getListenerInfo().mOnGenericMotionListener = l;
5067 * Register a callback to be invoked when a hover event is sent to this view.
5068 * @param l the hover listener to attach to this view
5070 public void setOnHoverListener(OnHoverListener l) {
5071 getListenerInfo().mOnHoverListener = l;
5075 * Register a drag event listener callback object for this View. The parameter is
5076 * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
5077 * View, the system calls the
5078 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
5079 * @param l An implementation of {@link android.view.View.OnDragListener}.
5081 public void setOnDragListener(OnDragListener l) {
5082 getListenerInfo().mOnDragListener = l;
5086 * Give this view focus. This will cause
5087 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
5089 * Note: this does not check whether this {@link View} should get focus, it just
5090 * gives it focus no matter what. It should only be called internally by framework
5091 * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
5093 * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
5094 * {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
5095 * focus moved when requestFocus() is called. It may not always
5096 * apply, in which case use the default View.FOCUS_DOWN.
5097 * @param previouslyFocusedRect The rectangle of the view that had focus
5098 * prior in this View's coordinate system.
5100 void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
5102 System.out.println(this + " requestFocus()");
5105 if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
5106 mPrivateFlags |= PFLAG_FOCUSED;
5108 View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
5110 if (mParent != null) {
5111 mParent.requestChildFocus(this, this);
5114 if (mAttachInfo != null) {
5115 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
5118 onFocusChanged(true, direction, previouslyFocusedRect);
5119 refreshDrawableState();
5124 * Populates <code>outRect</code> with the hotspot bounds. By default,
5125 * the hotspot bounds are identical to the screen bounds.
5127 * @param outRect rect to populate with hotspot bounds
5128 * @hide Only for internal use by views and widgets.
5130 public void getHotspotBounds(Rect outRect) {
5131 final Drawable background = getBackground();
5132 if (background != null) {
5133 background.getHotspotBounds(outRect);
5135 getBoundsOnScreen(outRect);
5140 * Request that a rectangle of this view be visible on the screen,
5141 * scrolling if necessary just enough.
5143 * <p>A View should call this if it maintains some notion of which part
5144 * of its content is interesting. For example, a text editing view
5145 * should call this when its cursor moves.
5147 * @param rectangle The rectangle.
5148 * @return Whether any parent scrolled.
5150 public boolean requestRectangleOnScreen(Rect rectangle) {
5151 return requestRectangleOnScreen(rectangle, false);
5155 * Request that a rectangle of this view be visible on the screen,
5156 * scrolling if necessary just enough.
5158 * <p>A View should call this if it maintains some notion of which part
5159 * of its content is interesting. For example, a text editing view
5160 * should call this when its cursor moves.
5162 * <p>When <code>immediate</code> is set to true, scrolling will not be
5165 * @param rectangle The rectangle.
5166 * @param immediate True to forbid animated scrolling, false otherwise
5167 * @return Whether any parent scrolled.
5169 public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
5170 if (mParent == null) {
5176 RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
5177 position.set(rectangle);
5179 ViewParent parent = mParent;
5180 boolean scrolled = false;
5181 while (parent != null) {
5182 rectangle.set((int) position.left, (int) position.top,
5183 (int) position.right, (int) position.bottom);
5185 scrolled |= parent.requestChildRectangleOnScreen(child,
5186 rectangle, immediate);
5188 if (!child.hasIdentityMatrix()) {
5189 child.getMatrix().mapRect(position);
5192 position.offset(child.mLeft, child.mTop);
5194 if (!(parent instanceof View)) {
5198 View parentView = (View) parent;
5200 position.offset(-parentView.getScrollX(), -parentView.getScrollY());
5203 parent = child.getParent();
5210 * Called when this view wants to give up focus. If focus is cleared
5211 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
5213 * <strong>Note:</strong> When a View clears focus the framework is trying
5214 * to give focus to the first focusable View from the top. Hence, if this
5215 * View is the first from the top that can take focus, then all callbacks
5216 * related to clearing focus will be invoked after which the framework will
5217 * give focus to this view.
5220 public void clearFocus() {
5222 System.out.println(this + " clearFocus()");
5225 clearFocusInternal(null, true, true);
5229 * Clears focus from the view, optionally propagating the change up through
5230 * the parent hierarchy and requesting that the root view place new focus.
5232 * @param propagate whether to propagate the change up through the parent
5234 * @param refocus when propagate is true, specifies whether to request the
5235 * root view place new focus
5237 void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
5238 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
5239 mPrivateFlags &= ~PFLAG_FOCUSED;
5241 if (propagate && mParent != null) {
5242 mParent.clearChildFocus(this);
5245 onFocusChanged(false, 0, null);
5246 refreshDrawableState();
5248 if (propagate && (!refocus || !rootViewRequestFocus())) {
5249 notifyGlobalFocusCleared(this);
5254 void notifyGlobalFocusCleared(View oldFocus) {
5255 if (oldFocus != null && mAttachInfo != null) {
5256 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
5260 boolean rootViewRequestFocus() {
5261 final View root = getRootView();
5262 return root != null && root.requestFocus();
5266 * Called internally by the view system when a new view is getting focus.
5267 * This is what clears the old focus.
5269 * <b>NOTE:</b> The parent view's focused child must be updated manually
5270 * after calling this method. Otherwise, the view hierarchy may be left in
5271 * an inconstent state.
5273 void unFocus(View focused) {
5275 System.out.println(this + " unFocus()");
5278 clearFocusInternal(focused, false, false);
5282 * Returns true if this view has focus itself, or is the ancestor of the
5283 * view that has focus.
5285 * @return True if this view has or contains focus, false otherwise.
5287 @ViewDebug.ExportedProperty(category = "focus")
5288 public boolean hasFocus() {
5289 return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5293 * Returns true if this view is focusable or if it contains a reachable View
5294 * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
5295 * is a View whose parents do not block descendants focus.
5297 * Only {@link #VISIBLE} views are considered focusable.
5299 * @return True if the view is focusable or if the view contains a focusable
5300 * View, false otherwise.
5302 * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
5303 * @see ViewGroup#getTouchscreenBlocksFocus()
5305 public boolean hasFocusable() {
5306 if (!isFocusableInTouchMode()) {
5307 for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
5308 final ViewGroup g = (ViewGroup) p;
5309 if (g.shouldBlockFocusForTouchscreen()) {
5314 return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
5318 * Called by the view system when the focus state of this view changes.
5319 * When the focus change event is caused by directional navigation, direction
5320 * and previouslyFocusedRect provide insight into where the focus is coming from.
5321 * When overriding, be sure to call up through to the super class so that
5322 * the standard focus handling will occur.
5324 * @param gainFocus True if the View has focus; false otherwise.
5325 * @param direction The direction focus has moved when requestFocus()
5326 * is called to give this view focus. Values are
5327 * {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
5328 * {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
5329 * It may not always apply, in which case use the default.
5330 * @param previouslyFocusedRect The rectangle, in this view's coordinate
5331 * system, of the previously focused view. If applicable, this will be
5332 * passed in as finer grained information about where the focus is coming
5333 * from (in addition to direction). Will be <code>null</code> otherwise.
5336 protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
5337 @Nullable Rect previouslyFocusedRect) {
5339 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
5341 notifyViewAccessibilityStateChangedIfNeeded(
5342 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5345 InputMethodManager imm = InputMethodManager.peekInstance();
5350 if (imm != null && mAttachInfo != null
5351 && mAttachInfo.mHasWindowFocus) {
5355 } else if (imm != null && mAttachInfo != null
5356 && mAttachInfo.mHasWindowFocus) {
5361 ListenerInfo li = mListenerInfo;
5362 if (li != null && li.mOnFocusChangeListener != null) {
5363 li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
5366 if (mAttachInfo != null) {
5367 mAttachInfo.mKeyDispatchState.reset(this);
5372 * Sends an accessibility event of the given type. If accessibility is
5373 * not enabled this method has no effect. The default implementation calls
5374 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
5375 * to populate information about the event source (this View), then calls
5376 * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
5377 * populate the text content of the event source including its descendants,
5379 * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
5380 * on its parent to request sending of the event to interested parties.
5382 * If an {@link AccessibilityDelegate} has been specified via calling
5383 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5384 * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
5385 * responsible for handling this call.
5388 * @param eventType The type of the event to send, as defined by several types from
5389 * {@link android.view.accessibility.AccessibilityEvent}, such as
5390 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
5391 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
5393 * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5394 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5395 * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
5396 * @see AccessibilityDelegate
5398 public void sendAccessibilityEvent(int eventType) {
5399 if (mAccessibilityDelegate != null) {
5400 mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
5402 sendAccessibilityEventInternal(eventType);
5407 * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
5408 * {@link AccessibilityEvent} to make an announcement which is related to some
5409 * sort of a context change for which none of the events representing UI transitions
5410 * is a good fit. For example, announcing a new page in a book. If accessibility
5411 * is not enabled this method does nothing.
5413 * @param text The announcement text.
5415 public void announceForAccessibility(CharSequence text) {
5416 if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
5417 AccessibilityEvent event = AccessibilityEvent.obtain(
5418 AccessibilityEvent.TYPE_ANNOUNCEMENT);
5419 onInitializeAccessibilityEvent(event);
5420 event.getText().add(text);
5421 event.setContentDescription(null);
5422 mParent.requestSendAccessibilityEvent(this, event);
5427 * @see #sendAccessibilityEvent(int)
5429 * Note: Called from the default {@link AccessibilityDelegate}.
5433 public void sendAccessibilityEventInternal(int eventType) {
5434 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
5435 sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
5440 * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
5441 * takes as an argument an empty {@link AccessibilityEvent} and does not
5442 * perform a check whether accessibility is enabled.
5444 * If an {@link AccessibilityDelegate} has been specified via calling
5445 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5446 * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
5447 * is responsible for handling this call.
5450 * @param event The event to send.
5452 * @see #sendAccessibilityEvent(int)
5454 public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
5455 if (mAccessibilityDelegate != null) {
5456 mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
5458 sendAccessibilityEventUncheckedInternal(event);
5463 * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
5465 * Note: Called from the default {@link AccessibilityDelegate}.
5469 public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
5473 onInitializeAccessibilityEvent(event);
5474 // Only a subset of accessibility events populates text content.
5475 if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
5476 dispatchPopulateAccessibilityEvent(event);
5478 // In the beginning we called #isShown(), so we know that getParent() is not null.
5479 getParent().requestSendAccessibilityEvent(this, event);
5483 * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
5484 * to its children for adding their text content to the event. Note that the
5485 * event text is populated in a separate dispatch path since we add to the
5486 * event not only the text of the source but also the text of all its descendants.
5487 * A typical implementation will call
5488 * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
5489 * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5490 * on each child. Override this method if custom population of the event text
5491 * content is required.
5493 * If an {@link AccessibilityDelegate} has been specified via calling
5494 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5495 * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
5496 * is responsible for handling this call.
5499 * <em>Note:</em> Accessibility events of certain types are not dispatched for
5500 * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
5503 * @param event The event.
5505 * @return True if the event population was completed.
5507 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
5508 if (mAccessibilityDelegate != null) {
5509 return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
5511 return dispatchPopulateAccessibilityEventInternal(event);
5516 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5518 * Note: Called from the default {@link AccessibilityDelegate}.
5522 public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5523 onPopulateAccessibilityEvent(event);
5528 * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5529 * giving a chance to this View to populate the accessibility event with its
5530 * text content. While this method is free to modify event
5531 * attributes other than text content, doing so should normally be performed in
5532 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
5534 * Example: Adding formatted date string to an accessibility event in addition
5535 * to the text added by the super implementation:
5536 * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5537 * super.onPopulateAccessibilityEvent(event);
5538 * final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
5539 * String selectedDateUtterance = DateUtils.formatDateTime(mContext,
5540 * mCurrentDate.getTimeInMillis(), flags);
5541 * event.getText().add(selectedDateUtterance);
5544 * If an {@link AccessibilityDelegate} has been specified via calling
5545 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5546 * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
5547 * is responsible for handling this call.
5549 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5550 * information to the event, in case the default implementation has basic information to add.
5553 * @param event The accessibility event which to populate.
5555 * @see #sendAccessibilityEvent(int)
5556 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5559 public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5560 if (mAccessibilityDelegate != null) {
5561 mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
5563 onPopulateAccessibilityEventInternal(event);
5568 * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
5570 * Note: Called from the default {@link AccessibilityDelegate}.
5574 public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5578 * Initializes an {@link AccessibilityEvent} with information about
5579 * this View which is the event source. In other words, the source of
5580 * an accessibility event is the view whose state change triggered firing
5583 * Example: Setting the password property of an event in addition
5584 * to properties set by the super implementation:
5585 * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5586 * super.onInitializeAccessibilityEvent(event);
5587 * event.setPassword(true);
5590 * If an {@link AccessibilityDelegate} has been specified via calling
5591 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5592 * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
5593 * is responsible for handling this call.
5595 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5596 * information to the event, in case the default implementation has basic information to add.
5598 * @param event The event to initialize.
5600 * @see #sendAccessibilityEvent(int)
5601 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5604 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5605 if (mAccessibilityDelegate != null) {
5606 mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
5608 onInitializeAccessibilityEventInternal(event);
5613 * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5615 * Note: Called from the default {@link AccessibilityDelegate}.
5619 public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
5620 event.setSource(this);
5621 event.setClassName(getAccessibilityClassName());
5622 event.setPackageName(getContext().getPackageName());
5623 event.setEnabled(isEnabled());
5624 event.setContentDescription(mContentDescription);
5626 switch (event.getEventType()) {
5627 case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
5628 ArrayList<View> focusablesTempList = (mAttachInfo != null)
5629 ? mAttachInfo.mTempArrayList : new ArrayList<View>();
5630 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
5631 event.setItemCount(focusablesTempList.size());
5632 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
5633 if (mAttachInfo != null) {
5634 focusablesTempList.clear();
5637 case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
5638 CharSequence text = getIterableTextForAccessibility();
5639 if (text != null && text.length() > 0) {
5640 event.setFromIndex(getAccessibilitySelectionStart());
5641 event.setToIndex(getAccessibilitySelectionEnd());
5642 event.setItemCount(text.length());
5649 * Returns an {@link AccessibilityNodeInfo} representing this view from the
5650 * point of view of an {@link android.accessibilityservice.AccessibilityService}.
5651 * This method is responsible for obtaining an accessibility node info from a
5652 * pool of reusable instances and calling
5653 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
5654 * initialize the former.
5656 * Note: The client is responsible for recycling the obtained instance by calling
5657 * {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
5660 * @return A populated {@link AccessibilityNodeInfo}.
5662 * @see AccessibilityNodeInfo
5664 public AccessibilityNodeInfo createAccessibilityNodeInfo() {
5665 if (mAccessibilityDelegate != null) {
5666 return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
5668 return createAccessibilityNodeInfoInternal();
5673 * @see #createAccessibilityNodeInfo()
5677 public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
5678 AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
5679 if (provider != null) {
5680 return provider.createAccessibilityNodeInfo(View.NO_ID);
5682 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
5683 onInitializeAccessibilityNodeInfo(info);
5689 * Initializes an {@link AccessibilityNodeInfo} with information about this view.
5690 * The base implementation sets:
5692 * <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
5693 * <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
5694 * <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
5695 * <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
5696 * <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
5697 * <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
5698 * <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
5699 * <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
5700 * <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
5701 * <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
5702 * <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
5703 * <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
5706 * Subclasses should override this method, call the super implementation,
5707 * and set additional attributes.
5710 * If an {@link AccessibilityDelegate} has been specified via calling
5711 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5712 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
5713 * is responsible for handling this call.
5716 * @param info The instance to initialize.
5719 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
5720 if (mAccessibilityDelegate != null) {
5721 mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
5723 onInitializeAccessibilityNodeInfoInternal(info);
5728 * Gets the location of this view in screen coordinates.
5730 * @param outRect The output location
5733 public void getBoundsOnScreen(Rect outRect) {
5734 getBoundsOnScreen(outRect, false);
5738 * Gets the location of this view in screen coordinates.
5740 * @param outRect The output location
5741 * @param clipToParent Whether to clip child bounds to the parent ones.
5744 public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
5745 if (mAttachInfo == null) {
5749 RectF position = mAttachInfo.mTmpTransformRect;
5750 position.set(0, 0, mRight - mLeft, mBottom - mTop);
5752 if (!hasIdentityMatrix()) {
5753 getMatrix().mapRect(position);
5756 position.offset(mLeft, mTop);
5758 ViewParent parent = mParent;
5759 while (parent instanceof View) {
5760 View parentView = (View) parent;
5762 position.offset(-parentView.mScrollX, -parentView.mScrollY);
5765 position.left = Math.max(position.left, 0);
5766 position.top = Math.max(position.top, 0);
5767 position.right = Math.min(position.right, parentView.getWidth());
5768 position.bottom = Math.min(position.bottom, parentView.getHeight());
5771 if (!parentView.hasIdentityMatrix()) {
5772 parentView.getMatrix().mapRect(position);
5775 position.offset(parentView.mLeft, parentView.mTop);
5777 parent = parentView.mParent;
5780 if (parent instanceof ViewRootImpl) {
5781 ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
5782 position.offset(0, -viewRootImpl.mCurScrollY);
5785 position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
5787 outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
5788 (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
5792 * Return the class name of this object to be used for accessibility purposes.
5793 * Subclasses should only override this if they are implementing something that
5794 * should be seen as a completely new class of view when used by accessibility,
5795 * unrelated to the class it is deriving from. This is used to fill in
5796 * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
5798 public CharSequence getAccessibilityClassName() {
5799 return View.class.getName();
5803 * Called when assist structure is being retrieved from a view as part of
5804 * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
5805 * @param structure Fill in with structured view data. The default implementation
5806 * fills in all data that can be inferred from the view itself.
5808 public void onProvideAssistStructure(ViewAssistStructure structure) {
5810 if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
5811 && (id&0x0000ffff) != 0) {
5812 String pkg, type, entry;
5814 final Resources res = getResources();
5815 entry = res.getResourceEntryName(id);
5816 type = res.getResourceTypeName(id);
5817 pkg = res.getResourcePackageName(id);
5818 } catch (Resources.NotFoundException e) {
5819 entry = type = pkg = null;
5821 structure.setId(id, pkg, type, entry);
5823 structure.setId(id, null, null, null);
5825 structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
5826 structure.setVisibility(getVisibility());
5827 structure.setEnabled(isEnabled());
5828 if (isClickable()) {
5829 structure.setClickable(true);
5831 if (isFocusable()) {
5832 structure.setFocusable(true);
5835 structure.setFocused(true);
5837 if (isAccessibilityFocused()) {
5838 structure.setAccessibilityFocused(true);
5841 structure.setSelected(true);
5843 if (isActivated()) {
5844 structure.setActivated(true);
5846 if (isLongClickable()) {
5847 structure.setLongClickable(true);
5849 if (this instanceof Checkable) {
5850 structure.setCheckable(true);
5851 if (((Checkable)this).isChecked()) {
5852 structure.setChecked(true);
5855 structure.setClassName(getAccessibilityClassName().toString());
5856 structure.setContentDescription(getContentDescription());
5860 * Called when assist structure is being retrieved from a view as part of
5861 * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
5862 * generate additional virtual structure under this view. The defaullt implementation
5863 * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
5864 * view's virtual accessibility nodes, if any. You can override this for a more
5865 * optimal implementation providing this data.
5867 public void onProvideVirtualAssistStructure(ViewAssistStructure structure) {
5868 AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
5869 if (provider != null) {
5870 AccessibilityNodeInfo info = createAccessibilityNodeInfo();
5871 Log.i("View", "Provider of " + this + ": children=" + info.getChildCount());
5872 structure.setChildCount(1);
5873 ViewAssistStructure root = structure.newChild(0);
5874 populateVirtualAssistStructure(root, provider, info);
5879 private void populateVirtualAssistStructure(ViewAssistStructure structure,
5880 AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
5881 structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
5883 Rect rect = structure.getTempRect();
5884 info.getBoundsInParent(rect);
5885 structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
5886 structure.setVisibility(VISIBLE);
5887 structure.setEnabled(info.isEnabled());
5888 if (info.isClickable()) {
5889 structure.setClickable(true);
5891 if (info.isFocusable()) {
5892 structure.setFocusable(true);
5894 if (info.isFocused()) {
5895 structure.setFocused(true);
5897 if (info.isAccessibilityFocused()) {
5898 structure.setAccessibilityFocused(true);
5900 if (info.isSelected()) {
5901 structure.setSelected(true);
5903 if (info.isLongClickable()) {
5904 structure.setLongClickable(true);
5906 if (info.isCheckable()) {
5907 structure.setCheckable(true);
5908 if (info.isChecked()) {
5909 structure.setChecked(true);
5912 CharSequence cname = info.getClassName();
5913 structure.setClassName(cname != null ? cname.toString() : null);
5914 structure.setContentDescription(info.getContentDescription());
5915 Log.i("View", "vassist " + cname + " @ " + rect.toShortString()
5916 + " text=" + info.getText() + " cd=" + info.getContentDescription());
5917 if (info.getText() != null || info.getError() != null) {
5918 structure.setText(info.getText(), info.getTextSelectionStart(),
5919 info.getTextSelectionEnd());
5921 final int NCHILDREN = info.getChildCount();
5922 if (NCHILDREN > 0) {
5923 structure.setChildCount(NCHILDREN);
5924 for (int i=0; i<NCHILDREN; i++) {
5925 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
5926 AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
5927 ViewAssistStructure child = structure.newChild(i);
5928 populateVirtualAssistStructure(child, provider, cinfo);
5935 * Dispatch creation of {@link ViewAssistStructure} down the hierarchy. The default
5936 * implementation calls {@link #onProvideAssistStructure} and
5937 * {@link #onProvideVirtualAssistStructure}.
5939 public void dispatchProvideAssistStructure(ViewAssistStructure structure) {
5940 if (!isAssistBlocked()) {
5941 onProvideAssistStructure(structure);
5942 onProvideVirtualAssistStructure(structure);
5944 structure.setClassName(getAccessibilityClassName().toString());
5945 structure.setAssistBlocked(true);
5950 * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
5952 * Note: Called from the default {@link AccessibilityDelegate}.
5956 public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
5957 Rect bounds = mAttachInfo.mTmpInvalRect;
5959 getDrawingRect(bounds);
5960 info.setBoundsInParent(bounds);
5962 getBoundsOnScreen(bounds, true);
5963 info.setBoundsInScreen(bounds);
5965 ViewParent parent = getParentForAccessibility();
5966 if (parent instanceof View) {
5967 info.setParent((View) parent);
5970 if (mID != View.NO_ID) {
5971 View rootView = getRootView();
5972 if (rootView == null) {
5976 View label = rootView.findLabelForView(this, mID);
5977 if (label != null) {
5978 info.setLabeledBy(label);
5981 if ((mAttachInfo.mAccessibilityFetchFlags
5982 & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
5983 && Resources.resourceHasPackage(mID)) {
5985 String viewId = getResources().getResourceName(mID);
5986 info.setViewIdResourceName(viewId);
5987 } catch (Resources.NotFoundException nfe) {
5993 if (mLabelForId != View.NO_ID) {
5994 View rootView = getRootView();
5995 if (rootView == null) {
5998 View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
5999 if (labeled != null) {
6000 info.setLabelFor(labeled);
6004 if (mAccessibilityTraversalBeforeId != View.NO_ID) {
6005 View rootView = getRootView();
6006 if (rootView == null) {
6009 View next = rootView.findViewInsideOutShouldExist(this,
6010 mAccessibilityTraversalBeforeId);
6012 info.setTraversalBefore(next);
6016 if (mAccessibilityTraversalAfterId != View.NO_ID) {
6017 View rootView = getRootView();
6018 if (rootView == null) {
6021 View next = rootView.findViewInsideOutShouldExist(this,
6022 mAccessibilityTraversalAfterId);
6024 info.setTraversalAfter(next);
6028 info.setVisibleToUser(isVisibleToUser());
6030 info.setPackageName(mContext.getPackageName());
6031 info.setClassName(getAccessibilityClassName());
6032 info.setContentDescription(getContentDescription());
6034 info.setEnabled(isEnabled());
6035 info.setClickable(isClickable());
6036 info.setFocusable(isFocusable());
6037 info.setFocused(isFocused());
6038 info.setAccessibilityFocused(isAccessibilityFocused());
6039 info.setSelected(isSelected());
6040 info.setLongClickable(isLongClickable());
6041 info.setLiveRegion(getAccessibilityLiveRegion());
6043 // TODO: These make sense only if we are in an AdapterView but all
6044 // views can be selected. Maybe from accessibility perspective
6045 // we should report as selectable view in an AdapterView.
6046 info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
6047 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
6049 if (isFocusable()) {
6051 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
6053 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
6057 if (!isAccessibilityFocused()) {
6058 info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
6060 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
6063 if (isClickable() && isEnabled()) {
6064 info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
6067 if (isLongClickable() && isEnabled()) {
6068 info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
6071 CharSequence text = getIterableTextForAccessibility();
6072 if (text != null && text.length() > 0) {
6073 info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
6075 info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
6076 info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
6077 info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
6078 info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
6079 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
6080 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
6083 info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
6086 private View findLabelForView(View view, int labeledId) {
6087 if (mMatchLabelForPredicate == null) {
6088 mMatchLabelForPredicate = new MatchLabelForPredicate();
6090 mMatchLabelForPredicate.mLabeledId = labeledId;
6091 return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
6095 * Computes whether this view is visible to the user. Such a view is
6096 * attached, visible, all its predecessors are visible, it is not clipped
6097 * entirely by its predecessors, and has an alpha greater than zero.
6099 * @return Whether the view is visible on the screen.
6103 protected boolean isVisibleToUser() {
6104 return isVisibleToUser(null);
6108 * Computes whether the given portion of this view is visible to the user.
6109 * Such a view is attached, visible, all its predecessors are visible,
6110 * has an alpha greater than zero, and the specified portion is not
6111 * clipped entirely by its predecessors.
6113 * @param boundInView the portion of the view to test; coordinates should be relative; may be
6114 * <code>null</code>, and the entire view will be tested in this case.
6115 * When <code>true</code> is returned by the function, the actual visible
6116 * region will be stored in this parameter; that is, if boundInView is fully
6117 * contained within the view, no modification will be made, otherwise regions
6118 * outside of the visible area of the view will be clipped.
6120 * @return Whether the specified portion of the view is visible on the screen.
6124 protected boolean isVisibleToUser(Rect boundInView) {
6125 if (mAttachInfo != null) {
6126 // Attached to invisible window means this view is not visible.
6127 if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
6130 // An invisible predecessor or one with alpha zero means
6131 // that this view is not visible to the user.
6132 Object current = this;
6133 while (current instanceof View) {
6134 View view = (View) current;
6135 // We have attach info so this view is attached and there is no
6136 // need to check whether we reach to ViewRootImpl on the way up.
6137 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
6138 view.getVisibility() != VISIBLE) {
6141 current = view.mParent;
6143 // Check if the view is entirely covered by its predecessors.
6144 Rect visibleRect = mAttachInfo.mTmpInvalRect;
6145 Point offset = mAttachInfo.mPoint;
6146 if (!getGlobalVisibleRect(visibleRect, offset)) {
6149 // Check if the visible portion intersects the rectangle of interest.
6150 if (boundInView != null) {
6151 visibleRect.offset(-offset.x, -offset.y);
6152 return boundInView.intersect(visibleRect);
6160 * Returns the delegate for implementing accessibility support via
6161 * composition. For more details see {@link AccessibilityDelegate}.
6163 * @return The delegate, or null if none set.
6167 public AccessibilityDelegate getAccessibilityDelegate() {
6168 return mAccessibilityDelegate;
6172 * Sets a delegate for implementing accessibility support via composition as
6173 * opposed to inheritance. The delegate's primary use is for implementing
6174 * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
6176 * @param delegate The delegate instance.
6178 * @see AccessibilityDelegate
6180 public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
6181 mAccessibilityDelegate = delegate;
6185 * Gets the provider for managing a virtual view hierarchy rooted at this View
6186 * and reported to {@link android.accessibilityservice.AccessibilityService}s
6187 * that explore the window content.
6189 * If this method returns an instance, this instance is responsible for managing
6190 * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
6191 * View including the one representing the View itself. Similarly the returned
6192 * instance is responsible for performing accessibility actions on any virtual
6193 * view or the root view itself.
6196 * If an {@link AccessibilityDelegate} has been specified via calling
6197 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6198 * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
6199 * is responsible for handling this call.
6202 * @return The provider.
6204 * @see AccessibilityNodeProvider
6206 public AccessibilityNodeProvider getAccessibilityNodeProvider() {
6207 if (mAccessibilityDelegate != null) {
6208 return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
6215 * Gets the unique identifier of this view on the screen for accessibility purposes.
6216 * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
6218 * @return The view accessibility id.
6222 public int getAccessibilityViewId() {
6223 if (mAccessibilityViewId == NO_ID) {
6224 mAccessibilityViewId = sNextAccessibilityViewId++;
6226 return mAccessibilityViewId;
6230 * Gets the unique identifier of the window in which this View reseides.
6232 * @return The window accessibility id.
6236 public int getAccessibilityWindowId() {
6237 return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
6238 : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
6242 * Gets the {@link View} description. It briefly describes the view and is
6243 * primarily used for accessibility support. Set this property to enable
6244 * better accessibility support for your application. This is especially
6245 * true for views that do not have textual representation (For example,
6248 * @return The content description.
6250 * @attr ref android.R.styleable#View_contentDescription
6252 @ViewDebug.ExportedProperty(category = "accessibility")
6253 public CharSequence getContentDescription() {
6254 return mContentDescription;
6258 * Sets the {@link View} description. It briefly describes the view and is
6259 * primarily used for accessibility support. Set this property to enable
6260 * better accessibility support for your application. This is especially
6261 * true for views that do not have textual representation (For example,
6264 * @param contentDescription The content description.
6266 * @attr ref android.R.styleable#View_contentDescription
6268 @RemotableViewMethod
6269 public void setContentDescription(CharSequence contentDescription) {
6270 if (mContentDescription == null) {
6271 if (contentDescription == null) {
6274 } else if (mContentDescription.equals(contentDescription)) {
6277 mContentDescription = contentDescription;
6278 final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
6279 if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
6280 setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
6281 notifySubtreeAccessibilityStateChangedIfNeeded();
6283 notifyViewAccessibilityStateChangedIfNeeded(
6284 AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
6289 * Sets the id of a view before which this one is visited in accessibility traversal.
6290 * A screen-reader must visit the content of this view before the content of the one
6291 * it precedes. For example, if view B is set to be before view A, then a screen-reader
6292 * will traverse the entire content of B before traversing the entire content of A,
6293 * regardles of what traversal strategy it is using.
6295 * Views that do not have specified before/after relationships are traversed in order
6296 * determined by the screen-reader.
6299 * Setting that this view is before a view that is not important for accessibility
6300 * or if this view is not important for accessibility will have no effect as the
6301 * screen-reader is not aware of unimportant views.
6304 * @param beforeId The id of a view this one precedes in accessibility traversal.
6306 * @attr ref android.R.styleable#View_accessibilityTraversalBefore
6308 * @see #setImportantForAccessibility(int)
6310 @RemotableViewMethod
6311 public void setAccessibilityTraversalBefore(int beforeId) {
6312 if (mAccessibilityTraversalBeforeId == beforeId) {
6315 mAccessibilityTraversalBeforeId = beforeId;
6316 notifyViewAccessibilityStateChangedIfNeeded(
6317 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6321 * Gets the id of a view before which this one is visited in accessibility traversal.
6323 * @return The id of a view this one precedes in accessibility traversal if
6324 * specified, otherwise {@link #NO_ID}.
6326 * @see #setAccessibilityTraversalBefore(int)
6328 public int getAccessibilityTraversalBefore() {
6329 return mAccessibilityTraversalBeforeId;
6333 * Sets the id of a view after which this one is visited in accessibility traversal.
6334 * A screen-reader must visit the content of the other view before the content of this
6335 * one. For example, if view B is set to be after view A, then a screen-reader
6336 * will traverse the entire content of A before traversing the entire content of B,
6337 * regardles of what traversal strategy it is using.
6339 * Views that do not have specified before/after relationships are traversed in order
6340 * determined by the screen-reader.
6343 * Setting that this view is after a view that is not important for accessibility
6344 * or if this view is not important for accessibility will have no effect as the
6345 * screen-reader is not aware of unimportant views.
6348 * @param afterId The id of a view this one succedees in accessibility traversal.
6350 * @attr ref android.R.styleable#View_accessibilityTraversalAfter
6352 * @see #setImportantForAccessibility(int)
6354 @RemotableViewMethod
6355 public void setAccessibilityTraversalAfter(int afterId) {
6356 if (mAccessibilityTraversalAfterId == afterId) {
6359 mAccessibilityTraversalAfterId = afterId;
6360 notifyViewAccessibilityStateChangedIfNeeded(
6361 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6365 * Gets the id of a view after which this one is visited in accessibility traversal.
6367 * @return The id of a view this one succeedes in accessibility traversal if
6368 * specified, otherwise {@link #NO_ID}.
6370 * @see #setAccessibilityTraversalAfter(int)
6372 public int getAccessibilityTraversalAfter() {
6373 return mAccessibilityTraversalAfterId;
6377 * Gets the id of a view for which this view serves as a label for
6378 * accessibility purposes.
6380 * @return The labeled view id.
6382 @ViewDebug.ExportedProperty(category = "accessibility")
6383 public int getLabelFor() {
6388 * Sets the id of a view for which this view serves as a label for
6389 * accessibility purposes.
6391 * @param id The labeled view id.
6393 @RemotableViewMethod
6394 public void setLabelFor(@IdRes int id) {
6395 if (mLabelForId == id) {
6399 if (mLabelForId != View.NO_ID
6400 && mID == View.NO_ID) {
6401 mID = generateViewId();
6403 notifyViewAccessibilityStateChangedIfNeeded(
6404 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6408 * Invoked whenever this view loses focus, either by losing window focus or by losing
6409 * focus within its window. This method can be used to clear any state tied to the
6410 * focus. For instance, if a button is held pressed with the trackball and the window
6411 * loses focus, this method can be used to cancel the press.
6413 * Subclasses of View overriding this method should always call super.onFocusLost().
6415 * @see #onFocusChanged(boolean, int, android.graphics.Rect)
6416 * @see #onWindowFocusChanged(boolean)
6418 * @hide pending API council approval
6421 protected void onFocusLost() {
6422 resetPressedState();
6425 private void resetPressedState() {
6426 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
6433 if (!mHasPerformedLongPress) {
6434 removeLongPressCallback();
6440 * Returns true if this view has focus
6442 * @return True if this view has focus, false otherwise.
6444 @ViewDebug.ExportedProperty(category = "focus")
6445 public boolean isFocused() {
6446 return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6450 * Find the view in the hierarchy rooted at this view that currently has
6453 * @return The view that currently has focus, or null if no focused view can
6456 public View findFocus() {
6457 return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
6461 * Indicates whether this view is one of the set of scrollable containers in
6464 * @return whether this view is one of the set of scrollable containers in
6467 * @attr ref android.R.styleable#View_isScrollContainer
6469 public boolean isScrollContainer() {
6470 return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
6474 * Change whether this view is one of the set of scrollable containers in
6475 * its window. This will be used to determine whether the window can
6476 * resize or must pan when a soft input area is open -- scrollable
6477 * containers allow the window to use resize mode since the container
6478 * will appropriately shrink.
6480 * @attr ref android.R.styleable#View_isScrollContainer
6482 public void setScrollContainer(boolean isScrollContainer) {
6483 if (isScrollContainer) {
6484 if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
6485 mAttachInfo.mScrollContainers.add(this);
6486 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
6488 mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
6490 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
6491 mAttachInfo.mScrollContainers.remove(this);
6493 mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
6498 * Returns the quality of the drawing cache.
6500 * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6501 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6503 * @see #setDrawingCacheQuality(int)
6504 * @see #setDrawingCacheEnabled(boolean)
6505 * @see #isDrawingCacheEnabled()
6507 * @attr ref android.R.styleable#View_drawingCacheQuality
6509 @DrawingCacheQuality
6510 public int getDrawingCacheQuality() {
6511 return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
6515 * Set the drawing cache quality of this view. This value is used only when the
6516 * drawing cache is enabled
6518 * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6519 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6521 * @see #getDrawingCacheQuality()
6522 * @see #setDrawingCacheEnabled(boolean)
6523 * @see #isDrawingCacheEnabled()
6525 * @attr ref android.R.styleable#View_drawingCacheQuality
6527 public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
6528 setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
6532 * Returns whether the screen should remain on, corresponding to the current
6533 * value of {@link #KEEP_SCREEN_ON}.
6535 * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
6537 * @see #setKeepScreenOn(boolean)
6539 * @attr ref android.R.styleable#View_keepScreenOn
6541 public boolean getKeepScreenOn() {
6542 return (mViewFlags & KEEP_SCREEN_ON) != 0;
6546 * Controls whether the screen should remain on, modifying the
6547 * value of {@link #KEEP_SCREEN_ON}.
6549 * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
6551 * @see #getKeepScreenOn()
6553 * @attr ref android.R.styleable#View_keepScreenOn
6555 public void setKeepScreenOn(boolean keepScreenOn) {
6556 setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
6560 * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6561 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6563 * @attr ref android.R.styleable#View_nextFocusLeft
6565 public int getNextFocusLeftId() {
6566 return mNextFocusLeftId;
6570 * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6571 * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
6572 * decide automatically.
6574 * @attr ref android.R.styleable#View_nextFocusLeft
6576 public void setNextFocusLeftId(int nextFocusLeftId) {
6577 mNextFocusLeftId = nextFocusLeftId;
6581 * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6582 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6584 * @attr ref android.R.styleable#View_nextFocusRight
6586 public int getNextFocusRightId() {
6587 return mNextFocusRightId;
6591 * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6592 * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
6593 * decide automatically.
6595 * @attr ref android.R.styleable#View_nextFocusRight
6597 public void setNextFocusRightId(int nextFocusRightId) {
6598 mNextFocusRightId = nextFocusRightId;
6602 * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6603 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6605 * @attr ref android.R.styleable#View_nextFocusUp
6607 public int getNextFocusUpId() {
6608 return mNextFocusUpId;
6612 * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6613 * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
6614 * decide automatically.
6616 * @attr ref android.R.styleable#View_nextFocusUp
6618 public void setNextFocusUpId(int nextFocusUpId) {
6619 mNextFocusUpId = nextFocusUpId;
6623 * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
6624 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6626 * @attr ref android.R.styleable#View_nextFocusDown
6628 public int getNextFocusDownId() {
6629 return mNextFocusDownId;
6633 * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
6634 * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
6635 * decide automatically.
6637 * @attr ref android.R.styleable#View_nextFocusDown
6639 public void setNextFocusDownId(int nextFocusDownId) {
6640 mNextFocusDownId = nextFocusDownId;
6644 * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
6645 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6647 * @attr ref android.R.styleable#View_nextFocusForward
6649 public int getNextFocusForwardId() {
6650 return mNextFocusForwardId;
6654 * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
6655 * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
6656 * decide automatically.
6658 * @attr ref android.R.styleable#View_nextFocusForward
6660 public void setNextFocusForwardId(int nextFocusForwardId) {
6661 mNextFocusForwardId = nextFocusForwardId;
6665 * Returns the visibility of this view and all of its ancestors
6667 * @return True if this view and all of its ancestors are {@link #VISIBLE}
6669 public boolean isShown() {
6670 View current = this;
6671 //noinspection ConstantConditions
6673 if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6676 ViewParent parent = current.mParent;
6677 if (parent == null) {
6678 return false; // We are not attached to the view root
6680 if (!(parent instanceof View)) {
6683 current = (View) parent;
6684 } while (current != null);
6690 * Called by the view hierarchy when the content insets for a window have
6691 * changed, to allow it to adjust its content to fit within those windows.
6692 * The content insets tell you the space that the status bar, input method,
6693 * and other system windows infringe on the application's window.
6695 * <p>You do not normally need to deal with this function, since the default
6696 * window decoration given to applications takes care of applying it to the
6697 * content of the window. If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
6698 * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
6699 * and your content can be placed under those system elements. You can then
6700 * use this method within your view hierarchy if you have parts of your UI
6701 * which you would like to ensure are not being covered.
6703 * <p>The default implementation of this method simply applies the content
6704 * insets to the view's padding, consuming that content (modifying the
6705 * insets to be 0), and returning true. This behavior is off by default, but can
6706 * be enabled through {@link #setFitsSystemWindows(boolean)}.
6708 * <p>This function's traversal down the hierarchy is depth-first. The same content
6709 * insets object is propagated down the hierarchy, so any changes made to it will
6710 * be seen by all following views (including potentially ones above in
6711 * the hierarchy since this is a depth-first traversal). The first view
6712 * that returns true will abort the entire traversal.
6714 * <p>The default implementation works well for a situation where it is
6715 * used with a container that covers the entire window, allowing it to
6716 * apply the appropriate insets to its content on all edges. If you need
6717 * a more complicated layout (such as two different views fitting system
6718 * windows, one on the top of the window, and one on the bottom),
6719 * you can override the method and handle the insets however you would like.
6720 * Note that the insets provided by the framework are always relative to the
6721 * far edges of the window, not accounting for the location of the called view
6722 * within that window. (In fact when this method is called you do not yet know
6723 * where the layout will place the view, as it is done before layout happens.)
6725 * <p>Note: unlike many View methods, there is no dispatch phase to this
6726 * call. If you are overriding it in a ViewGroup and want to allow the
6727 * call to continue to your children, you must be sure to call the super
6730 * <p>Here is a sample layout that makes use of fitting system windows
6731 * to have controls for a video view placed inside of the window decorations
6732 * that it hides and shows. This can be used with code like the second
6733 * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
6735 * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
6737 * @param insets Current content insets of the window. Prior to
6738 * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
6739 * the insets or else you and Android will be unhappy.
6741 * @return {@code true} if this view applied the insets and it should not
6742 * continue propagating further down the hierarchy, {@code false} otherwise.
6743 * @see #getFitsSystemWindows()
6744 * @see #setFitsSystemWindows(boolean)
6745 * @see #setSystemUiVisibility(int)
6747 * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
6748 * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
6749 * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
6750 * to implement handling their own insets.
6752 protected boolean fitSystemWindows(Rect insets) {
6753 if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
6754 if (insets == null) {
6755 // Null insets by definition have already been consumed.
6756 // This call cannot apply insets since there are none to apply,
6760 // If we're not in the process of dispatching the newer apply insets call,
6761 // that means we're not in the compatibility path. Dispatch into the newer
6762 // apply insets path and take things from there.
6764 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
6765 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
6767 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
6770 // We're being called from the newer apply insets path.
6771 // Perform the standard fallback behavior.
6772 return fitSystemWindowsInt(insets);
6776 private boolean fitSystemWindowsInt(Rect insets) {
6777 if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
6778 mUserPaddingStart = UNDEFINED_PADDING;
6779 mUserPaddingEnd = UNDEFINED_PADDING;
6780 Rect localInsets = sThreadLocal.get();
6781 if (localInsets == null) {
6782 localInsets = new Rect();
6783 sThreadLocal.set(localInsets);
6785 boolean res = computeFitSystemWindows(insets, localInsets);
6786 mUserPaddingLeftInitial = localInsets.left;
6787 mUserPaddingRightInitial = localInsets.right;
6788 internalSetPadding(localInsets.left, localInsets.top,
6789 localInsets.right, localInsets.bottom);
6796 * Called when the view should apply {@link WindowInsets} according to its internal policy.
6798 * <p>This method should be overridden by views that wish to apply a policy different from or
6799 * in addition to the default behavior. Clients that wish to force a view subtree
6800 * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
6802 * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
6803 * it will be called during dispatch instead of this method. The listener may optionally
6804 * call this method from its own implementation if it wishes to apply the view's default
6805 * insets policy in addition to its own.</p>
6807 * <p>Implementations of this method should either return the insets parameter unchanged
6808 * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
6809 * that this view applied itself. This allows new inset types added in future platform
6810 * versions to pass through existing implementations unchanged without being erroneously
6813 * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
6814 * property is set then the view will consume the system window insets and apply them
6815 * as padding for the view.</p>
6817 * @param insets Insets to apply
6818 * @return The supplied insets with any applied insets consumed
6820 public WindowInsets onApplyWindowInsets(WindowInsets insets) {
6821 if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
6822 // We weren't called from within a direct call to fitSystemWindows,
6823 // call into it as a fallback in case we're in a class that overrides it
6824 // and has logic to perform.
6825 if (fitSystemWindows(insets.getSystemWindowInsets())) {
6826 return insets.consumeSystemWindowInsets();
6829 // We were called from within a direct call to fitSystemWindows.
6830 if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
6831 return insets.consumeSystemWindowInsets();
6838 * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
6839 * window insets to this view. The listener's
6840 * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
6841 * method will be called instead of the view's
6842 * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
6844 * @param listener Listener to set
6846 * @see #onApplyWindowInsets(WindowInsets)
6848 public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
6849 getListenerInfo().mOnApplyWindowInsetsListener = listener;
6853 * Request to apply the given window insets to this view or another view in its subtree.
6855 * <p>This method should be called by clients wishing to apply insets corresponding to areas
6856 * obscured by window decorations or overlays. This can include the status and navigation bars,
6857 * action bars, input methods and more. New inset categories may be added in the future.
6858 * The method returns the insets provided minus any that were applied by this view or its
6861 * <p>Clients wishing to provide custom behavior should override the
6862 * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
6863 * {@link OnApplyWindowInsetsListener} via the
6864 * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
6867 * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
6870 * @param insets Insets to apply
6871 * @return The provided insets minus the insets that were consumed
6873 public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
6875 mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
6876 if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
6877 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
6879 return onApplyWindowInsets(insets);
6882 mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
6887 * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
6888 * only available if the view is attached.
6890 * @return WindowInsets from the top of the view hierarchy or null if View is detached
6892 public WindowInsets getRootWindowInsets() {
6893 if (mAttachInfo != null) {
6894 return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
6900 * @hide Compute the insets that should be consumed by this view and the ones
6901 * that should propagate to those under it.
6903 protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
6904 if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
6905 || mAttachInfo == null
6906 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
6907 && !mAttachInfo.mOverscanRequested)) {
6908 outLocalInsets.set(inoutInsets);
6909 inoutInsets.set(0, 0, 0, 0);
6912 // The application wants to take care of fitting system window for
6913 // the content... however we still need to take care of any overscan here.
6914 final Rect overscan = mAttachInfo.mOverscanInsets;
6915 outLocalInsets.set(overscan);
6916 inoutInsets.left -= overscan.left;
6917 inoutInsets.top -= overscan.top;
6918 inoutInsets.right -= overscan.right;
6919 inoutInsets.bottom -= overscan.bottom;
6925 * Compute insets that should be consumed by this view and the ones that should propagate
6926 * to those under it.
6928 * @param in Insets currently being processed by this View, likely received as a parameter
6929 * to {@link #onApplyWindowInsets(WindowInsets)}.
6930 * @param outLocalInsets A Rect that will receive the insets that should be consumed
6932 * @return Insets that should be passed along to views under this one
6934 public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
6935 if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
6936 || mAttachInfo == null
6937 || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
6938 outLocalInsets.set(in.getSystemWindowInsets());
6939 return in.consumeSystemWindowInsets();
6941 outLocalInsets.set(0, 0, 0, 0);
6947 * Sets whether or not this view should account for system screen decorations
6948 * such as the status bar and inset its content; that is, controlling whether
6949 * the default implementation of {@link #fitSystemWindows(Rect)} will be
6950 * executed. See that method for more details.
6952 * <p>Note that if you are providing your own implementation of
6953 * {@link #fitSystemWindows(Rect)}, then there is no need to set this
6954 * flag to true -- your implementation will be overriding the default
6955 * implementation that checks this flag.
6957 * @param fitSystemWindows If true, then the default implementation of
6958 * {@link #fitSystemWindows(Rect)} will be executed.
6960 * @attr ref android.R.styleable#View_fitsSystemWindows
6961 * @see #getFitsSystemWindows()
6962 * @see #fitSystemWindows(Rect)
6963 * @see #setSystemUiVisibility(int)
6965 public void setFitsSystemWindows(boolean fitSystemWindows) {
6966 setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
6970 * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
6971 * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
6974 * @return {@code true} if the default implementation of
6975 * {@link #fitSystemWindows(Rect)} will be executed.
6977 * @attr ref android.R.styleable#View_fitsSystemWindows
6978 * @see #setFitsSystemWindows(boolean)
6979 * @see #fitSystemWindows(Rect)
6980 * @see #setSystemUiVisibility(int)
6982 @ViewDebug.ExportedProperty
6983 public boolean getFitsSystemWindows() {
6984 return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
6988 public boolean fitsSystemWindows() {
6989 return getFitsSystemWindows();
6993 * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
6994 * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
6996 public void requestFitSystemWindows() {
6997 if (mParent != null) {
6998 mParent.requestFitSystemWindows();
7003 * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
7005 public void requestApplyInsets() {
7006 requestFitSystemWindows();
7010 * For use by PhoneWindow to make its own system window fitting optional.
7013 public void makeOptionalFitsSystemWindows() {
7014 setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
7018 * Returns the visibility status for this view.
7020 * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7021 * @attr ref android.R.styleable#View_visibility
7023 @ViewDebug.ExportedProperty(mapping = {
7024 @ViewDebug.IntToString(from = VISIBLE, to = "VISIBLE"),
7025 @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
7026 @ViewDebug.IntToString(from = GONE, to = "GONE")
7029 public int getVisibility() {
7030 return mViewFlags & VISIBILITY_MASK;
7034 * Set the enabled state of this view.
7036 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7037 * @attr ref android.R.styleable#View_visibility
7039 @RemotableViewMethod
7040 public void setVisibility(@Visibility int visibility) {
7041 setFlags(visibility, VISIBILITY_MASK);
7045 * Returns the enabled status for this view. The interpretation of the
7046 * enabled state varies by subclass.
7048 * @return True if this view is enabled, false otherwise.
7050 @ViewDebug.ExportedProperty
7051 public boolean isEnabled() {
7052 return (mViewFlags & ENABLED_MASK) == ENABLED;
7056 * Set the enabled state of this view. The interpretation of the enabled
7057 * state varies by subclass.
7059 * @param enabled True if this view is enabled, false otherwise.
7061 @RemotableViewMethod
7062 public void setEnabled(boolean enabled) {
7063 if (enabled == isEnabled()) return;
7065 setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
7068 * The View most likely has to change its appearance, so refresh
7069 * the drawable state.
7071 refreshDrawableState();
7073 // Invalidate too, since the default behavior for views is to be
7074 // be drawn at 50% alpha rather than to change the drawable.
7078 cancelPendingInputEvents();
7083 * Set whether this view can receive the focus.
7085 * Setting this to false will also ensure that this view is not focusable
7088 * @param focusable If true, this view can receive the focus.
7090 * @see #setFocusableInTouchMode(boolean)
7091 * @attr ref android.R.styleable#View_focusable
7093 public void setFocusable(boolean focusable) {
7095 setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
7097 setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
7101 * Set whether this view can receive focus while in touch mode.
7103 * Setting this to true will also ensure that this view is focusable.
7105 * @param focusableInTouchMode If true, this view can receive the focus while
7108 * @see #setFocusable(boolean)
7109 * @attr ref android.R.styleable#View_focusableInTouchMode
7111 public void setFocusableInTouchMode(boolean focusableInTouchMode) {
7112 // Focusable in touch mode should always be set before the focusable flag
7113 // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
7114 // which, in touch mode, will not successfully request focus on this view
7115 // because the focusable in touch mode flag is not set
7116 setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
7117 if (focusableInTouchMode) {
7118 setFlags(FOCUSABLE, FOCUSABLE_MASK);
7123 * Set whether this view should have sound effects enabled for events such as
7124 * clicking and touching.
7126 * <p>You may wish to disable sound effects for a view if you already play sounds,
7127 * for instance, a dial key that plays dtmf tones.
7129 * @param soundEffectsEnabled whether sound effects are enabled for this view.
7130 * @see #isSoundEffectsEnabled()
7131 * @see #playSoundEffect(int)
7132 * @attr ref android.R.styleable#View_soundEffectsEnabled
7134 public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
7135 setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
7139 * @return whether this view should have sound effects enabled for events such as
7140 * clicking and touching.
7142 * @see #setSoundEffectsEnabled(boolean)
7143 * @see #playSoundEffect(int)
7144 * @attr ref android.R.styleable#View_soundEffectsEnabled
7146 @ViewDebug.ExportedProperty
7147 public boolean isSoundEffectsEnabled() {
7148 return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
7152 * Set whether this view should have haptic feedback for events such as
7155 * <p>You may wish to disable haptic feedback if your view already controls
7156 * its own haptic feedback.
7158 * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
7159 * @see #isHapticFeedbackEnabled()
7160 * @see #performHapticFeedback(int)
7161 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7163 public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
7164 setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
7168 * @return whether this view should have haptic feedback enabled for events
7171 * @see #setHapticFeedbackEnabled(boolean)
7172 * @see #performHapticFeedback(int)
7173 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7175 @ViewDebug.ExportedProperty
7176 public boolean isHapticFeedbackEnabled() {
7177 return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
7181 * Returns the layout direction for this view.
7183 * @return One of {@link #LAYOUT_DIRECTION_LTR},
7184 * {@link #LAYOUT_DIRECTION_RTL},
7185 * {@link #LAYOUT_DIRECTION_INHERIT} or
7186 * {@link #LAYOUT_DIRECTION_LOCALE}.
7188 * @attr ref android.R.styleable#View_layoutDirection
7192 @ViewDebug.ExportedProperty(category = "layout", mapping = {
7193 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "LTR"),
7194 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RTL"),
7195 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
7196 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE, to = "LOCALE")
7199 public int getRawLayoutDirection() {
7200 return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
7204 * Set the layout direction for this view. This will propagate a reset of layout direction
7205 * resolution to the view's children and resolve layout direction for this view.
7207 * @param layoutDirection the layout direction to set. Should be one of:
7209 * {@link #LAYOUT_DIRECTION_LTR},
7210 * {@link #LAYOUT_DIRECTION_RTL},
7211 * {@link #LAYOUT_DIRECTION_INHERIT},
7212 * {@link #LAYOUT_DIRECTION_LOCALE}.
7214 * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
7215 * proceeds up the parent chain of the view to get the value. If there is no parent, then it
7216 * will return the default {@link #LAYOUT_DIRECTION_LTR}.
7218 * @attr ref android.R.styleable#View_layoutDirection
7220 @RemotableViewMethod
7221 public void setLayoutDirection(@LayoutDir int layoutDirection) {
7222 if (getRawLayoutDirection() != layoutDirection) {
7223 // Reset the current layout direction and the resolved one
7224 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
7225 resetRtlProperties();
7226 // Set the new layout direction (filtered)
7228 ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
7229 // We need to resolve all RTL properties as they all depend on layout direction
7230 resolveRtlPropertiesIfNeeded();
7237 * Returns the resolved layout direction for this view.
7239 * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
7240 * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
7242 * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
7243 * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
7245 * @attr ref android.R.styleable#View_layoutDirection
7247 @ViewDebug.ExportedProperty(category = "layout", mapping = {
7248 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
7249 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
7252 public int getLayoutDirection() {
7253 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
7254 if (targetSdkVersion < JELLY_BEAN_MR1) {
7255 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
7256 return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
7258 return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
7259 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
7263 * Indicates whether or not this view's layout is right-to-left. This is resolved from
7264 * layout attribute and/or the inherited value from the parent
7266 * @return true if the layout is right-to-left.
7270 @ViewDebug.ExportedProperty(category = "layout")
7271 public boolean isLayoutRtl() {
7272 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
7276 * Indicates whether the view is currently tracking transient state that the
7277 * app should not need to concern itself with saving and restoring, but that
7278 * the framework should take special note to preserve when possible.
7280 * <p>A view with transient state cannot be trivially rebound from an external
7281 * data source, such as an adapter binding item views in a list. This may be
7282 * because the view is performing an animation, tracking user selection
7283 * of content, or similar.</p>
7285 * @return true if the view has transient state
7287 @ViewDebug.ExportedProperty(category = "layout")
7288 public boolean hasTransientState() {
7289 return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
7293 * Set whether this view is currently tracking transient state that the
7294 * framework should attempt to preserve when possible. This flag is reference counted,
7295 * so every call to setHasTransientState(true) should be paired with a later call
7296 * to setHasTransientState(false).
7298 * <p>A view with transient state cannot be trivially rebound from an external
7299 * data source, such as an adapter binding item views in a list. This may be
7300 * because the view is performing an animation, tracking user selection
7301 * of content, or similar.</p>
7303 * @param hasTransientState true if this view has transient state
7305 public void setHasTransientState(boolean hasTransientState) {
7306 mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
7307 mTransientStateCount - 1;
7308 if (mTransientStateCount < 0) {
7309 mTransientStateCount = 0;
7310 Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
7311 "unmatched pair of setHasTransientState calls");
7312 } else if ((hasTransientState && mTransientStateCount == 1) ||
7313 (!hasTransientState && mTransientStateCount == 0)) {
7314 // update flag if we've just incremented up from 0 or decremented down to 0
7315 mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
7316 (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
7317 if (mParent != null) {
7319 mParent.childHasTransientStateChanged(this, hasTransientState);
7320 } catch (AbstractMethodError e) {
7321 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
7322 " does not fully implement ViewParent", e);
7329 * Returns true if this view is currently attached to a window.
7331 public boolean isAttachedToWindow() {
7332 return mAttachInfo != null;
7336 * Returns true if this view has been through at least one layout since it
7337 * was last attached to or detached from a window.
7339 public boolean isLaidOut() {
7340 return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
7344 * If this view doesn't do any drawing on its own, set this flag to
7345 * allow further optimizations. By default, this flag is not set on
7346 * View, but could be set on some View subclasses such as ViewGroup.
7348 * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
7349 * you should clear this flag.
7351 * @param willNotDraw whether or not this View draw on its own
7353 public void setWillNotDraw(boolean willNotDraw) {
7354 setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
7358 * Returns whether or not this View draws on its own.
7360 * @return true if this view has nothing to draw, false otherwise
7362 @ViewDebug.ExportedProperty(category = "drawing")
7363 public boolean willNotDraw() {
7364 return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
7368 * When a View's drawing cache is enabled, drawing is redirected to an
7369 * offscreen bitmap. Some views, like an ImageView, must be able to
7370 * bypass this mechanism if they already draw a single bitmap, to avoid
7371 * unnecessary usage of the memory.
7373 * @param willNotCacheDrawing true if this view does not cache its
7374 * drawing, false otherwise
7376 public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
7377 setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
7381 * Returns whether or not this View can cache its drawing or not.
7383 * @return true if this view does not cache its drawing, false otherwise
7385 @ViewDebug.ExportedProperty(category = "drawing")
7386 public boolean willNotCacheDrawing() {
7387 return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
7391 * Indicates whether this view reacts to click events or not.
7393 * @return true if the view is clickable, false otherwise
7395 * @see #setClickable(boolean)
7396 * @attr ref android.R.styleable#View_clickable
7398 @ViewDebug.ExportedProperty
7399 public boolean isClickable() {
7400 return (mViewFlags & CLICKABLE) == CLICKABLE;
7404 * Enables or disables click events for this view. When a view
7405 * is clickable it will change its state to "pressed" on every click.
7406 * Subclasses should set the view clickable to visually react to
7409 * @param clickable true to make the view clickable, false otherwise
7411 * @see #isClickable()
7412 * @attr ref android.R.styleable#View_clickable
7414 public void setClickable(boolean clickable) {
7415 setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
7419 * Indicates whether this view reacts to long click events or not.
7421 * @return true if the view is long clickable, false otherwise
7423 * @see #setLongClickable(boolean)
7424 * @attr ref android.R.styleable#View_longClickable
7426 public boolean isLongClickable() {
7427 return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
7431 * Enables or disables long click events for this view. When a view is long
7432 * clickable it reacts to the user holding down the button for a longer
7433 * duration than a tap. This event can either launch the listener or a
7436 * @param longClickable true to make the view long clickable, false otherwise
7437 * @see #isLongClickable()
7438 * @attr ref android.R.styleable#View_longClickable
7440 public void setLongClickable(boolean longClickable) {
7441 setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
7445 * Sets the pressed state for this view and provides a touch coordinate for
7446 * animation hinting.
7448 * @param pressed Pass true to set the View's internal state to "pressed",
7449 * or false to reverts the View's internal state from a
7450 * previously set "pressed" state.
7451 * @param x The x coordinate of the touch that caused the press
7452 * @param y The y coordinate of the touch that caused the press
7454 private void setPressed(boolean pressed, float x, float y) {
7456 drawableHotspotChanged(x, y);
7459 setPressed(pressed);
7463 * Sets the pressed state for this view.
7465 * @see #isClickable()
7466 * @see #setClickable(boolean)
7468 * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
7469 * the View's internal state from a previously set "pressed" state.
7471 public void setPressed(boolean pressed) {
7472 final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
7475 mPrivateFlags |= PFLAG_PRESSED;
7477 mPrivateFlags &= ~PFLAG_PRESSED;
7481 refreshDrawableState();
7483 dispatchSetPressed(pressed);
7487 * Dispatch setPressed to all of this View's children.
7489 * @see #setPressed(boolean)
7491 * @param pressed The new pressed state
7493 protected void dispatchSetPressed(boolean pressed) {
7497 * Indicates whether the view is currently in pressed state. Unless
7498 * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
7499 * the pressed state.
7501 * @see #setPressed(boolean)
7502 * @see #isClickable()
7503 * @see #setClickable(boolean)
7505 * @return true if the view is currently pressed, false otherwise
7507 @ViewDebug.ExportedProperty
7508 public boolean isPressed() {
7509 return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
7513 * Indicates whether this view will participate in data collection through
7514 * {@link android.view.ViewAssistStructure}. If true, it will not provide any data
7515 * for itself or its children. If false, the normal data collection will be allowed.
7517 * @return Returns false if assist data collection is not blocked, else true.
7519 * @see #setAssistBlocked(boolean)
7520 * @attr ref android.R.styleable#View_assistBlocked
7522 public boolean isAssistBlocked() {
7523 return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
7527 * Controls whether assist data collection from this view and its children is enabled
7528 * (that is, whether {@link #onProvideAssistStructure} and
7529 * {@link #onProvideVirtualAssistStructure} will be called). The default value is false,
7530 * allowing normal assist collection. Setting this to false will disable assist collection.
7532 * @param enabled Set to true to <em>disable</em> assist data collection, or false
7533 * (the default) to allow it.
7535 * @see #isAssistBlocked()
7536 * @see #onProvideAssistStructure
7537 * @see #onProvideVirtualAssistStructure
7538 * @attr ref android.R.styleable#View_assistBlocked
7540 public void setAssistBlocked(boolean enabled) {
7542 mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
7544 mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
7549 * Indicates whether this view will save its state (that is,
7550 * whether its {@link #onSaveInstanceState} method will be called).
7552 * @return Returns true if the view state saving is enabled, else false.
7554 * @see #setSaveEnabled(boolean)
7555 * @attr ref android.R.styleable#View_saveEnabled
7557 public boolean isSaveEnabled() {
7558 return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
7562 * Controls whether the saving of this view's state is
7563 * enabled (that is, whether its {@link #onSaveInstanceState} method
7564 * will be called). Note that even if freezing is enabled, the
7565 * view still must have an id assigned to it (via {@link #setId(int)})
7566 * for its state to be saved. This flag can only disable the
7567 * saving of this view; any child views may still have their state saved.
7569 * @param enabled Set to false to <em>disable</em> state saving, or true
7570 * (the default) to allow it.
7572 * @see #isSaveEnabled()
7574 * @see #onSaveInstanceState()
7575 * @attr ref android.R.styleable#View_saveEnabled
7577 public void setSaveEnabled(boolean enabled) {
7578 setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
7582 * Gets whether the framework should discard touches when the view's
7583 * window is obscured by another visible window.
7584 * Refer to the {@link View} security documentation for more details.
7586 * @return True if touch filtering is enabled.
7588 * @see #setFilterTouchesWhenObscured(boolean)
7589 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
7591 @ViewDebug.ExportedProperty
7592 public boolean getFilterTouchesWhenObscured() {
7593 return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
7597 * Sets whether the framework should discard touches when the view's
7598 * window is obscured by another visible window.
7599 * Refer to the {@link View} security documentation for more details.
7601 * @param enabled True if touch filtering should be enabled.
7603 * @see #getFilterTouchesWhenObscured
7604 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
7606 public void setFilterTouchesWhenObscured(boolean enabled) {
7607 setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
7608 FILTER_TOUCHES_WHEN_OBSCURED);
7612 * Indicates whether the entire hierarchy under this view will save its
7613 * state when a state saving traversal occurs from its parent. The default
7614 * is true; if false, these views will not be saved unless
7615 * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
7617 * @return Returns true if the view state saving from parent is enabled, else false.
7619 * @see #setSaveFromParentEnabled(boolean)
7621 public boolean isSaveFromParentEnabled() {
7622 return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
7626 * Controls whether the entire hierarchy under this view will save its
7627 * state when a state saving traversal occurs from its parent. The default
7628 * is true; if false, these views will not be saved unless
7629 * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
7631 * @param enabled Set to false to <em>disable</em> state saving, or true
7632 * (the default) to allow it.
7634 * @see #isSaveFromParentEnabled()
7636 * @see #onSaveInstanceState()
7638 public void setSaveFromParentEnabled(boolean enabled) {
7639 setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
7644 * Returns whether this View is able to take focus.
7646 * @return True if this view can take focus, or false otherwise.
7647 * @attr ref android.R.styleable#View_focusable
7649 @ViewDebug.ExportedProperty(category = "focus")
7650 public final boolean isFocusable() {
7651 return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
7655 * When a view is focusable, it may not want to take focus when in touch mode.
7656 * For example, a button would like focus when the user is navigating via a D-pad
7657 * so that the user can click on it, but once the user starts touching the screen,
7658 * the button shouldn't take focus
7659 * @return Whether the view is focusable in touch mode.
7660 * @attr ref android.R.styleable#View_focusableInTouchMode
7662 @ViewDebug.ExportedProperty
7663 public final boolean isFocusableInTouchMode() {
7664 return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
7668 * Find the nearest view in the specified direction that can take focus.
7669 * This does not actually give focus to that view.
7671 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7673 * @return The nearest focusable in the specified direction, or null if none
7676 public View focusSearch(@FocusRealDirection int direction) {
7677 if (mParent != null) {
7678 return mParent.focusSearch(this, direction);
7685 * This method is the last chance for the focused view and its ancestors to
7686 * respond to an arrow key. This is called when the focused view did not
7687 * consume the key internally, nor could the view system find a new view in
7688 * the requested direction to give focus to.
7690 * @param focused The currently focused view.
7691 * @param direction The direction focus wants to move. One of FOCUS_UP,
7692 * FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
7693 * @return True if the this view consumed this unhandled move.
7695 public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
7700 * If a user manually specified the next view id for a particular direction,
7701 * use the root to look up the view.
7702 * @param root The root view of the hierarchy containing this view.
7703 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
7704 * or FOCUS_BACKWARD.
7705 * @return The user specified next view, or null if there is none.
7707 View findUserSetNextFocus(View root, @FocusDirection int direction) {
7708 switch (direction) {
7710 if (mNextFocusLeftId == View.NO_ID) return null;
7711 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
7713 if (mNextFocusRightId == View.NO_ID) return null;
7714 return findViewInsideOutShouldExist(root, mNextFocusRightId);
7716 if (mNextFocusUpId == View.NO_ID) return null;
7717 return findViewInsideOutShouldExist(root, mNextFocusUpId);
7719 if (mNextFocusDownId == View.NO_ID) return null;
7720 return findViewInsideOutShouldExist(root, mNextFocusDownId);
7722 if (mNextFocusForwardId == View.NO_ID) return null;
7723 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
7724 case FOCUS_BACKWARD: {
7725 if (mID == View.NO_ID) return null;
7727 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
7729 public boolean apply(View t) {
7730 return t.mNextFocusForwardId == id;
7738 private View findViewInsideOutShouldExist(View root, int id) {
7739 if (mMatchIdPredicate == null) {
7740 mMatchIdPredicate = new MatchIdPredicate();
7742 mMatchIdPredicate.mId = id;
7743 View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
7744 if (result == null) {
7745 Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
7751 * Find and return all focusable views that are descendants of this view,
7752 * possibly including this view if it is focusable itself.
7754 * @param direction The direction of the focus
7755 * @return A list of focusable views
7757 public ArrayList<View> getFocusables(@FocusDirection int direction) {
7758 ArrayList<View> result = new ArrayList<View>(24);
7759 addFocusables(result, direction);
7764 * Add any focusable views that are descendants of this view (possibly
7765 * including this view if it is focusable itself) to views. If we are in touch mode,
7766 * only add views that are also focusable in touch mode.
7768 * @param views Focusable views found so far
7769 * @param direction The direction of the focus
7771 public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
7772 addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
7776 * Adds any focusable views that are descendants of this view (possibly
7777 * including this view if it is focusable itself) to views. This method
7778 * adds all focusable views regardless if we are in touch mode or
7779 * only views focusable in touch mode if we are in touch mode or
7780 * only views that can take accessibility focus if accessibility is enabled
7781 * depending on the focusable mode parameter.
7783 * @param views Focusable views found so far or null if all we are interested is
7784 * the number of focusables.
7785 * @param direction The direction of the focus.
7786 * @param focusableMode The type of focusables to be added.
7788 * @see #FOCUSABLES_ALL
7789 * @see #FOCUSABLES_TOUCH_MODE
7791 public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
7792 @FocusableMode int focusableMode) {
7793 if (views == null) {
7796 if (!isFocusable()) {
7799 if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
7800 && isInTouchMode() && !isFocusableInTouchMode()) {
7807 * Finds the Views that contain given text. The containment is case insensitive.
7808 * The search is performed by either the text that the View renders or the content
7809 * description that describes the view for accessibility purposes and the view does
7810 * not render or both. Clients can specify how the search is to be performed via
7811 * passing the {@link #FIND_VIEWS_WITH_TEXT} and
7812 * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
7814 * @param outViews The output list of matching Views.
7815 * @param searched The text to match against.
7817 * @see #FIND_VIEWS_WITH_TEXT
7818 * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
7819 * @see #setContentDescription(CharSequence)
7821 public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
7822 @FindViewFlags int flags) {
7823 if (getAccessibilityNodeProvider() != null) {
7824 if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
7827 } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
7828 && (searched != null && searched.length() > 0)
7829 && (mContentDescription != null && mContentDescription.length() > 0)) {
7830 String searchedLowerCase = searched.toString().toLowerCase();
7831 String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
7832 if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
7839 * Find and return all touchable views that are descendants of this view,
7840 * possibly including this view if it is touchable itself.
7842 * @return A list of touchable views
7844 public ArrayList<View> getTouchables() {
7845 ArrayList<View> result = new ArrayList<View>();
7846 addTouchables(result);
7851 * Add any touchable views that are descendants of this view (possibly
7852 * including this view if it is touchable itself) to views.
7854 * @param views Touchable views found so far
7856 public void addTouchables(ArrayList<View> views) {
7857 final int viewFlags = mViewFlags;
7859 if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
7860 && (viewFlags & ENABLED_MASK) == ENABLED) {
7866 * Returns whether this View is accessibility focused.
7868 * @return True if this View is accessibility focused.
7870 public boolean isAccessibilityFocused() {
7871 return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
7875 * Call this to try to give accessibility focus to this view.
7877 * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
7878 * returns false or the view is no visible or the view already has accessibility
7881 * See also {@link #focusSearch(int)}, which is what you call to say that you
7882 * have focus, and you want your parent to look for the next one.
7884 * @return Whether this view actually took accessibility focus.
7888 public boolean requestAccessibilityFocus() {
7889 AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
7890 if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
7893 if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7896 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
7897 mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
7898 ViewRootImpl viewRootImpl = getViewRootImpl();
7899 if (viewRootImpl != null) {
7900 viewRootImpl.setAccessibilityFocus(this, null);
7903 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
7910 * Call this to try to clear accessibility focus of this view.
7912 * See also {@link #focusSearch(int)}, which is what you call to say that you
7913 * have focus, and you want your parent to look for the next one.
7917 public void clearAccessibilityFocus() {
7918 clearAccessibilityFocusNoCallbacks();
7919 // Clear the global reference of accessibility focus if this
7920 // view or any of its descendants had accessibility focus.
7921 ViewRootImpl viewRootImpl = getViewRootImpl();
7922 if (viewRootImpl != null) {
7923 View focusHost = viewRootImpl.getAccessibilityFocusedHost();
7924 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
7925 viewRootImpl.setAccessibilityFocus(null, null);
7930 private void sendAccessibilityHoverEvent(int eventType) {
7931 // Since we are not delivering to a client accessibility events from not
7932 // important views (unless the clinet request that) we need to fire the
7933 // event from the deepest view exposed to the client. As a consequence if
7934 // the user crosses a not exposed view the client will see enter and exit
7935 // of the exposed predecessor followed by and enter and exit of that same
7936 // predecessor when entering and exiting the not exposed descendant. This
7937 // is fine since the client has a clear idea which view is hovered at the
7938 // price of a couple more events being sent. This is a simple and
7939 // working solution.
7942 if (source.includeForAccessibility()) {
7943 source.sendAccessibilityEvent(eventType);
7946 ViewParent parent = source.getParent();
7947 if (parent instanceof View) {
7948 source = (View) parent;
7956 * Clears accessibility focus without calling any callback methods
7957 * normally invoked in {@link #clearAccessibilityFocus()}. This method
7958 * is used for clearing accessibility focus when giving this focus to
7961 void clearAccessibilityFocusNoCallbacks() {
7962 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
7963 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
7965 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
7970 * Call this to try to give focus to a specific view or to one of its
7973 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7974 * false), or if it is focusable and it is not focusable in touch mode
7975 * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7977 * See also {@link #focusSearch(int)}, which is what you call to say that you
7978 * have focus, and you want your parent to look for the next one.
7980 * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
7981 * {@link #FOCUS_DOWN} and <code>null</code>.
7983 * @return Whether this view or one of its descendants actually took focus.
7985 public final boolean requestFocus() {
7986 return requestFocus(View.FOCUS_DOWN);
7990 * Call this to try to give focus to a specific view or to one of its
7991 * descendants and give it a hint about what direction focus is heading.
7993 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7994 * false), or if it is focusable and it is not focusable in touch mode
7995 * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7997 * See also {@link #focusSearch(int)}, which is what you call to say that you
7998 * have focus, and you want your parent to look for the next one.
8000 * This is equivalent to calling {@link #requestFocus(int, Rect)} with
8001 * <code>null</code> set for the previously focused rectangle.
8003 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8004 * @return Whether this view or one of its descendants actually took focus.
8006 public final boolean requestFocus(int direction) {
8007 return requestFocus(direction, null);
8011 * Call this to try to give focus to a specific view or to one of its descendants
8012 * and give it hints about the direction and a specific rectangle that the focus
8013 * is coming from. The rectangle can help give larger views a finer grained hint
8014 * about where focus is coming from, and therefore, where to show selection, or
8015 * forward focus change internally.
8017 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8018 * false), or if it is focusable and it is not focusable in touch mode
8019 * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8021 * A View will not take focus if it is not visible.
8023 * A View will not take focus if one of its parents has
8024 * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
8025 * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
8027 * See also {@link #focusSearch(int)}, which is what you call to say that you
8028 * have focus, and you want your parent to look for the next one.
8030 * You may wish to override this method if your custom {@link View} has an internal
8031 * {@link View} that it wishes to forward the request to.
8033 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8034 * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
8035 * to give a finer grained hint about where focus is coming from. May be null
8036 * if there is no hint.
8037 * @return Whether this view or one of its descendants actually took focus.
8039 public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
8040 return requestFocusNoSearch(direction, previouslyFocusedRect);
8043 private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
8044 // need to be focusable
8045 if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
8046 (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8050 // need to be focusable in touch mode if in touch mode
8051 if (isInTouchMode() &&
8052 (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
8056 // need to not have any parents blocking us
8057 if (hasAncestorThatBlocksDescendantFocus()) {
8061 handleFocusGainInternal(direction, previouslyFocusedRect);
8066 * Call this to try to give focus to a specific view or to one of its descendants. This is a
8067 * special variant of {@link #requestFocus() } that will allow views that are not focusable in
8068 * touch mode to request focus when they are touched.
8070 * @return Whether this view or one of its descendants actually took focus.
8072 * @see #isInTouchMode()
8075 public final boolean requestFocusFromTouch() {
8076 // Leave touch mode if we need to
8077 if (isInTouchMode()) {
8078 ViewRootImpl viewRoot = getViewRootImpl();
8079 if (viewRoot != null) {
8080 viewRoot.ensureTouchMode(false);
8083 return requestFocus(View.FOCUS_DOWN);
8087 * @return Whether any ancestor of this view blocks descendant focus.
8089 private boolean hasAncestorThatBlocksDescendantFocus() {
8090 final boolean focusableInTouchMode = isFocusableInTouchMode();
8091 ViewParent ancestor = mParent;
8092 while (ancestor instanceof ViewGroup) {
8093 final ViewGroup vgAncestor = (ViewGroup) ancestor;
8094 if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
8095 || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
8098 ancestor = vgAncestor.getParent();
8105 * Gets the mode for determining whether this View is important for accessibility
8106 * which is if it fires accessibility events and if it is reported to
8107 * accessibility services that query the screen.
8109 * @return The mode for determining whether a View is important for accessibility.
8111 * @attr ref android.R.styleable#View_importantForAccessibility
8113 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8114 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8115 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8116 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8118 @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
8119 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
8120 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
8121 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
8122 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
8123 to = "noHideDescendants")
8125 public int getImportantForAccessibility() {
8126 return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8127 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8131 * Sets the live region mode for this view. This indicates to accessibility
8132 * services whether they should automatically notify the user about changes
8133 * to the view's content description or text, or to the content descriptions
8134 * or text of the view's children (where applicable).
8136 * For example, in a login screen with a TextView that displays an "incorrect
8137 * password" notification, that view should be marked as a live region with
8138 * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8140 * To disable change notifications for this view, use
8141 * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
8142 * mode for most views.
8144 * To indicate that the user should be notified of changes, use
8145 * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8147 * If the view's changes should interrupt ongoing speech and notify the user
8148 * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
8150 * @param mode The live region mode for this view, one of:
8152 * <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
8153 * <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
8154 * <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
8156 * @attr ref android.R.styleable#View_accessibilityLiveRegion
8158 public void setAccessibilityLiveRegion(int mode) {
8159 if (mode != getAccessibilityLiveRegion()) {
8160 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8161 mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
8162 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8163 notifyViewAccessibilityStateChangedIfNeeded(
8164 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8169 * Gets the live region mode for this View.
8171 * @return The live region mode for the view.
8173 * @attr ref android.R.styleable#View_accessibilityLiveRegion
8175 * @see #setAccessibilityLiveRegion(int)
8177 public int getAccessibilityLiveRegion() {
8178 return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
8179 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
8183 * Sets how to determine whether this view is important for accessibility
8184 * which is if it fires accessibility events and if it is reported to
8185 * accessibility services that query the screen.
8187 * @param mode How to determine whether this view is important for accessibility.
8189 * @attr ref android.R.styleable#View_importantForAccessibility
8191 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8192 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8193 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8194 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8196 public void setImportantForAccessibility(int mode) {
8197 final int oldMode = getImportantForAccessibility();
8198 if (mode != oldMode) {
8199 // If we're moving between AUTO and another state, we might not need
8200 // to send a subtree changed notification. We'll store the computed
8201 // importance, since we'll need to check it later to make sure.
8202 final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
8203 || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
8204 final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
8205 mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8206 mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
8207 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8208 if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
8209 notifySubtreeAccessibilityStateChangedIfNeeded();
8211 notifyViewAccessibilityStateChangedIfNeeded(
8212 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8218 * Computes whether this view should be exposed for accessibility. In
8219 * general, views that are interactive or provide information are exposed
8220 * while views that serve only as containers are hidden.
8222 * If an ancestor of this view has importance
8223 * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
8224 * returns <code>false</code>.
8226 * Otherwise, the value is computed according to the view's
8227 * {@link #getImportantForAccessibility()} value:
8229 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
8230 * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
8232 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
8233 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
8234 * view satisfies any of the following:
8236 * <li>Is actionable, e.g. {@link #isClickable()},
8237 * {@link #isLongClickable()}, or {@link #isFocusable()}
8238 * <li>Has an {@link AccessibilityDelegate}
8239 * <li>Has an interaction listener, e.g. {@link OnTouchListener},
8240 * {@link OnKeyListener}, etc.
8241 * <li>Is an accessibility live region, e.g.
8242 * {@link #getAccessibilityLiveRegion()} is not
8243 * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
8247 * @return Whether the view is exposed for accessibility.
8248 * @see #setImportantForAccessibility(int)
8249 * @see #getImportantForAccessibility()
8251 public boolean isImportantForAccessibility() {
8252 final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8253 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8254 if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
8255 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8259 // Check parent mode to ensure we're not hidden.
8260 ViewParent parent = mParent;
8261 while (parent instanceof View) {
8262 if (((View) parent).getImportantForAccessibility()
8263 == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8266 parent = parent.getParent();
8269 return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
8270 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
8271 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
8275 * Gets the parent for accessibility purposes. Note that the parent for
8276 * accessibility is not necessary the immediate parent. It is the first
8277 * predecessor that is important for accessibility.
8279 * @return The parent for accessibility purposes.
8281 public ViewParent getParentForAccessibility() {
8282 if (mParent instanceof View) {
8283 View parentView = (View) mParent;
8284 if (parentView.includeForAccessibility()) {
8287 return mParent.getParentForAccessibility();
8294 * Adds the children of a given View for accessibility. Since some Views are
8295 * not important for accessibility the children for accessibility are not
8296 * necessarily direct children of the view, rather they are the first level of
8297 * descendants important for accessibility.
8299 * @param children The list of children for accessibility.
8301 public void addChildrenForAccessibility(ArrayList<View> children) {
8306 * Whether to regard this view for accessibility. A view is regarded for
8307 * accessibility if it is important for accessibility or the querying
8308 * accessibility service has explicitly requested that view not
8309 * important for accessibility are regarded.
8311 * @return Whether to regard the view for accessibility.
8315 public boolean includeForAccessibility() {
8316 if (mAttachInfo != null) {
8317 return (mAttachInfo.mAccessibilityFetchFlags
8318 & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
8319 || isImportantForAccessibility();
8325 * Returns whether the View is considered actionable from
8326 * accessibility perspective. Such view are important for
8329 * @return True if the view is actionable for accessibility.
8333 public boolean isActionableForAccessibility() {
8334 return (isClickable() || isLongClickable() || isFocusable());
8338 * Returns whether the View has registered callbacks which makes it
8339 * important for accessibility.
8341 * @return True if the view is actionable for accessibility.
8343 private boolean hasListenersForAccessibility() {
8344 ListenerInfo info = getListenerInfo();
8345 return mTouchDelegate != null || info.mOnKeyListener != null
8346 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
8347 || info.mOnHoverListener != null || info.mOnDragListener != null;
8351 * Notifies that the accessibility state of this view changed. The change
8352 * is local to this view and does not represent structural changes such
8353 * as children and parent. For example, the view became focusable. The
8354 * notification is at at most once every
8355 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8356 * to avoid unnecessary load to the system. Also once a view has a pending
8357 * notification this method is a NOP until the notification has been sent.
8361 public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
8362 if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
8365 if (mSendViewStateChangedAccessibilityEvent == null) {
8366 mSendViewStateChangedAccessibilityEvent =
8367 new SendViewStateChangedAccessibilityEvent();
8369 mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
8373 * Notifies that the accessibility state of this view changed. The change
8374 * is *not* local to this view and does represent structural changes such
8375 * as children and parent. For example, the view size changed. The
8376 * notification is at at most once every
8377 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8378 * to avoid unnecessary load to the system. Also once a view has a pending
8379 * notification this method is a NOP until the notification has been sent.
8383 public void notifySubtreeAccessibilityStateChangedIfNeeded() {
8384 if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
8387 if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
8388 mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8389 if (mParent != null) {
8391 mParent.notifySubtreeAccessibilityStateChanged(
8392 this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
8393 } catch (AbstractMethodError e) {
8394 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8395 " does not fully implement ViewParent", e);
8402 * Reset the flag indicating the accessibility state of the subtree rooted
8403 * at this view changed.
8405 void resetSubtreeAccessibilityStateChanged() {
8406 mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8410 * Report an accessibility action to this view's parents for delegated processing.
8412 * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
8413 * call this method to delegate an accessibility action to a supporting parent. If the parent
8414 * returns true from its
8415 * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
8416 * method this method will return true to signify that the action was consumed.</p>
8418 * <p>This method is useful for implementing nested scrolling child views. If
8419 * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
8420 * a custom view implementation may invoke this method to allow a parent to consume the
8421 * scroll first. If this method returns true the custom view should skip its own scrolling
8424 * @param action Accessibility action to delegate
8425 * @param arguments Optional action arguments
8426 * @return true if the action was consumed by a parent
8428 public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
8429 for (ViewParent p = getParent(); p != null; p = p.getParent()) {
8430 if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
8438 * Performs the specified accessibility action on the view. For
8439 * possible accessibility actions look at {@link AccessibilityNodeInfo}.
8441 * If an {@link AccessibilityDelegate} has been specified via calling
8442 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8443 * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
8444 * is responsible for handling this call.
8447 * <p>The default implementation will delegate
8448 * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
8449 * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
8450 * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
8452 * @param action The action to perform.
8453 * @param arguments Optional action arguments.
8454 * @return Whether the action was performed.
8456 public boolean performAccessibilityAction(int action, Bundle arguments) {
8457 if (mAccessibilityDelegate != null) {
8458 return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
8460 return performAccessibilityActionInternal(action, arguments);
8465 * @see #performAccessibilityAction(int, Bundle)
8467 * Note: Called from the default {@link AccessibilityDelegate}.
8471 public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
8472 if (isNestedScrollingEnabled()
8473 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
8474 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD)) {
8475 if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
8481 case AccessibilityNodeInfo.ACTION_CLICK: {
8482 if (isClickable()) {
8487 case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
8488 if (isLongClickable()) {
8493 case AccessibilityNodeInfo.ACTION_FOCUS: {
8495 // Get out of touch mode since accessibility
8496 // wants to move focus around.
8497 getViewRootImpl().ensureTouchMode(false);
8498 return requestFocus();
8501 case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
8504 return !isFocused();
8507 case AccessibilityNodeInfo.ACTION_SELECT: {
8508 if (!isSelected()) {
8510 return isSelected();
8513 case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
8516 return !isSelected();
8519 case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
8520 if (!isAccessibilityFocused()) {
8521 return requestAccessibilityFocus();
8524 case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
8525 if (isAccessibilityFocused()) {
8526 clearAccessibilityFocus();
8530 case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
8531 if (arguments != null) {
8532 final int granularity = arguments.getInt(
8533 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8534 final boolean extendSelection = arguments.getBoolean(
8535 AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8536 return traverseAtGranularity(granularity, true, extendSelection);
8539 case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
8540 if (arguments != null) {
8541 final int granularity = arguments.getInt(
8542 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8543 final boolean extendSelection = arguments.getBoolean(
8544 AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8545 return traverseAtGranularity(granularity, false, extendSelection);
8548 case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
8549 CharSequence text = getIterableTextForAccessibility();
8553 final int start = (arguments != null) ? arguments.getInt(
8554 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
8555 final int end = (arguments != null) ? arguments.getInt(
8556 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
8557 // Only cursor position can be specified (selection length == 0)
8558 if ((getAccessibilitySelectionStart() != start
8559 || getAccessibilitySelectionEnd() != end)
8560 && (start == end)) {
8561 setAccessibilitySelection(start, end);
8562 notifyViewAccessibilityStateChangedIfNeeded(
8563 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8567 case R.id.accessibilityActionShowOnScreen: {
8568 if (mAttachInfo != null) {
8569 final Rect r = mAttachInfo.mTmpInvalRect;
8571 return requestRectangleOnScreen(r, true);
8578 private boolean traverseAtGranularity(int granularity, boolean forward,
8579 boolean extendSelection) {
8580 CharSequence text = getIterableTextForAccessibility();
8581 if (text == null || text.length() == 0) {
8584 TextSegmentIterator iterator = getIteratorForGranularity(granularity);
8585 if (iterator == null) {
8588 int current = getAccessibilitySelectionEnd();
8589 if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
8590 current = forward ? 0 : text.length();
8592 final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
8593 if (range == null) {
8596 final int segmentStart = range[0];
8597 final int segmentEnd = range[1];
8600 if (extendSelection && isAccessibilitySelectionExtendable()) {
8601 selectionStart = getAccessibilitySelectionStart();
8602 if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
8603 selectionStart = forward ? segmentStart : segmentEnd;
8605 selectionEnd = forward ? segmentEnd : segmentStart;
8607 selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
8609 setAccessibilitySelection(selectionStart, selectionEnd);
8610 final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
8611 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
8612 sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
8617 * Gets the text reported for accessibility purposes.
8619 * @return The accessibility text.
8623 public CharSequence getIterableTextForAccessibility() {
8624 return getContentDescription();
8628 * Gets whether accessibility selection can be extended.
8630 * @return If selection is extensible.
8634 public boolean isAccessibilitySelectionExtendable() {
8641 public int getAccessibilitySelectionStart() {
8642 return mAccessibilityCursorPosition;
8648 public int getAccessibilitySelectionEnd() {
8649 return getAccessibilitySelectionStart();
8655 public void setAccessibilitySelection(int start, int end) {
8656 if (start == end && end == mAccessibilityCursorPosition) {
8659 if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
8660 mAccessibilityCursorPosition = start;
8662 mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
8664 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
8667 private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
8668 int fromIndex, int toIndex) {
8669 if (mParent == null) {
8672 AccessibilityEvent event = AccessibilityEvent.obtain(
8673 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
8674 onInitializeAccessibilityEvent(event);
8675 onPopulateAccessibilityEvent(event);
8676 event.setFromIndex(fromIndex);
8677 event.setToIndex(toIndex);
8678 event.setAction(action);
8679 event.setMovementGranularity(granularity);
8680 mParent.requestSendAccessibilityEvent(this, event);
8686 public TextSegmentIterator getIteratorForGranularity(int granularity) {
8687 switch (granularity) {
8688 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
8689 CharSequence text = getIterableTextForAccessibility();
8690 if (text != null && text.length() > 0) {
8691 CharacterTextSegmentIterator iterator =
8692 CharacterTextSegmentIterator.getInstance(
8693 mContext.getResources().getConfiguration().locale);
8694 iterator.initialize(text.toString());
8698 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
8699 CharSequence text = getIterableTextForAccessibility();
8700 if (text != null && text.length() > 0) {
8701 WordTextSegmentIterator iterator =
8702 WordTextSegmentIterator.getInstance(
8703 mContext.getResources().getConfiguration().locale);
8704 iterator.initialize(text.toString());
8708 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
8709 CharSequence text = getIterableTextForAccessibility();
8710 if (text != null && text.length() > 0) {
8711 ParagraphTextSegmentIterator iterator =
8712 ParagraphTextSegmentIterator.getInstance();
8713 iterator.initialize(text.toString());
8724 public void dispatchStartTemporaryDetach() {
8725 onStartTemporaryDetach();
8729 * This is called when a container is going to temporarily detach a child, with
8730 * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
8731 * It will either be followed by {@link #onFinishTemporaryDetach()} or
8732 * {@link #onDetachedFromWindow()} when the container is done.
8734 public void onStartTemporaryDetach() {
8735 removeUnsetPressCallback();
8736 mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
8742 public void dispatchFinishTemporaryDetach() {
8743 onFinishTemporaryDetach();
8747 * Called after {@link #onStartTemporaryDetach} when the container is done
8748 * changing the view.
8750 public void onFinishTemporaryDetach() {
8754 * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
8755 * for this view's window. Returns null if the view is not currently attached
8756 * to the window. Normally you will not need to use this directly, but
8757 * just use the standard high-level event callbacks like
8758 * {@link #onKeyDown(int, KeyEvent)}.
8760 public KeyEvent.DispatcherState getKeyDispatcherState() {
8761 return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
8765 * Dispatch a key event before it is processed by any input method
8766 * associated with the view hierarchy. This can be used to intercept
8767 * key events in special situations before the IME consumes them; a
8768 * typical example would be handling the BACK key to update the application's
8769 * UI instead of allowing the IME to see it and close itself.
8771 * @param event The key event to be dispatched.
8772 * @return True if the event was handled, false otherwise.
8774 public boolean dispatchKeyEventPreIme(KeyEvent event) {
8775 return onKeyPreIme(event.getKeyCode(), event);
8779 * Dispatch a key event to the next view on the focus path. This path runs
8780 * from the top of the view tree down to the currently focused view. If this
8781 * view has focus, it will dispatch to itself. Otherwise it will dispatch
8782 * the next node down the focus path. This method also fires any key
8785 * @param event The key event to be dispatched.
8786 * @return True if the event was handled, false otherwise.
8788 public boolean dispatchKeyEvent(KeyEvent event) {
8789 if (mInputEventConsistencyVerifier != null) {
8790 mInputEventConsistencyVerifier.onKeyEvent(event, 0);
8793 // Give any attached key listener a first crack at the event.
8794 //noinspection SimplifiableIfStatement
8795 ListenerInfo li = mListenerInfo;
8796 if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
8797 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
8801 if (event.dispatch(this, mAttachInfo != null
8802 ? mAttachInfo.mKeyDispatchState : null, this)) {
8806 if (mInputEventConsistencyVerifier != null) {
8807 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8813 * Dispatches a key shortcut event.
8815 * @param event The key event to be dispatched.
8816 * @return True if the event was handled by the view, false otherwise.
8818 public boolean dispatchKeyShortcutEvent(KeyEvent event) {
8819 return onKeyShortcut(event.getKeyCode(), event);
8823 * Pass the touch screen motion event down to the target view, or this
8824 * view if it is the target.
8826 * @param event The motion event to be dispatched.
8827 * @return True if the event was handled by the view, false otherwise.
8829 public boolean dispatchTouchEvent(MotionEvent event) {
8830 // If the event should be handled by accessibility focus first.
8831 if (event.isTargetAccessibilityFocus()) {
8832 // We don't have focus or no virtual descendant has it, do not handle the event.
8833 if (!isAccessibilityFocusedViewOrHost()) {
8836 // We have focus and got the event, then use normal event dispatch.
8837 event.setTargetAccessibilityFocus(false);
8840 boolean result = false;
8842 if (mInputEventConsistencyVerifier != null) {
8843 mInputEventConsistencyVerifier.onTouchEvent(event, 0);
8846 final int actionMasked = event.getActionMasked();
8847 if (actionMasked == MotionEvent.ACTION_DOWN) {
8848 // Defensive cleanup for new gesture
8852 if (onFilterTouchEventForSecurity(event)) {
8853 //noinspection SimplifiableIfStatement
8854 ListenerInfo li = mListenerInfo;
8855 if (li != null && li.mOnTouchListener != null
8856 && (mViewFlags & ENABLED_MASK) == ENABLED
8857 && li.mOnTouchListener.onTouch(this, event)) {
8861 if (!result && onTouchEvent(event)) {
8866 if (!result && mInputEventConsistencyVerifier != null) {
8867 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8870 // Clean up after nested scrolls if this is the end of a gesture;
8871 // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
8873 if (actionMasked == MotionEvent.ACTION_UP ||
8874 actionMasked == MotionEvent.ACTION_CANCEL ||
8875 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
8882 boolean isAccessibilityFocusedViewOrHost() {
8883 return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
8884 .getAccessibilityFocusedHost() == this);
8888 * Filter the touch event to apply security policies.
8890 * @param event The motion event to be filtered.
8891 * @return True if the event should be dispatched, false if the event should be dropped.
8893 * @see #getFilterTouchesWhenObscured
8895 public boolean onFilterTouchEventForSecurity(MotionEvent event) {
8896 //noinspection RedundantIfStatement
8897 if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
8898 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
8899 // Window is obscured, drop this touch.
8906 * Pass a trackball motion event down to the focused view.
8908 * @param event The motion event to be dispatched.
8909 * @return True if the event was handled by the view, false otherwise.
8911 public boolean dispatchTrackballEvent(MotionEvent event) {
8912 if (mInputEventConsistencyVerifier != null) {
8913 mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
8916 return onTrackballEvent(event);
8920 * Dispatch a generic motion event.
8922 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
8923 * are delivered to the view under the pointer. All other generic motion events are
8924 * delivered to the focused view. Hover events are handled specially and are delivered
8925 * to {@link #onHoverEvent(MotionEvent)}.
8928 * @param event The motion event to be dispatched.
8929 * @return True if the event was handled by the view, false otherwise.
8931 public boolean dispatchGenericMotionEvent(MotionEvent event) {
8932 if (mInputEventConsistencyVerifier != null) {
8933 mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
8936 final int source = event.getSource();
8937 if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
8938 final int action = event.getAction();
8939 if (action == MotionEvent.ACTION_HOVER_ENTER
8940 || action == MotionEvent.ACTION_HOVER_MOVE
8941 || action == MotionEvent.ACTION_HOVER_EXIT) {
8942 if (dispatchHoverEvent(event)) {
8945 } else if (dispatchGenericPointerEvent(event)) {
8948 } else if (dispatchGenericFocusedEvent(event)) {
8952 if (dispatchGenericMotionEventInternal(event)) {
8956 if (mInputEventConsistencyVerifier != null) {
8957 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8962 private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
8963 //noinspection SimplifiableIfStatement
8964 ListenerInfo li = mListenerInfo;
8965 if (li != null && li.mOnGenericMotionListener != null
8966 && (mViewFlags & ENABLED_MASK) == ENABLED
8967 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
8971 if (onGenericMotionEvent(event)) {
8975 if (mInputEventConsistencyVerifier != null) {
8976 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8982 * Dispatch a hover event.
8984 * Do not call this method directly.
8985 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8988 * @param event The motion event to be dispatched.
8989 * @return True if the event was handled by the view, false otherwise.
8991 protected boolean dispatchHoverEvent(MotionEvent event) {
8992 ListenerInfo li = mListenerInfo;
8993 //noinspection SimplifiableIfStatement
8994 if (li != null && li.mOnHoverListener != null
8995 && (mViewFlags & ENABLED_MASK) == ENABLED
8996 && li.mOnHoverListener.onHover(this, event)) {
9000 return onHoverEvent(event);
9004 * Returns true if the view has a child to which it has recently sent
9005 * {@link MotionEvent#ACTION_HOVER_ENTER}. If this view is hovered and
9006 * it does not have a hovered child, then it must be the innermost hovered view.
9009 protected boolean hasHoveredChild() {
9014 * Dispatch a generic motion event to the view under the first pointer.
9016 * Do not call this method directly.
9017 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9020 * @param event The motion event to be dispatched.
9021 * @return True if the event was handled by the view, false otherwise.
9023 protected boolean dispatchGenericPointerEvent(MotionEvent event) {
9028 * Dispatch a generic motion event to the currently focused view.
9030 * Do not call this method directly.
9031 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9034 * @param event The motion event to be dispatched.
9035 * @return True if the event was handled by the view, false otherwise.
9037 protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
9042 * Dispatch a pointer event.
9044 * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
9045 * other events to {@link #onGenericMotionEvent(MotionEvent)}. This separation of concerns
9046 * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
9047 * and should not be expected to handle other pointing device features.
9050 * @param event The motion event to be dispatched.
9051 * @return True if the event was handled by the view, false otherwise.
9054 public final boolean dispatchPointerEvent(MotionEvent event) {
9055 if (event.isTouchEvent()) {
9056 return dispatchTouchEvent(event);
9058 return dispatchGenericMotionEvent(event);
9063 * Called when the window containing this view gains or loses window focus.
9064 * ViewGroups should override to route to their children.
9066 * @param hasFocus True if the window containing this view now has focus,
9069 public void dispatchWindowFocusChanged(boolean hasFocus) {
9070 onWindowFocusChanged(hasFocus);
9074 * Called when the window containing this view gains or loses focus. Note
9075 * that this is separate from view focus: to receive key events, both
9076 * your view and its window must have focus. If a window is displayed
9077 * on top of yours that takes input focus, then your own window will lose
9078 * focus but the view focus will remain unchanged.
9080 * @param hasWindowFocus True if the window containing this view now has
9081 * focus, false otherwise.
9083 public void onWindowFocusChanged(boolean hasWindowFocus) {
9084 InputMethodManager imm = InputMethodManager.peekInstance();
9085 if (!hasWindowFocus) {
9089 if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9092 removeLongPressCallback();
9093 removeTapCallback();
9095 } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9098 refreshDrawableState();
9102 * Returns true if this view is in a window that currently has window focus.
9103 * Note that this is not the same as the view itself having focus.
9105 * @return True if this view is in a window that currently has window focus.
9107 public boolean hasWindowFocus() {
9108 return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
9112 * Dispatch a view visibility change down the view hierarchy.
9113 * ViewGroups should override to route to their children.
9114 * @param changedView The view whose visibility changed. Could be 'this' or
9116 * @param visibility The new visibility of changedView: {@link #VISIBLE},
9117 * {@link #INVISIBLE} or {@link #GONE}.
9119 protected void dispatchVisibilityChanged(@NonNull View changedView,
9120 @Visibility int visibility) {
9121 onVisibilityChanged(changedView, visibility);
9125 * Called when the visibility of the view or an ancestor of the view has
9128 * @param changedView The view whose visibility changed. May be
9129 * {@code this} or an ancestor view.
9130 * @param visibility The new visibility, one of {@link #VISIBLE},
9131 * {@link #INVISIBLE} or {@link #GONE}.
9133 protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
9134 final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
9136 if (mAttachInfo != null) {
9137 initialAwakenScrollBars();
9139 mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
9143 final Drawable dr = mBackground;
9144 if (dr != null && visible != dr.isVisible()) {
9145 dr.setVisible(visible, false);
9147 final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
9148 if (fg != null && visible != fg.isVisible()) {
9149 fg.setVisible(visible, false);
9154 * Dispatch a hint about whether this view is displayed. For instance, when
9155 * a View moves out of the screen, it might receives a display hint indicating
9156 * the view is not displayed. Applications should not <em>rely</em> on this hint
9157 * as there is no guarantee that they will receive one.
9159 * @param hint A hint about whether or not this view is displayed:
9160 * {@link #VISIBLE} or {@link #INVISIBLE}.
9162 public void dispatchDisplayHint(@Visibility int hint) {
9163 onDisplayHint(hint);
9167 * Gives this view a hint about whether is displayed or not. For instance, when
9168 * a View moves out of the screen, it might receives a display hint indicating
9169 * the view is not displayed. Applications should not <em>rely</em> on this hint
9170 * as there is no guarantee that they will receive one.
9172 * @param hint A hint about whether or not this view is displayed:
9173 * {@link #VISIBLE} or {@link #INVISIBLE}.
9175 protected void onDisplayHint(@Visibility int hint) {
9179 * Dispatch a window visibility change down the view hierarchy.
9180 * ViewGroups should override to route to their children.
9182 * @param visibility The new visibility of the window.
9184 * @see #onWindowVisibilityChanged(int)
9186 public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
9187 onWindowVisibilityChanged(visibility);
9191 * Called when the window containing has change its visibility
9192 * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}). Note
9193 * that this tells you whether or not your window is being made visible
9194 * to the window manager; this does <em>not</em> tell you whether or not
9195 * your window is obscured by other windows on the screen, even if it
9196 * is itself visible.
9198 * @param visibility The new visibility of the window.
9200 protected void onWindowVisibilityChanged(@Visibility int visibility) {
9201 if (visibility == VISIBLE) {
9202 initialAwakenScrollBars();
9207 * Returns the current visibility of the window this view is attached to
9208 * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
9210 * @return Returns the current visibility of the view's window.
9213 public int getWindowVisibility() {
9214 return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
9218 * Retrieve the overall visible display size in which the window this view is
9219 * attached to has been positioned in. This takes into account screen
9220 * decorations above the window, for both cases where the window itself
9221 * is being position inside of them or the window is being placed under
9222 * then and covered insets are used for the window to position its content
9223 * inside. In effect, this tells you the available area where content can
9224 * be placed and remain visible to users.
9226 * <p>This function requires an IPC back to the window manager to retrieve
9227 * the requested information, so should not be used in performance critical
9228 * code like drawing.
9230 * @param outRect Filled in with the visible display frame. If the view
9231 * is not attached to a window, this is simply the raw display size.
9233 public void getWindowVisibleDisplayFrame(Rect outRect) {
9234 if (mAttachInfo != null) {
9236 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
9237 } catch (RemoteException e) {
9240 // XXX This is really broken, and probably all needs to be done
9241 // in the window manager, and we need to know more about whether
9242 // we want the area behind or in front of the IME.
9243 final Rect insets = mAttachInfo.mVisibleInsets;
9244 outRect.left += insets.left;
9245 outRect.top += insets.top;
9246 outRect.right -= insets.right;
9247 outRect.bottom -= insets.bottom;
9250 // The view is not attached to a display so we don't have a context.
9251 // Make a best guess about the display size.
9252 Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
9253 d.getRectSize(outRect);
9257 * Dispatch a notification about a resource configuration change down
9258 * the view hierarchy.
9259 * ViewGroups should override to route to their children.
9261 * @param newConfig The new resource configuration.
9263 * @see #onConfigurationChanged(android.content.res.Configuration)
9265 public void dispatchConfigurationChanged(Configuration newConfig) {
9266 onConfigurationChanged(newConfig);
9270 * Called when the current configuration of the resources being used
9271 * by the application have changed. You can use this to decide when
9272 * to reload resources that can changed based on orientation and other
9273 * configuration characteristics. You only need to use this if you are
9274 * not relying on the normal {@link android.app.Activity} mechanism of
9275 * recreating the activity instance upon a configuration change.
9277 * @param newConfig The new resource configuration.
9279 protected void onConfigurationChanged(Configuration newConfig) {
9283 * Private function to aggregate all per-view attributes in to the view
9286 void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9287 performCollectViewAttributes(attachInfo, visibility);
9290 void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9291 if ((visibility & VISIBILITY_MASK) == VISIBLE) {
9292 if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
9293 attachInfo.mKeepScreenOn = true;
9295 attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
9296 ListenerInfo li = mListenerInfo;
9297 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
9298 attachInfo.mHasSystemUiListeners = true;
9303 void needGlobalAttributesUpdate(boolean force) {
9304 final AttachInfo ai = mAttachInfo;
9305 if (ai != null && !ai.mRecomputeGlobalAttributes) {
9306 if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
9307 || ai.mHasSystemUiListeners) {
9308 ai.mRecomputeGlobalAttributes = true;
9314 * Returns whether the device is currently in touch mode. Touch mode is entered
9315 * once the user begins interacting with the device by touch, and affects various
9316 * things like whether focus is always visible to the user.
9318 * @return Whether the device is in touch mode.
9320 @ViewDebug.ExportedProperty
9321 public boolean isInTouchMode() {
9322 if (mAttachInfo != null) {
9323 return mAttachInfo.mInTouchMode;
9325 return ViewRootImpl.isInTouchMode();
9330 * Returns the context the view is running in, through which it can
9331 * access the current theme, resources, etc.
9333 * @return The view's Context.
9335 @ViewDebug.CapturedViewProperty
9336 public final Context getContext() {
9341 * Handle a key event before it is processed by any input method
9342 * associated with the view hierarchy. This can be used to intercept
9343 * key events in special situations before the IME consumes them; a
9344 * typical example would be handling the BACK key to update the application's
9345 * UI instead of allowing the IME to see it and close itself.
9347 * @param keyCode The value in event.getKeyCode().
9348 * @param event Description of the key event.
9349 * @return If you handled the event, return true. If you want to allow the
9350 * event to be handled by the next receiver, return false.
9352 public boolean onKeyPreIme(int keyCode, KeyEvent event) {
9357 * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
9358 * KeyEvent.Callback.onKeyDown()}: perform press of the view
9359 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
9360 * is released, if the view is enabled and clickable.
9362 * <p>Key presses in software keyboards will generally NOT trigger this listener,
9363 * although some may elect to do so in some situations. Do not rely on this to
9364 * catch software key presses.
9366 * @param keyCode A key code that represents the button pressed, from
9367 * {@link android.view.KeyEvent}.
9368 * @param event The KeyEvent object that defines the button action.
9370 public boolean onKeyDown(int keyCode, KeyEvent event) {
9371 boolean result = false;
9373 if (KeyEvent.isConfirmKey(keyCode)) {
9374 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9377 // Long clickable items don't necessarily have to be clickable
9378 if (((mViewFlags & CLICKABLE) == CLICKABLE ||
9379 (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
9380 (event.getRepeatCount() == 0)) {
9382 checkForLongClick(0);
9390 * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
9391 * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
9393 * <p>Key presses in software keyboards will generally NOT trigger this listener,
9394 * although some may elect to do so in some situations. Do not rely on this to
9395 * catch software key presses.
9397 public boolean onKeyLongPress(int keyCode, KeyEvent event) {
9402 * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
9403 * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
9404 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
9405 * {@link KeyEvent#KEYCODE_ENTER} is released.
9406 * <p>Key presses in software keyboards will generally NOT trigger this listener,
9407 * although some may elect to do so in some situations. Do not rely on this to
9408 * catch software key presses.
9410 * @param keyCode A key code that represents the button pressed, from
9411 * {@link android.view.KeyEvent}.
9412 * @param event The KeyEvent object that defines the button action.
9414 public boolean onKeyUp(int keyCode, KeyEvent event) {
9415 if (KeyEvent.isConfirmKey(keyCode)) {
9416 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9419 if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
9422 if (!mHasPerformedLongPress) {
9423 // This is a tap, so remove the longpress check
9424 removeLongPressCallback();
9425 return performClick();
9433 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
9434 * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
9436 * <p>Key presses in software keyboards will generally NOT trigger this listener,
9437 * although some may elect to do so in some situations. Do not rely on this to
9438 * catch software key presses.
9440 * @param keyCode A key code that represents the button pressed, from
9441 * {@link android.view.KeyEvent}.
9442 * @param repeatCount The number of times the action was made.
9443 * @param event The KeyEvent object that defines the button action.
9445 public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
9450 * Called on the focused view when a key shortcut event is not handled.
9451 * Override this method to implement local key shortcuts for the View.
9452 * Key shortcuts can also be implemented by setting the
9453 * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
9455 * @param keyCode The value in event.getKeyCode().
9456 * @param event Description of the key event.
9457 * @return If you handled the event, return true. If you want to allow the
9458 * event to be handled by the next receiver, return false.
9460 public boolean onKeyShortcut(int keyCode, KeyEvent event) {
9465 * Check whether the called view is a text editor, in which case it
9466 * would make sense to automatically display a soft input window for
9467 * it. Subclasses should override this if they implement
9468 * {@link #onCreateInputConnection(EditorInfo)} to return true if
9469 * a call on that method would return a non-null InputConnection, and
9470 * they are really a first-class editor that the user would normally
9471 * start typing on when the go into a window containing your view.
9473 * <p>The default implementation always returns false. This does
9474 * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
9475 * will not be called or the user can not otherwise perform edits on your
9476 * view; it is just a hint to the system that this is not the primary
9477 * purpose of this view.
9479 * @return Returns true if this view is a text editor, else false.
9481 public boolean onCheckIsTextEditor() {
9486 * Create a new InputConnection for an InputMethod to interact
9487 * with the view. The default implementation returns null, since it doesn't
9488 * support input methods. You can override this to implement such support.
9489 * This is only needed for views that take focus and text input.
9491 * <p>When implementing this, you probably also want to implement
9492 * {@link #onCheckIsTextEditor()} to indicate you will return a
9493 * non-null InputConnection.</p>
9495 * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
9496 * object correctly and in its entirety, so that the connected IME can rely
9497 * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
9498 * and {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
9499 * must be filled in with the correct cursor position for IMEs to work correctly
9500 * with your application.</p>
9502 * @param outAttrs Fill in with attribute information about the connection.
9504 public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
9509 * Called by the {@link android.view.inputmethod.InputMethodManager}
9510 * when a view who is not the current
9511 * input connection target is trying to make a call on the manager. The
9512 * default implementation returns false; you can override this to return
9513 * true for certain views if you are performing InputConnection proxying
9515 * @param view The View that is making the InputMethodManager call.
9516 * @return Return true to allow the call, false to reject.
9518 public boolean checkInputConnectionProxy(View view) {
9523 * Show the context menu for this view. It is not safe to hold on to the
9524 * menu after returning from this method.
9526 * You should normally not overload this method. Overload
9527 * {@link #onCreateContextMenu(ContextMenu)} or define an
9528 * {@link OnCreateContextMenuListener} to add items to the context menu.
9530 * @param menu The context menu to populate
9532 public void createContextMenu(ContextMenu menu) {
9533 ContextMenuInfo menuInfo = getContextMenuInfo();
9535 // Sets the current menu info so all items added to menu will have
9536 // my extra info set.
9537 ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
9539 onCreateContextMenu(menu);
9540 ListenerInfo li = mListenerInfo;
9541 if (li != null && li.mOnCreateContextMenuListener != null) {
9542 li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
9545 // Clear the extra information so subsequent items that aren't mine don't
9546 // have my extra info.
9547 ((MenuBuilder)menu).setCurrentMenuInfo(null);
9549 if (mParent != null) {
9550 mParent.createContextMenu(menu);
9555 * Views should implement this if they have extra information to associate
9556 * with the context menu. The return result is supplied as a parameter to
9557 * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
9560 * @return Extra information about the item for which the context menu
9561 * should be shown. This information will vary across different
9562 * subclasses of View.
9564 protected ContextMenuInfo getContextMenuInfo() {
9569 * Views should implement this if the view itself is going to add items to
9572 * @param menu the context menu to populate
9574 protected void onCreateContextMenu(ContextMenu menu) {
9578 * Implement this method to handle trackball motion events. The
9579 * <em>relative</em> movement of the trackball since the last event
9580 * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
9581 * {@link MotionEvent#getY MotionEvent.getY()}. These are normalized so
9582 * that a movement of 1 corresponds to the user pressing one DPAD key (so
9583 * they will often be fractional values, representing the more fine-grained
9584 * movement information available from a trackball).
9586 * @param event The motion event.
9587 * @return True if the event was handled, false otherwise.
9589 public boolean onTrackballEvent(MotionEvent event) {
9594 * Implement this method to handle generic motion events.
9596 * Generic motion events describe joystick movements, mouse hovers, track pad
9597 * touches, scroll wheel movements and other input events. The
9598 * {@link MotionEvent#getSource() source} of the motion event specifies
9599 * the class of input that was received. Implementations of this method
9600 * must examine the bits in the source before processing the event.
9601 * The following code example shows how this is done.
9603 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
9604 * are delivered to the view under the pointer. All other generic motion events are
9605 * delivered to the focused view.
9607 * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
9608 * if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
9609 * if (event.getAction() == MotionEvent.ACTION_MOVE) {
9610 * // process the joystick movement...
9614 * if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
9615 * switch (event.getAction()) {
9616 * case MotionEvent.ACTION_HOVER_MOVE:
9617 * // process the mouse hover movement...
9619 * case MotionEvent.ACTION_SCROLL:
9620 * // process the scroll wheel movement...
9624 * return super.onGenericMotionEvent(event);
9627 * @param event The generic motion event being processed.
9628 * @return True if the event was handled, false otherwise.
9630 public boolean onGenericMotionEvent(MotionEvent event) {
9635 * Implement this method to handle hover events.
9637 * This method is called whenever a pointer is hovering into, over, or out of the
9638 * bounds of a view and the view is not currently being touched.
9639 * Hover events are represented as pointer events with action
9640 * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
9641 * or {@link MotionEvent#ACTION_HOVER_EXIT}.
9644 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
9645 * when the pointer enters the bounds of the view.</li>
9646 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
9647 * when the pointer has already entered the bounds of the view and has moved.</li>
9648 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
9649 * when the pointer has exited the bounds of the view or when the pointer is
9650 * about to go down due to a button click, tap, or similar user action that
9651 * causes the view to be touched.</li>
9654 * The view should implement this method to return true to indicate that it is
9655 * handling the hover event, such as by changing its drawable state.
9657 * The default implementation calls {@link #setHovered} to update the hovered state
9658 * of the view when a hover enter or hover exit event is received, if the view
9659 * is enabled and is clickable. The default implementation also sends hover
9660 * accessibility events.
9663 * @param event The motion event that describes the hover.
9664 * @return True if the view handled the hover event.
9668 * @see #onHoverChanged
9670 public boolean onHoverEvent(MotionEvent event) {
9671 // The root view may receive hover (or touch) events that are outside the bounds of
9672 // the window. This code ensures that we only send accessibility events for
9673 // hovers that are actually within the bounds of the root view.
9674 final int action = event.getActionMasked();
9675 if (!mSendingHoverAccessibilityEvents) {
9676 if ((action == MotionEvent.ACTION_HOVER_ENTER
9677 || action == MotionEvent.ACTION_HOVER_MOVE)
9678 && !hasHoveredChild()
9679 && pointInView(event.getX(), event.getY())) {
9680 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
9681 mSendingHoverAccessibilityEvents = true;
9684 if (action == MotionEvent.ACTION_HOVER_EXIT
9685 || (action == MotionEvent.ACTION_MOVE
9686 && !pointInView(event.getX(), event.getY()))) {
9687 mSendingHoverAccessibilityEvents = false;
9688 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
9692 if (isHoverable()) {
9694 case MotionEvent.ACTION_HOVER_ENTER:
9697 case MotionEvent.ACTION_HOVER_EXIT:
9702 // Dispatch the event to onGenericMotionEvent before returning true.
9703 // This is to provide compatibility with existing applications that
9704 // handled HOVER_MOVE events in onGenericMotionEvent and that would
9705 // break because of the new default handling for hoverable views
9707 // Note that onGenericMotionEvent will be called by default when
9708 // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
9709 dispatchGenericMotionEventInternal(event);
9710 // The event was already handled by calling setHovered(), so always
9719 * Returns true if the view should handle {@link #onHoverEvent}
9720 * by calling {@link #setHovered} to change its hovered state.
9722 * @return True if the view is hoverable.
9724 private boolean isHoverable() {
9725 final int viewFlags = mViewFlags;
9726 if ((viewFlags & ENABLED_MASK) == DISABLED) {
9730 return (viewFlags & CLICKABLE) == CLICKABLE
9731 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
9735 * Returns true if the view is currently hovered.
9737 * @return True if the view is currently hovered.
9740 * @see #onHoverChanged
9742 @ViewDebug.ExportedProperty
9743 public boolean isHovered() {
9744 return (mPrivateFlags & PFLAG_HOVERED) != 0;
9748 * Sets whether the view is currently hovered.
9750 * Calling this method also changes the drawable state of the view. This
9751 * enables the view to react to hover by using different drawable resources
9752 * to change its appearance.
9754 * The {@link #onHoverChanged} method is called when the hovered state changes.
9757 * @param hovered True if the view is hovered.
9760 * @see #onHoverChanged
9762 public void setHovered(boolean hovered) {
9764 if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
9765 mPrivateFlags |= PFLAG_HOVERED;
9766 refreshDrawableState();
9767 onHoverChanged(true);
9770 if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
9771 mPrivateFlags &= ~PFLAG_HOVERED;
9772 refreshDrawableState();
9773 onHoverChanged(false);
9779 * Implement this method to handle hover state changes.
9781 * This method is called whenever the hover state changes as a result of a
9782 * call to {@link #setHovered}.
9785 * @param hovered The current hover state, as returned by {@link #isHovered}.
9790 public void onHoverChanged(boolean hovered) {
9794 * Implement this method to handle touch screen motion events.
9796 * If this method is used to detect click actions, it is recommended that
9797 * the actions be performed by implementing and calling
9798 * {@link #performClick()}. This will ensure consistent system behavior,
9801 * <li>obeying click sound preferences
9802 * <li>dispatching OnClickListener calls
9803 * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
9804 * accessibility features are enabled
9807 * @param event The motion event.
9808 * @return True if the event was handled, false otherwise.
9810 public boolean onTouchEvent(MotionEvent event) {
9811 final float x = event.getX();
9812 final float y = event.getY();
9813 final int viewFlags = mViewFlags;
9815 if ((viewFlags & ENABLED_MASK) == DISABLED) {
9816 if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
9819 // A disabled view that is clickable still consumes the touch
9820 // events, it just doesn't respond to them.
9821 return (((viewFlags & CLICKABLE) == CLICKABLE ||
9822 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
9825 if (mTouchDelegate != null) {
9826 if (mTouchDelegate.onTouchEvent(event)) {
9831 if (((viewFlags & CLICKABLE) == CLICKABLE ||
9832 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
9833 switch (event.getAction()) {
9834 case MotionEvent.ACTION_UP:
9835 boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
9836 if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
9837 // take focus if we don't have it already and we should in
9839 boolean focusTaken = false;
9840 if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
9841 focusTaken = requestFocus();
9845 // The button is being released before we actually
9846 // showed it as pressed. Make it show the pressed
9847 // state now (before scheduling the click) to ensure
9848 // the user sees it.
9849 setPressed(true, x, y);
9852 if (!mHasPerformedLongPress) {
9853 // This is a tap, so remove the longpress check
9854 removeLongPressCallback();
9856 // Only perform take click actions if we were in the pressed state
9858 // Use a Runnable and post this rather than calling
9859 // performClick directly. This lets other visual state
9860 // of the view update before click actions start.
9861 if (mPerformClick == null) {
9862 mPerformClick = new PerformClick();
9864 if (!post(mPerformClick)) {
9870 if (mUnsetPressedState == null) {
9871 mUnsetPressedState = new UnsetPressedState();
9875 postDelayed(mUnsetPressedState,
9876 ViewConfiguration.getPressedStateDuration());
9877 } else if (!post(mUnsetPressedState)) {
9878 // If the post failed, unpress right now
9879 mUnsetPressedState.run();
9882 removeTapCallback();
9886 case MotionEvent.ACTION_DOWN:
9887 mHasPerformedLongPress = false;
9889 if (performButtonActionOnTouchDown(event)) {
9893 // Walk up the hierarchy to determine if we're inside a scrolling container.
9894 boolean isInScrollingContainer = isInScrollingContainer();
9896 // For views inside a scrolling container, delay the pressed feedback for
9897 // a short period in case this is a scroll.
9898 if (isInScrollingContainer) {
9899 mPrivateFlags |= PFLAG_PREPRESSED;
9900 if (mPendingCheckForTap == null) {
9901 mPendingCheckForTap = new CheckForTap();
9903 mPendingCheckForTap.x = event.getX();
9904 mPendingCheckForTap.y = event.getY();
9905 postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
9907 // Not inside a scrolling container, so show the feedback right away
9908 setPressed(true, x, y);
9909 checkForLongClick(0);
9913 case MotionEvent.ACTION_CANCEL:
9915 removeTapCallback();
9916 removeLongPressCallback();
9919 case MotionEvent.ACTION_MOVE:
9920 drawableHotspotChanged(x, y);
9922 // Be lenient about moving outside of buttons
9923 if (!pointInView(x, y, mTouchSlop)) {
9925 removeTapCallback();
9926 if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
9927 // Remove any future long press/tap checks
9928 removeLongPressCallback();
9945 public boolean isInScrollingContainer() {
9946 ViewParent p = getParent();
9947 while (p != null && p instanceof ViewGroup) {
9948 if (((ViewGroup) p).shouldDelayChildPressedState()) {
9957 * Remove the longpress detection timer.
9959 private void removeLongPressCallback() {
9960 if (mPendingCheckForLongPress != null) {
9961 removeCallbacks(mPendingCheckForLongPress);
9966 * Remove the pending click action
9968 private void removePerformClickCallback() {
9969 if (mPerformClick != null) {
9970 removeCallbacks(mPerformClick);
9975 * Remove the prepress detection timer.
9977 private void removeUnsetPressCallback() {
9978 if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
9980 removeCallbacks(mUnsetPressedState);
9985 * Remove the tap detection timer.
9987 private void removeTapCallback() {
9988 if (mPendingCheckForTap != null) {
9989 mPrivateFlags &= ~PFLAG_PREPRESSED;
9990 removeCallbacks(mPendingCheckForTap);
9995 * Cancels a pending long press. Your subclass can use this if you
9996 * want the context menu to come up if the user presses and holds
9997 * at the same place, but you don't want it to come up if they press
9998 * and then move around enough to cause scrolling.
10000 public void cancelLongPress() {
10001 removeLongPressCallback();
10004 * The prepressed state handled by the tap callback is a display
10005 * construct, but the tap callback will post a long press callback
10006 * less its own timeout. Remove it here.
10008 removeTapCallback();
10012 * Remove the pending callback for sending a
10013 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
10015 private void removeSendViewScrolledAccessibilityEventCallback() {
10016 if (mSendViewScrolledAccessibilityEvent != null) {
10017 removeCallbacks(mSendViewScrolledAccessibilityEvent);
10018 mSendViewScrolledAccessibilityEvent.mIsPending = false;
10023 * Sets the TouchDelegate for this View.
10025 public void setTouchDelegate(TouchDelegate delegate) {
10026 mTouchDelegate = delegate;
10030 * Gets the TouchDelegate for this View.
10032 public TouchDelegate getTouchDelegate() {
10033 return mTouchDelegate;
10037 * Request unbuffered dispatch of the given stream of MotionEvents to this View.
10039 * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
10040 * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
10041 * available. This method should only be called for touch events.
10043 * <p class="note">This api is not intended for most applications. Buffered dispatch
10044 * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
10045 * streams will not improve your input latency. Side effects include: increased latency,
10046 * jittery scrolls and inability to take advantage of system resampling. Talk to your input
10047 * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
10050 public final void requestUnbufferedDispatch(MotionEvent event) {
10051 final int action = event.getAction();
10052 if (mAttachInfo == null
10053 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
10054 || !event.isTouchEvent()) {
10057 mAttachInfo.mUnbufferedDispatchRequested = true;
10061 * Set flags controlling behavior of this view.
10063 * @param flags Constant indicating the value which should be set
10064 * @param mask Constant indicating the bit range that should be changed
10066 void setFlags(int flags, int mask) {
10067 final boolean accessibilityEnabled =
10068 AccessibilityManager.getInstance(mContext).isEnabled();
10069 final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
10071 int old = mViewFlags;
10072 mViewFlags = (mViewFlags & ~mask) | (flags & mask);
10074 int changed = mViewFlags ^ old;
10075 if (changed == 0) {
10078 int privateFlags = mPrivateFlags;
10080 /* Check if the FOCUSABLE bit has changed */
10081 if (((changed & FOCUSABLE_MASK) != 0) &&
10082 ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
10083 if (((old & FOCUSABLE_MASK) == FOCUSABLE)
10084 && ((privateFlags & PFLAG_FOCUSED) != 0)) {
10085 /* Give up focus if we are no longer focusable */
10087 } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
10088 && ((privateFlags & PFLAG_FOCUSED) == 0)) {
10090 * Tell the view system that we are now available to take focus
10091 * if no one else already has it.
10093 if (mParent != null) mParent.focusableViewAvailable(this);
10097 final int newVisibility = flags & VISIBILITY_MASK;
10098 if (newVisibility == VISIBLE) {
10099 if ((changed & VISIBILITY_MASK) != 0) {
10101 * If this view is becoming visible, invalidate it in case it changed while
10102 * it was not visible. Marking it drawn ensures that the invalidation will
10105 mPrivateFlags |= PFLAG_DRAWN;
10108 needGlobalAttributesUpdate(true);
10110 // a view becoming visible is worth notifying the parent
10111 // about in case nothing has focus. even if this specific view
10112 // isn't focusable, it may contain something that is, so let
10113 // the root view try to give this focus if nothing else does.
10114 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
10115 mParent.focusableViewAvailable(this);
10120 /* Check if the GONE bit has changed */
10121 if ((changed & GONE) != 0) {
10122 needGlobalAttributesUpdate(false);
10125 if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
10126 if (hasFocus()) clearFocus();
10127 clearAccessibilityFocus();
10128 destroyDrawingCache();
10129 if (mParent instanceof View) {
10130 // GONE views noop invalidation, so invalidate the parent
10131 ((View) mParent).invalidate(true);
10133 // Mark the view drawn to ensure that it gets invalidated properly the next
10134 // time it is visible and gets invalidated
10135 mPrivateFlags |= PFLAG_DRAWN;
10137 if (mAttachInfo != null) {
10138 mAttachInfo.mViewVisibilityChanged = true;
10142 /* Check if the VISIBLE bit has changed */
10143 if ((changed & INVISIBLE) != 0) {
10144 needGlobalAttributesUpdate(false);
10146 * If this view is becoming invisible, set the DRAWN flag so that
10147 * the next invalidate() will not be skipped.
10149 mPrivateFlags |= PFLAG_DRAWN;
10151 if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
10152 // root view becoming invisible shouldn't clear focus and accessibility focus
10153 if (getRootView() != this) {
10154 if (hasFocus()) clearFocus();
10155 clearAccessibilityFocus();
10158 if (mAttachInfo != null) {
10159 mAttachInfo.mViewVisibilityChanged = true;
10163 if ((changed & VISIBILITY_MASK) != 0) {
10164 // If the view is invisible, cleanup its display list to free up resources
10165 if (newVisibility != VISIBLE && mAttachInfo != null) {
10169 if (mParent instanceof ViewGroup) {
10170 ((ViewGroup) mParent).onChildVisibilityChanged(this,
10171 (changed & VISIBILITY_MASK), newVisibility);
10172 ((View) mParent).invalidate(true);
10173 } else if (mParent != null) {
10174 mParent.invalidateChild(this, null);
10176 dispatchVisibilityChanged(this, newVisibility);
10178 notifySubtreeAccessibilityStateChangedIfNeeded();
10181 if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
10182 destroyDrawingCache();
10185 if ((changed & DRAWING_CACHE_ENABLED) != 0) {
10186 destroyDrawingCache();
10187 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10188 invalidateParentCaches();
10191 if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
10192 destroyDrawingCache();
10193 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10196 if ((changed & DRAW_MASK) != 0) {
10197 if ((mViewFlags & WILL_NOT_DRAW) != 0) {
10198 if (mBackground != null) {
10199 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10200 mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
10202 mPrivateFlags |= PFLAG_SKIP_DRAW;
10205 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10211 if ((changed & KEEP_SCREEN_ON) != 0) {
10212 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
10213 mParent.recomputeViewAttributes(this);
10217 if (accessibilityEnabled) {
10218 if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
10219 || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0) {
10220 if (oldIncludeForAccessibility != includeForAccessibility()) {
10221 notifySubtreeAccessibilityStateChangedIfNeeded();
10223 notifyViewAccessibilityStateChangedIfNeeded(
10224 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10226 } else if ((changed & ENABLED_MASK) != 0) {
10227 notifyViewAccessibilityStateChangedIfNeeded(
10228 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10234 * Change the view's z order in the tree, so it's on top of other sibling
10235 * views. This ordering change may affect layout, if the parent container
10236 * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
10237 * to {@link android.os.Build.VERSION_CODES#KITKAT} this
10238 * method should be followed by calls to {@link #requestLayout()} and
10239 * {@link View#invalidate()} on the view's parent to force the parent to redraw
10240 * with the new child ordering.
10242 * @see ViewGroup#bringChildToFront(View)
10244 public void bringToFront() {
10245 if (mParent != null) {
10246 mParent.bringChildToFront(this);
10251 * This is called in response to an internal scroll in this view (i.e., the
10252 * view scrolled its own contents). This is typically as a result of
10253 * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
10256 * @param l Current horizontal scroll origin.
10257 * @param t Current vertical scroll origin.
10258 * @param oldl Previous horizontal scroll origin.
10259 * @param oldt Previous vertical scroll origin.
10261 protected void onScrollChanged(int l, int t, int oldl, int oldt) {
10262 notifySubtreeAccessibilityStateChangedIfNeeded();
10264 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10265 postSendViewScrolledAccessibilityEventCallback();
10268 mBackgroundSizeChanged = true;
10269 if (mForegroundInfo != null) {
10270 mForegroundInfo.mBoundsChanged = true;
10273 final AttachInfo ai = mAttachInfo;
10275 ai.mViewScrollChanged = true;
10278 if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
10279 mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
10284 * Interface definition for a callback to be invoked when the scroll
10285 * X or Y positions of a view change.
10287 * <b>Note:</b> Some views handle scrolling independently from View and may
10288 * have their own separate listeners for scroll-type events. For example,
10289 * {@link android.widget.ListView ListView} allows clients to register an
10290 * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
10291 * to listen for changes in list scroll position.
10293 * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
10295 public interface OnScrollChangeListener {
10297 * Called when the scroll position of a view changes.
10299 * @param v The view whose scroll position has changed.
10300 * @param scrollX Current horizontal scroll origin.
10301 * @param scrollY Current vertical scroll origin.
10302 * @param oldScrollX Previous horizontal scroll origin.
10303 * @param oldScrollY Previous vertical scroll origin.
10305 void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
10309 * Interface definition for a callback to be invoked when the layout bounds of a view
10310 * changes due to layout processing.
10312 public interface OnLayoutChangeListener {
10314 * Called when the layout bounds of a view changes due to layout processing.
10316 * @param v The view whose bounds have changed.
10317 * @param left The new value of the view's left property.
10318 * @param top The new value of the view's top property.
10319 * @param right The new value of the view's right property.
10320 * @param bottom The new value of the view's bottom property.
10321 * @param oldLeft The previous value of the view's left property.
10322 * @param oldTop The previous value of the view's top property.
10323 * @param oldRight The previous value of the view's right property.
10324 * @param oldBottom The previous value of the view's bottom property.
10326 void onLayoutChange(View v, int left, int top, int right, int bottom,
10327 int oldLeft, int oldTop, int oldRight, int oldBottom);
10331 * This is called during layout when the size of this view has changed. If
10332 * you were just added to the view hierarchy, you're called with the old
10335 * @param w Current width of this view.
10336 * @param h Current height of this view.
10337 * @param oldw Old width of this view.
10338 * @param oldh Old height of this view.
10340 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
10344 * Called by draw to draw the child views. This may be overridden
10345 * by derived classes to gain control just before its children are drawn
10346 * (but after its own view has been drawn).
10347 * @param canvas the canvas on which to draw the view
10349 protected void dispatchDraw(Canvas canvas) {
10354 * Gets the parent of this view. Note that the parent is a
10355 * ViewParent and not necessarily a View.
10357 * @return Parent of this view.
10359 public final ViewParent getParent() {
10364 * Set the horizontal scrolled position of your view. This will cause a call to
10365 * {@link #onScrollChanged(int, int, int, int)} and the view will be
10367 * @param value the x position to scroll to
10369 public void setScrollX(int value) {
10370 scrollTo(value, mScrollY);
10374 * Set the vertical scrolled position of your view. This will cause a call to
10375 * {@link #onScrollChanged(int, int, int, int)} and the view will be
10377 * @param value the y position to scroll to
10379 public void setScrollY(int value) {
10380 scrollTo(mScrollX, value);
10384 * Return the scrolled left position of this view. This is the left edge of
10385 * the displayed part of your view. You do not need to draw any pixels
10386 * farther left, since those are outside of the frame of your view on
10389 * @return The left edge of the displayed part of your view, in pixels.
10391 public final int getScrollX() {
10396 * Return the scrolled top position of this view. This is the top edge of
10397 * the displayed part of your view. You do not need to draw any pixels above
10398 * it, since those are outside of the frame of your view on screen.
10400 * @return The top edge of the displayed part of your view, in pixels.
10402 public final int getScrollY() {
10407 * Return the width of the your view.
10409 * @return The width of your view, in pixels.
10411 @ViewDebug.ExportedProperty(category = "layout")
10412 public final int getWidth() {
10413 return mRight - mLeft;
10417 * Return the height of your view.
10419 * @return The height of your view, in pixels.
10421 @ViewDebug.ExportedProperty(category = "layout")
10422 public final int getHeight() {
10423 return mBottom - mTop;
10427 * Return the visible drawing bounds of your view. Fills in the output
10428 * rectangle with the values from getScrollX(), getScrollY(),
10429 * getWidth(), and getHeight(). These bounds do not account for any
10430 * transformation properties currently set on the view, such as
10431 * {@link #setScaleX(float)} or {@link #setRotation(float)}.
10433 * @param outRect The (scrolled) drawing bounds of the view.
10435 public void getDrawingRect(Rect outRect) {
10436 outRect.left = mScrollX;
10437 outRect.top = mScrollY;
10438 outRect.right = mScrollX + (mRight - mLeft);
10439 outRect.bottom = mScrollY + (mBottom - mTop);
10443 * Like {@link #getMeasuredWidthAndState()}, but only returns the
10444 * raw width component (that is the result is masked by
10445 * {@link #MEASURED_SIZE_MASK}).
10447 * @return The raw measured width of this view.
10449 public final int getMeasuredWidth() {
10450 return mMeasuredWidth & MEASURED_SIZE_MASK;
10454 * Return the full width measurement information for this view as computed
10455 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask
10456 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10457 * This should be used during measurement and layout calculations only. Use
10458 * {@link #getWidth()} to see how wide a view is after layout.
10460 * @return The measured width of this view as a bit mask.
10462 @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
10463 @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
10464 name = "MEASURED_STATE_TOO_SMALL"),
10466 public final int getMeasuredWidthAndState() {
10467 return mMeasuredWidth;
10471 * Like {@link #getMeasuredHeightAndState()}, but only returns the
10472 * raw width component (that is the result is masked by
10473 * {@link #MEASURED_SIZE_MASK}).
10475 * @return The raw measured height of this view.
10477 public final int getMeasuredHeight() {
10478 return mMeasuredHeight & MEASURED_SIZE_MASK;
10482 * Return the full height measurement information for this view as computed
10483 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask
10484 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10485 * This should be used during measurement and layout calculations only. Use
10486 * {@link #getHeight()} to see how wide a view is after layout.
10488 * @return The measured width of this view as a bit mask.
10490 @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
10491 @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
10492 name = "MEASURED_STATE_TOO_SMALL"),
10494 public final int getMeasuredHeightAndState() {
10495 return mMeasuredHeight;
10499 * Return only the state bits of {@link #getMeasuredWidthAndState()}
10500 * and {@link #getMeasuredHeightAndState()}, combined into one integer.
10501 * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
10502 * and the height component is at the shifted bits
10503 * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
10505 public final int getMeasuredState() {
10506 return (mMeasuredWidth&MEASURED_STATE_MASK)
10507 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
10508 & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
10512 * The transform matrix of this view, which is calculated based on the current
10513 * rotation, scale, and pivot properties.
10515 * @see #getRotation()
10516 * @see #getScaleX()
10517 * @see #getScaleY()
10518 * @see #getPivotX()
10519 * @see #getPivotY()
10520 * @return The current transform matrix for the view
10522 public Matrix getMatrix() {
10523 ensureTransformationInfo();
10524 final Matrix matrix = mTransformationInfo.mMatrix;
10525 mRenderNode.getMatrix(matrix);
10530 * Returns true if the transform matrix is the identity matrix.
10531 * Recomputes the matrix if necessary.
10533 * @return True if the transform matrix is the identity matrix, false otherwise.
10535 final boolean hasIdentityMatrix() {
10536 return mRenderNode.hasIdentityMatrix();
10539 void ensureTransformationInfo() {
10540 if (mTransformationInfo == null) {
10541 mTransformationInfo = new TransformationInfo();
10546 * Utility method to retrieve the inverse of the current mMatrix property.
10547 * We cache the matrix to avoid recalculating it when transform properties
10548 * have not changed.
10550 * @return The inverse of the current matrix of this view.
10553 public final Matrix getInverseMatrix() {
10554 ensureTransformationInfo();
10555 if (mTransformationInfo.mInverseMatrix == null) {
10556 mTransformationInfo.mInverseMatrix = new Matrix();
10558 final Matrix matrix = mTransformationInfo.mInverseMatrix;
10559 mRenderNode.getInverseMatrix(matrix);
10564 * Gets the distance along the Z axis from the camera to this view.
10566 * @see #setCameraDistance(float)
10568 * @return The distance along the Z axis.
10570 public float getCameraDistance() {
10571 final float dpi = mResources.getDisplayMetrics().densityDpi;
10572 return -(mRenderNode.getCameraDistance() * dpi);
10576 * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
10577 * views are drawn) from the camera to this view. The camera's distance
10578 * affects 3D transformations, for instance rotations around the X and Y
10579 * axis. If the rotationX or rotationY properties are changed and this view is
10580 * large (more than half the size of the screen), it is recommended to always
10581 * use a camera distance that's greater than the height (X axis rotation) or
10582 * the width (Y axis rotation) of this view.</p>
10584 * <p>The distance of the camera from the view plane can have an affect on the
10585 * perspective distortion of the view when it is rotated around the x or y axis.
10586 * For example, a large distance will result in a large viewing angle, and there
10587 * will not be much perspective distortion of the view as it rotates. A short
10588 * distance may cause much more perspective distortion upon rotation, and can
10589 * also result in some drawing artifacts if the rotated view ends up partially
10590 * behind the camera (which is why the recommendation is to use a distance at
10591 * least as far as the size of the view, if the view is to be rotated.)</p>
10593 * <p>The distance is expressed in "depth pixels." The default distance depends
10594 * on the screen density. For instance, on a medium density display, the
10595 * default distance is 1280. On a high density display, the default distance
10598 * <p>If you want to specify a distance that leads to visually consistent
10599 * results across various densities, use the following formula:</p>
10601 * float scale = context.getResources().getDisplayMetrics().density;
10602 * view.setCameraDistance(distance * scale);
10605 * <p>The density scale factor of a high density display is 1.5,
10606 * and 1920 = 1280 * 1.5.</p>
10608 * @param distance The distance in "depth pixels", if negative the opposite
10611 * @see #setRotationX(float)
10612 * @see #setRotationY(float)
10614 public void setCameraDistance(float distance) {
10615 final float dpi = mResources.getDisplayMetrics().densityDpi;
10617 invalidateViewProperty(true, false);
10618 mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
10619 invalidateViewProperty(false, false);
10621 invalidateParentIfNeededAndWasQuickRejected();
10625 * The degrees that the view is rotated around the pivot point.
10627 * @see #setRotation(float)
10628 * @see #getPivotX()
10629 * @see #getPivotY()
10631 * @return The degrees of rotation.
10633 @ViewDebug.ExportedProperty(category = "drawing")
10634 public float getRotation() {
10635 return mRenderNode.getRotation();
10639 * Sets the degrees that the view is rotated around the pivot point. Increasing values
10640 * result in clockwise rotation.
10642 * @param rotation The degrees of rotation.
10644 * @see #getRotation()
10645 * @see #getPivotX()
10646 * @see #getPivotY()
10647 * @see #setRotationX(float)
10648 * @see #setRotationY(float)
10650 * @attr ref android.R.styleable#View_rotation
10652 public void setRotation(float rotation) {
10653 if (rotation != getRotation()) {
10654 // Double-invalidation is necessary to capture view's old and new areas
10655 invalidateViewProperty(true, false);
10656 mRenderNode.setRotation(rotation);
10657 invalidateViewProperty(false, true);
10659 invalidateParentIfNeededAndWasQuickRejected();
10660 notifySubtreeAccessibilityStateChangedIfNeeded();
10665 * The degrees that the view is rotated around the vertical axis through the pivot point.
10667 * @see #getPivotX()
10668 * @see #getPivotY()
10669 * @see #setRotationY(float)
10671 * @return The degrees of Y rotation.
10673 @ViewDebug.ExportedProperty(category = "drawing")
10674 public float getRotationY() {
10675 return mRenderNode.getRotationY();
10679 * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
10680 * Increasing values result in counter-clockwise rotation from the viewpoint of looking
10683 * When rotating large views, it is recommended to adjust the camera distance
10684 * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
10686 * @param rotationY The degrees of Y rotation.
10688 * @see #getRotationY()
10689 * @see #getPivotX()
10690 * @see #getPivotY()
10691 * @see #setRotation(float)
10692 * @see #setRotationX(float)
10693 * @see #setCameraDistance(float)
10695 * @attr ref android.R.styleable#View_rotationY
10697 public void setRotationY(float rotationY) {
10698 if (rotationY != getRotationY()) {
10699 invalidateViewProperty(true, false);
10700 mRenderNode.setRotationY(rotationY);
10701 invalidateViewProperty(false, true);
10703 invalidateParentIfNeededAndWasQuickRejected();
10704 notifySubtreeAccessibilityStateChangedIfNeeded();
10709 * The degrees that the view is rotated around the horizontal axis through the pivot point.
10711 * @see #getPivotX()
10712 * @see #getPivotY()
10713 * @see #setRotationX(float)
10715 * @return The degrees of X rotation.
10717 @ViewDebug.ExportedProperty(category = "drawing")
10718 public float getRotationX() {
10719 return mRenderNode.getRotationX();
10723 * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
10724 * Increasing values result in clockwise rotation from the viewpoint of looking down the
10727 * When rotating large views, it is recommended to adjust the camera distance
10728 * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
10730 * @param rotationX The degrees of X rotation.
10732 * @see #getRotationX()
10733 * @see #getPivotX()
10734 * @see #getPivotY()
10735 * @see #setRotation(float)
10736 * @see #setRotationY(float)
10737 * @see #setCameraDistance(float)
10739 * @attr ref android.R.styleable#View_rotationX
10741 public void setRotationX(float rotationX) {
10742 if (rotationX != getRotationX()) {
10743 invalidateViewProperty(true, false);
10744 mRenderNode.setRotationX(rotationX);
10745 invalidateViewProperty(false, true);
10747 invalidateParentIfNeededAndWasQuickRejected();
10748 notifySubtreeAccessibilityStateChangedIfNeeded();
10753 * The amount that the view is scaled in x around the pivot point, as a proportion of
10754 * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
10756 * <p>By default, this is 1.0f.
10758 * @see #getPivotX()
10759 * @see #getPivotY()
10760 * @return The scaling factor.
10762 @ViewDebug.ExportedProperty(category = "drawing")
10763 public float getScaleX() {
10764 return mRenderNode.getScaleX();
10768 * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
10769 * the view's unscaled width. A value of 1 means that no scaling is applied.
10771 * @param scaleX The scaling factor.
10772 * @see #getPivotX()
10773 * @see #getPivotY()
10775 * @attr ref android.R.styleable#View_scaleX
10777 public void setScaleX(float scaleX) {
10778 if (scaleX != getScaleX()) {
10779 invalidateViewProperty(true, false);
10780 mRenderNode.setScaleX(scaleX);
10781 invalidateViewProperty(false, true);
10783 invalidateParentIfNeededAndWasQuickRejected();
10784 notifySubtreeAccessibilityStateChangedIfNeeded();
10789 * The amount that the view is scaled in y around the pivot point, as a proportion of
10790 * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
10792 * <p>By default, this is 1.0f.
10794 * @see #getPivotX()
10795 * @see #getPivotY()
10796 * @return The scaling factor.
10798 @ViewDebug.ExportedProperty(category = "drawing")
10799 public float getScaleY() {
10800 return mRenderNode.getScaleY();
10804 * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
10805 * the view's unscaled width. A value of 1 means that no scaling is applied.
10807 * @param scaleY The scaling factor.
10808 * @see #getPivotX()
10809 * @see #getPivotY()
10811 * @attr ref android.R.styleable#View_scaleY
10813 public void setScaleY(float scaleY) {
10814 if (scaleY != getScaleY()) {
10815 invalidateViewProperty(true, false);
10816 mRenderNode.setScaleY(scaleY);
10817 invalidateViewProperty(false, true);
10819 invalidateParentIfNeededAndWasQuickRejected();
10820 notifySubtreeAccessibilityStateChangedIfNeeded();
10825 * The x location of the point around which the view is {@link #setRotation(float) rotated}
10826 * and {@link #setScaleX(float) scaled}.
10828 * @see #getRotation()
10829 * @see #getScaleX()
10830 * @see #getScaleY()
10831 * @see #getPivotY()
10832 * @return The x location of the pivot point.
10834 * @attr ref android.R.styleable#View_transformPivotX
10836 @ViewDebug.ExportedProperty(category = "drawing")
10837 public float getPivotX() {
10838 return mRenderNode.getPivotX();
10842 * Sets the x location of the point around which the view is
10843 * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
10844 * By default, the pivot point is centered on the object.
10845 * Setting this property disables this behavior and causes the view to use only the
10846 * explicitly set pivotX and pivotY values.
10848 * @param pivotX The x location of the pivot point.
10849 * @see #getRotation()
10850 * @see #getScaleX()
10851 * @see #getScaleY()
10852 * @see #getPivotY()
10854 * @attr ref android.R.styleable#View_transformPivotX
10856 public void setPivotX(float pivotX) {
10857 if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
10858 invalidateViewProperty(true, false);
10859 mRenderNode.setPivotX(pivotX);
10860 invalidateViewProperty(false, true);
10862 invalidateParentIfNeededAndWasQuickRejected();
10867 * The y location of the point around which the view is {@link #setRotation(float) rotated}
10868 * and {@link #setScaleY(float) scaled}.
10870 * @see #getRotation()
10871 * @see #getScaleX()
10872 * @see #getScaleY()
10873 * @see #getPivotY()
10874 * @return The y location of the pivot point.
10876 * @attr ref android.R.styleable#View_transformPivotY
10878 @ViewDebug.ExportedProperty(category = "drawing")
10879 public float getPivotY() {
10880 return mRenderNode.getPivotY();
10884 * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
10885 * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
10886 * Setting this property disables this behavior and causes the view to use only the
10887 * explicitly set pivotX and pivotY values.
10889 * @param pivotY The y location of the pivot point.
10890 * @see #getRotation()
10891 * @see #getScaleX()
10892 * @see #getScaleY()
10893 * @see #getPivotY()
10895 * @attr ref android.R.styleable#View_transformPivotY
10897 public void setPivotY(float pivotY) {
10898 if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
10899 invalidateViewProperty(true, false);
10900 mRenderNode.setPivotY(pivotY);
10901 invalidateViewProperty(false, true);
10903 invalidateParentIfNeededAndWasQuickRejected();
10908 * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
10909 * completely transparent and 1 means the view is completely opaque.
10911 * <p>By default this is 1.0f.
10912 * @return The opacity of the view.
10914 @ViewDebug.ExportedProperty(category = "drawing")
10915 public float getAlpha() {
10916 return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
10920 * Returns whether this View has content which overlaps.
10922 * <p>This function, intended to be overridden by specific View types, is an optimization when
10923 * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
10924 * an offscreen buffer and then composited into place, which can be expensive. If the view has
10925 * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
10926 * directly. An example of overlapping rendering is a TextView with a background image, such as
10927 * a Button. An example of non-overlapping rendering is a TextView with no background, or an
10928 * ImageView with only the foreground image. The default implementation returns true; subclasses
10929 * should override if they have cases which can be optimized.</p>
10931 * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
10932 * necessitates that a View return true if it uses the methods internally without passing the
10933 * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
10935 * @return true if the content in this view might overlap, false otherwise.
10937 @ViewDebug.ExportedProperty(category = "drawing")
10938 public boolean hasOverlappingRendering() {
10943 * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
10944 * completely transparent and 1 means the view is completely opaque.</p>
10946 * <p> Note that setting alpha to a translucent value (0 < alpha < 1) can have significant
10947 * performance implications, especially for large views. It is best to use the alpha property
10948 * sparingly and transiently, as in the case of fading animations.</p>
10950 * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
10951 * strongly recommended for performance reasons to either override
10952 * {@link #hasOverlappingRendering()} to return false if appropriate, or setting a
10953 * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view.</p>
10955 * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
10956 * responsible for applying the opacity itself.</p>
10958 * <p>Note that if the view is backed by a
10959 * {@link #setLayerType(int, android.graphics.Paint) layer} and is associated with a
10960 * {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an alpha value less than
10961 * 1.0 will supersede the alpha of the layer paint.</p>
10963 * @param alpha The opacity of the view.
10965 * @see #hasOverlappingRendering()
10966 * @see #setLayerType(int, android.graphics.Paint)
10968 * @attr ref android.R.styleable#View_alpha
10970 public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
10971 ensureTransformationInfo();
10972 if (mTransformationInfo.mAlpha != alpha) {
10973 mTransformationInfo.mAlpha = alpha;
10974 if (onSetAlpha((int) (alpha * 255))) {
10975 mPrivateFlags |= PFLAG_ALPHA_SET;
10976 // subclass is handling alpha - don't optimize rendering cache invalidation
10977 invalidateParentCaches();
10980 mPrivateFlags &= ~PFLAG_ALPHA_SET;
10981 invalidateViewProperty(true, false);
10982 mRenderNode.setAlpha(getFinalAlpha());
10983 notifyViewAccessibilityStateChangedIfNeeded(
10984 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10990 * Faster version of setAlpha() which performs the same steps except there are
10991 * no calls to invalidate(). The caller of this function should perform proper invalidation
10992 * on the parent and this object. The return value indicates whether the subclass handles
10993 * alpha (the return value for onSetAlpha()).
10995 * @param alpha The new value for the alpha property
10996 * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
10997 * the new value for the alpha property is different from the old value
10999 boolean setAlphaNoInvalidation(float alpha) {
11000 ensureTransformationInfo();
11001 if (mTransformationInfo.mAlpha != alpha) {
11002 mTransformationInfo.mAlpha = alpha;
11003 boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
11004 if (subclassHandlesAlpha) {
11005 mPrivateFlags |= PFLAG_ALPHA_SET;
11008 mPrivateFlags &= ~PFLAG_ALPHA_SET;
11009 mRenderNode.setAlpha(getFinalAlpha());
11016 * This property is hidden and intended only for use by the Fade transition, which
11017 * animates it to produce a visual translucency that does not side-effect (or get
11018 * affected by) the real alpha property. This value is composited with the other
11019 * alpha value (and the AlphaAnimation value, when that is present) to produce
11020 * a final visual translucency result, which is what is passed into the DisplayList.
11024 public void setTransitionAlpha(float alpha) {
11025 ensureTransformationInfo();
11026 if (mTransformationInfo.mTransitionAlpha != alpha) {
11027 mTransformationInfo.mTransitionAlpha = alpha;
11028 mPrivateFlags &= ~PFLAG_ALPHA_SET;
11029 invalidateViewProperty(true, false);
11030 mRenderNode.setAlpha(getFinalAlpha());
11035 * Calculates the visual alpha of this view, which is a combination of the actual
11036 * alpha value and the transitionAlpha value (if set).
11038 private float getFinalAlpha() {
11039 if (mTransformationInfo != null) {
11040 return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
11046 * This property is hidden and intended only for use by the Fade transition, which
11047 * animates it to produce a visual translucency that does not side-effect (or get
11048 * affected by) the real alpha property. This value is composited with the other
11049 * alpha value (and the AlphaAnimation value, when that is present) to produce
11050 * a final visual translucency result, which is what is passed into the DisplayList.
11054 @ViewDebug.ExportedProperty(category = "drawing")
11055 public float getTransitionAlpha() {
11056 return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
11060 * Top position of this view relative to its parent.
11062 * @return The top of this view, in pixels.
11064 @ViewDebug.CapturedViewProperty
11065 public final int getTop() {
11070 * Sets the top position of this view relative to its parent. This method is meant to be called
11071 * by the layout system and should not generally be called otherwise, because the property
11072 * may be changed at any time by the layout.
11074 * @param top The top of this view, in pixels.
11076 public final void setTop(int top) {
11078 final boolean matrixIsIdentity = hasIdentityMatrix();
11079 if (matrixIsIdentity) {
11080 if (mAttachInfo != null) {
11090 invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
11093 // Double-invalidation is necessary to capture view's old and new areas
11097 int width = mRight - mLeft;
11098 int oldHeight = mBottom - mTop;
11101 mRenderNode.setTop(mTop);
11103 sizeChange(width, mBottom - mTop, width, oldHeight);
11105 if (!matrixIsIdentity) {
11106 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11109 mBackgroundSizeChanged = true;
11110 if (mForegroundInfo != null) {
11111 mForegroundInfo.mBoundsChanged = true;
11113 invalidateParentIfNeeded();
11114 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11115 // View was rejected last time it was drawn by its parent; this may have changed
11116 invalidateParentIfNeeded();
11122 * Bottom position of this view relative to its parent.
11124 * @return The bottom of this view, in pixels.
11126 @ViewDebug.CapturedViewProperty
11127 public final int getBottom() {
11132 * True if this view has changed since the last time being drawn.
11134 * @return The dirty state of this view.
11136 public boolean isDirty() {
11137 return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
11141 * Sets the bottom position of this view relative to its parent. This method is meant to be
11142 * called by the layout system and should not generally be called otherwise, because the
11143 * property may be changed at any time by the layout.
11145 * @param bottom The bottom of this view, in pixels.
11147 public final void setBottom(int bottom) {
11148 if (bottom != mBottom) {
11149 final boolean matrixIsIdentity = hasIdentityMatrix();
11150 if (matrixIsIdentity) {
11151 if (mAttachInfo != null) {
11153 if (bottom < mBottom) {
11154 maxBottom = mBottom;
11156 maxBottom = bottom;
11158 invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
11161 // Double-invalidation is necessary to capture view's old and new areas
11165 int width = mRight - mLeft;
11166 int oldHeight = mBottom - mTop;
11169 mRenderNode.setBottom(mBottom);
11171 sizeChange(width, mBottom - mTop, width, oldHeight);
11173 if (!matrixIsIdentity) {
11174 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11177 mBackgroundSizeChanged = true;
11178 if (mForegroundInfo != null) {
11179 mForegroundInfo.mBoundsChanged = true;
11181 invalidateParentIfNeeded();
11182 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11183 // View was rejected last time it was drawn by its parent; this may have changed
11184 invalidateParentIfNeeded();
11190 * Left position of this view relative to its parent.
11192 * @return The left edge of this view, in pixels.
11194 @ViewDebug.CapturedViewProperty
11195 public final int getLeft() {
11200 * Sets the left position of this view relative to its parent. This method is meant to be called
11201 * by the layout system and should not generally be called otherwise, because the property
11202 * may be changed at any time by the layout.
11204 * @param left The left of this view, in pixels.
11206 public final void setLeft(int left) {
11207 if (left != mLeft) {
11208 final boolean matrixIsIdentity = hasIdentityMatrix();
11209 if (matrixIsIdentity) {
11210 if (mAttachInfo != null) {
11213 if (left < mLeft) {
11215 xLoc = left - mLeft;
11220 invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
11223 // Double-invalidation is necessary to capture view's old and new areas
11227 int oldWidth = mRight - mLeft;
11228 int height = mBottom - mTop;
11231 mRenderNode.setLeft(left);
11233 sizeChange(mRight - mLeft, height, oldWidth, height);
11235 if (!matrixIsIdentity) {
11236 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11239 mBackgroundSizeChanged = true;
11240 if (mForegroundInfo != null) {
11241 mForegroundInfo.mBoundsChanged = true;
11243 invalidateParentIfNeeded();
11244 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11245 // View was rejected last time it was drawn by its parent; this may have changed
11246 invalidateParentIfNeeded();
11252 * Right position of this view relative to its parent.
11254 * @return The right edge of this view, in pixels.
11256 @ViewDebug.CapturedViewProperty
11257 public final int getRight() {
11262 * Sets the right position of this view relative to its parent. This method is meant to be called
11263 * by the layout system and should not generally be called otherwise, because the property
11264 * may be changed at any time by the layout.
11266 * @param right The right of this view, in pixels.
11268 public final void setRight(int right) {
11269 if (right != mRight) {
11270 final boolean matrixIsIdentity = hasIdentityMatrix();
11271 if (matrixIsIdentity) {
11272 if (mAttachInfo != null) {
11274 if (right < mRight) {
11279 invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
11282 // Double-invalidation is necessary to capture view's old and new areas
11286 int oldWidth = mRight - mLeft;
11287 int height = mBottom - mTop;
11290 mRenderNode.setRight(mRight);
11292 sizeChange(mRight - mLeft, height, oldWidth, height);
11294 if (!matrixIsIdentity) {
11295 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11298 mBackgroundSizeChanged = true;
11299 if (mForegroundInfo != null) {
11300 mForegroundInfo.mBoundsChanged = true;
11302 invalidateParentIfNeeded();
11303 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11304 // View was rejected last time it was drawn by its parent; this may have changed
11305 invalidateParentIfNeeded();
11311 * The visual x position of this view, in pixels. This is equivalent to the
11312 * {@link #setTranslationX(float) translationX} property plus the current
11313 * {@link #getLeft() left} property.
11315 * @return The visual x position of this view, in pixels.
11317 @ViewDebug.ExportedProperty(category = "drawing")
11318 public float getX() {
11319 return mLeft + getTranslationX();
11323 * Sets the visual x position of this view, in pixels. This is equivalent to setting the
11324 * {@link #setTranslationX(float) translationX} property to be the difference between
11325 * the x value passed in and the current {@link #getLeft() left} property.
11327 * @param x The visual x position of this view, in pixels.
11329 public void setX(float x) {
11330 setTranslationX(x - mLeft);
11334 * The visual y position of this view, in pixels. This is equivalent to the
11335 * {@link #setTranslationY(float) translationY} property plus the current
11336 * {@link #getTop() top} property.
11338 * @return The visual y position of this view, in pixels.
11340 @ViewDebug.ExportedProperty(category = "drawing")
11341 public float getY() {
11342 return mTop + getTranslationY();
11346 * Sets the visual y position of this view, in pixels. This is equivalent to setting the
11347 * {@link #setTranslationY(float) translationY} property to be the difference between
11348 * the y value passed in and the current {@link #getTop() top} property.
11350 * @param y The visual y position of this view, in pixels.
11352 public void setY(float y) {
11353 setTranslationY(y - mTop);
11357 * The visual z position of this view, in pixels. This is equivalent to the
11358 * {@link #setTranslationZ(float) translationZ} property plus the current
11359 * {@link #getElevation() elevation} property.
11361 * @return The visual z position of this view, in pixels.
11363 @ViewDebug.ExportedProperty(category = "drawing")
11364 public float getZ() {
11365 return getElevation() + getTranslationZ();
11369 * Sets the visual z position of this view, in pixels. This is equivalent to setting the
11370 * {@link #setTranslationZ(float) translationZ} property to be the difference between
11371 * the x value passed in and the current {@link #getElevation() elevation} property.
11373 * @param z The visual z position of this view, in pixels.
11375 public void setZ(float z) {
11376 setTranslationZ(z - getElevation());
11380 * The base elevation of this view relative to its parent, in pixels.
11382 * @return The base depth position of the view, in pixels.
11384 @ViewDebug.ExportedProperty(category = "drawing")
11385 public float getElevation() {
11386 return mRenderNode.getElevation();
11390 * Sets the base elevation of this view, in pixels.
11392 * @attr ref android.R.styleable#View_elevation
11394 public void setElevation(float elevation) {
11395 if (elevation != getElevation()) {
11396 invalidateViewProperty(true, false);
11397 mRenderNode.setElevation(elevation);
11398 invalidateViewProperty(false, true);
11400 invalidateParentIfNeededAndWasQuickRejected();
11405 * The horizontal location of this view relative to its {@link #getLeft() left} position.
11406 * This position is post-layout, in addition to wherever the object's
11407 * layout placed it.
11409 * @return The horizontal position of this view relative to its left position, in pixels.
11411 @ViewDebug.ExportedProperty(category = "drawing")
11412 public float getTranslationX() {
11413 return mRenderNode.getTranslationX();
11417 * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
11418 * This effectively positions the object post-layout, in addition to wherever the object's
11419 * layout placed it.
11421 * @param translationX The horizontal position of this view relative to its left position,
11424 * @attr ref android.R.styleable#View_translationX
11426 public void setTranslationX(float translationX) {
11427 if (translationX != getTranslationX()) {
11428 invalidateViewProperty(true, false);
11429 mRenderNode.setTranslationX(translationX);
11430 invalidateViewProperty(false, true);
11432 invalidateParentIfNeededAndWasQuickRejected();
11433 notifySubtreeAccessibilityStateChangedIfNeeded();
11438 * The vertical location of this view relative to its {@link #getTop() top} position.
11439 * This position is post-layout, in addition to wherever the object's
11440 * layout placed it.
11442 * @return The vertical position of this view relative to its top position,
11445 @ViewDebug.ExportedProperty(category = "drawing")
11446 public float getTranslationY() {
11447 return mRenderNode.getTranslationY();
11451 * Sets the vertical location of this view relative to its {@link #getTop() top} position.
11452 * This effectively positions the object post-layout, in addition to wherever the object's
11453 * layout placed it.
11455 * @param translationY The vertical position of this view relative to its top position,
11458 * @attr ref android.R.styleable#View_translationY
11460 public void setTranslationY(float translationY) {
11461 if (translationY != getTranslationY()) {
11462 invalidateViewProperty(true, false);
11463 mRenderNode.setTranslationY(translationY);
11464 invalidateViewProperty(false, true);
11466 invalidateParentIfNeededAndWasQuickRejected();
11467 notifySubtreeAccessibilityStateChangedIfNeeded();
11472 * The depth location of this view relative to its {@link #getElevation() elevation}.
11474 * @return The depth of this view relative to its elevation.
11476 @ViewDebug.ExportedProperty(category = "drawing")
11477 public float getTranslationZ() {
11478 return mRenderNode.getTranslationZ();
11482 * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
11484 * @attr ref android.R.styleable#View_translationZ
11486 public void setTranslationZ(float translationZ) {
11487 if (translationZ != getTranslationZ()) {
11488 invalidateViewProperty(true, false);
11489 mRenderNode.setTranslationZ(translationZ);
11490 invalidateViewProperty(false, true);
11492 invalidateParentIfNeededAndWasQuickRejected();
11497 public void setAnimationMatrix(Matrix matrix) {
11498 invalidateViewProperty(true, false);
11499 mRenderNode.setAnimationMatrix(matrix);
11500 invalidateViewProperty(false, true);
11502 invalidateParentIfNeededAndWasQuickRejected();
11506 * Returns the current StateListAnimator if exists.
11508 * @return StateListAnimator or null if it does not exists
11509 * @see #setStateListAnimator(android.animation.StateListAnimator)
11511 public StateListAnimator getStateListAnimator() {
11512 return mStateListAnimator;
11516 * Attaches the provided StateListAnimator to this View.
11518 * Any previously attached StateListAnimator will be detached.
11520 * @param stateListAnimator The StateListAnimator to update the view
11521 * @see {@link android.animation.StateListAnimator}
11523 public void setStateListAnimator(StateListAnimator stateListAnimator) {
11524 if (mStateListAnimator == stateListAnimator) {
11527 if (mStateListAnimator != null) {
11528 mStateListAnimator.setTarget(null);
11530 mStateListAnimator = stateListAnimator;
11531 if (stateListAnimator != null) {
11532 stateListAnimator.setTarget(this);
11533 if (isAttachedToWindow()) {
11534 stateListAnimator.setState(getDrawableState());
11540 * Returns whether the Outline should be used to clip the contents of the View.
11542 * Note that this flag will only be respected if the View's Outline returns true from
11543 * {@link Outline#canClip()}.
11545 * @see #setOutlineProvider(ViewOutlineProvider)
11546 * @see #setClipToOutline(boolean)
11548 public final boolean getClipToOutline() {
11549 return mRenderNode.getClipToOutline();
11553 * Sets whether the View's Outline should be used to clip the contents of the View.
11555 * Only a single non-rectangular clip can be applied on a View at any time.
11556 * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
11557 * circular reveal} animation take priority over Outline clipping, and
11558 * child Outline clipping takes priority over Outline clipping done by a
11561 * Note that this flag will only be respected if the View's Outline returns true from
11562 * {@link Outline#canClip()}.
11564 * @see #setOutlineProvider(ViewOutlineProvider)
11565 * @see #getClipToOutline()
11567 public void setClipToOutline(boolean clipToOutline) {
11569 if (getClipToOutline() != clipToOutline) {
11570 mRenderNode.setClipToOutline(clipToOutline);
11574 // correspond to the enum values of View_outlineProvider
11575 private static final int PROVIDER_BACKGROUND = 0;
11576 private static final int PROVIDER_NONE = 1;
11577 private static final int PROVIDER_BOUNDS = 2;
11578 private static final int PROVIDER_PADDED_BOUNDS = 3;
11579 private void setOutlineProviderFromAttribute(int providerInt) {
11580 switch (providerInt) {
11581 case PROVIDER_BACKGROUND:
11582 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
11584 case PROVIDER_NONE:
11585 setOutlineProvider(null);
11587 case PROVIDER_BOUNDS:
11588 setOutlineProvider(ViewOutlineProvider.BOUNDS);
11590 case PROVIDER_PADDED_BOUNDS:
11591 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
11597 * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
11598 * the shape of the shadow it casts, and enables outline clipping.
11600 * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
11601 * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
11602 * outline provider with this method allows this behavior to be overridden.
11604 * If the ViewOutlineProvider is null, if querying it for an outline returns false,
11605 * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
11607 * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
11609 * @see #setClipToOutline(boolean)
11610 * @see #getClipToOutline()
11611 * @see #getOutlineProvider()
11613 public void setOutlineProvider(ViewOutlineProvider provider) {
11614 mOutlineProvider = provider;
11615 invalidateOutline();
11619 * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
11620 * that defines the shape of the shadow it casts, and enables outline clipping.
11622 * @see #setOutlineProvider(ViewOutlineProvider)
11624 public ViewOutlineProvider getOutlineProvider() {
11625 return mOutlineProvider;
11629 * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
11631 * @see #setOutlineProvider(ViewOutlineProvider)
11633 public void invalidateOutline() {
11636 notifySubtreeAccessibilityStateChangedIfNeeded();
11637 invalidateViewProperty(false, false);
11641 * Internal version of {@link #invalidateOutline()} which invalidates the
11642 * outline without invalidating the view itself. This is intended to be called from
11643 * within methods in the View class itself which are the result of the view being
11644 * invalidated already. For example, when we are drawing the background of a View,
11645 * we invalidate the outline in case it changed in the meantime, but we do not
11646 * need to invalidate the view because we're already drawing the background as part
11647 * of drawing the view in response to an earlier invalidation of the view.
11649 private void rebuildOutline() {
11650 // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
11651 if (mAttachInfo == null) return;
11653 if (mOutlineProvider == null) {
11654 // no provider, remove outline
11655 mRenderNode.setOutline(null);
11657 final Outline outline = mAttachInfo.mTmpOutline;
11658 outline.setEmpty();
11659 outline.setAlpha(1.0f);
11661 mOutlineProvider.getOutline(this, outline);
11662 mRenderNode.setOutline(outline);
11667 * HierarchyViewer only
11671 @ViewDebug.ExportedProperty(category = "drawing")
11672 public boolean hasShadow() {
11673 return mRenderNode.hasShadow();
11678 public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
11679 mRenderNode.setRevealClip(shouldClip, x, y, radius);
11680 invalidateViewProperty(false, false);
11684 * Hit rectangle in parent's coordinates
11686 * @param outRect The hit rectangle of the view.
11688 public void getHitRect(Rect outRect) {
11689 if (hasIdentityMatrix() || mAttachInfo == null) {
11690 outRect.set(mLeft, mTop, mRight, mBottom);
11692 final RectF tmpRect = mAttachInfo.mTmpTransformRect;
11693 tmpRect.set(0, 0, getWidth(), getHeight());
11694 getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
11695 outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
11696 (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
11701 * Determines whether the given point, in local coordinates is inside the view.
11703 /*package*/ final boolean pointInView(float localX, float localY) {
11704 return localX >= 0 && localX < (mRight - mLeft)
11705 && localY >= 0 && localY < (mBottom - mTop);
11709 * Utility method to determine whether the given point, in local coordinates,
11710 * is inside the view, where the area of the view is expanded by the slop factor.
11711 * This method is called while processing touch-move events to determine if the event
11712 * is still within the view.
11716 public boolean pointInView(float localX, float localY, float slop) {
11717 return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
11718 localY < ((mBottom - mTop) + slop);
11722 * When a view has focus and the user navigates away from it, the next view is searched for
11723 * starting from the rectangle filled in by this method.
11725 * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
11726 * of the view. However, if your view maintains some idea of internal selection,
11727 * such as a cursor, or a selected row or column, you should override this method and
11728 * fill in a more specific rectangle.
11730 * @param r The rectangle to fill in, in this view's coordinates.
11732 public void getFocusedRect(Rect r) {
11737 * If some part of this view is not clipped by any of its parents, then
11738 * return that area in r in global (root) coordinates. To convert r to local
11739 * coordinates (without taking possible View rotations into account), offset
11740 * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
11741 * If the view is completely clipped or translated out, return false.
11743 * @param r If true is returned, r holds the global coordinates of the
11744 * visible portion of this view.
11745 * @param globalOffset If true is returned, globalOffset holds the dx,dy
11746 * between this view and its root. globalOffet may be null.
11747 * @return true if r is non-empty (i.e. part of the view is visible at the
11750 public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
11751 int width = mRight - mLeft;
11752 int height = mBottom - mTop;
11753 if (width > 0 && height > 0) {
11754 r.set(0, 0, width, height);
11755 if (globalOffset != null) {
11756 globalOffset.set(-mScrollX, -mScrollY);
11758 return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
11763 public final boolean getGlobalVisibleRect(Rect r) {
11764 return getGlobalVisibleRect(r, null);
11767 public final boolean getLocalVisibleRect(Rect r) {
11768 final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
11769 if (getGlobalVisibleRect(r, offset)) {
11770 r.offset(-offset.x, -offset.y); // make r local
11777 * Offset this view's vertical location by the specified number of pixels.
11779 * @param offset the number of pixels to offset the view by
11781 public void offsetTopAndBottom(int offset) {
11783 final boolean matrixIsIdentity = hasIdentityMatrix();
11784 if (matrixIsIdentity) {
11785 if (isHardwareAccelerated()) {
11786 invalidateViewProperty(false, false);
11788 final ViewParent p = mParent;
11789 if (p != null && mAttachInfo != null) {
11790 final Rect r = mAttachInfo.mTmpInvalRect;
11795 minTop = mTop + offset;
11796 maxBottom = mBottom;
11800 maxBottom = mBottom + offset;
11803 r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
11804 p.invalidateChild(this, r);
11808 invalidateViewProperty(false, false);
11813 mRenderNode.offsetTopAndBottom(offset);
11814 if (isHardwareAccelerated()) {
11815 invalidateViewProperty(false, false);
11817 if (!matrixIsIdentity) {
11818 invalidateViewProperty(false, true);
11820 invalidateParentIfNeeded();
11822 notifySubtreeAccessibilityStateChangedIfNeeded();
11827 * Offset this view's horizontal location by the specified amount of pixels.
11829 * @param offset the number of pixels to offset the view by
11831 public void offsetLeftAndRight(int offset) {
11833 final boolean matrixIsIdentity = hasIdentityMatrix();
11834 if (matrixIsIdentity) {
11835 if (isHardwareAccelerated()) {
11836 invalidateViewProperty(false, false);
11838 final ViewParent p = mParent;
11839 if (p != null && mAttachInfo != null) {
11840 final Rect r = mAttachInfo.mTmpInvalRect;
11844 minLeft = mLeft + offset;
11848 maxRight = mRight + offset;
11850 r.set(0, 0, maxRight - minLeft, mBottom - mTop);
11851 p.invalidateChild(this, r);
11855 invalidateViewProperty(false, false);
11860 mRenderNode.offsetLeftAndRight(offset);
11861 if (isHardwareAccelerated()) {
11862 invalidateViewProperty(false, false);
11864 if (!matrixIsIdentity) {
11865 invalidateViewProperty(false, true);
11867 invalidateParentIfNeeded();
11869 notifySubtreeAccessibilityStateChangedIfNeeded();
11874 * Get the LayoutParams associated with this view. All views should have
11875 * layout parameters. These supply parameters to the <i>parent</i> of this
11876 * view specifying how it should be arranged. There are many subclasses of
11877 * ViewGroup.LayoutParams, and these correspond to the different subclasses
11878 * of ViewGroup that are responsible for arranging their children.
11880 * This method may return null if this View is not attached to a parent
11881 * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
11882 * was not invoked successfully. When a View is attached to a parent
11883 * ViewGroup, this method must not return null.
11885 * @return The LayoutParams associated with this view, or null if no
11886 * parameters have been set yet
11888 @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
11889 public ViewGroup.LayoutParams getLayoutParams() {
11890 return mLayoutParams;
11894 * Set the layout parameters associated with this view. These supply
11895 * parameters to the <i>parent</i> of this view specifying how it should be
11896 * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
11897 * correspond to the different subclasses of ViewGroup that are responsible
11898 * for arranging their children.
11900 * @param params The layout parameters for this view, cannot be null
11902 public void setLayoutParams(ViewGroup.LayoutParams params) {
11903 if (params == null) {
11904 throw new NullPointerException("Layout parameters cannot be null");
11906 mLayoutParams = params;
11907 resolveLayoutParams();
11908 if (mParent instanceof ViewGroup) {
11909 ((ViewGroup) mParent).onSetLayoutParams(this, params);
11915 * Resolve the layout parameters depending on the resolved layout direction
11919 public void resolveLayoutParams() {
11920 if (mLayoutParams != null) {
11921 mLayoutParams.resolveLayoutDirection(getLayoutDirection());
11926 * Set the scrolled position of your view. This will cause a call to
11927 * {@link #onScrollChanged(int, int, int, int)} and the view will be
11929 * @param x the x position to scroll to
11930 * @param y the y position to scroll to
11932 public void scrollTo(int x, int y) {
11933 if (mScrollX != x || mScrollY != y) {
11934 int oldX = mScrollX;
11935 int oldY = mScrollY;
11938 invalidateParentCaches();
11939 onScrollChanged(mScrollX, mScrollY, oldX, oldY);
11940 if (!awakenScrollBars()) {
11941 postInvalidateOnAnimation();
11947 * Move the scrolled position of your view. This will cause a call to
11948 * {@link #onScrollChanged(int, int, int, int)} and the view will be
11950 * @param x the amount of pixels to scroll by horizontally
11951 * @param y the amount of pixels to scroll by vertically
11953 public void scrollBy(int x, int y) {
11954 scrollTo(mScrollX + x, mScrollY + y);
11958 * <p>Trigger the scrollbars to draw. When invoked this method starts an
11959 * animation to fade the scrollbars out after a default delay. If a subclass
11960 * provides animated scrolling, the start delay should equal the duration
11961 * of the scrolling animation.</p>
11963 * <p>The animation starts only if at least one of the scrollbars is
11964 * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
11965 * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11966 * this method returns true, and false otherwise. If the animation is
11967 * started, this method calls {@link #invalidate()}; in that case the
11968 * caller should not call {@link #invalidate()}.</p>
11970 * <p>This method should be invoked every time a subclass directly updates
11971 * the scroll parameters.</p>
11973 * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
11974 * and {@link #scrollTo(int, int)}.</p>
11976 * @return true if the animation is played, false otherwise
11978 * @see #awakenScrollBars(int)
11979 * @see #scrollBy(int, int)
11980 * @see #scrollTo(int, int)
11981 * @see #isHorizontalScrollBarEnabled()
11982 * @see #isVerticalScrollBarEnabled()
11983 * @see #setHorizontalScrollBarEnabled(boolean)
11984 * @see #setVerticalScrollBarEnabled(boolean)
11986 protected boolean awakenScrollBars() {
11987 return mScrollCache != null &&
11988 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
11992 * Trigger the scrollbars to draw.
11993 * This method differs from awakenScrollBars() only in its default duration.
11994 * initialAwakenScrollBars() will show the scroll bars for longer than
11995 * usual to give the user more of a chance to notice them.
11997 * @return true if the animation is played, false otherwise.
11999 private boolean initialAwakenScrollBars() {
12000 return mScrollCache != null &&
12001 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
12006 * Trigger the scrollbars to draw. When invoked this method starts an
12007 * animation to fade the scrollbars out after a fixed delay. If a subclass
12008 * provides animated scrolling, the start delay should equal the duration of
12009 * the scrolling animation.
12013 * The animation starts only if at least one of the scrollbars is enabled,
12014 * as specified by {@link #isHorizontalScrollBarEnabled()} and
12015 * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12016 * this method returns true, and false otherwise. If the animation is
12017 * started, this method calls {@link #invalidate()}; in that case the caller
12018 * should not call {@link #invalidate()}.
12022 * This method should be invoked every time a subclass directly updates the
12023 * scroll parameters.
12026 * @param startDelay the delay, in milliseconds, after which the animation
12027 * should start; when the delay is 0, the animation starts
12029 * @return true if the animation is played, false otherwise
12031 * @see #scrollBy(int, int)
12032 * @see #scrollTo(int, int)
12033 * @see #isHorizontalScrollBarEnabled()
12034 * @see #isVerticalScrollBarEnabled()
12035 * @see #setHorizontalScrollBarEnabled(boolean)
12036 * @see #setVerticalScrollBarEnabled(boolean)
12038 protected boolean awakenScrollBars(int startDelay) {
12039 return awakenScrollBars(startDelay, true);
12044 * Trigger the scrollbars to draw. When invoked this method starts an
12045 * animation to fade the scrollbars out after a fixed delay. If a subclass
12046 * provides animated scrolling, the start delay should equal the duration of
12047 * the scrolling animation.
12051 * The animation starts only if at least one of the scrollbars is enabled,
12052 * as specified by {@link #isHorizontalScrollBarEnabled()} and
12053 * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12054 * this method returns true, and false otherwise. If the animation is
12055 * started, this method calls {@link #invalidate()} if the invalidate parameter
12056 * is set to true; in that case the caller
12057 * should not call {@link #invalidate()}.
12061 * This method should be invoked every time a subclass directly updates the
12062 * scroll parameters.
12065 * @param startDelay the delay, in milliseconds, after which the animation
12066 * should start; when the delay is 0, the animation starts
12069 * @param invalidate Whether this method should call invalidate
12071 * @return true if the animation is played, false otherwise
12073 * @see #scrollBy(int, int)
12074 * @see #scrollTo(int, int)
12075 * @see #isHorizontalScrollBarEnabled()
12076 * @see #isVerticalScrollBarEnabled()
12077 * @see #setHorizontalScrollBarEnabled(boolean)
12078 * @see #setVerticalScrollBarEnabled(boolean)
12080 protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
12081 final ScrollabilityCache scrollCache = mScrollCache;
12083 if (scrollCache == null || !scrollCache.fadeScrollBars) {
12087 if (scrollCache.scrollBar == null) {
12088 scrollCache.scrollBar = new ScrollBarDrawable();
12089 scrollCache.scrollBar.setCallback(this);
12090 scrollCache.scrollBar.setState(getDrawableState());
12093 if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
12096 // Invalidate to show the scrollbars
12097 postInvalidateOnAnimation();
12100 if (scrollCache.state == ScrollabilityCache.OFF) {
12101 // FIXME: this is copied from WindowManagerService.
12102 // We should get this value from the system when it
12103 // is possible to do so.
12104 final int KEY_REPEAT_FIRST_DELAY = 750;
12105 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
12108 // Tell mScrollCache when we should start fading. This may
12109 // extend the fade start time if one was already scheduled
12110 long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
12111 scrollCache.fadeStartTime = fadeStartTime;
12112 scrollCache.state = ScrollabilityCache.ON;
12114 // Schedule our fader to run, unscheduling any old ones first
12115 if (mAttachInfo != null) {
12116 mAttachInfo.mHandler.removeCallbacks(scrollCache);
12117 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
12127 * Do not invalidate views which are not visible and which are not running an animation. They
12128 * will not get drawn and they should not set dirty flags as if they will be drawn
12130 private boolean skipInvalidate() {
12131 return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
12132 (!(mParent instanceof ViewGroup) ||
12133 !((ViewGroup) mParent).isViewTransitioning(this));
12137 * Mark the area defined by dirty as needing to be drawn. If the view is
12138 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12139 * point in the future.
12141 * This must be called from a UI thread. To call from a non-UI thread, call
12142 * {@link #postInvalidate()}.
12144 * <b>WARNING:</b> In API 19 and below, this method may be destructive to
12147 * @param dirty the rectangle representing the bounds of the dirty region
12149 public void invalidate(Rect dirty) {
12150 final int scrollX = mScrollX;
12151 final int scrollY = mScrollY;
12152 invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
12153 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
12157 * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
12158 * coordinates of the dirty rect are relative to the view. If the view is
12159 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12160 * point in the future.
12162 * This must be called from a UI thread. To call from a non-UI thread, call
12163 * {@link #postInvalidate()}.
12165 * @param l the left position of the dirty region
12166 * @param t the top position of the dirty region
12167 * @param r the right position of the dirty region
12168 * @param b the bottom position of the dirty region
12170 public void invalidate(int l, int t, int r, int b) {
12171 final int scrollX = mScrollX;
12172 final int scrollY = mScrollY;
12173 invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
12177 * Invalidate the whole view. If the view is visible,
12178 * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
12181 * This must be called from a UI thread. To call from a non-UI thread, call
12182 * {@link #postInvalidate()}.
12184 public void invalidate() {
12189 * This is where the invalidate() work actually happens. A full invalidate()
12190 * causes the drawing cache to be invalidated, but this function can be
12191 * called with invalidateCache set to false to skip that invalidation step
12192 * for cases that do not need it (for example, a component that remains at
12193 * the same dimensions with the same content).
12195 * @param invalidateCache Whether the drawing cache for this view should be
12196 * invalidated as well. This is usually true for a full
12197 * invalidate, but may be set to false if the View's contents or
12198 * dimensions have not changed.
12200 void invalidate(boolean invalidateCache) {
12201 invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
12204 void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
12205 boolean fullInvalidate) {
12206 if (mGhostView != null) {
12207 mGhostView.invalidate(true);
12211 if (skipInvalidate()) {
12215 if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
12216 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
12217 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
12218 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
12219 if (fullInvalidate) {
12220 mLastIsOpaque = isOpaque();
12221 mPrivateFlags &= ~PFLAG_DRAWN;
12224 mPrivateFlags |= PFLAG_DIRTY;
12226 if (invalidateCache) {
12227 mPrivateFlags |= PFLAG_INVALIDATED;
12228 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12231 // Propagate the damage rectangle to the parent view.
12232 final AttachInfo ai = mAttachInfo;
12233 final ViewParent p = mParent;
12234 if (p != null && ai != null && l < r && t < b) {
12235 final Rect damage = ai.mTmpInvalRect;
12236 damage.set(l, t, r, b);
12237 p.invalidateChild(this, damage);
12240 // Damage the entire projection receiver, if necessary.
12241 if (mBackground != null && mBackground.isProjected()) {
12242 final View receiver = getProjectionReceiver();
12243 if (receiver != null) {
12244 receiver.damageInParent();
12248 // Damage the entire IsolatedZVolume receiving this view's shadow.
12249 if (isHardwareAccelerated() && getZ() != 0) {
12250 damageShadowReceiver();
12256 * @return this view's projection receiver, or {@code null} if none exists
12258 private View getProjectionReceiver() {
12259 ViewParent p = getParent();
12260 while (p != null && p instanceof View) {
12261 final View v = (View) p;
12262 if (v.isProjectionReceiver()) {
12272 * @return whether the view is a projection receiver
12274 private boolean isProjectionReceiver() {
12275 return mBackground != null;
12279 * Damage area of the screen that can be covered by this View's shadow.
12281 * This method will guarantee that any changes to shadows cast by a View
12282 * are damaged on the screen for future redraw.
12284 private void damageShadowReceiver() {
12285 final AttachInfo ai = mAttachInfo;
12287 ViewParent p = getParent();
12288 if (p != null && p instanceof ViewGroup) {
12289 final ViewGroup vg = (ViewGroup) p;
12290 vg.damageInParent();
12296 * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
12297 * set any flags or handle all of the cases handled by the default invalidation methods.
12298 * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
12299 * dirty rect. This method calls into fast invalidation methods in ViewGroup that
12300 * walk up the hierarchy, transforming the dirty rect as necessary.
12302 * The method also handles normal invalidation logic if display list properties are not
12303 * being used in this view. The invalidateParent and forceRedraw flags are used by that
12304 * backup approach, to handle these cases used in the various property-setting methods.
12306 * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
12307 * are not being used in this view
12308 * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
12309 * list properties are not being used in this view
12311 void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
12312 if (!isHardwareAccelerated()
12313 || !mRenderNode.isValid()
12314 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
12315 if (invalidateParent) {
12316 invalidateParentCaches();
12319 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12325 if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
12326 damageShadowReceiver();
12331 * Tells the parent view to damage this view's bounds.
12335 protected void damageInParent() {
12336 final AttachInfo ai = mAttachInfo;
12337 final ViewParent p = mParent;
12338 if (p != null && ai != null) {
12339 final Rect r = ai.mTmpInvalRect;
12340 r.set(0, 0, mRight - mLeft, mBottom - mTop);
12341 if (mParent instanceof ViewGroup) {
12342 ((ViewGroup) mParent).damageChild(this, r);
12344 mParent.invalidateChild(this, r);
12350 * Utility method to transform a given Rect by the current matrix of this view.
12352 void transformRect(final Rect rect) {
12353 if (!getMatrix().isIdentity()) {
12354 RectF boundingRect = mAttachInfo.mTmpTransformRect;
12355 boundingRect.set(rect);
12356 getMatrix().mapRect(boundingRect);
12357 rect.set((int) Math.floor(boundingRect.left),
12358 (int) Math.floor(boundingRect.top),
12359 (int) Math.ceil(boundingRect.right),
12360 (int) Math.ceil(boundingRect.bottom));
12365 * Used to indicate that the parent of this view should clear its caches. This functionality
12366 * is used to force the parent to rebuild its display list (when hardware-accelerated),
12367 * which is necessary when various parent-managed properties of the view change, such as
12368 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
12369 * clears the parent caches and does not causes an invalidate event.
12373 protected void invalidateParentCaches() {
12374 if (mParent instanceof View) {
12375 ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
12380 * Used to indicate that the parent of this view should be invalidated. This functionality
12381 * is used to force the parent to rebuild its display list (when hardware-accelerated),
12382 * which is necessary when various parent-managed properties of the view change, such as
12383 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
12384 * an invalidation event to the parent.
12388 protected void invalidateParentIfNeeded() {
12389 if (isHardwareAccelerated() && mParent instanceof View) {
12390 ((View) mParent).invalidate(true);
12397 protected void invalidateParentIfNeededAndWasQuickRejected() {
12398 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
12399 // View was rejected last time it was drawn by its parent; this may have changed
12400 invalidateParentIfNeeded();
12405 * Indicates whether this View is opaque. An opaque View guarantees that it will
12406 * draw all the pixels overlapping its bounds using a fully opaque color.
12408 * Subclasses of View should override this method whenever possible to indicate
12409 * whether an instance is opaque. Opaque Views are treated in a special way by
12410 * the View hierarchy, possibly allowing it to perform optimizations during
12411 * invalidate/draw passes.
12413 * @return True if this View is guaranteed to be fully opaque, false otherwise.
12415 @ViewDebug.ExportedProperty(category = "drawing")
12416 public boolean isOpaque() {
12417 return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
12418 getFinalAlpha() >= 1.0f;
12424 protected void computeOpaqueFlags() {
12426 // - Has a background
12427 // - Background is opaque
12428 // - Doesn't have scrollbars or scrollbars overlay
12430 if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
12431 mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
12433 mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
12436 final int flags = mViewFlags;
12437 if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
12438 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
12439 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
12440 mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
12442 mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
12449 protected boolean hasOpaqueScrollbars() {
12450 return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
12454 * @return A handler associated with the thread running the View. This
12455 * handler can be used to pump events in the UI events queue.
12457 public Handler getHandler() {
12458 final AttachInfo attachInfo = mAttachInfo;
12459 if (attachInfo != null) {
12460 return attachInfo.mHandler;
12466 * Gets the view root associated with the View.
12467 * @return The view root, or null if none.
12470 public ViewRootImpl getViewRootImpl() {
12471 if (mAttachInfo != null) {
12472 return mAttachInfo.mViewRootImpl;
12480 public HardwareRenderer getHardwareRenderer() {
12481 return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
12485 * <p>Causes the Runnable to be added to the message queue.
12486 * The runnable will be run on the user interface thread.</p>
12488 * @param action The Runnable that will be executed.
12490 * @return Returns true if the Runnable was successfully placed in to the
12491 * message queue. Returns false on failure, usually because the
12492 * looper processing the message queue is exiting.
12494 * @see #postDelayed
12495 * @see #removeCallbacks
12497 public boolean post(Runnable action) {
12498 final AttachInfo attachInfo = mAttachInfo;
12499 if (attachInfo != null) {
12500 return attachInfo.mHandler.post(action);
12502 // Assume that post will succeed later
12503 ViewRootImpl.getRunQueue().post(action);
12508 * <p>Causes the Runnable to be added to the message queue, to be run
12509 * after the specified amount of time elapses.
12510 * The runnable will be run on the user interface thread.</p>
12512 * @param action The Runnable that will be executed.
12513 * @param delayMillis The delay (in milliseconds) until the Runnable
12514 * will be executed.
12516 * @return true if the Runnable was successfully placed in to the
12517 * message queue. Returns false on failure, usually because the
12518 * looper processing the message queue is exiting. Note that a
12519 * result of true does not mean the Runnable will be processed --
12520 * if the looper is quit before the delivery time of the message
12521 * occurs then the message will be dropped.
12524 * @see #removeCallbacks
12526 public boolean postDelayed(Runnable action, long delayMillis) {
12527 final AttachInfo attachInfo = mAttachInfo;
12528 if (attachInfo != null) {
12529 return attachInfo.mHandler.postDelayed(action, delayMillis);
12531 // Assume that post will succeed later
12532 ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
12537 * <p>Causes the Runnable to execute on the next animation time step.
12538 * The runnable will be run on the user interface thread.</p>
12540 * @param action The Runnable that will be executed.
12542 * @see #postOnAnimationDelayed
12543 * @see #removeCallbacks
12545 public void postOnAnimation(Runnable action) {
12546 final AttachInfo attachInfo = mAttachInfo;
12547 if (attachInfo != null) {
12548 attachInfo.mViewRootImpl.mChoreographer.postCallback(
12549 Choreographer.CALLBACK_ANIMATION, action, null);
12551 // Assume that post will succeed later
12552 ViewRootImpl.getRunQueue().post(action);
12557 * <p>Causes the Runnable to execute on the next animation time step,
12558 * after the specified amount of time elapses.
12559 * The runnable will be run on the user interface thread.</p>
12561 * @param action The Runnable that will be executed.
12562 * @param delayMillis The delay (in milliseconds) until the Runnable
12563 * will be executed.
12565 * @see #postOnAnimation
12566 * @see #removeCallbacks
12568 public void postOnAnimationDelayed(Runnable action, long delayMillis) {
12569 final AttachInfo attachInfo = mAttachInfo;
12570 if (attachInfo != null) {
12571 attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
12572 Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
12574 // Assume that post will succeed later
12575 ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
12580 * <p>Removes the specified Runnable from the message queue.</p>
12582 * @param action The Runnable to remove from the message handling queue
12584 * @return true if this view could ask the Handler to remove the Runnable,
12585 * false otherwise. When the returned value is true, the Runnable
12586 * may or may not have been actually removed from the message queue
12587 * (for instance, if the Runnable was not in the queue already.)
12590 * @see #postDelayed
12591 * @see #postOnAnimation
12592 * @see #postOnAnimationDelayed
12594 public boolean removeCallbacks(Runnable action) {
12595 if (action != null) {
12596 final AttachInfo attachInfo = mAttachInfo;
12597 if (attachInfo != null) {
12598 attachInfo.mHandler.removeCallbacks(action);
12599 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
12600 Choreographer.CALLBACK_ANIMATION, action, null);
12602 // Assume that post will succeed later
12603 ViewRootImpl.getRunQueue().removeCallbacks(action);
12609 * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
12610 * Use this to invalidate the View from a non-UI thread.</p>
12612 * <p>This method can be invoked from outside of the UI thread
12613 * only when this View is attached to a window.</p>
12615 * @see #invalidate()
12616 * @see #postInvalidateDelayed(long)
12618 public void postInvalidate() {
12619 postInvalidateDelayed(0);
12623 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
12624 * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
12626 * <p>This method can be invoked from outside of the UI thread
12627 * only when this View is attached to a window.</p>
12629 * @param left The left coordinate of the rectangle to invalidate.
12630 * @param top The top coordinate of the rectangle to invalidate.
12631 * @param right The right coordinate of the rectangle to invalidate.
12632 * @param bottom The bottom coordinate of the rectangle to invalidate.
12634 * @see #invalidate(int, int, int, int)
12635 * @see #invalidate(Rect)
12636 * @see #postInvalidateDelayed(long, int, int, int, int)
12638 public void postInvalidate(int left, int top, int right, int bottom) {
12639 postInvalidateDelayed(0, left, top, right, bottom);
12643 * <p>Cause an invalidate to happen on a subsequent cycle through the event
12644 * loop. Waits for the specified amount of time.</p>
12646 * <p>This method can be invoked from outside of the UI thread
12647 * only when this View is attached to a window.</p>
12649 * @param delayMilliseconds the duration in milliseconds to delay the
12652 * @see #invalidate()
12653 * @see #postInvalidate()
12655 public void postInvalidateDelayed(long delayMilliseconds) {
12656 // We try only with the AttachInfo because there's no point in invalidating
12657 // if we are not attached to our window
12658 final AttachInfo attachInfo = mAttachInfo;
12659 if (attachInfo != null) {
12660 attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
12665 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
12666 * through the event loop. Waits for the specified amount of time.</p>
12668 * <p>This method can be invoked from outside of the UI thread
12669 * only when this View is attached to a window.</p>
12671 * @param delayMilliseconds the duration in milliseconds to delay the
12673 * @param left The left coordinate of the rectangle to invalidate.
12674 * @param top The top coordinate of the rectangle to invalidate.
12675 * @param right The right coordinate of the rectangle to invalidate.
12676 * @param bottom The bottom coordinate of the rectangle to invalidate.
12678 * @see #invalidate(int, int, int, int)
12679 * @see #invalidate(Rect)
12680 * @see #postInvalidate(int, int, int, int)
12682 public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
12683 int right, int bottom) {
12685 // We try only with the AttachInfo because there's no point in invalidating
12686 // if we are not attached to our window
12687 final AttachInfo attachInfo = mAttachInfo;
12688 if (attachInfo != null) {
12689 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
12690 info.target = this;
12693 info.right = right;
12694 info.bottom = bottom;
12696 attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
12701 * <p>Cause an invalidate to happen on the next animation time step, typically the
12702 * next display frame.</p>
12704 * <p>This method can be invoked from outside of the UI thread
12705 * only when this View is attached to a window.</p>
12707 * @see #invalidate()
12709 public void postInvalidateOnAnimation() {
12710 // We try only with the AttachInfo because there's no point in invalidating
12711 // if we are not attached to our window
12712 final AttachInfo attachInfo = mAttachInfo;
12713 if (attachInfo != null) {
12714 attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
12719 * <p>Cause an invalidate of the specified area to happen on the next animation
12720 * time step, typically the next display frame.</p>
12722 * <p>This method can be invoked from outside of the UI thread
12723 * only when this View is attached to a window.</p>
12725 * @param left The left coordinate of the rectangle to invalidate.
12726 * @param top The top coordinate of the rectangle to invalidate.
12727 * @param right The right coordinate of the rectangle to invalidate.
12728 * @param bottom The bottom coordinate of the rectangle to invalidate.
12730 * @see #invalidate(int, int, int, int)
12731 * @see #invalidate(Rect)
12733 public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
12734 // We try only with the AttachInfo because there's no point in invalidating
12735 // if we are not attached to our window
12736 final AttachInfo attachInfo = mAttachInfo;
12737 if (attachInfo != null) {
12738 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
12739 info.target = this;
12742 info.right = right;
12743 info.bottom = bottom;
12745 attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
12750 * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
12751 * This event is sent at most once every
12752 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
12754 private void postSendViewScrolledAccessibilityEventCallback() {
12755 if (mSendViewScrolledAccessibilityEvent == null) {
12756 mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
12758 if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
12759 mSendViewScrolledAccessibilityEvent.mIsPending = true;
12760 postDelayed(mSendViewScrolledAccessibilityEvent,
12761 ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
12766 * Called by a parent to request that a child update its values for mScrollX
12767 * and mScrollY if necessary. This will typically be done if the child is
12768 * animating a scroll using a {@link android.widget.Scroller Scroller}
12771 public void computeScroll() {
12775 * <p>Indicate whether the horizontal edges are faded when the view is
12776 * scrolled horizontally.</p>
12778 * @return true if the horizontal edges should are faded on scroll, false
12781 * @see #setHorizontalFadingEdgeEnabled(boolean)
12783 * @attr ref android.R.styleable#View_requiresFadingEdge
12785 public boolean isHorizontalFadingEdgeEnabled() {
12786 return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
12790 * <p>Define whether the horizontal edges should be faded when this view
12791 * is scrolled horizontally.</p>
12793 * @param horizontalFadingEdgeEnabled true if the horizontal edges should
12794 * be faded when the view is scrolled
12797 * @see #isHorizontalFadingEdgeEnabled()
12799 * @attr ref android.R.styleable#View_requiresFadingEdge
12801 public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
12802 if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
12803 if (horizontalFadingEdgeEnabled) {
12807 mViewFlags ^= FADING_EDGE_HORIZONTAL;
12812 * <p>Indicate whether the vertical edges are faded when the view is
12813 * scrolled horizontally.</p>
12815 * @return true if the vertical edges should are faded on scroll, false
12818 * @see #setVerticalFadingEdgeEnabled(boolean)
12820 * @attr ref android.R.styleable#View_requiresFadingEdge
12822 public boolean isVerticalFadingEdgeEnabled() {
12823 return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
12827 * <p>Define whether the vertical edges should be faded when this view
12828 * is scrolled vertically.</p>
12830 * @param verticalFadingEdgeEnabled true if the vertical edges should
12831 * be faded when the view is scrolled
12834 * @see #isVerticalFadingEdgeEnabled()
12836 * @attr ref android.R.styleable#View_requiresFadingEdge
12838 public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
12839 if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
12840 if (verticalFadingEdgeEnabled) {
12844 mViewFlags ^= FADING_EDGE_VERTICAL;
12849 * Returns the strength, or intensity, of the top faded edge. The strength is
12850 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12851 * returns 0.0 or 1.0 but no value in between.
12853 * Subclasses should override this method to provide a smoother fade transition
12854 * when scrolling occurs.
12856 * @return the intensity of the top fade as a float between 0.0f and 1.0f
12858 protected float getTopFadingEdgeStrength() {
12859 return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
12863 * Returns the strength, or intensity, of the bottom faded edge. The strength is
12864 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12865 * returns 0.0 or 1.0 but no value in between.
12867 * Subclasses should override this method to provide a smoother fade transition
12868 * when scrolling occurs.
12870 * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
12872 protected float getBottomFadingEdgeStrength() {
12873 return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
12874 computeVerticalScrollRange() ? 1.0f : 0.0f;
12878 * Returns the strength, or intensity, of the left faded edge. The strength is
12879 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12880 * returns 0.0 or 1.0 but no value in between.
12882 * Subclasses should override this method to provide a smoother fade transition
12883 * when scrolling occurs.
12885 * @return the intensity of the left fade as a float between 0.0f and 1.0f
12887 protected float getLeftFadingEdgeStrength() {
12888 return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
12892 * Returns the strength, or intensity, of the right faded edge. The strength is
12893 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12894 * returns 0.0 or 1.0 but no value in between.
12896 * Subclasses should override this method to provide a smoother fade transition
12897 * when scrolling occurs.
12899 * @return the intensity of the right fade as a float between 0.0f and 1.0f
12901 protected float getRightFadingEdgeStrength() {
12902 return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
12903 computeHorizontalScrollRange() ? 1.0f : 0.0f;
12907 * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
12908 * scrollbar is not drawn by default.</p>
12910 * @return true if the horizontal scrollbar should be painted, false
12913 * @see #setHorizontalScrollBarEnabled(boolean)
12915 public boolean isHorizontalScrollBarEnabled() {
12916 return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
12920 * <p>Define whether the horizontal scrollbar should be drawn or not. The
12921 * scrollbar is not drawn by default.</p>
12923 * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
12926 * @see #isHorizontalScrollBarEnabled()
12928 public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
12929 if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
12930 mViewFlags ^= SCROLLBARS_HORIZONTAL;
12931 computeOpaqueFlags();
12937 * <p>Indicate whether the vertical scrollbar should be drawn or not. The
12938 * scrollbar is not drawn by default.</p>
12940 * @return true if the vertical scrollbar should be painted, false
12943 * @see #setVerticalScrollBarEnabled(boolean)
12945 public boolean isVerticalScrollBarEnabled() {
12946 return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
12950 * <p>Define whether the vertical scrollbar should be drawn or not. The
12951 * scrollbar is not drawn by default.</p>
12953 * @param verticalScrollBarEnabled true if the vertical scrollbar should
12956 * @see #isVerticalScrollBarEnabled()
12958 public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
12959 if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
12960 mViewFlags ^= SCROLLBARS_VERTICAL;
12961 computeOpaqueFlags();
12969 protected void recomputePadding() {
12970 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
12974 * Define whether scrollbars will fade when the view is not scrolling.
12976 * @param fadeScrollbars whether to enable fading
12978 * @attr ref android.R.styleable#View_fadeScrollbars
12980 public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
12982 final ScrollabilityCache scrollabilityCache = mScrollCache;
12983 scrollabilityCache.fadeScrollBars = fadeScrollbars;
12984 if (fadeScrollbars) {
12985 scrollabilityCache.state = ScrollabilityCache.OFF;
12987 scrollabilityCache.state = ScrollabilityCache.ON;
12993 * Returns true if scrollbars will fade when this view is not scrolling
12995 * @return true if scrollbar fading is enabled
12997 * @attr ref android.R.styleable#View_fadeScrollbars
12999 public boolean isScrollbarFadingEnabled() {
13000 return mScrollCache != null && mScrollCache.fadeScrollBars;
13005 * Returns the delay before scrollbars fade.
13007 * @return the delay before scrollbars fade
13009 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13011 public int getScrollBarDefaultDelayBeforeFade() {
13012 return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
13013 mScrollCache.scrollBarDefaultDelayBeforeFade;
13017 * Define the delay before scrollbars fade.
13019 * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
13021 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13023 public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
13024 getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
13029 * Returns the scrollbar fade duration.
13031 * @return the scrollbar fade duration
13033 * @attr ref android.R.styleable#View_scrollbarFadeDuration
13035 public int getScrollBarFadeDuration() {
13036 return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
13037 mScrollCache.scrollBarFadeDuration;
13041 * Define the scrollbar fade duration.
13043 * @param scrollBarFadeDuration - the scrollbar fade duration
13045 * @attr ref android.R.styleable#View_scrollbarFadeDuration
13047 public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
13048 getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
13053 * Returns the scrollbar size.
13055 * @return the scrollbar size
13057 * @attr ref android.R.styleable#View_scrollbarSize
13059 public int getScrollBarSize() {
13060 return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
13061 mScrollCache.scrollBarSize;
13065 * Define the scrollbar size.
13067 * @param scrollBarSize - the scrollbar size
13069 * @attr ref android.R.styleable#View_scrollbarSize
13071 public void setScrollBarSize(int scrollBarSize) {
13072 getScrollCache().scrollBarSize = scrollBarSize;
13076 * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
13077 * inset. When inset, they add to the padding of the view. And the scrollbars
13078 * can be drawn inside the padding area or on the edge of the view. For example,
13079 * if a view has a background drawable and you want to draw the scrollbars
13080 * inside the padding specified by the drawable, you can use
13081 * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
13082 * appear at the edge of the view, ignoring the padding, then you can use
13083 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
13084 * @param style the style of the scrollbars. Should be one of
13085 * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
13086 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
13087 * @see #SCROLLBARS_INSIDE_OVERLAY
13088 * @see #SCROLLBARS_INSIDE_INSET
13089 * @see #SCROLLBARS_OUTSIDE_OVERLAY
13090 * @see #SCROLLBARS_OUTSIDE_INSET
13092 * @attr ref android.R.styleable#View_scrollbarStyle
13094 public void setScrollBarStyle(@ScrollBarStyle int style) {
13095 if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
13096 mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
13097 computeOpaqueFlags();
13103 * <p>Returns the current scrollbar style.</p>
13104 * @return the current scrollbar style
13105 * @see #SCROLLBARS_INSIDE_OVERLAY
13106 * @see #SCROLLBARS_INSIDE_INSET
13107 * @see #SCROLLBARS_OUTSIDE_OVERLAY
13108 * @see #SCROLLBARS_OUTSIDE_INSET
13110 * @attr ref android.R.styleable#View_scrollbarStyle
13112 @ViewDebug.ExportedProperty(mapping = {
13113 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
13114 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
13115 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
13116 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
13119 public int getScrollBarStyle() {
13120 return mViewFlags & SCROLLBARS_STYLE_MASK;
13124 * <p>Compute the horizontal range that the horizontal scrollbar
13127 * <p>The range is expressed in arbitrary units that must be the same as the
13128 * units used by {@link #computeHorizontalScrollExtent()} and
13129 * {@link #computeHorizontalScrollOffset()}.</p>
13131 * <p>The default range is the drawing width of this view.</p>
13133 * @return the total horizontal range represented by the horizontal
13136 * @see #computeHorizontalScrollExtent()
13137 * @see #computeHorizontalScrollOffset()
13138 * @see android.widget.ScrollBarDrawable
13140 protected int computeHorizontalScrollRange() {
13145 * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
13146 * within the horizontal range. This value is used to compute the position
13147 * of the thumb within the scrollbar's track.</p>
13149 * <p>The range is expressed in arbitrary units that must be the same as the
13150 * units used by {@link #computeHorizontalScrollRange()} and
13151 * {@link #computeHorizontalScrollExtent()}.</p>
13153 * <p>The default offset is the scroll offset of this view.</p>
13155 * @return the horizontal offset of the scrollbar's thumb
13157 * @see #computeHorizontalScrollRange()
13158 * @see #computeHorizontalScrollExtent()
13159 * @see android.widget.ScrollBarDrawable
13161 protected int computeHorizontalScrollOffset() {
13166 * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
13167 * within the horizontal range. This value is used to compute the length
13168 * of the thumb within the scrollbar's track.</p>
13170 * <p>The range is expressed in arbitrary units that must be the same as the
13171 * units used by {@link #computeHorizontalScrollRange()} and
13172 * {@link #computeHorizontalScrollOffset()}.</p>
13174 * <p>The default extent is the drawing width of this view.</p>
13176 * @return the horizontal extent of the scrollbar's thumb
13178 * @see #computeHorizontalScrollRange()
13179 * @see #computeHorizontalScrollOffset()
13180 * @see android.widget.ScrollBarDrawable
13182 protected int computeHorizontalScrollExtent() {
13187 * <p>Compute the vertical range that the vertical scrollbar represents.</p>
13189 * <p>The range is expressed in arbitrary units that must be the same as the
13190 * units used by {@link #computeVerticalScrollExtent()} and
13191 * {@link #computeVerticalScrollOffset()}.</p>
13193 * @return the total vertical range represented by the vertical scrollbar
13195 * <p>The default range is the drawing height of this view.</p>
13197 * @see #computeVerticalScrollExtent()
13198 * @see #computeVerticalScrollOffset()
13199 * @see android.widget.ScrollBarDrawable
13201 protected int computeVerticalScrollRange() {
13202 return getHeight();
13206 * <p>Compute the vertical offset of the vertical scrollbar's thumb
13207 * within the horizontal range. This value is used to compute the position
13208 * of the thumb within the scrollbar's track.</p>
13210 * <p>The range is expressed in arbitrary units that must be the same as the
13211 * units used by {@link #computeVerticalScrollRange()} and
13212 * {@link #computeVerticalScrollExtent()}.</p>
13214 * <p>The default offset is the scroll offset of this view.</p>
13216 * @return the vertical offset of the scrollbar's thumb
13218 * @see #computeVerticalScrollRange()
13219 * @see #computeVerticalScrollExtent()
13220 * @see android.widget.ScrollBarDrawable
13222 protected int computeVerticalScrollOffset() {
13227 * <p>Compute the vertical extent of the vertical scrollbar's thumb
13228 * within the vertical range. This value is used to compute the length
13229 * of the thumb within the scrollbar's track.</p>
13231 * <p>The range is expressed in arbitrary units that must be the same as the
13232 * units used by {@link #computeVerticalScrollRange()} and
13233 * {@link #computeVerticalScrollOffset()}.</p>
13235 * <p>The default extent is the drawing height of this view.</p>
13237 * @return the vertical extent of the scrollbar's thumb
13239 * @see #computeVerticalScrollRange()
13240 * @see #computeVerticalScrollOffset()
13241 * @see android.widget.ScrollBarDrawable
13243 protected int computeVerticalScrollExtent() {
13244 return getHeight();
13248 * Check if this view can be scrolled horizontally in a certain direction.
13250 * @param direction Negative to check scrolling left, positive to check scrolling right.
13251 * @return true if this view can be scrolled in the specified direction, false otherwise.
13253 public boolean canScrollHorizontally(int direction) {
13254 final int offset = computeHorizontalScrollOffset();
13255 final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
13256 if (range == 0) return false;
13257 if (direction < 0) {
13260 return offset < range - 1;
13265 * Check if this view can be scrolled vertically in a certain direction.
13267 * @param direction Negative to check scrolling up, positive to check scrolling down.
13268 * @return true if this view can be scrolled in the specified direction, false otherwise.
13270 public boolean canScrollVertically(int direction) {
13271 final int offset = computeVerticalScrollOffset();
13272 final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
13273 if (range == 0) return false;
13274 if (direction < 0) {
13277 return offset < range - 1;
13282 * <p>Request the drawing of the horizontal and the vertical scrollbar. The
13283 * scrollbars are painted only if they have been awakened first.</p>
13285 * @param canvas the canvas on which to draw the scrollbars
13287 * @see #awakenScrollBars(int)
13289 protected final void onDrawScrollBars(Canvas canvas) {
13290 // scrollbars are drawn only when the animation is running
13291 final ScrollabilityCache cache = mScrollCache;
13292 if (cache != null) {
13294 int state = cache.state;
13296 if (state == ScrollabilityCache.OFF) {
13300 boolean invalidate = false;
13302 if (state == ScrollabilityCache.FADING) {
13303 // We're fading -- get our fade interpolation
13304 if (cache.interpolatorValues == null) {
13305 cache.interpolatorValues = new float[1];
13308 float[] values = cache.interpolatorValues;
13310 // Stops the animation if we're done
13311 if (cache.scrollBarInterpolator.timeToValues(values) ==
13312 Interpolator.Result.FREEZE_END) {
13313 cache.state = ScrollabilityCache.OFF;
13315 cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
13318 // This will make the scroll bars inval themselves after
13319 // drawing. We only want this when we're fading so that
13320 // we prevent excessive redraws
13323 // We're just on -- but we may have been fading before so
13325 cache.scrollBar.mutate().setAlpha(255);
13329 final int viewFlags = mViewFlags;
13331 final boolean drawHorizontalScrollBar =
13332 (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
13333 final boolean drawVerticalScrollBar =
13334 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
13335 && !isVerticalScrollBarHidden();
13337 if (drawVerticalScrollBar || drawHorizontalScrollBar) {
13338 final int width = mRight - mLeft;
13339 final int height = mBottom - mTop;
13341 final ScrollBarDrawable scrollBar = cache.scrollBar;
13343 final int scrollX = mScrollX;
13344 final int scrollY = mScrollY;
13345 final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
13352 if (drawHorizontalScrollBar) {
13353 int size = scrollBar.getSize(false);
13355 size = cache.scrollBarSize;
13358 scrollBar.setParameters(computeHorizontalScrollRange(),
13359 computeHorizontalScrollOffset(),
13360 computeHorizontalScrollExtent(), false);
13361 final int verticalScrollBarGap = drawVerticalScrollBar ?
13362 getVerticalScrollbarWidth() : 0;
13363 top = scrollY + height - size - (mUserPaddingBottom & inside);
13364 left = scrollX + (mPaddingLeft & inside);
13365 right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
13366 bottom = top + size;
13367 onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
13369 invalidate(left, top, right, bottom);
13373 if (drawVerticalScrollBar) {
13374 int size = scrollBar.getSize(true);
13376 size = cache.scrollBarSize;
13379 scrollBar.setParameters(computeVerticalScrollRange(),
13380 computeVerticalScrollOffset(),
13381 computeVerticalScrollExtent(), true);
13382 int verticalScrollbarPosition = mVerticalScrollbarPosition;
13383 if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
13384 verticalScrollbarPosition = isLayoutRtl() ?
13385 SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
13387 switch (verticalScrollbarPosition) {
13389 case SCROLLBAR_POSITION_RIGHT:
13390 left = scrollX + width - size - (mUserPaddingRight & inside);
13392 case SCROLLBAR_POSITION_LEFT:
13393 left = scrollX + (mUserPaddingLeft & inside);
13396 top = scrollY + (mPaddingTop & inside);
13397 right = left + size;
13398 bottom = scrollY + height - (mUserPaddingBottom & inside);
13399 onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
13401 invalidate(left, top, right, bottom);
13409 * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
13410 * FastScroller is visible.
13411 * @return whether to temporarily hide the vertical scrollbar
13414 protected boolean isVerticalScrollBarHidden() {
13419 * <p>Draw the horizontal scrollbar if
13420 * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
13422 * @param canvas the canvas on which to draw the scrollbar
13423 * @param scrollBar the scrollbar's drawable
13425 * @see #isHorizontalScrollBarEnabled()
13426 * @see #computeHorizontalScrollRange()
13427 * @see #computeHorizontalScrollExtent()
13428 * @see #computeHorizontalScrollOffset()
13429 * @see android.widget.ScrollBarDrawable
13432 protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
13433 int l, int t, int r, int b) {
13434 scrollBar.setBounds(l, t, r, b);
13435 scrollBar.draw(canvas);
13439 * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
13440 * returns true.</p>
13442 * @param canvas the canvas on which to draw the scrollbar
13443 * @param scrollBar the scrollbar's drawable
13445 * @see #isVerticalScrollBarEnabled()
13446 * @see #computeVerticalScrollRange()
13447 * @see #computeVerticalScrollExtent()
13448 * @see #computeVerticalScrollOffset()
13449 * @see android.widget.ScrollBarDrawable
13452 protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
13453 int l, int t, int r, int b) {
13454 scrollBar.setBounds(l, t, r, b);
13455 scrollBar.draw(canvas);
13459 * Implement this to do your drawing.
13461 * @param canvas the canvas on which the background will be drawn
13463 protected void onDraw(Canvas canvas) {
13467 * Caller is responsible for calling requestLayout if necessary.
13468 * (This allows addViewInLayout to not request a new layout.)
13470 void assignParent(ViewParent parent) {
13471 if (mParent == null) {
13473 } else if (parent == null) {
13476 throw new RuntimeException("view " + this + " being added, but"
13477 + " it already has a parent");
13482 * This is called when the view is attached to a window. At this point it
13483 * has a Surface and will start drawing. Note that this function is
13484 * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
13485 * however it may be called any time before the first onDraw -- including
13486 * before or after {@link #onMeasure(int, int)}.
13488 * @see #onDetachedFromWindow()
13491 protected void onAttachedToWindow() {
13492 if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
13493 mParent.requestTransparentRegion(this);
13496 if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
13497 initialAwakenScrollBars();
13498 mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
13501 mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
13503 jumpDrawablesToCurrentState();
13505 resetSubtreeAccessibilityStateChanged();
13507 // rebuild, since Outline not maintained while View is detached
13511 InputMethodManager imm = InputMethodManager.peekInstance();
13519 * Resolve all RTL related properties.
13521 * @return true if resolution of RTL properties has been done
13525 public boolean resolveRtlPropertiesIfNeeded() {
13526 if (!needRtlPropertiesResolution()) return false;
13528 // Order is important here: LayoutDirection MUST be resolved first
13529 if (!isLayoutDirectionResolved()) {
13530 resolveLayoutDirection();
13531 resolveLayoutParams();
13533 // ... then we can resolve the others properties depending on the resolved LayoutDirection.
13534 if (!isTextDirectionResolved()) {
13535 resolveTextDirection();
13537 if (!isTextAlignmentResolved()) {
13538 resolveTextAlignment();
13540 // Should resolve Drawables before Padding because we need the layout direction of the
13541 // Drawable to correctly resolve Padding.
13542 if (!areDrawablesResolved()) {
13543 resolveDrawables();
13545 if (!isPaddingResolved()) {
13548 onRtlPropertiesChanged(getLayoutDirection());
13553 * Reset resolution of all RTL related properties.
13557 public void resetRtlProperties() {
13558 resetResolvedLayoutDirection();
13559 resetResolvedTextDirection();
13560 resetResolvedTextAlignment();
13561 resetResolvedPadding();
13562 resetResolvedDrawables();
13566 * @see #onScreenStateChanged(int)
13568 void dispatchScreenStateChanged(int screenState) {
13569 onScreenStateChanged(screenState);
13573 * This method is called whenever the state of the screen this view is
13574 * attached to changes. A state change will usually occurs when the screen
13575 * turns on or off (whether it happens automatically or the user does it
13578 * @param screenState The new state of the screen. Can be either
13579 * {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
13581 public void onScreenStateChanged(int screenState) {
13585 * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
13587 private boolean hasRtlSupport() {
13588 return mContext.getApplicationInfo().hasRtlSupport();
13592 * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
13593 * RTL not supported)
13595 private boolean isRtlCompatibilityMode() {
13596 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
13597 return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
13601 * @return true if RTL properties need resolution.
13604 private boolean needRtlPropertiesResolution() {
13605 return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
13609 * Called when any RTL property (layout direction or text direction or text alignment) has
13612 * Subclasses need to override this method to take care of cached information that depends on the
13613 * resolved layout direction, or to inform child views that inherit their layout direction.
13615 * The default implementation does nothing.
13617 * @param layoutDirection the direction of the layout
13619 * @see #LAYOUT_DIRECTION_LTR
13620 * @see #LAYOUT_DIRECTION_RTL
13622 public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
13626 * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
13627 * that the parent directionality can and will be resolved before its children.
13629 * @return true if resolution has been done, false otherwise.
13633 public boolean resolveLayoutDirection() {
13634 // Clear any previous layout direction resolution
13635 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
13637 if (hasRtlSupport()) {
13638 // Set resolved depending on layout direction
13639 switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
13640 PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
13641 case LAYOUT_DIRECTION_INHERIT:
13642 // We cannot resolve yet. LTR is by default and let the resolution happen again
13643 // later to get the correct resolved value
13644 if (!canResolveLayoutDirection()) return false;
13646 // Parent has not yet resolved, LTR is still the default
13648 if (!mParent.isLayoutDirectionResolved()) return false;
13650 if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
13651 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13653 } catch (AbstractMethodError e) {
13654 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13655 " does not fully implement ViewParent", e);
13658 case LAYOUT_DIRECTION_RTL:
13659 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13661 case LAYOUT_DIRECTION_LOCALE:
13662 if((LAYOUT_DIRECTION_RTL ==
13663 TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
13664 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13668 // Nothing to do, LTR by default
13673 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
13678 * Check if layout direction resolution can be done.
13680 * @return true if layout direction resolution can be done otherwise return false.
13682 public boolean canResolveLayoutDirection() {
13683 switch (getRawLayoutDirection()) {
13684 case LAYOUT_DIRECTION_INHERIT:
13685 if (mParent != null) {
13687 return mParent.canResolveLayoutDirection();
13688 } catch (AbstractMethodError e) {
13689 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13690 " does not fully implement ViewParent", e);
13701 * Reset the resolved layout direction. Layout direction will be resolved during a call to
13702 * {@link #onMeasure(int, int)}.
13706 public void resetResolvedLayoutDirection() {
13707 // Reset the current resolved bits
13708 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
13712 * @return true if the layout direction is inherited.
13716 public boolean isLayoutDirectionInherited() {
13717 return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
13721 * @return true if layout direction has been resolved.
13723 public boolean isLayoutDirectionResolved() {
13724 return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
13728 * Return if padding has been resolved
13732 boolean isPaddingResolved() {
13733 return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
13737 * Resolves padding depending on layout direction, if applicable, and
13738 * recomputes internal padding values to adjust for scroll bars.
13742 public void resolvePadding() {
13743 final int resolvedLayoutDirection = getLayoutDirection();
13745 if (!isRtlCompatibilityMode()) {
13746 // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
13747 // If start / end padding are defined, they will be resolved (hence overriding) to
13748 // left / right or right / left depending on the resolved layout direction.
13749 // If start / end padding are not defined, use the left / right ones.
13750 if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
13751 Rect padding = sThreadLocal.get();
13752 if (padding == null) {
13753 padding = new Rect();
13754 sThreadLocal.set(padding);
13756 mBackground.getPadding(padding);
13757 if (!mLeftPaddingDefined) {
13758 mUserPaddingLeftInitial = padding.left;
13760 if (!mRightPaddingDefined) {
13761 mUserPaddingRightInitial = padding.right;
13764 switch (resolvedLayoutDirection) {
13765 case LAYOUT_DIRECTION_RTL:
13766 if (mUserPaddingStart != UNDEFINED_PADDING) {
13767 mUserPaddingRight = mUserPaddingStart;
13769 mUserPaddingRight = mUserPaddingRightInitial;
13771 if (mUserPaddingEnd != UNDEFINED_PADDING) {
13772 mUserPaddingLeft = mUserPaddingEnd;
13774 mUserPaddingLeft = mUserPaddingLeftInitial;
13777 case LAYOUT_DIRECTION_LTR:
13779 if (mUserPaddingStart != UNDEFINED_PADDING) {
13780 mUserPaddingLeft = mUserPaddingStart;
13782 mUserPaddingLeft = mUserPaddingLeftInitial;
13784 if (mUserPaddingEnd != UNDEFINED_PADDING) {
13785 mUserPaddingRight = mUserPaddingEnd;
13787 mUserPaddingRight = mUserPaddingRightInitial;
13791 mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
13794 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
13795 onRtlPropertiesChanged(resolvedLayoutDirection);
13797 mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
13801 * Reset the resolved layout direction.
13805 public void resetResolvedPadding() {
13806 resetResolvedPaddingInternal();
13810 * Used when we only want to reset *this* view's padding and not trigger overrides
13811 * in ViewGroup that reset children too.
13813 void resetResolvedPaddingInternal() {
13814 mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
13818 * This is called when the view is detached from a window. At this point it
13819 * no longer has a surface for drawing.
13821 * @see #onAttachedToWindow()
13824 protected void onDetachedFromWindow() {
13828 * This is a framework-internal mirror of onDetachedFromWindow() that's called
13829 * after onDetachedFromWindow().
13831 * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
13832 * The super method should be called at the end of the overridden method to ensure
13833 * subclasses are destroyed first
13838 protected void onDetachedFromWindowInternal() {
13839 mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
13840 mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
13842 removeUnsetPressCallback();
13843 removeLongPressCallback();
13844 removePerformClickCallback();
13845 removeSendViewScrolledAccessibilityEventCallback();
13846 stopNestedScroll();
13848 // Anything that started animating right before detach should already
13849 // be in its final state when re-attached.
13850 jumpDrawablesToCurrentState();
13852 destroyDrawingCache();
13855 mCurrentAnimation = null;
13858 private void cleanupDraw() {
13859 resetDisplayList();
13860 if (mAttachInfo != null) {
13861 mAttachInfo.mViewRootImpl.cancelInvalidate(this);
13865 void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
13869 * @return The number of times this view has been attached to a window
13871 protected int getWindowAttachCount() {
13872 return mWindowAttachCount;
13876 * Retrieve a unique token identifying the window this view is attached to.
13877 * @return Return the window's token for use in
13878 * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
13880 public IBinder getWindowToken() {
13881 return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
13885 * Retrieve the {@link WindowId} for the window this view is
13886 * currently attached to.
13888 public WindowId getWindowId() {
13889 if (mAttachInfo == null) {
13892 if (mAttachInfo.mWindowId == null) {
13894 mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
13895 mAttachInfo.mWindowToken);
13896 mAttachInfo.mWindowId = new WindowId(
13897 mAttachInfo.mIWindowId);
13898 } catch (RemoteException e) {
13901 return mAttachInfo.mWindowId;
13905 * Retrieve a unique token identifying the top-level "real" window of
13906 * the window that this view is attached to. That is, this is like
13907 * {@link #getWindowToken}, except if the window this view in is a panel
13908 * window (attached to another containing window), then the token of
13909 * the containing window is returned instead.
13911 * @return Returns the associated window token, either
13912 * {@link #getWindowToken()} or the containing window's token.
13914 public IBinder getApplicationWindowToken() {
13915 AttachInfo ai = mAttachInfo;
13917 IBinder appWindowToken = ai.mPanelParentWindowToken;
13918 if (appWindowToken == null) {
13919 appWindowToken = ai.mWindowToken;
13921 return appWindowToken;
13927 * Gets the logical display to which the view's window has been attached.
13929 * @return The logical display, or null if the view is not currently attached to a window.
13931 public Display getDisplay() {
13932 return mAttachInfo != null ? mAttachInfo.mDisplay : null;
13936 * Retrieve private session object this view hierarchy is using to
13937 * communicate with the window manager.
13938 * @return the session object to communicate with the window manager
13940 /*package*/ IWindowSession getWindowSession() {
13941 return mAttachInfo != null ? mAttachInfo.mSession : null;
13945 * @param info the {@link android.view.View.AttachInfo} to associated with
13948 void dispatchAttachedToWindow(AttachInfo info, int visibility) {
13949 //System.out.println("Attached! " + this);
13950 mAttachInfo = info;
13951 if (mOverlay != null) {
13952 mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
13954 mWindowAttachCount++;
13955 // We will need to evaluate the drawable state at least once.
13956 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
13957 if (mFloatingTreeObserver != null) {
13958 info.mTreeObserver.merge(mFloatingTreeObserver);
13959 mFloatingTreeObserver = null;
13961 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
13962 mAttachInfo.mScrollContainers.add(this);
13963 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
13965 performCollectViewAttributes(mAttachInfo, visibility);
13966 onAttachedToWindow();
13968 ListenerInfo li = mListenerInfo;
13969 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
13970 li != null ? li.mOnAttachStateChangeListeners : null;
13971 if (listeners != null && listeners.size() > 0) {
13972 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
13973 // perform the dispatching. The iterator is a safe guard against listeners that
13974 // could mutate the list by calling the various add/remove methods. This prevents
13975 // the array from being modified while we iterate it.
13976 for (OnAttachStateChangeListener listener : listeners) {
13977 listener.onViewAttachedToWindow(this);
13981 int vis = info.mWindowVisibility;
13983 onWindowVisibilityChanged(vis);
13985 if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
13986 // If nobody has evaluated the drawable state yet, then do it now.
13987 refreshDrawableState();
13989 needGlobalAttributesUpdate(false);
13992 void dispatchDetachedFromWindow() {
13993 AttachInfo info = mAttachInfo;
13994 if (info != null) {
13995 int vis = info.mWindowVisibility;
13997 onWindowVisibilityChanged(GONE);
14001 onDetachedFromWindow();
14002 onDetachedFromWindowInternal();
14004 ListenerInfo li = mListenerInfo;
14005 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14006 li != null ? li.mOnAttachStateChangeListeners : null;
14007 if (listeners != null && listeners.size() > 0) {
14008 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14009 // perform the dispatching. The iterator is a safe guard against listeners that
14010 // could mutate the list by calling the various add/remove methods. This prevents
14011 // the array from being modified while we iterate it.
14012 for (OnAttachStateChangeListener listener : listeners) {
14013 listener.onViewDetachedFromWindow(this);
14017 if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
14018 mAttachInfo.mScrollContainers.remove(this);
14019 mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
14022 mAttachInfo = null;
14023 if (mOverlay != null) {
14024 mOverlay.getOverlayView().dispatchDetachedFromWindow();
14029 * Cancel any deferred high-level input events that were previously posted to the event queue.
14031 * <p>Many views post high-level events such as click handlers to the event queue
14032 * to run deferred in order to preserve a desired user experience - clearing visible
14033 * pressed states before executing, etc. This method will abort any events of this nature
14034 * that are currently in flight.</p>
14036 * <p>Custom views that generate their own high-level deferred input events should override
14037 * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
14039 * <p>This will also cancel pending input events for any child views.</p>
14041 * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
14042 * This will not impact newer events posted after this call that may occur as a result of
14043 * lower-level input events still waiting in the queue. If you are trying to prevent
14044 * double-submitted events for the duration of some sort of asynchronous transaction
14045 * you should also take other steps to protect against unexpected double inputs e.g. calling
14046 * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
14047 * the transaction completes, tracking already submitted transaction IDs, etc.</p>
14049 public final void cancelPendingInputEvents() {
14050 dispatchCancelPendingInputEvents();
14054 * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
14055 * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
14057 void dispatchCancelPendingInputEvents() {
14058 mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
14059 onCancelPendingInputEvents();
14060 if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
14061 throw new SuperNotCalledException("View " + getClass().getSimpleName() +
14062 " did not call through to super.onCancelPendingInputEvents()");
14067 * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
14070 * <p>This method is responsible for removing any pending high-level input events that were
14071 * posted to the event queue to run later. Custom view classes that post their own deferred
14072 * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
14073 * {@link android.os.Handler} should override this method, call
14074 * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
14077 public void onCancelPendingInputEvents() {
14078 removePerformClickCallback();
14080 mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
14084 * Store this view hierarchy's frozen state into the given container.
14086 * @param container The SparseArray in which to save the view's state.
14088 * @see #restoreHierarchyState(android.util.SparseArray)
14089 * @see #dispatchSaveInstanceState(android.util.SparseArray)
14090 * @see #onSaveInstanceState()
14092 public void saveHierarchyState(SparseArray<Parcelable> container) {
14093 dispatchSaveInstanceState(container);
14097 * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
14098 * this view and its children. May be overridden to modify how freezing happens to a
14099 * view's children; for example, some views may want to not store state for their children.
14101 * @param container The SparseArray in which to save the view's state.
14103 * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14104 * @see #saveHierarchyState(android.util.SparseArray)
14105 * @see #onSaveInstanceState()
14107 protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
14108 if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
14109 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14110 Parcelable state = onSaveInstanceState();
14111 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14112 throw new IllegalStateException(
14113 "Derived class did not call super.onSaveInstanceState()");
14115 if (state != null) {
14116 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
14117 // + ": " + state);
14118 container.put(mID, state);
14124 * Hook allowing a view to generate a representation of its internal state
14125 * that can later be used to create a new instance with that same state.
14126 * This state should only contain information that is not persistent or can
14127 * not be reconstructed later. For example, you will never store your
14128 * current position on screen because that will be computed again when a
14129 * new instance of the view is placed in its view hierarchy.
14131 * Some examples of things you may store here: the current cursor position
14132 * in a text view (but usually not the text itself since that is stored in a
14133 * content provider or other persistent storage), the currently selected
14134 * item in a list view.
14136 * @return Returns a Parcelable object containing the view's current dynamic
14137 * state, or null if there is nothing interesting to save. The
14138 * default implementation returns null.
14139 * @see #onRestoreInstanceState(android.os.Parcelable)
14140 * @see #saveHierarchyState(android.util.SparseArray)
14141 * @see #dispatchSaveInstanceState(android.util.SparseArray)
14142 * @see #setSaveEnabled(boolean)
14145 protected Parcelable onSaveInstanceState() {
14146 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
14147 if (mStartActivityRequestWho != null) {
14148 BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
14149 state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
14152 return BaseSavedState.EMPTY_STATE;
14156 * Restore this view hierarchy's frozen state from the given container.
14158 * @param container The SparseArray which holds previously frozen states.
14160 * @see #saveHierarchyState(android.util.SparseArray)
14161 * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14162 * @see #onRestoreInstanceState(android.os.Parcelable)
14164 public void restoreHierarchyState(SparseArray<Parcelable> container) {
14165 dispatchRestoreInstanceState(container);
14169 * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
14170 * state for this view and its children. May be overridden to modify how restoring
14171 * happens to a view's children; for example, some views may want to not store state
14172 * for their children.
14174 * @param container The SparseArray which holds previously saved state.
14176 * @see #dispatchSaveInstanceState(android.util.SparseArray)
14177 * @see #restoreHierarchyState(android.util.SparseArray)
14178 * @see #onRestoreInstanceState(android.os.Parcelable)
14180 protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
14181 if (mID != NO_ID) {
14182 Parcelable state = container.get(mID);
14183 if (state != null) {
14184 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
14185 // + ": " + state);
14186 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14187 onRestoreInstanceState(state);
14188 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14189 throw new IllegalStateException(
14190 "Derived class did not call super.onRestoreInstanceState()");
14197 * Hook allowing a view to re-apply a representation of its internal state that had previously
14198 * been generated by {@link #onSaveInstanceState}. This function will never be called with a
14201 * @param state The frozen state that had previously been returned by
14202 * {@link #onSaveInstanceState}.
14204 * @see #onSaveInstanceState()
14205 * @see #restoreHierarchyState(android.util.SparseArray)
14206 * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14209 protected void onRestoreInstanceState(Parcelable state) {
14210 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
14211 if (state != null && !(state instanceof AbsSavedState)) {
14212 throw new IllegalArgumentException("Wrong state class, expecting View State but "
14213 + "received " + state.getClass().toString() + " instead. This usually happens "
14214 + "when two views of different type have the same id in the same hierarchy. "
14215 + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
14216 + "other views do not use the same id.");
14218 if (state != null && state instanceof BaseSavedState) {
14219 mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
14224 * <p>Return the time at which the drawing of the view hierarchy started.</p>
14226 * @return the drawing start time in milliseconds
14228 public long getDrawingTime() {
14229 return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
14233 * <p>Enables or disables the duplication of the parent's state into this view. When
14234 * duplication is enabled, this view gets its drawable state from its parent rather
14235 * than from its own internal properties.</p>
14237 * <p>Note: in the current implementation, setting this property to true after the
14238 * view was added to a ViewGroup might have no effect at all. This property should
14239 * always be used from XML or set to true before adding this view to a ViewGroup.</p>
14241 * <p>Note: if this view's parent addStateFromChildren property is enabled and this
14242 * property is enabled, an exception will be thrown.</p>
14244 * <p>Note: if the child view uses and updates additional states which are unknown to the
14245 * parent, these states should not be affected by this method.</p>
14247 * @param enabled True to enable duplication of the parent's drawable state, false
14250 * @see #getDrawableState()
14251 * @see #isDuplicateParentStateEnabled()
14253 public void setDuplicateParentStateEnabled(boolean enabled) {
14254 setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
14258 * <p>Indicates whether this duplicates its drawable state from its parent.</p>
14260 * @return True if this view's drawable state is duplicated from the parent,
14263 * @see #getDrawableState()
14264 * @see #setDuplicateParentStateEnabled(boolean)
14266 public boolean isDuplicateParentStateEnabled() {
14267 return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
14271 * <p>Specifies the type of layer backing this view. The layer can be
14272 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14273 * {@link #LAYER_TYPE_HARDWARE}.</p>
14275 * <p>A layer is associated with an optional {@link android.graphics.Paint}
14276 * instance that controls how the layer is composed on screen. The following
14277 * properties of the paint are taken into account when composing the layer:</p>
14279 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
14280 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
14281 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
14284 * <p>If this view has an alpha value set to < 1.0 by calling
14285 * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
14286 * by this view's alpha value.</p>
14288 * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
14289 * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
14290 * for more information on when and how to use layers.</p>
14292 * @param layerType The type of layer to use with this view, must be one of
14293 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14294 * {@link #LAYER_TYPE_HARDWARE}
14295 * @param paint The paint used to compose the layer. This argument is optional
14296 * and can be null. It is ignored when the layer type is
14297 * {@link #LAYER_TYPE_NONE}
14299 * @see #getLayerType()
14300 * @see #LAYER_TYPE_NONE
14301 * @see #LAYER_TYPE_SOFTWARE
14302 * @see #LAYER_TYPE_HARDWARE
14303 * @see #setAlpha(float)
14305 * @attr ref android.R.styleable#View_layerType
14307 public void setLayerType(int layerType, Paint paint) {
14308 if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
14309 throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
14310 + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
14313 boolean typeChanged = mRenderNode.setLayerType(layerType);
14315 if (!typeChanged) {
14316 setLayerPaint(paint);
14320 // Destroy any previous software drawing cache if needed
14321 if (mLayerType == LAYER_TYPE_SOFTWARE) {
14322 destroyDrawingCache();
14325 mLayerType = layerType;
14326 final boolean layerDisabled = (mLayerType == LAYER_TYPE_NONE);
14327 mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
14328 mRenderNode.setLayerPaint(mLayerPaint);
14330 // draw() behaves differently if we are on a layer, so we need to
14331 // invalidate() here
14332 invalidateParentCaches();
14337 * Updates the {@link Paint} object used with the current layer (used only if the current
14338 * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
14339 * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
14340 * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
14341 * ensure that the view gets redrawn immediately.
14343 * <p>A layer is associated with an optional {@link android.graphics.Paint}
14344 * instance that controls how the layer is composed on screen. The following
14345 * properties of the paint are taken into account when composing the layer:</p>
14347 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
14348 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
14349 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
14352 * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
14353 * alpha value of the layer's paint is superseded by this view's alpha value.</p>
14355 * @param paint The paint used to compose the layer. This argument is optional
14356 * and can be null. It is ignored when the layer type is
14357 * {@link #LAYER_TYPE_NONE}
14359 * @see #setLayerType(int, android.graphics.Paint)
14361 public void setLayerPaint(Paint paint) {
14362 int layerType = getLayerType();
14363 if (layerType != LAYER_TYPE_NONE) {
14364 mLayerPaint = paint == null ? new Paint() : paint;
14365 if (layerType == LAYER_TYPE_HARDWARE) {
14366 if (mRenderNode.setLayerPaint(mLayerPaint)) {
14367 invalidateViewProperty(false, false);
14376 * Indicates whether this view has a static layer. A view with layer type
14377 * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
14380 boolean hasStaticLayer() {
14385 * Indicates what type of layer is currently associated with this view. By default
14386 * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
14387 * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
14388 * for more information on the different types of layers.
14390 * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14391 * {@link #LAYER_TYPE_HARDWARE}
14393 * @see #setLayerType(int, android.graphics.Paint)
14394 * @see #buildLayer()
14395 * @see #LAYER_TYPE_NONE
14396 * @see #LAYER_TYPE_SOFTWARE
14397 * @see #LAYER_TYPE_HARDWARE
14399 public int getLayerType() {
14404 * Forces this view's layer to be created and this view to be rendered
14405 * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
14406 * invoking this method will have no effect.
14408 * This method can for instance be used to render a view into its layer before
14409 * starting an animation. If this view is complex, rendering into the layer
14410 * before starting the animation will avoid skipping frames.
14412 * @throws IllegalStateException If this view is not attached to a window
14414 * @see #setLayerType(int, android.graphics.Paint)
14416 public void buildLayer() {
14417 if (mLayerType == LAYER_TYPE_NONE) return;
14419 final AttachInfo attachInfo = mAttachInfo;
14420 if (attachInfo == null) {
14421 throw new IllegalStateException("This view must be attached to a window first");
14424 if (getWidth() == 0 || getHeight() == 0) {
14428 switch (mLayerType) {
14429 case LAYER_TYPE_HARDWARE:
14430 updateDisplayListIfDirty();
14431 if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
14432 attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
14435 case LAYER_TYPE_SOFTWARE:
14436 buildDrawingCache(true);
14442 * If this View draws with a HardwareLayer, returns it.
14443 * Otherwise returns null
14445 * TODO: Only TextureView uses this, can we eliminate it?
14447 HardwareLayer getHardwareLayer() {
14452 * Destroys all hardware rendering resources. This method is invoked
14453 * when the system needs to reclaim resources. Upon execution of this
14454 * method, you should free any OpenGL resources created by the view.
14456 * Note: you <strong>must</strong> call
14457 * <code>super.destroyHardwareResources()</code> when overriding
14463 protected void destroyHardwareResources() {
14464 // Although the Layer will be destroyed by RenderNode, we want to release
14465 // the staging display list, which is also a signal to RenderNode that it's
14466 // safe to free its copy of the display list as it knows that we will
14467 // push an updated DisplayList if we try to draw again
14468 resetDisplayList();
14472 * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
14473 * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
14474 * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
14475 * the cache is enabled. To benefit from the cache, you must request the drawing cache by
14476 * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
14479 * <p>Enabling the drawing cache is similar to
14480 * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
14481 * acceleration is turned off. When hardware acceleration is turned on, enabling the
14482 * drawing cache has no effect on rendering because the system uses a different mechanism
14483 * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
14484 * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
14485 * for information on how to enable software and hardware layers.</p>
14487 * <p>This API can be used to manually generate
14488 * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
14489 * {@link #getDrawingCache()}.</p>
14491 * @param enabled true to enable the drawing cache, false otherwise
14493 * @see #isDrawingCacheEnabled()
14494 * @see #getDrawingCache()
14495 * @see #buildDrawingCache()
14496 * @see #setLayerType(int, android.graphics.Paint)
14498 public void setDrawingCacheEnabled(boolean enabled) {
14499 mCachingFailed = false;
14500 setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
14504 * <p>Indicates whether the drawing cache is enabled for this view.</p>
14506 * @return true if the drawing cache is enabled
14508 * @see #setDrawingCacheEnabled(boolean)
14509 * @see #getDrawingCache()
14511 @ViewDebug.ExportedProperty(category = "drawing")
14512 public boolean isDrawingCacheEnabled() {
14513 return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
14517 * Debugging utility which recursively outputs the dirty state of a view and its
14522 @SuppressWarnings({"UnusedDeclaration"})
14523 public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
14524 Log.d("View", indent + this + " DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
14525 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
14526 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
14527 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
14529 mPrivateFlags &= clearMask;
14531 if (this instanceof ViewGroup) {
14532 ViewGroup parent = (ViewGroup) this;
14533 final int count = parent.getChildCount();
14534 for (int i = 0; i < count; i++) {
14535 final View child = parent.getChildAt(i);
14536 child.outputDirtyFlags(indent + " ", clear, clearMask);
14542 * This method is used by ViewGroup to cause its children to restore or recreate their
14543 * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
14544 * to recreate its own display list, which would happen if it went through the normal
14545 * draw/dispatchDraw mechanisms.
14549 protected void dispatchGetDisplayList() {}
14552 * A view that is not attached or hardware accelerated cannot create a display list.
14553 * This method checks these conditions and returns the appropriate result.
14555 * @return true if view has the ability to create a display list, false otherwise.
14559 public boolean canHaveDisplayList() {
14560 return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
14563 private void updateDisplayListIfDirty() {
14564 final RenderNode renderNode = mRenderNode;
14565 if (!canHaveDisplayList()) {
14566 // can't populate RenderNode, don't try
14570 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
14571 || !renderNode.isValid()
14572 || (mRecreateDisplayList)) {
14573 // Don't need to recreate the display list, just need to tell our
14574 // children to restore/recreate theirs
14575 if (renderNode.isValid()
14576 && !mRecreateDisplayList) {
14577 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
14578 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14579 dispatchGetDisplayList();
14581 return; // no work needed
14584 // If we got here, we're recreating it. Mark it as such to ensure that
14585 // we copy in child display lists into ours in drawChild()
14586 mRecreateDisplayList = true;
14588 int width = mRight - mLeft;
14589 int height = mBottom - mTop;
14590 int layerType = getLayerType();
14592 final DisplayListCanvas canvas = renderNode.start(width, height);
14593 canvas.setHighContrastText(mAttachInfo.mHighContrastText);
14596 final HardwareLayer layer = getHardwareLayer();
14597 if (layer != null && layer.isValid()) {
14598 canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
14599 } else if (layerType == LAYER_TYPE_SOFTWARE) {
14600 buildDrawingCache(true);
14601 Bitmap cache = getDrawingCache(true);
14602 if (cache != null) {
14603 canvas.drawBitmap(cache, 0, 0, mLayerPaint);
14608 canvas.translate(-mScrollX, -mScrollY);
14609 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
14610 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14612 // Fast path for layouts with no backgrounds
14613 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14614 dispatchDraw(canvas);
14615 if (mOverlay != null && !mOverlay.isEmpty()) {
14616 mOverlay.getOverlayView().draw(canvas);
14623 renderNode.end(canvas);
14624 setDisplayListProperties(renderNode);
14627 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
14628 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14633 * Returns a RenderNode with View draw content recorded, which can be
14634 * used to draw this view again without executing its draw method.
14636 * @return A RenderNode ready to replay, or null if caching is not enabled.
14640 public RenderNode getDisplayList() {
14641 updateDisplayListIfDirty();
14642 return mRenderNode;
14645 private void resetDisplayList() {
14646 if (mRenderNode.isValid()) {
14647 mRenderNode.destroyDisplayListData();
14650 if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
14651 mBackgroundRenderNode.destroyDisplayListData();
14656 * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
14658 * @return A non-scaled bitmap representing this view or null if cache is disabled.
14660 * @see #getDrawingCache(boolean)
14662 public Bitmap getDrawingCache() {
14663 return getDrawingCache(false);
14667 * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
14668 * is null when caching is disabled. If caching is enabled and the cache is not ready,
14669 * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
14670 * draw from the cache when the cache is enabled. To benefit from the cache, you must
14671 * request the drawing cache by calling this method and draw it on screen if the
14672 * returned bitmap is not null.</p>
14674 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
14675 * this method will create a bitmap of the same size as this view. Because this bitmap
14676 * will be drawn scaled by the parent ViewGroup, the result on screen might show
14677 * scaling artifacts. To avoid such artifacts, you should call this method by setting
14678 * the auto scaling to true. Doing so, however, will generate a bitmap of a different
14679 * size than the view. This implies that your application must be able to handle this
14682 * @param autoScale Indicates whether the generated bitmap should be scaled based on
14683 * the current density of the screen when the application is in compatibility
14686 * @return A bitmap representing this view or null if cache is disabled.
14688 * @see #setDrawingCacheEnabled(boolean)
14689 * @see #isDrawingCacheEnabled()
14690 * @see #buildDrawingCache(boolean)
14691 * @see #destroyDrawingCache()
14693 public Bitmap getDrawingCache(boolean autoScale) {
14694 if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
14697 if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
14698 buildDrawingCache(autoScale);
14700 return autoScale ? mDrawingCache : mUnscaledDrawingCache;
14704 * <p>Frees the resources used by the drawing cache. If you call
14705 * {@link #buildDrawingCache()} manually without calling
14706 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
14707 * should cleanup the cache with this method afterwards.</p>
14709 * @see #setDrawingCacheEnabled(boolean)
14710 * @see #buildDrawingCache()
14711 * @see #getDrawingCache()
14713 public void destroyDrawingCache() {
14714 if (mDrawingCache != null) {
14715 mDrawingCache.recycle();
14716 mDrawingCache = null;
14718 if (mUnscaledDrawingCache != null) {
14719 mUnscaledDrawingCache.recycle();
14720 mUnscaledDrawingCache = null;
14725 * Setting a solid background color for the drawing cache's bitmaps will improve
14726 * performance and memory usage. Note, though that this should only be used if this
14727 * view will always be drawn on top of a solid color.
14729 * @param color The background color to use for the drawing cache's bitmap
14731 * @see #setDrawingCacheEnabled(boolean)
14732 * @see #buildDrawingCache()
14733 * @see #getDrawingCache()
14735 public void setDrawingCacheBackgroundColor(@ColorInt int color) {
14736 if (color != mDrawingCacheBackgroundColor) {
14737 mDrawingCacheBackgroundColor = color;
14738 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
14743 * @see #setDrawingCacheBackgroundColor(int)
14745 * @return The background color to used for the drawing cache's bitmap
14748 public int getDrawingCacheBackgroundColor() {
14749 return mDrawingCacheBackgroundColor;
14753 * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
14755 * @see #buildDrawingCache(boolean)
14757 public void buildDrawingCache() {
14758 buildDrawingCache(false);
14762 * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
14764 * <p>If you call {@link #buildDrawingCache()} manually without calling
14765 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
14766 * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
14768 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
14769 * this method will create a bitmap of the same size as this view. Because this bitmap
14770 * will be drawn scaled by the parent ViewGroup, the result on screen might show
14771 * scaling artifacts. To avoid such artifacts, you should call this method by setting
14772 * the auto scaling to true. Doing so, however, will generate a bitmap of a different
14773 * size than the view. This implies that your application must be able to handle this
14776 * <p>You should avoid calling this method when hardware acceleration is enabled. If
14777 * you do not need the drawing cache bitmap, calling this method will increase memory
14778 * usage and cause the view to be rendered in software once, thus negatively impacting
14781 * @see #getDrawingCache()
14782 * @see #destroyDrawingCache()
14784 public void buildDrawingCache(boolean autoScale) {
14785 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
14786 mDrawingCache == null : mUnscaledDrawingCache == null)) {
14787 if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
14788 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
14789 "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
14792 buildDrawingCacheImpl(autoScale);
14794 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
14800 * private, internal implementation of buildDrawingCache, used to enable tracing
14802 private void buildDrawingCacheImpl(boolean autoScale) {
14803 mCachingFailed = false;
14805 int width = mRight - mLeft;
14806 int height = mBottom - mTop;
14808 final AttachInfo attachInfo = mAttachInfo;
14809 final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
14811 if (autoScale && scalingRequired) {
14812 width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
14813 height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
14816 final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
14817 final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
14818 final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
14820 final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
14821 final long drawingCacheSize =
14822 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
14823 if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
14824 if (width > 0 && height > 0) {
14825 Log.w(VIEW_LOG_TAG, "View too large to fit into drawing cache, needs "
14826 + projectedBitmapSize + " bytes, only "
14827 + drawingCacheSize + " available");
14829 destroyDrawingCache();
14830 mCachingFailed = true;
14834 boolean clear = true;
14835 Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
14837 if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
14838 Bitmap.Config quality;
14840 // Never pick ARGB_4444 because it looks awful
14841 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
14842 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
14843 case DRAWING_CACHE_QUALITY_AUTO:
14844 case DRAWING_CACHE_QUALITY_LOW:
14845 case DRAWING_CACHE_QUALITY_HIGH:
14847 quality = Bitmap.Config.ARGB_8888;
14851 // Optimization for translucent windows
14852 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
14853 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
14856 // Try to cleanup memory
14857 if (bitmap != null) bitmap.recycle();
14860 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
14861 width, height, quality);
14862 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
14864 mDrawingCache = bitmap;
14866 mUnscaledDrawingCache = bitmap;
14868 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
14869 } catch (OutOfMemoryError e) {
14870 // If there is not enough memory to create the bitmap cache, just
14871 // ignore the issue as bitmap caches are not required to draw the
14874 mDrawingCache = null;
14876 mUnscaledDrawingCache = null;
14878 mCachingFailed = true;
14882 clear = drawingCacheBackgroundColor != 0;
14886 if (attachInfo != null) {
14887 canvas = attachInfo.mCanvas;
14888 if (canvas == null) {
14889 canvas = new Canvas();
14891 canvas.setBitmap(bitmap);
14892 // Temporarily clobber the cached Canvas in case one of our children
14893 // is also using a drawing cache. Without this, the children would
14894 // steal the canvas by attaching their own bitmap to it and bad, bad
14895 // thing would happen (invisible views, corrupted drawings, etc.)
14896 attachInfo.mCanvas = null;
14898 // This case should hopefully never or seldom happen
14899 canvas = new Canvas(bitmap);
14903 bitmap.eraseColor(drawingCacheBackgroundColor);
14907 final int restoreCount = canvas.save();
14909 if (autoScale && scalingRequired) {
14910 final float scale = attachInfo.mApplicationScale;
14911 canvas.scale(scale, scale);
14914 canvas.translate(-mScrollX, -mScrollY);
14916 mPrivateFlags |= PFLAG_DRAWN;
14917 if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
14918 mLayerType != LAYER_TYPE_NONE) {
14919 mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
14922 // Fast path for layouts with no backgrounds
14923 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14924 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14925 dispatchDraw(canvas);
14926 if (mOverlay != null && !mOverlay.isEmpty()) {
14927 mOverlay.getOverlayView().draw(canvas);
14933 canvas.restoreToCount(restoreCount);
14934 canvas.setBitmap(null);
14936 if (attachInfo != null) {
14937 // Restore the cached Canvas for our siblings
14938 attachInfo.mCanvas = canvas;
14943 * Create a snapshot of the view into a bitmap. We should probably make
14944 * some form of this public, but should think about the API.
14946 Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
14947 int width = mRight - mLeft;
14948 int height = mBottom - mTop;
14950 final AttachInfo attachInfo = mAttachInfo;
14951 final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
14952 width = (int) ((width * scale) + 0.5f);
14953 height = (int) ((height * scale) + 0.5f);
14955 Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
14956 width > 0 ? width : 1, height > 0 ? height : 1, quality);
14957 if (bitmap == null) {
14958 throw new OutOfMemoryError();
14961 Resources resources = getResources();
14962 if (resources != null) {
14963 bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
14967 if (attachInfo != null) {
14968 canvas = attachInfo.mCanvas;
14969 if (canvas == null) {
14970 canvas = new Canvas();
14972 canvas.setBitmap(bitmap);
14973 // Temporarily clobber the cached Canvas in case one of our children
14974 // is also using a drawing cache. Without this, the children would
14975 // steal the canvas by attaching their own bitmap to it and bad, bad
14976 // things would happen (invisible views, corrupted drawings, etc.)
14977 attachInfo.mCanvas = null;
14979 // This case should hopefully never or seldom happen
14980 canvas = new Canvas(bitmap);
14983 if ((backgroundColor & 0xff000000) != 0) {
14984 bitmap.eraseColor(backgroundColor);
14988 final int restoreCount = canvas.save();
14989 canvas.scale(scale, scale);
14990 canvas.translate(-mScrollX, -mScrollY);
14992 // Temporarily remove the dirty mask
14993 int flags = mPrivateFlags;
14994 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14996 // Fast path for layouts with no backgrounds
14997 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14998 dispatchDraw(canvas);
14999 if (mOverlay != null && !mOverlay.isEmpty()) {
15000 mOverlay.getOverlayView().draw(canvas);
15006 mPrivateFlags = flags;
15008 canvas.restoreToCount(restoreCount);
15009 canvas.setBitmap(null);
15011 if (attachInfo != null) {
15012 // Restore the cached Canvas for our siblings
15013 attachInfo.mCanvas = canvas;
15020 * Indicates whether this View is currently in edit mode. A View is usually
15021 * in edit mode when displayed within a developer tool. For instance, if
15022 * this View is being drawn by a visual user interface builder, this method
15023 * should return true.
15025 * Subclasses should check the return value of this method to provide
15026 * different behaviors if their normal behavior might interfere with the
15027 * host environment. For instance: the class spawns a thread in its
15028 * constructor, the drawing code relies on device-specific features, etc.
15030 * This method is usually checked in the drawing code of custom widgets.
15032 * @return True if this View is in edit mode, false otherwise.
15034 public boolean isInEditMode() {
15039 * If the View draws content inside its padding and enables fading edges,
15040 * it needs to support padding offsets. Padding offsets are added to the
15041 * fading edges to extend the length of the fade so that it covers pixels
15042 * drawn inside the padding.
15044 * Subclasses of this class should override this method if they need
15045 * to draw content inside the padding.
15047 * @return True if padding offset must be applied, false otherwise.
15049 * @see #getLeftPaddingOffset()
15050 * @see #getRightPaddingOffset()
15051 * @see #getTopPaddingOffset()
15052 * @see #getBottomPaddingOffset()
15056 protected boolean isPaddingOffsetRequired() {
15061 * Amount by which to extend the left fading region. Called only when
15062 * {@link #isPaddingOffsetRequired()} returns true.
15064 * @return The left padding offset in pixels.
15066 * @see #isPaddingOffsetRequired()
15070 protected int getLeftPaddingOffset() {
15075 * Amount by which to extend the right fading region. Called only when
15076 * {@link #isPaddingOffsetRequired()} returns true.
15078 * @return The right padding offset in pixels.
15080 * @see #isPaddingOffsetRequired()
15084 protected int getRightPaddingOffset() {
15089 * Amount by which to extend the top fading region. Called only when
15090 * {@link #isPaddingOffsetRequired()} returns true.
15092 * @return The top padding offset in pixels.
15094 * @see #isPaddingOffsetRequired()
15098 protected int getTopPaddingOffset() {
15103 * Amount by which to extend the bottom fading region. Called only when
15104 * {@link #isPaddingOffsetRequired()} returns true.
15106 * @return The bottom padding offset in pixels.
15108 * @see #isPaddingOffsetRequired()
15112 protected int getBottomPaddingOffset() {
15118 * @param offsetRequired
15120 protected int getFadeTop(boolean offsetRequired) {
15121 int top = mPaddingTop;
15122 if (offsetRequired) top += getTopPaddingOffset();
15128 * @param offsetRequired
15130 protected int getFadeHeight(boolean offsetRequired) {
15131 int padding = mPaddingTop;
15132 if (offsetRequired) padding += getTopPaddingOffset();
15133 return mBottom - mTop - mPaddingBottom - padding;
15137 * <p>Indicates whether this view is attached to a hardware accelerated
15138 * window or not.</p>
15140 * <p>Even if this method returns true, it does not mean that every call
15141 * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
15142 * accelerated {@link android.graphics.Canvas}. For instance, if this view
15143 * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
15144 * window is hardware accelerated,
15145 * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
15146 * return false, and this method will return true.</p>
15148 * @return True if the view is attached to a window and the window is
15149 * hardware accelerated; false in any other case.
15151 @ViewDebug.ExportedProperty(category = "drawing")
15152 public boolean isHardwareAccelerated() {
15153 return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
15157 * Sets a rectangular area on this view to which the view will be clipped
15158 * when it is drawn. Setting the value to null will remove the clip bounds
15159 * and the view will draw normally, using its full bounds.
15161 * @param clipBounds The rectangular area, in the local coordinates of
15162 * this view, to which future drawing operations will be clipped.
15164 public void setClipBounds(Rect clipBounds) {
15165 if (clipBounds == mClipBounds
15166 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
15169 if (clipBounds != null) {
15170 if (mClipBounds == null) {
15171 mClipBounds = new Rect(clipBounds);
15173 mClipBounds.set(clipBounds);
15176 mClipBounds = null;
15178 mRenderNode.setClipBounds(mClipBounds);
15179 invalidateViewProperty(false, false);
15183 * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
15185 * @return A copy of the current clip bounds if clip bounds are set,
15188 public Rect getClipBounds() {
15189 return (mClipBounds != null) ? new Rect(mClipBounds) : null;
15194 * Populates an output rectangle with the clip bounds of the view,
15195 * returning {@code true} if successful or {@code false} if the view's
15196 * clip bounds are {@code null}.
15198 * @param outRect rectangle in which to place the clip bounds of the view
15199 * @return {@code true} if successful or {@code false} if the view's
15200 * clip bounds are {@code null}
15202 public boolean getClipBounds(Rect outRect) {
15203 if (mClipBounds != null) {
15204 outRect.set(mClipBounds);
15211 * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
15212 * case of an active Animation being run on the view.
15214 private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
15215 Animation a, boolean scalingRequired) {
15216 Transformation invalidationTransform;
15217 final int flags = parent.mGroupFlags;
15218 final boolean initialized = a.isInitialized();
15219 if (!initialized) {
15220 a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
15221 a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
15222 if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
15223 onAnimationStart();
15226 final Transformation t = parent.getChildTransformation();
15227 boolean more = a.getTransformation(drawingTime, t, 1f);
15228 if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
15229 if (parent.mInvalidationTransformation == null) {
15230 parent.mInvalidationTransformation = new Transformation();
15232 invalidationTransform = parent.mInvalidationTransformation;
15233 a.getTransformation(drawingTime, invalidationTransform, 1f);
15235 invalidationTransform = t;
15239 if (!a.willChangeBounds()) {
15240 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
15241 ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
15242 parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
15243 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
15244 // The child need to draw an animation, potentially offscreen, so
15245 // make sure we do not cancel invalidate requests
15246 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
15247 parent.invalidate(mLeft, mTop, mRight, mBottom);
15250 if (parent.mInvalidateRegion == null) {
15251 parent.mInvalidateRegion = new RectF();
15253 final RectF region = parent.mInvalidateRegion;
15254 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
15255 invalidationTransform);
15257 // The child need to draw an animation, potentially offscreen, so
15258 // make sure we do not cancel invalidate requests
15259 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
15261 final int left = mLeft + (int) region.left;
15262 final int top = mTop + (int) region.top;
15263 parent.invalidate(left, top, left + (int) (region.width() + .5f),
15264 top + (int) (region.height() + .5f));
15271 * This method is called by getDisplayList() when a display list is recorded for a View.
15272 * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
15274 void setDisplayListProperties(RenderNode renderNode) {
15275 if (renderNode != null) {
15276 renderNode.setHasOverlappingRendering(hasOverlappingRendering());
15277 renderNode.setClipToBounds(mParent instanceof ViewGroup
15278 && ((ViewGroup) mParent).getClipChildren());
15281 if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
15282 ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
15283 ViewGroup parentVG = (ViewGroup) mParent;
15284 final Transformation t = parentVG.getChildTransformation();
15285 if (parentVG.getChildStaticTransformation(this, t)) {
15286 final int transformType = t.getTransformationType();
15287 if (transformType != Transformation.TYPE_IDENTITY) {
15288 if ((transformType & Transformation.TYPE_ALPHA) != 0) {
15289 alpha = t.getAlpha();
15291 if ((transformType & Transformation.TYPE_MATRIX) != 0) {
15292 renderNode.setStaticMatrix(t.getMatrix());
15297 if (mTransformationInfo != null) {
15298 alpha *= getFinalAlpha();
15300 final int multipliedAlpha = (int) (255 * alpha);
15301 if (onSetAlpha(multipliedAlpha)) {
15305 renderNode.setAlpha(alpha);
15306 } else if (alpha < 1) {
15307 renderNode.setAlpha(alpha);
15313 * This method is called by ViewGroup.drawChild() to have each child view draw itself.
15315 * This is where the View specializes rendering behavior based on layer type,
15316 * and hardware acceleration.
15318 boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
15319 final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
15320 /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
15322 * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
15323 * HW accelerated, it can't handle drawing RenderNodes.
15325 boolean drawingWithRenderNode = mAttachInfo != null
15326 && mAttachInfo.mHardwareAccelerated
15327 && hardwareAcceleratedCanvas;
15329 boolean more = false;
15330 final boolean childHasIdentityMatrix = hasIdentityMatrix();
15331 final int parentFlags = parent.mGroupFlags;
15333 if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
15334 parent.getChildTransformation().clear();
15335 parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15338 Transformation transformToApply = null;
15339 boolean concatMatrix = false;
15340 final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
15341 final Animation a = getAnimation();
15343 more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
15344 concatMatrix = a.willChangeTransformationMatrix();
15345 if (concatMatrix) {
15346 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
15348 transformToApply = parent.getChildTransformation();
15350 if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
15351 // No longer animating: clear out old animation matrix
15352 mRenderNode.setAnimationMatrix(null);
15353 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
15355 if (!drawingWithRenderNode
15356 && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
15357 final Transformation t = parent.getChildTransformation();
15358 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
15359 if (hasTransform) {
15360 final int transformType = t.getTransformationType();
15361 transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
15362 concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
15367 concatMatrix |= !childHasIdentityMatrix;
15369 // Sets the flag as early as possible to allow draw() implementations
15370 // to call invalidate() successfully when doing animations
15371 mPrivateFlags |= PFLAG_DRAWN;
15373 if (!concatMatrix &&
15374 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
15375 ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
15376 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
15377 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
15378 mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
15381 mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
15383 if (hardwareAcceleratedCanvas) {
15384 // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
15385 // retain the flag's value temporarily in the mRecreateDisplayList flag
15386 mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
15387 mPrivateFlags &= ~PFLAG_INVALIDATED;
15390 RenderNode renderNode = null;
15391 Bitmap cache = null;
15392 int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
15393 if (layerType == LAYER_TYPE_SOFTWARE
15394 || (!drawingWithRenderNode && layerType != LAYER_TYPE_NONE)) {
15395 // If not drawing with RenderNode, treat HW layers as SW
15396 layerType = LAYER_TYPE_SOFTWARE;
15397 buildDrawingCache(true);
15398 cache = getDrawingCache(true);
15401 if (drawingWithRenderNode) {
15402 // Delay getting the display list until animation-driven alpha values are
15403 // set up and possibly passed on to the view
15404 renderNode = getDisplayList();
15405 if (!renderNode.isValid()) {
15406 // Uncommon, but possible. If a view is removed from the hierarchy during the call
15407 // to getDisplayList(), the display list will be marked invalid and we should not
15408 // try to use it again.
15410 drawingWithRenderNode = false;
15416 if (!drawingWithRenderNode) {
15422 final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
15423 final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
15425 int restoreTo = -1;
15426 if (!drawingWithRenderNode || transformToApply != null) {
15427 restoreTo = canvas.save();
15429 if (offsetForScroll) {
15430 canvas.translate(mLeft - sx, mTop - sy);
15432 if (!drawingWithRenderNode) {
15433 canvas.translate(mLeft, mTop);
15435 if (scalingRequired) {
15436 if (drawingWithRenderNode) {
15437 // TODO: Might not need this if we put everything inside the DL
15438 restoreTo = canvas.save();
15440 // mAttachInfo cannot be null, otherwise scalingRequired == false
15441 final float scale = 1.0f / mAttachInfo.mApplicationScale;
15442 canvas.scale(scale, scale);
15446 float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
15447 if (transformToApply != null
15449 || !hasIdentityMatrix()
15450 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
15451 if (transformToApply != null || !childHasIdentityMatrix) {
15455 if (offsetForScroll) {
15460 if (transformToApply != null) {
15461 if (concatMatrix) {
15462 if (drawingWithRenderNode) {
15463 renderNode.setAnimationMatrix(transformToApply.getMatrix());
15465 // Undo the scroll translation, apply the transformation matrix,
15466 // then redo the scroll translate to get the correct result.
15467 canvas.translate(-transX, -transY);
15468 canvas.concat(transformToApply.getMatrix());
15469 canvas.translate(transX, transY);
15471 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15474 float transformAlpha = transformToApply.getAlpha();
15475 if (transformAlpha < 1) {
15476 alpha *= transformAlpha;
15477 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15481 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
15482 canvas.translate(-transX, -transY);
15483 canvas.concat(getMatrix());
15484 canvas.translate(transX, transY);
15488 // Deal with alpha if it is or used to be <1
15489 if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
15491 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
15493 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
15495 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15496 if (!drawingWithDrawingCache) {
15497 final int multipliedAlpha = (int) (255 * alpha);
15498 if (!onSetAlpha(multipliedAlpha)) {
15499 if (drawingWithRenderNode) {
15500 renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
15501 } else if (layerType == LAYER_TYPE_NONE) {
15502 int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
15503 if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0) {
15504 layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
15506 canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
15507 multipliedAlpha, layerFlags);
15510 // Alpha is handled by the child directly, clobber the layer's alpha
15511 mPrivateFlags |= PFLAG_ALPHA_SET;
15515 } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
15517 mPrivateFlags &= ~PFLAG_ALPHA_SET;
15520 if (!drawingWithRenderNode) {
15521 // apply clips directly, since RenderNode won't do it for this draw
15522 if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
15523 if (offsetForScroll) {
15524 canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
15526 if (!scalingRequired || cache == null) {
15527 canvas.clipRect(0, 0, getWidth(), getHeight());
15529 canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
15534 if (mClipBounds != null) {
15535 // clip bounds ignore scroll
15536 canvas.clipRect(mClipBounds);
15540 if (!drawingWithDrawingCache) {
15541 if (drawingWithRenderNode) {
15542 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15543 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
15545 // Fast path for layouts with no backgrounds
15546 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15547 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15548 dispatchDraw(canvas);
15553 } else if (cache != null) {
15554 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15556 int restoreAlpha = 0;
15558 if (layerType == LAYER_TYPE_NONE) {
15559 cachePaint = parent.mCachePaint;
15560 if (cachePaint == null) {
15561 cachePaint = new Paint();
15562 cachePaint.setDither(false);
15563 parent.mCachePaint = cachePaint;
15566 cachePaint = mLayerPaint;
15567 restoreAlpha = mLayerPaint.getAlpha();
15569 cachePaint.setAlpha((int) (alpha * 255));
15570 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
15571 cachePaint.setAlpha(restoreAlpha);
15574 if (restoreTo >= 0) {
15575 canvas.restoreToCount(restoreTo);
15578 if (a != null && !more) {
15579 if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
15582 parent.finishAnimatingView(this, a);
15585 if (more && hardwareAcceleratedCanvas) {
15586 if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
15587 // alpha animations should cause the child to recreate its display list
15592 mRecreateDisplayList = false;
15598 * Manually render this view (and all of its children) to the given Canvas.
15599 * The view must have already done a full layout before this function is
15600 * called. When implementing a view, implement
15601 * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
15602 * If you do need to override this method, call the superclass version.
15604 * @param canvas The Canvas to which the View is rendered.
15607 public void draw(Canvas canvas) {
15608 final int privateFlags = mPrivateFlags;
15609 final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
15610 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
15611 mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
15614 * Draw traversal performs several drawing steps which must be executed
15615 * in the appropriate order:
15617 * 1. Draw the background
15618 * 2. If necessary, save the canvas' layers to prepare for fading
15619 * 3. Draw view's content
15621 * 5. If necessary, draw the fading edges and restore layers
15622 * 6. Draw decorations (scrollbars for instance)
15625 // Step 1, draw the background, if needed
15628 if (!dirtyOpaque) {
15629 drawBackground(canvas);
15632 // skip step 2 & 5 if possible (common case)
15633 final int viewFlags = mViewFlags;
15634 boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
15635 boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
15636 if (!verticalEdges && !horizontalEdges) {
15637 // Step 3, draw the content
15638 if (!dirtyOpaque) onDraw(canvas);
15640 // Step 4, draw the children
15641 dispatchDraw(canvas);
15643 // Overlay is part of the content and draws beneath Foreground
15644 if (mOverlay != null && !mOverlay.isEmpty()) {
15645 mOverlay.getOverlayView().dispatchDraw(canvas);
15648 // Step 6, draw decorations (foreground, scrollbars)
15649 onDrawForeground(canvas);
15656 * Here we do the full fledged routine...
15657 * (this is an uncommon case where speed matters less,
15658 * this is why we repeat some of the tests that have been
15662 boolean drawTop = false;
15663 boolean drawBottom = false;
15664 boolean drawLeft = false;
15665 boolean drawRight = false;
15667 float topFadeStrength = 0.0f;
15668 float bottomFadeStrength = 0.0f;
15669 float leftFadeStrength = 0.0f;
15670 float rightFadeStrength = 0.0f;
15672 // Step 2, save the canvas' layers
15673 int paddingLeft = mPaddingLeft;
15675 final boolean offsetRequired = isPaddingOffsetRequired();
15676 if (offsetRequired) {
15677 paddingLeft += getLeftPaddingOffset();
15680 int left = mScrollX + paddingLeft;
15681 int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
15682 int top = mScrollY + getFadeTop(offsetRequired);
15683 int bottom = top + getFadeHeight(offsetRequired);
15685 if (offsetRequired) {
15686 right += getRightPaddingOffset();
15687 bottom += getBottomPaddingOffset();
15690 final ScrollabilityCache scrollabilityCache = mScrollCache;
15691 final float fadeHeight = scrollabilityCache.fadingEdgeLength;
15692 int length = (int) fadeHeight;
15694 // clip the fade length if top and bottom fades overlap
15695 // overlapping fades produce odd-looking artifacts
15696 if (verticalEdges && (top + length > bottom - length)) {
15697 length = (bottom - top) / 2;
15700 // also clip horizontal fades if necessary
15701 if (horizontalEdges && (left + length > right - length)) {
15702 length = (right - left) / 2;
15705 if (verticalEdges) {
15706 topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
15707 drawTop = topFadeStrength * fadeHeight > 1.0f;
15708 bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
15709 drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
15712 if (horizontalEdges) {
15713 leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
15714 drawLeft = leftFadeStrength * fadeHeight > 1.0f;
15715 rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
15716 drawRight = rightFadeStrength * fadeHeight > 1.0f;
15719 saveCount = canvas.getSaveCount();
15721 int solidColor = getSolidColor();
15722 if (solidColor == 0) {
15723 final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
15726 canvas.saveLayer(left, top, right, top + length, null, flags);
15730 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
15734 canvas.saveLayer(left, top, left + length, bottom, null, flags);
15738 canvas.saveLayer(right - length, top, right, bottom, null, flags);
15741 scrollabilityCache.setFadeColor(solidColor);
15744 // Step 3, draw the content
15745 if (!dirtyOpaque) onDraw(canvas);
15747 // Step 4, draw the children
15748 dispatchDraw(canvas);
15750 // Step 5, draw the fade effect and restore layers
15751 final Paint p = scrollabilityCache.paint;
15752 final Matrix matrix = scrollabilityCache.matrix;
15753 final Shader fade = scrollabilityCache.shader;
15756 matrix.setScale(1, fadeHeight * topFadeStrength);
15757 matrix.postTranslate(left, top);
15758 fade.setLocalMatrix(matrix);
15760 canvas.drawRect(left, top, right, top + length, p);
15764 matrix.setScale(1, fadeHeight * bottomFadeStrength);
15765 matrix.postRotate(180);
15766 matrix.postTranslate(left, bottom);
15767 fade.setLocalMatrix(matrix);
15769 canvas.drawRect(left, bottom - length, right, bottom, p);
15773 matrix.setScale(1, fadeHeight * leftFadeStrength);
15774 matrix.postRotate(-90);
15775 matrix.postTranslate(left, top);
15776 fade.setLocalMatrix(matrix);
15778 canvas.drawRect(left, top, left + length, bottom, p);
15782 matrix.setScale(1, fadeHeight * rightFadeStrength);
15783 matrix.postRotate(90);
15784 matrix.postTranslate(right, top);
15785 fade.setLocalMatrix(matrix);
15787 canvas.drawRect(right - length, top, right, bottom, p);
15790 canvas.restoreToCount(saveCount);
15792 // Overlay is part of the content and draws beneath Foreground
15793 if (mOverlay != null && !mOverlay.isEmpty()) {
15794 mOverlay.getOverlayView().dispatchDraw(canvas);
15797 // Step 6, draw decorations (foreground, scrollbars)
15798 onDrawForeground(canvas);
15802 * Draws the background onto the specified canvas.
15804 * @param canvas Canvas on which to draw the background
15806 private void drawBackground(Canvas canvas) {
15807 final Drawable background = mBackground;
15808 if (background == null) {
15812 setBackgroundBounds();
15814 // Attempt to use a display list if requested.
15815 if (canvas.isHardwareAccelerated() && mAttachInfo != null
15816 && mAttachInfo.mHardwareRenderer != null) {
15817 mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
15819 final RenderNode renderNode = mBackgroundRenderNode;
15820 if (renderNode != null && renderNode.isValid()) {
15821 setBackgroundRenderNodeProperties(renderNode);
15822 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
15827 final int scrollX = mScrollX;
15828 final int scrollY = mScrollY;
15829 if ((scrollX | scrollY) == 0) {
15830 background.draw(canvas);
15832 canvas.translate(scrollX, scrollY);
15833 background.draw(canvas);
15834 canvas.translate(-scrollX, -scrollY);
15839 * Sets the correct background bounds and rebuilds the outline, if needed.
15841 * This is called by LayoutLib.
15843 void setBackgroundBounds() {
15844 if (mBackgroundSizeChanged && mBackground != null) {
15845 mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
15846 mBackgroundSizeChanged = false;
15851 private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
15852 renderNode.setTranslationX(mScrollX);
15853 renderNode.setTranslationY(mScrollY);
15857 * Creates a new display list or updates the existing display list for the
15858 * specified Drawable.
15860 * @param drawable Drawable for which to create a display list
15861 * @param renderNode Existing RenderNode, or {@code null}
15862 * @return A valid display list for the specified drawable
15864 private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
15865 if (renderNode == null) {
15866 renderNode = RenderNode.create(drawable.getClass().getName(), this);
15869 final Rect bounds = drawable.getBounds();
15870 final int width = bounds.width();
15871 final int height = bounds.height();
15872 final DisplayListCanvas canvas = renderNode.start(width, height);
15874 // Reverse left/top translation done by drawable canvas, which will
15875 // instead be applied by rendernode's LTRB bounds below. This way, the
15876 // drawable's bounds match with its rendernode bounds and its content
15877 // will lie within those bounds in the rendernode tree.
15878 canvas.translate(-bounds.left, -bounds.top);
15881 drawable.draw(canvas);
15883 renderNode.end(canvas);
15886 // Set up drawable properties that are view-independent.
15887 renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
15888 renderNode.setProjectBackwards(drawable.isProjected());
15889 renderNode.setProjectionReceiver(true);
15890 renderNode.setClipToBounds(false);
15895 * Returns the overlay for this view, creating it if it does not yet exist.
15896 * Adding drawables to the overlay will cause them to be displayed whenever
15897 * the view itself is redrawn. Objects in the overlay should be actively
15898 * managed: remove them when they should not be displayed anymore. The
15899 * overlay will always have the same size as its host view.
15901 * <p>Note: Overlays do not currently work correctly with {@link
15902 * SurfaceView} or {@link TextureView}; contents in overlays for these
15903 * types of views may not display correctly.</p>
15905 * @return The ViewOverlay object for this view.
15908 public ViewOverlay getOverlay() {
15909 if (mOverlay == null) {
15910 mOverlay = new ViewOverlay(mContext, this);
15916 * Override this if your view is known to always be drawn on top of a solid color background,
15917 * and needs to draw fading edges. Returning a non-zero color enables the view system to
15918 * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
15919 * should be set to 0xFF.
15921 * @see #setVerticalFadingEdgeEnabled(boolean)
15922 * @see #setHorizontalFadingEdgeEnabled(boolean)
15924 * @return The known solid color background for this view, or 0 if the color may vary
15926 @ViewDebug.ExportedProperty(category = "drawing")
15928 public int getSolidColor() {
15933 * Build a human readable string representation of the specified view flags.
15935 * @param flags the view flags to convert to a string
15936 * @return a String representing the supplied flags
15938 private static String printFlags(int flags) {
15939 String output = "";
15941 if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
15942 output += "TAKES_FOCUS";
15946 switch (flags & VISIBILITY_MASK) {
15948 if (numFlags > 0) {
15951 output += "INVISIBLE";
15952 // USELESS HERE numFlags++;
15955 if (numFlags > 0) {
15959 // USELESS HERE numFlags++;
15968 * Build a human readable string representation of the specified private
15971 * @param privateFlags the private view flags to convert to a string
15972 * @return a String representing the supplied flags
15974 private static String printPrivateFlags(int privateFlags) {
15975 String output = "";
15978 if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
15979 output += "WANTS_FOCUS";
15983 if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
15984 if (numFlags > 0) {
15987 output += "FOCUSED";
15991 if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
15992 if (numFlags > 0) {
15995 output += "SELECTED";
15999 if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
16000 if (numFlags > 0) {
16003 output += "IS_ROOT_NAMESPACE";
16007 if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
16008 if (numFlags > 0) {
16011 output += "HAS_BOUNDS";
16015 if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
16016 if (numFlags > 0) {
16020 // USELESS HERE numFlags++;
16026 * <p>Indicates whether or not this view's layout will be requested during
16027 * the next hierarchy layout pass.</p>
16029 * @return true if the layout will be forced during next layout pass
16031 public boolean isLayoutRequested() {
16032 return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
16036 * Return true if o is a ViewGroup that is laying out using optical bounds.
16039 public static boolean isLayoutModeOptical(Object o) {
16040 return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
16043 private boolean setOpticalFrame(int left, int top, int right, int bottom) {
16044 Insets parentInsets = mParent instanceof View ?
16045 ((View) mParent).getOpticalInsets() : Insets.NONE;
16046 Insets childInsets = getOpticalInsets();
16048 left + parentInsets.left - childInsets.left,
16049 top + parentInsets.top - childInsets.top,
16050 right + parentInsets.left + childInsets.right,
16051 bottom + parentInsets.top + childInsets.bottom);
16055 * Assign a size and position to a view and all of its
16058 * <p>This is the second phase of the layout mechanism.
16059 * (The first is measuring). In this phase, each parent calls
16060 * layout on all of its children to position them.
16061 * This is typically done using the child measurements
16062 * that were stored in the measure pass().</p>
16064 * <p>Derived classes should not override this method.
16065 * Derived classes with children should override
16066 * onLayout. In that method, they should
16067 * call layout on each of their children.</p>
16069 * @param l Left position, relative to parent
16070 * @param t Top position, relative to parent
16071 * @param r Right position, relative to parent
16072 * @param b Bottom position, relative to parent
16074 @SuppressWarnings({"unchecked"})
16075 public void layout(int l, int t, int r, int b) {
16076 if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
16077 onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
16078 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
16083 int oldB = mBottom;
16086 boolean changed = isLayoutModeOptical(mParent) ?
16087 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
16089 if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
16090 onLayout(changed, l, t, r, b);
16091 mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
16093 ListenerInfo li = mListenerInfo;
16094 if (li != null && li.mOnLayoutChangeListeners != null) {
16095 ArrayList<OnLayoutChangeListener> listenersCopy =
16096 (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
16097 int numListeners = listenersCopy.size();
16098 for (int i = 0; i < numListeners; ++i) {
16099 listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
16104 mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
16105 mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
16109 * Called from layout when this view should
16110 * assign a size and position to each of its children.
16112 * Derived classes with children should override
16113 * this method and call layout on each of
16115 * @param changed This is a new size or position for this view
16116 * @param left Left position, relative to parent
16117 * @param top Top position, relative to parent
16118 * @param right Right position, relative to parent
16119 * @param bottom Bottom position, relative to parent
16121 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
16125 * Assign a size and position to this view.
16127 * This is called from layout.
16129 * @param left Left position, relative to parent
16130 * @param top Top position, relative to parent
16131 * @param right Right position, relative to parent
16132 * @param bottom Bottom position, relative to parent
16133 * @return true if the new size and position are different than the
16137 protected boolean setFrame(int left, int top, int right, int bottom) {
16138 boolean changed = false;
16141 Log.d("View", this + " View.setFrame(" + left + "," + top + ","
16142 + right + "," + bottom + ")");
16145 if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
16148 // Remember our drawn bit
16149 int drawn = mPrivateFlags & PFLAG_DRAWN;
16151 int oldWidth = mRight - mLeft;
16152 int oldHeight = mBottom - mTop;
16153 int newWidth = right - left;
16154 int newHeight = bottom - top;
16155 boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
16157 // Invalidate our old position
16158 invalidate(sizeChanged);
16164 mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
16166 mPrivateFlags |= PFLAG_HAS_BOUNDS;
16170 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
16173 if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
16174 // If we are visible, force the DRAWN bit to on so that
16175 // this invalidate will go through (at least to our parent).
16176 // This is because someone may have invalidated this view
16177 // before this call to setFrame came in, thereby clearing
16179 mPrivateFlags |= PFLAG_DRAWN;
16180 invalidate(sizeChanged);
16181 // parent display list may need to be recreated based on a change in the bounds
16183 invalidateParentCaches();
16186 // Reset drawn bit to original value (invalidate turns it off)
16187 mPrivateFlags |= drawn;
16189 mBackgroundSizeChanged = true;
16190 if (mForegroundInfo != null) {
16191 mForegroundInfo.mBoundsChanged = true;
16194 notifySubtreeAccessibilityStateChangedIfNeeded();
16200 * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
16203 public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
16204 setFrame(left, top, right, bottom);
16207 private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
16208 onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
16209 if (mOverlay != null) {
16210 mOverlay.getOverlayView().setRight(newWidth);
16211 mOverlay.getOverlayView().setBottom(newHeight);
16217 * Finalize inflating a view from XML. This is called as the last phase
16218 * of inflation, after all child views have been added.
16220 * <p>Even if the subclass overrides onFinishInflate, they should always be
16221 * sure to call the super method, so that we get called.
16224 protected void onFinishInflate() {
16228 * Returns the resources associated with this view.
16230 * @return Resources object.
16232 public Resources getResources() {
16237 * Invalidates the specified Drawable.
16239 * @param drawable the drawable to invalidate
16242 public void invalidateDrawable(@NonNull Drawable drawable) {
16243 if (verifyDrawable(drawable)) {
16244 final Rect dirty = drawable.getDirtyBounds();
16245 final int scrollX = mScrollX;
16246 final int scrollY = mScrollY;
16248 invalidate(dirty.left + scrollX, dirty.top + scrollY,
16249 dirty.right + scrollX, dirty.bottom + scrollY);
16255 * Schedules an action on a drawable to occur at a specified time.
16257 * @param who the recipient of the action
16258 * @param what the action to run on the drawable
16259 * @param when the time at which the action must occur. Uses the
16260 * {@link SystemClock#uptimeMillis} timebase.
16263 public void scheduleDrawable(Drawable who, Runnable what, long when) {
16264 if (verifyDrawable(who) && what != null) {
16265 final long delay = when - SystemClock.uptimeMillis();
16266 if (mAttachInfo != null) {
16267 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
16268 Choreographer.CALLBACK_ANIMATION, what, who,
16269 Choreographer.subtractFrameDelay(delay));
16271 ViewRootImpl.getRunQueue().postDelayed(what, delay);
16277 * Cancels a scheduled action on a drawable.
16279 * @param who the recipient of the action
16280 * @param what the action to cancel
16283 public void unscheduleDrawable(Drawable who, Runnable what) {
16284 if (verifyDrawable(who) && what != null) {
16285 if (mAttachInfo != null) {
16286 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
16287 Choreographer.CALLBACK_ANIMATION, what, who);
16289 ViewRootImpl.getRunQueue().removeCallbacks(what);
16294 * Unschedule any events associated with the given Drawable. This can be
16295 * used when selecting a new Drawable into a view, so that the previous
16296 * one is completely unscheduled.
16298 * @param who The Drawable to unschedule.
16300 * @see #drawableStateChanged
16302 public void unscheduleDrawable(Drawable who) {
16303 if (mAttachInfo != null && who != null) {
16304 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
16305 Choreographer.CALLBACK_ANIMATION, null, who);
16310 * Resolve the Drawables depending on the layout direction. This is implicitly supposing
16311 * that the View directionality can and will be resolved before its Drawables.
16313 * Will call {@link View#onResolveDrawables} when resolution is done.
16317 protected void resolveDrawables() {
16318 // Drawables resolution may need to happen before resolving the layout direction (which is
16319 // done only during the measure() call).
16320 // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
16321 // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
16322 // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
16323 // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
16324 // direction to be resolved as its resolved value will be the same as its raw value.
16325 if (!isLayoutDirectionResolved() &&
16326 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
16330 final int layoutDirection = isLayoutDirectionResolved() ?
16331 getLayoutDirection() : getRawLayoutDirection();
16333 if (mBackground != null) {
16334 mBackground.setLayoutDirection(layoutDirection);
16336 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
16337 mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
16339 mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
16340 onResolveDrawables(layoutDirection);
16343 boolean areDrawablesResolved() {
16344 return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
16348 * Called when layout direction has been resolved.
16350 * The default implementation does nothing.
16352 * @param layoutDirection The resolved layout direction.
16354 * @see #LAYOUT_DIRECTION_LTR
16355 * @see #LAYOUT_DIRECTION_RTL
16359 public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
16365 protected void resetResolvedDrawables() {
16366 resetResolvedDrawablesInternal();
16369 void resetResolvedDrawablesInternal() {
16370 mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
16374 * If your view subclass is displaying its own Drawable objects, it should
16375 * override this function and return true for any Drawable it is
16376 * displaying. This allows animations for those drawables to be
16379 * <p>Be sure to call through to the super class when overriding this
16382 * @param who The Drawable to verify. Return true if it is one you are
16383 * displaying, else return the result of calling through to the
16386 * @return boolean If true than the Drawable is being displayed in the
16387 * view; else false and it is not allowed to animate.
16389 * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
16390 * @see #drawableStateChanged()
16393 protected boolean verifyDrawable(Drawable who) {
16394 return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who)
16395 || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
16399 * This function is called whenever the state of the view changes in such
16400 * a way that it impacts the state of drawables being shown.
16402 * If the View has a StateListAnimator, it will also be called to run necessary state
16403 * change animations.
16405 * Be sure to call through to the superclass when overriding this function.
16407 * @see Drawable#setState(int[])
16410 protected void drawableStateChanged() {
16411 final int[] state = getDrawableState();
16413 final Drawable bg = mBackground;
16414 if (bg != null && bg.isStateful()) {
16415 bg.setState(state);
16418 final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
16419 if (fg != null && fg.isStateful()) {
16420 fg.setState(state);
16423 if (mScrollCache != null) {
16424 final Drawable scrollBar = mScrollCache.scrollBar;
16425 if (scrollBar != null && scrollBar.isStateful()) {
16426 scrollBar.setState(state);
16430 if (mStateListAnimator != null) {
16431 mStateListAnimator.setState(state);
16436 * This function is called whenever the view hotspot changes and needs to
16437 * be propagated to drawables or child views managed by the view.
16439 * Dispatching to child views is handled by
16440 * {@link #dispatchDrawableHotspotChanged(float, float)}.
16442 * Be sure to call through to the superclass when overriding this function.
16444 * @param x hotspot x coordinate
16445 * @param y hotspot y coordinate
16448 public void drawableHotspotChanged(float x, float y) {
16449 if (mBackground != null) {
16450 mBackground.setHotspot(x, y);
16452 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
16453 mForegroundInfo.mDrawable.setHotspot(x, y);
16456 dispatchDrawableHotspotChanged(x, y);
16460 * Dispatches drawableHotspotChanged to all of this View's children.
16462 * @param x hotspot x coordinate
16463 * @param y hotspot y coordinate
16464 * @see #drawableHotspotChanged(float, float)
16466 public void dispatchDrawableHotspotChanged(float x, float y) {
16470 * Call this to force a view to update its drawable state. This will cause
16471 * drawableStateChanged to be called on this view. Views that are interested
16472 * in the new state should call getDrawableState.
16474 * @see #drawableStateChanged
16475 * @see #getDrawableState
16477 public void refreshDrawableState() {
16478 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
16479 drawableStateChanged();
16481 ViewParent parent = mParent;
16482 if (parent != null) {
16483 parent.childDrawableStateChanged(this);
16488 * Return an array of resource IDs of the drawable states representing the
16489 * current state of the view.
16491 * @return The current drawable state
16493 * @see Drawable#setState(int[])
16494 * @see #drawableStateChanged()
16495 * @see #onCreateDrawableState(int)
16497 public final int[] getDrawableState() {
16498 if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
16499 return mDrawableState;
16501 mDrawableState = onCreateDrawableState(0);
16502 mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
16503 return mDrawableState;
16508 * Generate the new {@link android.graphics.drawable.Drawable} state for
16509 * this view. This is called by the view
16510 * system when the cached Drawable state is determined to be invalid. To
16511 * retrieve the current state, you should use {@link #getDrawableState}.
16513 * @param extraSpace if non-zero, this is the number of extra entries you
16514 * would like in the returned array in which you can place your own
16517 * @return Returns an array holding the current {@link Drawable} state of
16520 * @see #mergeDrawableStates(int[], int[])
16522 protected int[] onCreateDrawableState(int extraSpace) {
16523 if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
16524 mParent instanceof View) {
16525 return ((View) mParent).onCreateDrawableState(extraSpace);
16528 int[] drawableState;
16530 int privateFlags = mPrivateFlags;
16532 int viewStateIndex = 0;
16533 if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
16534 if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
16535 if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
16536 if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
16537 if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
16538 if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
16539 if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
16540 HardwareRenderer.isAvailable()) {
16541 // This is set if HW acceleration is requested, even if the current
16542 // process doesn't allow it. This is just to allow app preview
16543 // windows to better match their app.
16544 viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
16546 if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
16548 final int privateFlags2 = mPrivateFlags2;
16549 if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
16550 viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
16552 if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
16553 viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
16556 drawableState = StateSet.get(viewStateIndex);
16558 //noinspection ConstantIfStatement
16560 Log.i("View", "drawableStateIndex=" + viewStateIndex);
16561 Log.i("View", toString()
16562 + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
16563 + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
16564 + " fo=" + hasFocus()
16565 + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
16566 + " wf=" + hasWindowFocus()
16567 + ": " + Arrays.toString(drawableState));
16570 if (extraSpace == 0) {
16571 return drawableState;
16574 final int[] fullState;
16575 if (drawableState != null) {
16576 fullState = new int[drawableState.length + extraSpace];
16577 System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
16579 fullState = new int[extraSpace];
16586 * Merge your own state values in <var>additionalState</var> into the base
16587 * state values <var>baseState</var> that were returned by
16588 * {@link #onCreateDrawableState(int)}.
16590 * @param baseState The base state values returned by
16591 * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
16592 * own additional state values.
16594 * @param additionalState The additional state values you would like
16595 * added to <var>baseState</var>; this array is not modified.
16597 * @return As a convenience, the <var>baseState</var> array you originally
16598 * passed into the function is returned.
16600 * @see #onCreateDrawableState(int)
16602 protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
16603 final int N = baseState.length;
16605 while (i >= 0 && baseState[i] == 0) {
16608 System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
16613 * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
16614 * on all Drawable objects associated with this view.
16616 * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
16617 * attached to this view.
16619 public void jumpDrawablesToCurrentState() {
16620 if (mBackground != null) {
16621 mBackground.jumpToCurrentState();
16623 if (mStateListAnimator != null) {
16624 mStateListAnimator.jumpToCurrentState();
16626 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
16627 mForegroundInfo.mDrawable.jumpToCurrentState();
16632 * Sets the background color for this view.
16633 * @param color the color of the background
16635 @RemotableViewMethod
16636 public void setBackgroundColor(@ColorInt int color) {
16637 if (mBackground instanceof ColorDrawable) {
16638 ((ColorDrawable) mBackground.mutate()).setColor(color);
16639 computeOpaqueFlags();
16640 mBackgroundResource = 0;
16642 setBackground(new ColorDrawable(color));
16647 * If the view has a ColorDrawable background, returns the color of that
16650 * @return The color of the ColorDrawable background, if set, otherwise 0.
16653 public int getBackgroundColor() {
16654 if (mBackground instanceof ColorDrawable) {
16655 return ((ColorDrawable) mBackground).getColor();
16661 * Set the background to a given resource. The resource should refer to
16662 * a Drawable object or 0 to remove the background.
16663 * @param resid The identifier of the resource.
16665 * @attr ref android.R.styleable#View_background
16667 @RemotableViewMethod
16668 public void setBackgroundResource(@DrawableRes int resid) {
16669 if (resid != 0 && resid == mBackgroundResource) {
16675 d = mContext.getDrawable(resid);
16679 mBackgroundResource = resid;
16683 * Set the background to a given Drawable, or remove the background. If the
16684 * background has padding, this View's padding is set to the background's
16685 * padding. However, when a background is removed, this View's padding isn't
16686 * touched. If setting the padding is desired, please use
16687 * {@link #setPadding(int, int, int, int)}.
16689 * @param background The Drawable to use as the background, or null to remove the
16692 public void setBackground(Drawable background) {
16693 //noinspection deprecation
16694 setBackgroundDrawable(background);
16698 * @deprecated use {@link #setBackground(Drawable)} instead
16701 public void setBackgroundDrawable(Drawable background) {
16702 computeOpaqueFlags();
16704 if (background == mBackground) {
16708 boolean requestLayout = false;
16710 mBackgroundResource = 0;
16713 * Regardless of whether we're setting a new background or not, we want
16714 * to clear the previous drawable.
16716 if (mBackground != null) {
16717 mBackground.setCallback(null);
16718 unscheduleDrawable(mBackground);
16721 if (background != null) {
16722 Rect padding = sThreadLocal.get();
16723 if (padding == null) {
16724 padding = new Rect();
16725 sThreadLocal.set(padding);
16727 resetResolvedDrawablesInternal();
16728 background.setLayoutDirection(getLayoutDirection());
16729 if (background.getPadding(padding)) {
16730 resetResolvedPaddingInternal();
16731 switch (background.getLayoutDirection()) {
16732 case LAYOUT_DIRECTION_RTL:
16733 mUserPaddingLeftInitial = padding.right;
16734 mUserPaddingRightInitial = padding.left;
16735 internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
16737 case LAYOUT_DIRECTION_LTR:
16739 mUserPaddingLeftInitial = padding.left;
16740 mUserPaddingRightInitial = padding.right;
16741 internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
16743 mLeftPaddingDefined = false;
16744 mRightPaddingDefined = false;
16747 // Compare the minimum sizes of the old Drawable and the new. If there isn't an old or
16748 // if it has a different minimum size, we should layout again
16749 if (mBackground == null
16750 || mBackground.getMinimumHeight() != background.getMinimumHeight()
16751 || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
16752 requestLayout = true;
16755 background.setCallback(this);
16756 if (background.isStateful()) {
16757 background.setState(getDrawableState());
16759 background.setVisible(getVisibility() == VISIBLE, false);
16760 mBackground = background;
16762 applyBackgroundTint();
16764 if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
16765 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
16766 mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
16767 requestLayout = true;
16770 /* Remove the background */
16771 mBackground = null;
16773 if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) {
16775 * This view ONLY drew the background before and we're removing
16776 * the background, so now it won't draw anything
16777 * (hence we SKIP_DRAW)
16779 mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND;
16780 mPrivateFlags |= PFLAG_SKIP_DRAW;
16784 * When the background is set, we try to apply its padding to this
16785 * View. When the background is removed, we don't touch this View's
16786 * padding. This is noted in the Javadocs. Hence, we don't need to
16787 * requestLayout(), the invalidate() below is sufficient.
16790 // The old background's minimum size could have affected this
16791 // View's layout, so let's requestLayout
16792 requestLayout = true;
16795 computeOpaqueFlags();
16797 if (requestLayout) {
16801 mBackgroundSizeChanged = true;
16806 * Gets the background drawable
16808 * @return The drawable used as the background for this view, if any.
16810 * @see #setBackground(Drawable)
16812 * @attr ref android.R.styleable#View_background
16814 public Drawable getBackground() {
16815 return mBackground;
16819 * Applies a tint to the background drawable. Does not modify the current tint
16820 * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
16822 * Subsequent calls to {@link #setBackground(Drawable)} will automatically
16823 * mutate the drawable and apply the specified tint and tint mode using
16824 * {@link Drawable#setTintList(ColorStateList)}.
16826 * @param tint the tint to apply, may be {@code null} to clear tint
16828 * @attr ref android.R.styleable#View_backgroundTint
16829 * @see #getBackgroundTintList()
16830 * @see Drawable#setTintList(ColorStateList)
16832 public void setBackgroundTintList(@Nullable ColorStateList tint) {
16833 if (mBackgroundTint == null) {
16834 mBackgroundTint = new TintInfo();
16836 mBackgroundTint.mTintList = tint;
16837 mBackgroundTint.mHasTintList = true;
16839 applyBackgroundTint();
16843 * Return the tint applied to the background drawable, if specified.
16845 * @return the tint applied to the background drawable
16846 * @attr ref android.R.styleable#View_backgroundTint
16847 * @see #setBackgroundTintList(ColorStateList)
16850 public ColorStateList getBackgroundTintList() {
16851 return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
16855 * Specifies the blending mode used to apply the tint specified by
16856 * {@link #setBackgroundTintList(ColorStateList)}} to the background
16857 * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
16859 * @param tintMode the blending mode used to apply the tint, may be
16860 * {@code null} to clear tint
16861 * @attr ref android.R.styleable#View_backgroundTintMode
16862 * @see #getBackgroundTintMode()
16863 * @see Drawable#setTintMode(PorterDuff.Mode)
16865 public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
16866 if (mBackgroundTint == null) {
16867 mBackgroundTint = new TintInfo();
16869 mBackgroundTint.mTintMode = tintMode;
16870 mBackgroundTint.mHasTintMode = true;
16872 applyBackgroundTint();
16876 * Return the blending mode used to apply the tint to the background
16877 * drawable, if specified.
16879 * @return the blending mode used to apply the tint to the background
16881 * @attr ref android.R.styleable#View_backgroundTintMode
16882 * @see #setBackgroundTintMode(PorterDuff.Mode)
16885 public PorterDuff.Mode getBackgroundTintMode() {
16886 return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
16889 private void applyBackgroundTint() {
16890 if (mBackground != null && mBackgroundTint != null) {
16891 final TintInfo tintInfo = mBackgroundTint;
16892 if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
16893 mBackground = mBackground.mutate();
16895 if (tintInfo.mHasTintList) {
16896 mBackground.setTintList(tintInfo.mTintList);
16899 if (tintInfo.mHasTintMode) {
16900 mBackground.setTintMode(tintInfo.mTintMode);
16903 // The drawable (or one of its children) may not have been
16904 // stateful before applying the tint, so let's try again.
16905 if (mBackground.isStateful()) {
16906 mBackground.setState(getDrawableState());
16913 * Returns the drawable used as the foreground of this View. The
16914 * foreground drawable, if non-null, is always drawn on top of the view's content.
16916 * @return a Drawable or null if no foreground was set
16918 * @see #onDrawForeground(Canvas)
16920 public Drawable getForeground() {
16921 return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
16925 * Supply a Drawable that is to be rendered on top of all of the content in the view.
16927 * @param foreground the Drawable to be drawn on top of the children
16929 * @attr ref android.R.styleable#View_foreground
16931 public void setForeground(Drawable foreground) {
16932 if (mForegroundInfo == null) {
16933 if (foreground == null) {
16937 mForegroundInfo = new ForegroundInfo();
16940 if (foreground == mForegroundInfo.mDrawable) {
16945 if (mForegroundInfo.mDrawable != null) {
16946 mForegroundInfo.mDrawable.setCallback(null);
16947 unscheduleDrawable(mForegroundInfo.mDrawable);
16950 mForegroundInfo.mDrawable = foreground;
16951 mForegroundInfo.mBoundsChanged = true;
16952 if (foreground != null) {
16953 setWillNotDraw(false);
16954 foreground.setCallback(this);
16955 foreground.setLayoutDirection(getLayoutDirection());
16956 if (foreground.isStateful()) {
16957 foreground.setState(getDrawableState());
16959 applyForegroundTint();
16966 * Magic bit used to support features of framework-internal window decor implementation details.
16967 * This used to live exclusively in FrameLayout.
16969 * @return true if the foreground should draw inside the padding region or false
16970 * if it should draw inset by the view's padding
16971 * @hide internal use only; only used by FrameLayout and internal screen layouts.
16973 public boolean isForegroundInsidePadding() {
16974 return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
16978 * Describes how the foreground is positioned.
16980 * @return foreground gravity.
16982 * @see #setForegroundGravity(int)
16984 * @attr ref android.R.styleable#View_foregroundGravity
16986 public int getForegroundGravity() {
16987 return mForegroundInfo != null ? mForegroundInfo.mGravity
16988 : Gravity.START | Gravity.TOP;
16992 * Describes how the foreground is positioned. Defaults to START and TOP.
16994 * @param gravity see {@link android.view.Gravity}
16996 * @see #getForegroundGravity()
16998 * @attr ref android.R.styleable#View_foregroundGravity
17000 public void setForegroundGravity(int gravity) {
17001 if (mForegroundInfo == null) {
17002 mForegroundInfo = new ForegroundInfo();
17005 if (mForegroundInfo.mGravity != gravity) {
17006 if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
17007 gravity |= Gravity.START;
17010 if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
17011 gravity |= Gravity.TOP;
17014 mForegroundInfo.mGravity = gravity;
17020 * Applies a tint to the foreground drawable. Does not modify the current tint
17021 * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17023 * Subsequent calls to {@link #setForeground(Drawable)} will automatically
17024 * mutate the drawable and apply the specified tint and tint mode using
17025 * {@link Drawable#setTintList(ColorStateList)}.
17027 * @param tint the tint to apply, may be {@code null} to clear tint
17029 * @attr ref android.R.styleable#View_foregroundTint
17030 * @see #getForegroundTintList()
17031 * @see Drawable#setTintList(ColorStateList)
17033 public void setForegroundTintList(@Nullable ColorStateList tint) {
17034 if (mForegroundInfo == null) {
17035 mForegroundInfo = new ForegroundInfo();
17037 if (mForegroundInfo.mTintInfo == null) {
17038 mForegroundInfo.mTintInfo = new TintInfo();
17040 mForegroundInfo.mTintInfo.mTintList = tint;
17041 mForegroundInfo.mTintInfo.mHasTintList = true;
17043 applyForegroundTint();
17047 * Return the tint applied to the foreground drawable, if specified.
17049 * @return the tint applied to the foreground drawable
17050 * @attr ref android.R.styleable#View_foregroundTint
17051 * @see #setForegroundTintList(ColorStateList)
17054 public ColorStateList getForegroundTintList() {
17055 return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17056 ? mForegroundInfo.mTintInfo.mTintList : null;
17060 * Specifies the blending mode used to apply the tint specified by
17061 * {@link #setForegroundTintList(ColorStateList)}} to the background
17062 * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17064 * @param tintMode the blending mode used to apply the tint, may be
17065 * {@code null} to clear tint
17066 * @attr ref android.R.styleable#View_foregroundTintMode
17067 * @see #getForegroundTintMode()
17068 * @see Drawable#setTintMode(PorterDuff.Mode)
17070 public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17071 if (mBackgroundTint == null) {
17072 mBackgroundTint = new TintInfo();
17074 mBackgroundTint.mTintMode = tintMode;
17075 mBackgroundTint.mHasTintMode = true;
17077 applyBackgroundTint();
17081 * Return the blending mode used to apply the tint to the foreground
17082 * drawable, if specified.
17084 * @return the blending mode used to apply the tint to the foreground
17086 * @attr ref android.R.styleable#View_foregroundTintMode
17087 * @see #setBackgroundTintMode(PorterDuff.Mode)
17090 public PorterDuff.Mode getForegroundTintMode() {
17091 return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17092 ? mForegroundInfo.mTintInfo.mTintMode : null;
17095 private void applyForegroundTint() {
17096 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
17097 && mForegroundInfo.mTintInfo != null) {
17098 final TintInfo tintInfo = mForegroundInfo.mTintInfo;
17099 if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17100 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
17102 if (tintInfo.mHasTintList) {
17103 mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
17106 if (tintInfo.mHasTintMode) {
17107 mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
17110 // The drawable (or one of its children) may not have been
17111 // stateful before applying the tint, so let's try again.
17112 if (mForegroundInfo.mDrawable.isStateful()) {
17113 mForegroundInfo.mDrawable.setState(getDrawableState());
17120 * Draw any foreground content for this view.
17122 * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
17123 * drawable or other view-specific decorations. The foreground is drawn on top of the
17124 * primary view content.</p>
17126 * @param canvas canvas to draw into
17128 public void onDrawForeground(Canvas canvas) {
17129 onDrawScrollBars(canvas);
17131 final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17132 if (foreground != null) {
17133 if (mForegroundInfo.mBoundsChanged) {
17134 mForegroundInfo.mBoundsChanged = false;
17135 final Rect selfBounds = mForegroundInfo.mSelfBounds;
17136 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
17138 if (mForegroundInfo.mInsidePadding) {
17139 selfBounds.set(0, 0, getWidth(), getHeight());
17141 selfBounds.set(getPaddingLeft(), getPaddingTop(),
17142 getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
17145 final int ld = getLayoutDirection();
17146 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
17147 foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
17148 foreground.setBounds(overlayBounds);
17151 foreground.draw(canvas);
17156 * Sets the padding. The view may add on the space required to display
17157 * the scrollbars, depending on the style and visibility of the scrollbars.
17158 * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
17159 * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
17160 * from the values set in this call.
17162 * @attr ref android.R.styleable#View_padding
17163 * @attr ref android.R.styleable#View_paddingBottom
17164 * @attr ref android.R.styleable#View_paddingLeft
17165 * @attr ref android.R.styleable#View_paddingRight
17166 * @attr ref android.R.styleable#View_paddingTop
17167 * @param left the left padding in pixels
17168 * @param top the top padding in pixels
17169 * @param right the right padding in pixels
17170 * @param bottom the bottom padding in pixels
17172 public void setPadding(int left, int top, int right, int bottom) {
17173 resetResolvedPaddingInternal();
17175 mUserPaddingStart = UNDEFINED_PADDING;
17176 mUserPaddingEnd = UNDEFINED_PADDING;
17178 mUserPaddingLeftInitial = left;
17179 mUserPaddingRightInitial = right;
17181 mLeftPaddingDefined = true;
17182 mRightPaddingDefined = true;
17184 internalSetPadding(left, top, right, bottom);
17190 protected void internalSetPadding(int left, int top, int right, int bottom) {
17191 mUserPaddingLeft = left;
17192 mUserPaddingRight = right;
17193 mUserPaddingBottom = bottom;
17195 final int viewFlags = mViewFlags;
17196 boolean changed = false;
17198 // Common case is there are no scroll bars.
17199 if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
17200 if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
17201 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
17202 ? 0 : getVerticalScrollbarWidth();
17203 switch (mVerticalScrollbarPosition) {
17204 case SCROLLBAR_POSITION_DEFAULT:
17205 if (isLayoutRtl()) {
17211 case SCROLLBAR_POSITION_RIGHT:
17214 case SCROLLBAR_POSITION_LEFT:
17219 if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
17220 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
17221 ? 0 : getHorizontalScrollbarHeight();
17225 if (mPaddingLeft != left) {
17227 mPaddingLeft = left;
17229 if (mPaddingTop != top) {
17233 if (mPaddingRight != right) {
17235 mPaddingRight = right;
17237 if (mPaddingBottom != bottom) {
17239 mPaddingBottom = bottom;
17244 invalidateOutline();
17249 * Sets the relative padding. The view may add on the space required to display
17250 * the scrollbars, depending on the style and visibility of the scrollbars.
17251 * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
17252 * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
17253 * from the values set in this call.
17255 * @attr ref android.R.styleable#View_padding
17256 * @attr ref android.R.styleable#View_paddingBottom
17257 * @attr ref android.R.styleable#View_paddingStart
17258 * @attr ref android.R.styleable#View_paddingEnd
17259 * @attr ref android.R.styleable#View_paddingTop
17260 * @param start the start padding in pixels
17261 * @param top the top padding in pixels
17262 * @param end the end padding in pixels
17263 * @param bottom the bottom padding in pixels
17265 public void setPaddingRelative(int start, int top, int end, int bottom) {
17266 resetResolvedPaddingInternal();
17268 mUserPaddingStart = start;
17269 mUserPaddingEnd = end;
17270 mLeftPaddingDefined = true;
17271 mRightPaddingDefined = true;
17273 switch(getLayoutDirection()) {
17274 case LAYOUT_DIRECTION_RTL:
17275 mUserPaddingLeftInitial = end;
17276 mUserPaddingRightInitial = start;
17277 internalSetPadding(end, top, start, bottom);
17279 case LAYOUT_DIRECTION_LTR:
17281 mUserPaddingLeftInitial = start;
17282 mUserPaddingRightInitial = end;
17283 internalSetPadding(start, top, end, bottom);
17288 * Returns the top padding of this view.
17290 * @return the top padding in pixels
17292 public int getPaddingTop() {
17293 return mPaddingTop;
17297 * Returns the bottom padding of this view. If there are inset and enabled
17298 * scrollbars, this value may include the space required to display the
17299 * scrollbars as well.
17301 * @return the bottom padding in pixels
17303 public int getPaddingBottom() {
17304 return mPaddingBottom;
17308 * Returns the left padding of this view. If there are inset and enabled
17309 * scrollbars, this value may include the space required to display the
17310 * scrollbars as well.
17312 * @return the left padding in pixels
17314 public int getPaddingLeft() {
17315 if (!isPaddingResolved()) {
17318 return mPaddingLeft;
17322 * Returns the start padding of this view depending on its resolved layout direction.
17323 * If there are inset and enabled scrollbars, this value may include the space
17324 * required to display the scrollbars as well.
17326 * @return the start padding in pixels
17328 public int getPaddingStart() {
17329 if (!isPaddingResolved()) {
17332 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
17333 mPaddingRight : mPaddingLeft;
17337 * Returns the right padding of this view. If there are inset and enabled
17338 * scrollbars, this value may include the space required to display the
17339 * scrollbars as well.
17341 * @return the right padding in pixels
17343 public int getPaddingRight() {
17344 if (!isPaddingResolved()) {
17347 return mPaddingRight;
17351 * Returns the end padding of this view depending on its resolved layout direction.
17352 * If there are inset and enabled scrollbars, this value may include the space
17353 * required to display the scrollbars as well.
17355 * @return the end padding in pixels
17357 public int getPaddingEnd() {
17358 if (!isPaddingResolved()) {
17361 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
17362 mPaddingLeft : mPaddingRight;
17366 * Return if the padding has been set through relative values
17367 * {@link #setPaddingRelative(int, int, int, int)} or through
17368 * @attr ref android.R.styleable#View_paddingStart or
17369 * @attr ref android.R.styleable#View_paddingEnd
17371 * @return true if the padding is relative or false if it is not.
17373 public boolean isPaddingRelative() {
17374 return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
17377 Insets computeOpticalInsets() {
17378 return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
17384 public void resetPaddingToInitialValues() {
17385 if (isRtlCompatibilityMode()) {
17386 mPaddingLeft = mUserPaddingLeftInitial;
17387 mPaddingRight = mUserPaddingRightInitial;
17390 if (isLayoutRtl()) {
17391 mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
17392 mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
17394 mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
17395 mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
17402 public Insets getOpticalInsets() {
17403 if (mLayoutInsets == null) {
17404 mLayoutInsets = computeOpticalInsets();
17406 return mLayoutInsets;
17410 * Set this view's optical insets.
17412 * <p>This method should be treated similarly to setMeasuredDimension and not as a general
17413 * property. Views that compute their own optical insets should call it as part of measurement.
17414 * This method does not request layout. If you are setting optical insets outside of
17415 * measure/layout itself you will want to call requestLayout() yourself.
17419 public void setOpticalInsets(Insets insets) {
17420 mLayoutInsets = insets;
17424 * Changes the selection state of this view. A view can be selected or not.
17425 * Note that selection is not the same as focus. Views are typically
17426 * selected in the context of an AdapterView like ListView or GridView;
17427 * the selected view is the view that is highlighted.
17429 * @param selected true if the view must be selected, false otherwise
17431 public void setSelected(boolean selected) {
17432 //noinspection DoubleNegation
17433 if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
17434 mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
17435 if (!selected) resetPressedState();
17437 refreshDrawableState();
17438 dispatchSetSelected(selected);
17440 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
17442 notifyViewAccessibilityStateChangedIfNeeded(
17443 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
17449 * Dispatch setSelected to all of this View's children.
17451 * @see #setSelected(boolean)
17453 * @param selected The new selected state
17455 protected void dispatchSetSelected(boolean selected) {
17459 * Indicates the selection state of this view.
17461 * @return true if the view is selected, false otherwise
17463 @ViewDebug.ExportedProperty
17464 public boolean isSelected() {
17465 return (mPrivateFlags & PFLAG_SELECTED) != 0;
17469 * Changes the activated state of this view. A view can be activated or not.
17470 * Note that activation is not the same as selection. Selection is
17471 * a transient property, representing the view (hierarchy) the user is
17472 * currently interacting with. Activation is a longer-term state that the
17473 * user can move views in and out of. For example, in a list view with
17474 * single or multiple selection enabled, the views in the current selection
17475 * set are activated. (Um, yeah, we are deeply sorry about the terminology
17476 * here.) The activated state is propagated down to children of the view it
17479 * @param activated true if the view must be activated, false otherwise
17481 public void setActivated(boolean activated) {
17482 //noinspection DoubleNegation
17483 if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
17484 mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
17486 refreshDrawableState();
17487 dispatchSetActivated(activated);
17492 * Dispatch setActivated to all of this View's children.
17494 * @see #setActivated(boolean)
17496 * @param activated The new activated state
17498 protected void dispatchSetActivated(boolean activated) {
17502 * Indicates the activation state of this view.
17504 * @return true if the view is activated, false otherwise
17506 @ViewDebug.ExportedProperty
17507 public boolean isActivated() {
17508 return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
17512 * Returns the ViewTreeObserver for this view's hierarchy. The view tree
17513 * observer can be used to get notifications when global events, like
17516 * The returned ViewTreeObserver observer is not guaranteed to remain
17517 * valid for the lifetime of this View. If the caller of this method keeps
17518 * a long-lived reference to ViewTreeObserver, it should always check for
17519 * the return value of {@link ViewTreeObserver#isAlive()}.
17521 * @return The ViewTreeObserver for this view's hierarchy.
17523 public ViewTreeObserver getViewTreeObserver() {
17524 if (mAttachInfo != null) {
17525 return mAttachInfo.mTreeObserver;
17527 if (mFloatingTreeObserver == null) {
17528 mFloatingTreeObserver = new ViewTreeObserver();
17530 return mFloatingTreeObserver;
17534 * <p>Finds the topmost view in the current view hierarchy.</p>
17536 * @return the topmost view containing this view
17538 public View getRootView() {
17539 if (mAttachInfo != null) {
17540 final View v = mAttachInfo.mRootView;
17546 View parent = this;
17548 while (parent.mParent != null && parent.mParent instanceof View) {
17549 parent = (View) parent.mParent;
17556 * Transforms a motion event from view-local coordinates to on-screen
17559 * @param ev the view-local motion event
17560 * @return false if the transformation could not be applied
17563 public boolean toGlobalMotionEvent(MotionEvent ev) {
17564 final AttachInfo info = mAttachInfo;
17565 if (info == null) {
17569 final Matrix m = info.mTmpMatrix;
17570 m.set(Matrix.IDENTITY_MATRIX);
17571 transformMatrixToGlobal(m);
17577 * Transforms a motion event from on-screen coordinates to view-local
17580 * @param ev the on-screen motion event
17581 * @return false if the transformation could not be applied
17584 public boolean toLocalMotionEvent(MotionEvent ev) {
17585 final AttachInfo info = mAttachInfo;
17586 if (info == null) {
17590 final Matrix m = info.mTmpMatrix;
17591 m.set(Matrix.IDENTITY_MATRIX);
17592 transformMatrixToLocal(m);
17598 * Modifies the input matrix such that it maps view-local coordinates to
17599 * on-screen coordinates.
17601 * @param m input matrix to modify
17604 public void transformMatrixToGlobal(Matrix m) {
17605 final ViewParent parent = mParent;
17606 if (parent instanceof View) {
17607 final View vp = (View) parent;
17608 vp.transformMatrixToGlobal(m);
17609 m.preTranslate(-vp.mScrollX, -vp.mScrollY);
17610 } else if (parent instanceof ViewRootImpl) {
17611 final ViewRootImpl vr = (ViewRootImpl) parent;
17612 vr.transformMatrixToGlobal(m);
17613 m.preTranslate(0, -vr.mCurScrollY);
17616 m.preTranslate(mLeft, mTop);
17618 if (!hasIdentityMatrix()) {
17619 m.preConcat(getMatrix());
17624 * Modifies the input matrix such that it maps on-screen coordinates to
17625 * view-local coordinates.
17627 * @param m input matrix to modify
17630 public void transformMatrixToLocal(Matrix m) {
17631 final ViewParent parent = mParent;
17632 if (parent instanceof View) {
17633 final View vp = (View) parent;
17634 vp.transformMatrixToLocal(m);
17635 m.postTranslate(vp.mScrollX, vp.mScrollY);
17636 } else if (parent instanceof ViewRootImpl) {
17637 final ViewRootImpl vr = (ViewRootImpl) parent;
17638 vr.transformMatrixToLocal(m);
17639 m.postTranslate(0, vr.mCurScrollY);
17642 m.postTranslate(-mLeft, -mTop);
17644 if (!hasIdentityMatrix()) {
17645 m.postConcat(getInverseMatrix());
17652 @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
17653 @ViewDebug.IntToString(from = 0, to = "x"),
17654 @ViewDebug.IntToString(from = 1, to = "y")
17656 public int[] getLocationOnScreen() {
17657 int[] location = new int[2];
17658 getLocationOnScreen(location);
17663 * <p>Computes the coordinates of this view on the screen. The argument
17664 * must be an array of two integers. After the method returns, the array
17665 * contains the x and y location in that order.</p>
17667 * @param location an array of two integers in which to hold the coordinates
17669 public void getLocationOnScreen(@Size(2) int[] location) {
17670 getLocationInWindow(location);
17672 final AttachInfo info = mAttachInfo;
17673 if (info != null) {
17674 location[0] += info.mWindowLeft;
17675 location[1] += info.mWindowTop;
17680 * <p>Computes the coordinates of this view in its window. The argument
17681 * must be an array of two integers. After the method returns, the array
17682 * contains the x and y location in that order.</p>
17684 * @param location an array of two integers in which to hold the coordinates
17686 public void getLocationInWindow(@Size(2) int[] location) {
17687 if (location == null || location.length < 2) {
17688 throw new IllegalArgumentException("location must be an array of two integers");
17691 if (mAttachInfo == null) {
17692 // When the view is not attached to a window, this method does not make sense
17693 location[0] = location[1] = 0;
17697 float[] position = mAttachInfo.mTmpTransformLocation;
17698 position[0] = position[1] = 0.0f;
17700 if (!hasIdentityMatrix()) {
17701 getMatrix().mapPoints(position);
17704 position[0] += mLeft;
17705 position[1] += mTop;
17707 ViewParent viewParent = mParent;
17708 while (viewParent instanceof View) {
17709 final View view = (View) viewParent;
17711 position[0] -= view.mScrollX;
17712 position[1] -= view.mScrollY;
17714 if (!view.hasIdentityMatrix()) {
17715 view.getMatrix().mapPoints(position);
17718 position[0] += view.mLeft;
17719 position[1] += view.mTop;
17721 viewParent = view.mParent;
17724 if (viewParent instanceof ViewRootImpl) {
17726 final ViewRootImpl vr = (ViewRootImpl) viewParent;
17727 position[1] -= vr.mCurScrollY;
17730 location[0] = (int) (position[0] + 0.5f);
17731 location[1] = (int) (position[1] + 0.5f);
17736 * @param id the id of the view to be found
17737 * @return the view of the specified id, null if cannot be found
17739 protected View findViewTraversal(@IdRes int id) {
17748 * @param tag the tag of the view to be found
17749 * @return the view of specified tag, null if cannot be found
17751 protected View findViewWithTagTraversal(Object tag) {
17752 if (tag != null && tag.equals(mTag)) {
17760 * @param predicate The predicate to evaluate.
17761 * @param childToSkip If not null, ignores this child during the recursive traversal.
17762 * @return The first view that matches the predicate or null.
17764 protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
17765 if (predicate.apply(this)) {
17772 * Look for a child view with the given id. If this view has the given
17773 * id, return this view.
17775 * @param id The id to search for.
17776 * @return The view that has the given id in the hierarchy or null
17779 public final View findViewById(@IdRes int id) {
17783 return findViewTraversal(id);
17787 * Finds a view by its unuque and stable accessibility id.
17789 * @param accessibilityId The searched accessibility id.
17790 * @return The found view.
17792 final View findViewByAccessibilityId(int accessibilityId) {
17793 if (accessibilityId < 0) {
17796 return findViewByAccessibilityIdTraversal(accessibilityId);
17800 * Performs the traversal to find a view by its unuque and stable accessibility id.
17802 * <strong>Note:</strong>This method does not stop at the root namespace
17803 * boundary since the user can touch the screen at an arbitrary location
17804 * potentially crossing the root namespace bounday which will send an
17805 * accessibility event to accessibility services and they should be able
17806 * to obtain the event source. Also accessibility ids are guaranteed to be
17807 * unique in the window.
17809 * @param accessibilityId The accessibility id.
17810 * @return The found view.
17814 public View findViewByAccessibilityIdTraversal(int accessibilityId) {
17815 if (getAccessibilityViewId() == accessibilityId) {
17822 * Look for a child view with the given tag. If this view has the given
17823 * tag, return this view.
17825 * @param tag The tag to search for, using "tag.equals(getTag())".
17826 * @return The View that has the given tag in the hierarchy or null
17828 public final View findViewWithTag(Object tag) {
17832 return findViewWithTagTraversal(tag);
17837 * Look for a child view that matches the specified predicate.
17838 * If this view matches the predicate, return this view.
17840 * @param predicate The predicate to evaluate.
17841 * @return The first view that matches the predicate or null.
17843 public final View findViewByPredicate(Predicate<View> predicate) {
17844 return findViewByPredicateTraversal(predicate, null);
17849 * Look for a child view that matches the specified predicate,
17850 * starting with the specified view and its descendents and then
17851 * recusively searching the ancestors and siblings of that view
17852 * until this view is reached.
17854 * This method is useful in cases where the predicate does not match
17855 * a single unique view (perhaps multiple views use the same id)
17856 * and we are trying to find the view that is "closest" in scope to the
17859 * @param start The view to start from.
17860 * @param predicate The predicate to evaluate.
17861 * @return The first view that matches the predicate or null.
17863 public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
17864 View childToSkip = null;
17866 View view = start.findViewByPredicateTraversal(predicate, childToSkip);
17867 if (view != null || start == this) {
17871 ViewParent parent = start.getParent();
17872 if (parent == null || !(parent instanceof View)) {
17876 childToSkip = start;
17877 start = (View) parent;
17882 * Sets the identifier for this view. The identifier does not have to be
17883 * unique in this view's hierarchy. The identifier should be a positive
17888 * @see #findViewById(int)
17890 * @param id a number used to identify the view
17892 * @attr ref android.R.styleable#View_id
17894 public void setId(@IdRes int id) {
17896 if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
17897 mID = generateViewId();
17904 * @param isRoot true if the view belongs to the root namespace, false
17907 public void setIsRootNamespace(boolean isRoot) {
17909 mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
17911 mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
17918 * @return true if the view belongs to the root namespace, false otherwise
17920 public boolean isRootNamespace() {
17921 return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
17925 * Returns this view's identifier.
17927 * @return a positive integer used to identify the view or {@link #NO_ID}
17928 * if the view has no ID
17931 * @see #findViewById(int)
17932 * @attr ref android.R.styleable#View_id
17935 @ViewDebug.CapturedViewProperty
17936 public int getId() {
17941 * Returns this view's tag.
17943 * @return the Object stored in this view as a tag, or {@code null} if not
17946 * @see #setTag(Object)
17947 * @see #getTag(int)
17949 @ViewDebug.ExportedProperty
17950 public Object getTag() {
17955 * Sets the tag associated with this view. A tag can be used to mark
17956 * a view in its hierarchy and does not have to be unique within the
17957 * hierarchy. Tags can also be used to store data within a view without
17958 * resorting to another data structure.
17960 * @param tag an Object to tag the view with
17963 * @see #setTag(int, Object)
17965 public void setTag(final Object tag) {
17970 * Returns the tag associated with this view and the specified key.
17972 * @param key The key identifying the tag
17974 * @return the Object stored in this view as a tag, or {@code null} if not
17977 * @see #setTag(int, Object)
17980 public Object getTag(int key) {
17981 if (mKeyedTags != null) return mKeyedTags.get(key);
17986 * Sets a tag associated with this view and a key. A tag can be used
17987 * to mark a view in its hierarchy and does not have to be unique within
17988 * the hierarchy. Tags can also be used to store data within a view
17989 * without resorting to another data structure.
17991 * The specified key should be an id declared in the resources of the
17992 * application to ensure it is unique (see the <a
17993 * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
17994 * Keys identified as belonging to
17995 * the Android framework or not associated with any package will cause
17996 * an {@link IllegalArgumentException} to be thrown.
17998 * @param key The key identifying the tag
17999 * @param tag An Object to tag the view with
18001 * @throws IllegalArgumentException If they specified key is not valid
18003 * @see #setTag(Object)
18004 * @see #getTag(int)
18006 public void setTag(int key, final Object tag) {
18007 // If the package id is 0x00 or 0x01, it's either an undefined package
18008 // or a framework id
18009 if ((key >>> 24) < 2) {
18010 throw new IllegalArgumentException("The key must be an application-specific "
18014 setKeyedTag(key, tag);
18018 * Variation of {@link #setTag(int, Object)} that enforces the key to be a
18023 public void setTagInternal(int key, Object tag) {
18024 if ((key >>> 24) != 0x1) {
18025 throw new IllegalArgumentException("The key must be a framework-specific "
18029 setKeyedTag(key, tag);
18032 private void setKeyedTag(int key, Object tag) {
18033 if (mKeyedTags == null) {
18034 mKeyedTags = new SparseArray<Object>(2);
18037 mKeyedTags.put(key, tag);
18041 * Prints information about this view in the log output, with the tag
18042 * {@link #VIEW_LOG_TAG}.
18046 public void debug() {
18051 * Prints information about this view in the log output, with the tag
18052 * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
18053 * indentation defined by the <code>depth</code>.
18055 * @param depth the indentation level
18059 protected void debug(int depth) {
18060 String output = debugIndent(depth - 1);
18062 output += "+ " + this;
18065 output += " (id=" + id + ")";
18067 Object tag = getTag();
18069 output += " (tag=" + tag + ")";
18071 Log.d(VIEW_LOG_TAG, output);
18073 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
18074 output = debugIndent(depth) + " FOCUSED";
18075 Log.d(VIEW_LOG_TAG, output);
18078 output = debugIndent(depth);
18079 output += "frame={" + mLeft + ", " + mTop + ", " + mRight
18080 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
18082 Log.d(VIEW_LOG_TAG, output);
18084 if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
18085 || mPaddingBottom != 0) {
18086 output = debugIndent(depth);
18087 output += "padding={" + mPaddingLeft + ", " + mPaddingTop
18088 + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
18089 Log.d(VIEW_LOG_TAG, output);
18092 output = debugIndent(depth);
18093 output += "mMeasureWidth=" + mMeasuredWidth +
18094 " mMeasureHeight=" + mMeasuredHeight;
18095 Log.d(VIEW_LOG_TAG, output);
18097 output = debugIndent(depth);
18098 if (mLayoutParams == null) {
18099 output += "BAD! no layout params";
18101 output = mLayoutParams.debug(output);
18103 Log.d(VIEW_LOG_TAG, output);
18105 output = debugIndent(depth);
18106 output += "flags={";
18107 output += View.printFlags(mViewFlags);
18109 Log.d(VIEW_LOG_TAG, output);
18111 output = debugIndent(depth);
18112 output += "privateFlags={";
18113 output += View.printPrivateFlags(mPrivateFlags);
18115 Log.d(VIEW_LOG_TAG, output);
18119 * Creates a string of whitespaces used for indentation.
18121 * @param depth the indentation level
18122 * @return a String containing (depth * 2 + 3) * 2 white spaces
18126 protected static String debugIndent(int depth) {
18127 StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
18128 for (int i = 0; i < (depth * 2) + 3; i++) {
18129 spaces.append(' ').append(' ');
18131 return spaces.toString();
18135 * <p>Return the offset of the widget's text baseline from the widget's top
18136 * boundary. If this widget does not support baseline alignment, this
18137 * method returns -1. </p>
18139 * @return the offset of the baseline within the widget's bounds or -1
18140 * if baseline alignment is not supported
18142 @ViewDebug.ExportedProperty(category = "layout")
18143 public int getBaseline() {
18148 * Returns whether the view hierarchy is currently undergoing a layout pass. This
18149 * information is useful to avoid situations such as calling {@link #requestLayout()} during
18152 * @return whether the view hierarchy is currently undergoing a layout pass
18154 public boolean isInLayout() {
18155 ViewRootImpl viewRoot = getViewRootImpl();
18156 return (viewRoot != null && viewRoot.isInLayout());
18160 * Call this when something has changed which has invalidated the
18161 * layout of this view. This will schedule a layout pass of the view
18162 * tree. This should not be called while the view hierarchy is currently in a layout
18163 * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
18164 * end of the current layout pass (and then layout will run again) or after the current
18165 * frame is drawn and the next layout occurs.
18167 * <p>Subclasses which override this method should call the superclass method to
18168 * handle possible request-during-layout errors correctly.</p>
18171 public void requestLayout() {
18172 if (mMeasureCache != null) mMeasureCache.clear();
18174 if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
18175 // Only trigger request-during-layout logic if this is the view requesting it,
18176 // not the views in its parent hierarchy
18177 ViewRootImpl viewRoot = getViewRootImpl();
18178 if (viewRoot != null && viewRoot.isInLayout()) {
18179 if (!viewRoot.requestLayoutDuringLayout(this)) {
18183 mAttachInfo.mViewRequestingLayout = this;
18186 mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18187 mPrivateFlags |= PFLAG_INVALIDATED;
18189 if (mParent != null && !mParent.isLayoutRequested()) {
18190 mParent.requestLayout();
18192 if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
18193 mAttachInfo.mViewRequestingLayout = null;
18198 * Forces this view to be laid out during the next layout pass.
18199 * This method does not call requestLayout() or forceLayout()
18202 public void forceLayout() {
18203 if (mMeasureCache != null) mMeasureCache.clear();
18205 mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18206 mPrivateFlags |= PFLAG_INVALIDATED;
18211 * This is called to find out how big a view should be. The parent
18212 * supplies constraint information in the width and height parameters.
18216 * The actual measurement work of a view is performed in
18217 * {@link #onMeasure(int, int)}, called by this method. Therefore, only
18218 * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
18222 * @param widthMeasureSpec Horizontal space requirements as imposed by the
18224 * @param heightMeasureSpec Vertical space requirements as imposed by the
18227 * @see #onMeasure(int, int)
18229 public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
18230 boolean optical = isLayoutModeOptical(this);
18231 if (optical != isLayoutModeOptical(mParent)) {
18232 Insets insets = getOpticalInsets();
18233 int oWidth = insets.left + insets.right;
18234 int oHeight = insets.top + insets.bottom;
18235 widthMeasureSpec = MeasureSpec.adjust(widthMeasureSpec, optical ? -oWidth : oWidth);
18236 heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
18239 // Suppress sign extension for the low bytes
18240 long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
18241 if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
18243 final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
18244 final boolean isExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY &&
18245 MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
18246 final boolean matchingSize = isExactly &&
18247 getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec) &&
18248 getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
18249 if (forceLayout || !matchingSize &&
18250 (widthMeasureSpec != mOldWidthMeasureSpec ||
18251 heightMeasureSpec != mOldHeightMeasureSpec)) {
18253 // first clears the measured dimension flag
18254 mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
18256 resolveRtlPropertiesIfNeeded();
18258 int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
18259 if (cacheIndex < 0 || sIgnoreMeasureCache) {
18260 // measure ourselves, this should set the measured dimension flag back
18261 onMeasure(widthMeasureSpec, heightMeasureSpec);
18262 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18264 long value = mMeasureCache.valueAt(cacheIndex);
18265 // Casting a long to int drops the high 32 bits, no mask needed
18266 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
18267 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18270 // flag not set, setMeasuredDimension() was not invoked, we raise
18271 // an exception to warn the developer
18272 if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
18273 throw new IllegalStateException("View with id " + getId() + ": "
18274 + getClass().getName() + "#onMeasure() did not set the"
18275 + " measured dimension by calling"
18276 + " setMeasuredDimension()");
18279 mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
18282 mOldWidthMeasureSpec = widthMeasureSpec;
18283 mOldHeightMeasureSpec = heightMeasureSpec;
18285 mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
18286 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
18291 * Measure the view and its content to determine the measured width and the
18292 * measured height. This method is invoked by {@link #measure(int, int)} and
18293 * should be overridden by subclasses to provide accurate and efficient
18294 * measurement of their contents.
18298 * <strong>CONTRACT:</strong> When overriding this method, you
18299 * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
18300 * measured width and height of this view. Failure to do so will trigger an
18301 * <code>IllegalStateException</code>, thrown by
18302 * {@link #measure(int, int)}. Calling the superclass'
18303 * {@link #onMeasure(int, int)} is a valid use.
18307 * The base class implementation of measure defaults to the background size,
18308 * unless a larger size is allowed by the MeasureSpec. Subclasses should
18309 * override {@link #onMeasure(int, int)} to provide better measurements of
18314 * If this method is overridden, it is the subclass's responsibility to make
18315 * sure the measured height and width are at least the view's minimum height
18316 * and width ({@link #getSuggestedMinimumHeight()} and
18317 * {@link #getSuggestedMinimumWidth()}).
18320 * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
18321 * The requirements are encoded with
18322 * {@link android.view.View.MeasureSpec}.
18323 * @param heightMeasureSpec vertical space requirements as imposed by the parent.
18324 * The requirements are encoded with
18325 * {@link android.view.View.MeasureSpec}.
18327 * @see #getMeasuredWidth()
18328 * @see #getMeasuredHeight()
18329 * @see #setMeasuredDimension(int, int)
18330 * @see #getSuggestedMinimumHeight()
18331 * @see #getSuggestedMinimumWidth()
18332 * @see android.view.View.MeasureSpec#getMode(int)
18333 * @see android.view.View.MeasureSpec#getSize(int)
18335 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
18336 setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
18337 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
18341 * <p>This method must be called by {@link #onMeasure(int, int)} to store the
18342 * measured width and measured height. Failing to do so will trigger an
18343 * exception at measurement time.</p>
18345 * @param measuredWidth The measured width of this view. May be a complex
18346 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18347 * {@link #MEASURED_STATE_TOO_SMALL}.
18348 * @param measuredHeight The measured height of this view. May be a complex
18349 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18350 * {@link #MEASURED_STATE_TOO_SMALL}.
18352 protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
18353 boolean optical = isLayoutModeOptical(this);
18354 if (optical != isLayoutModeOptical(mParent)) {
18355 Insets insets = getOpticalInsets();
18356 int opticalWidth = insets.left + insets.right;
18357 int opticalHeight = insets.top + insets.bottom;
18359 measuredWidth += optical ? opticalWidth : -opticalWidth;
18360 measuredHeight += optical ? opticalHeight : -opticalHeight;
18362 setMeasuredDimensionRaw(measuredWidth, measuredHeight);
18366 * Sets the measured dimension without extra processing for things like optical bounds.
18367 * Useful for reapplying consistent values that have already been cooked with adjustments
18368 * for optical bounds, etc. such as those from the measurement cache.
18370 * @param measuredWidth The measured width of this view. May be a complex
18371 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18372 * {@link #MEASURED_STATE_TOO_SMALL}.
18373 * @param measuredHeight The measured height of this view. May be a complex
18374 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18375 * {@link #MEASURED_STATE_TOO_SMALL}.
18377 private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
18378 mMeasuredWidth = measuredWidth;
18379 mMeasuredHeight = measuredHeight;
18381 mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
18385 * Merge two states as returned by {@link #getMeasuredState()}.
18386 * @param curState The current state as returned from a view or the result
18387 * of combining multiple views.
18388 * @param newState The new view state to combine.
18389 * @return Returns a new integer reflecting the combination of the two
18392 public static int combineMeasuredStates(int curState, int newState) {
18393 return curState | newState;
18397 * Version of {@link #resolveSizeAndState(int, int, int)}
18398 * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
18400 public static int resolveSize(int size, int measureSpec) {
18401 return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
18405 * Utility to reconcile a desired size and state, with constraints imposed
18406 * by a MeasureSpec. Will take the desired size, unless a different size
18407 * is imposed by the constraints. The returned value is a compound integer,
18408 * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
18409 * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
18410 * resulting size is smaller than the size the view wants to be.
18412 * @param size How big the view wants to be.
18413 * @param measureSpec Constraints imposed by the parent.
18414 * @param childMeasuredState Size information bit mask for the view's
18416 * @return Size information bit mask as defined by
18417 * {@link #MEASURED_SIZE_MASK} and
18418 * {@link #MEASURED_STATE_TOO_SMALL}.
18420 public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
18421 final int specMode = MeasureSpec.getMode(measureSpec);
18422 final int specSize = MeasureSpec.getSize(measureSpec);
18424 switch (specMode) {
18425 case MeasureSpec.AT_MOST:
18426 if (specSize < size) {
18427 result = specSize | MEASURED_STATE_TOO_SMALL;
18432 case MeasureSpec.EXACTLY:
18435 case MeasureSpec.UNSPECIFIED:
18439 return result | (childMeasuredState & MEASURED_STATE_MASK);
18443 * Utility to return a default size. Uses the supplied size if the
18444 * MeasureSpec imposed no constraints. Will get larger if allowed
18445 * by the MeasureSpec.
18447 * @param size Default size for this view
18448 * @param measureSpec Constraints imposed by the parent
18449 * @return The size this view should be.
18451 public static int getDefaultSize(int size, int measureSpec) {
18453 int specMode = MeasureSpec.getMode(measureSpec);
18454 int specSize = MeasureSpec.getSize(measureSpec);
18456 switch (specMode) {
18457 case MeasureSpec.UNSPECIFIED:
18460 case MeasureSpec.AT_MOST:
18461 case MeasureSpec.EXACTLY:
18469 * Returns the suggested minimum height that the view should use. This
18470 * returns the maximum of the view's minimum height
18471 * and the background's minimum height
18472 * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
18474 * When being used in {@link #onMeasure(int, int)}, the caller should still
18475 * ensure the returned height is within the requirements of the parent.
18477 * @return The suggested minimum height of the view.
18479 protected int getSuggestedMinimumHeight() {
18480 return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
18485 * Returns the suggested minimum width that the view should use. This
18486 * returns the maximum of the view's minimum width)
18487 * and the background's minimum width
18488 * ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
18490 * When being used in {@link #onMeasure(int, int)}, the caller should still
18491 * ensure the returned width is within the requirements of the parent.
18493 * @return The suggested minimum width of the view.
18495 protected int getSuggestedMinimumWidth() {
18496 return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
18500 * Returns the minimum height of the view.
18502 * @return the minimum height the view will try to be.
18504 * @see #setMinimumHeight(int)
18506 * @attr ref android.R.styleable#View_minHeight
18508 public int getMinimumHeight() {
18513 * Sets the minimum height of the view. It is not guaranteed the view will
18514 * be able to achieve this minimum height (for example, if its parent layout
18515 * constrains it with less available height).
18517 * @param minHeight The minimum height the view will try to be.
18519 * @see #getMinimumHeight()
18521 * @attr ref android.R.styleable#View_minHeight
18523 public void setMinimumHeight(int minHeight) {
18524 mMinHeight = minHeight;
18529 * Returns the minimum width of the view.
18531 * @return the minimum width the view will try to be.
18533 * @see #setMinimumWidth(int)
18535 * @attr ref android.R.styleable#View_minWidth
18537 public int getMinimumWidth() {
18542 * Sets the minimum width of the view. It is not guaranteed the view will
18543 * be able to achieve this minimum width (for example, if its parent layout
18544 * constrains it with less available width).
18546 * @param minWidth The minimum width the view will try to be.
18548 * @see #getMinimumWidth()
18550 * @attr ref android.R.styleable#View_minWidth
18552 public void setMinimumWidth(int minWidth) {
18553 mMinWidth = minWidth;
18559 * Get the animation currently associated with this view.
18561 * @return The animation that is currently playing or
18562 * scheduled to play for this view.
18564 public Animation getAnimation() {
18565 return mCurrentAnimation;
18569 * Start the specified animation now.
18571 * @param animation the animation to start now
18573 public void startAnimation(Animation animation) {
18574 animation.setStartTime(Animation.START_ON_FIRST_FRAME);
18575 setAnimation(animation);
18576 invalidateParentCaches();
18581 * Cancels any animations for this view.
18583 public void clearAnimation() {
18584 if (mCurrentAnimation != null) {
18585 mCurrentAnimation.detach();
18587 mCurrentAnimation = null;
18588 invalidateParentIfNeeded();
18592 * Sets the next animation to play for this view.
18593 * If you want the animation to play immediately, use
18594 * {@link #startAnimation(android.view.animation.Animation)} instead.
18595 * This method provides allows fine-grained
18596 * control over the start time and invalidation, but you
18597 * must make sure that 1) the animation has a start time set, and
18598 * 2) the view's parent (which controls animations on its children)
18599 * will be invalidated when the animation is supposed to
18602 * @param animation The next animation, or null.
18604 public void setAnimation(Animation animation) {
18605 mCurrentAnimation = animation;
18607 if (animation != null) {
18608 // If the screen is off assume the animation start time is now instead of
18609 // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
18610 // would cause the animation to start when the screen turns back on
18611 if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
18612 && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
18613 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
18620 * Invoked by a parent ViewGroup to notify the start of the animation
18621 * currently associated with this view. If you override this method,
18622 * always call super.onAnimationStart();
18624 * @see #setAnimation(android.view.animation.Animation)
18625 * @see #getAnimation()
18628 protected void onAnimationStart() {
18629 mPrivateFlags |= PFLAG_ANIMATION_STARTED;
18633 * Invoked by a parent ViewGroup to notify the end of the animation
18634 * currently associated with this view. If you override this method,
18635 * always call super.onAnimationEnd();
18637 * @see #setAnimation(android.view.animation.Animation)
18638 * @see #getAnimation()
18641 protected void onAnimationEnd() {
18642 mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
18646 * Invoked if there is a Transform that involves alpha. Subclass that can
18647 * draw themselves with the specified alpha should return true, and then
18648 * respect that alpha when their onDraw() is called. If this returns false
18649 * then the view may be redirected to draw into an offscreen buffer to
18650 * fulfill the request, which will look fine, but may be slower than if the
18651 * subclass handles it internally. The default implementation returns false.
18653 * @param alpha The alpha (0..255) to apply to the view's drawing
18654 * @return true if the view can draw with the specified alpha.
18656 protected boolean onSetAlpha(int alpha) {
18661 * This is used by the RootView to perform an optimization when
18662 * the view hierarchy contains one or several SurfaceView.
18663 * SurfaceView is always considered transparent, but its children are not,
18664 * therefore all View objects remove themselves from the global transparent
18665 * region (passed as a parameter to this function).
18667 * @param region The transparent region for this ViewAncestor (window).
18669 * @return Returns true if the effective visibility of the view at this
18670 * point is opaque, regardless of the transparent region; returns false
18671 * if it is possible for underlying windows to be seen behind the view.
18675 public boolean gatherTransparentRegion(Region region) {
18676 final AttachInfo attachInfo = mAttachInfo;
18677 if (region != null && attachInfo != null) {
18678 final int pflags = mPrivateFlags;
18679 if ((pflags & PFLAG_SKIP_DRAW) == 0) {
18680 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
18681 // remove it from the transparent region.
18682 final int[] location = attachInfo.mTransparentLocation;
18683 getLocationInWindow(location);
18684 region.op(location[0], location[1], location[0] + mRight - mLeft,
18685 location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
18686 } else if ((pflags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null &&
18687 mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
18688 // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
18689 // exists, so we remove the background drawable's non-transparent
18690 // parts from this transparent region.
18691 applyDrawableToTransparentRegion(mBackground, region);
18693 final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18694 if (foreground != null) {
18695 applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
18702 * Play a sound effect for this view.
18704 * <p>The framework will play sound effects for some built in actions, such as
18705 * clicking, but you may wish to play these effects in your widget,
18706 * for instance, for internal navigation.
18708 * <p>The sound effect will only be played if sound effects are enabled by the user, and
18709 * {@link #isSoundEffectsEnabled()} is true.
18711 * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
18713 public void playSoundEffect(int soundConstant) {
18714 if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
18717 mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
18723 * <p>Provide haptic feedback to the user for this view.
18725 * <p>The framework will provide haptic feedback for some built in actions,
18726 * such as long presses, but you may wish to provide feedback for your
18729 * <p>The feedback will only be performed if
18730 * {@link #isHapticFeedbackEnabled()} is true.
18732 * @param feedbackConstant One of the constants defined in
18733 * {@link HapticFeedbackConstants}
18735 public boolean performHapticFeedback(int feedbackConstant) {
18736 return performHapticFeedback(feedbackConstant, 0);
18742 * <p>Like {@link #performHapticFeedback(int)}, with additional options.
18744 * @param feedbackConstant One of the constants defined in
18745 * {@link HapticFeedbackConstants}
18746 * @param flags Additional flags as per {@link HapticFeedbackConstants}.
18748 public boolean performHapticFeedback(int feedbackConstant, int flags) {
18749 if (mAttachInfo == null) {
18752 //noinspection SimplifiableIfStatement
18753 if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
18754 && !isHapticFeedbackEnabled()) {
18757 return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
18758 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
18762 * Request that the visibility of the status bar or other screen/window
18763 * decorations be changed.
18765 * <p>This method is used to put the over device UI into temporary modes
18766 * where the user's attention is focused more on the application content,
18767 * by dimming or hiding surrounding system affordances. This is typically
18768 * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
18769 * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
18770 * to be placed behind the action bar (and with these flags other system
18771 * affordances) so that smooth transitions between hiding and showing them
18774 * <p>Two representative examples of the use of system UI visibility is
18775 * implementing a content browsing application (like a magazine reader)
18776 * and a video playing application.
18778 * <p>The first code shows a typical implementation of a View in a content
18779 * browsing application. In this implementation, the application goes
18780 * into a content-oriented mode by hiding the status bar and action bar,
18781 * and putting the navigation elements into lights out mode. The user can
18782 * then interact with content while in this mode. Such an application should
18783 * provide an easy way for the user to toggle out of the mode (such as to
18784 * check information in the status bar or access notifications). In the
18785 * implementation here, this is done simply by tapping on the content.
18787 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
18790 * <p>This second code sample shows a typical implementation of a View
18791 * in a video playing application. In this situation, while the video is
18792 * playing the application would like to go into a complete full-screen mode,
18793 * to use as much of the display as possible for the video. When in this state
18794 * the user can not interact with the application; the system intercepts
18795 * touching on the screen to pop the UI out of full screen mode. See
18796 * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
18798 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
18801 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
18802 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
18803 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
18804 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
18805 * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
18807 public void setSystemUiVisibility(int visibility) {
18808 if (visibility != mSystemUiVisibility) {
18809 mSystemUiVisibility = visibility;
18810 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
18811 mParent.recomputeViewAttributes(this);
18817 * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
18818 * @return Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
18819 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
18820 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
18821 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
18822 * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
18824 public int getSystemUiVisibility() {
18825 return mSystemUiVisibility;
18829 * Returns the current system UI visibility that is currently set for
18830 * the entire window. This is the combination of the
18831 * {@link #setSystemUiVisibility(int)} values supplied by all of the
18832 * views in the window.
18834 public int getWindowSystemUiVisibility() {
18835 return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
18839 * Override to find out when the window's requested system UI visibility
18840 * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
18841 * This is different from the callbacks received through
18842 * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
18843 * in that this is only telling you about the local request of the window,
18844 * not the actual values applied by the system.
18846 public void onWindowSystemUiVisibilityChanged(int visible) {
18850 * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
18851 * the view hierarchy.
18853 public void dispatchWindowSystemUiVisiblityChanged(int visible) {
18854 onWindowSystemUiVisibilityChanged(visible);
18858 * Set a listener to receive callbacks when the visibility of the system bar changes.
18859 * @param l The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
18861 public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
18862 getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
18863 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
18864 mParent.recomputeViewAttributes(this);
18869 * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
18870 * the view hierarchy.
18872 public void dispatchSystemUiVisibilityChanged(int visibility) {
18873 ListenerInfo li = mListenerInfo;
18874 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
18875 li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
18876 visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
18880 boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
18881 int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
18882 if (val != mSystemUiVisibility) {
18883 setSystemUiVisibility(val);
18890 public void setDisabledSystemUiVisibility(int flags) {
18891 if (mAttachInfo != null) {
18892 if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
18893 mAttachInfo.mDisabledSystemUiVisibility = flags;
18894 if (mParent != null) {
18895 mParent.recomputeViewAttributes(this);
18902 * Creates an image that the system displays during the drag and drop
18903 * operation. This is called a "drag shadow". The default implementation
18904 * for a DragShadowBuilder based on a View returns an image that has exactly the same
18905 * appearance as the given View. The default also positions the center of the drag shadow
18906 * directly under the touch point. If no View is provided (the constructor with no parameters
18907 * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
18908 * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
18909 * default is an invisible drag shadow.
18911 * You are not required to use the View you provide to the constructor as the basis of the
18912 * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
18913 * anything you want as the drag shadow.
18916 * You pass a DragShadowBuilder object to the system when you start the drag. The system
18917 * calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
18918 * size and position of the drag shadow. It uses this data to construct a
18919 * {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
18920 * so that your application can draw the shadow image in the Canvas.
18923 * <div class="special reference">
18924 * <h3>Developer Guides</h3>
18925 * <p>For a guide to implementing drag and drop features, read the
18926 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
18929 public static class DragShadowBuilder {
18930 private final WeakReference<View> mView;
18933 * Constructs a shadow image builder based on a View. By default, the resulting drag
18934 * shadow will have the same appearance and dimensions as the View, with the touch point
18935 * over the center of the View.
18936 * @param view A View. Any View in scope can be used.
18938 public DragShadowBuilder(View view) {
18939 mView = new WeakReference<View>(view);
18943 * Construct a shadow builder object with no associated View. This
18944 * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
18945 * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
18946 * to supply the drag shadow's dimensions and appearance without
18947 * reference to any View object. If they are not overridden, then the result is an
18948 * invisible drag shadow.
18950 public DragShadowBuilder() {
18951 mView = new WeakReference<View>(null);
18955 * Returns the View object that had been passed to the
18956 * {@link #View.DragShadowBuilder(View)}
18957 * constructor. If that View parameter was {@code null} or if the
18958 * {@link #View.DragShadowBuilder()}
18959 * constructor was used to instantiate the builder object, this method will return
18962 * @return The View object associate with this builder object.
18964 @SuppressWarnings({"JavadocReference"})
18965 final public View getView() {
18966 return mView.get();
18970 * Provides the metrics for the shadow image. These include the dimensions of
18971 * the shadow image, and the point within that shadow that should
18972 * be centered under the touch location while dragging.
18974 * The default implementation sets the dimensions of the shadow to be the
18975 * same as the dimensions of the View itself and centers the shadow under
18979 * @param shadowSize A {@link android.graphics.Point} containing the width and height
18980 * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
18981 * desired width and must set {@link android.graphics.Point#y} to the desired height of the
18984 * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
18985 * shadow image that should be underneath the touch point during the drag and drop
18986 * operation. Your application must set {@link android.graphics.Point#x} to the
18987 * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
18989 public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
18990 final View view = mView.get();
18991 if (view != null) {
18992 shadowSize.set(view.getWidth(), view.getHeight());
18993 shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
18995 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
19000 * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
19001 * based on the dimensions it received from the
19002 * {@link #onProvideShadowMetrics(Point, Point)} callback.
19004 * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
19006 public void onDrawShadow(Canvas canvas) {
19007 final View view = mView.get();
19008 if (view != null) {
19011 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
19017 * Starts a drag and drop operation. When your application calls this method, it passes a
19018 * {@link android.view.View.DragShadowBuilder} object to the system. The
19019 * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
19020 * to get metrics for the drag shadow, and then calls the object's
19021 * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
19023 * Once the system has the drag shadow, it begins the drag and drop operation by sending
19024 * drag events to all the View objects in your application that are currently visible. It does
19025 * this either by calling the View object's drag listener (an implementation of
19026 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
19027 * View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
19028 * Both are passed a {@link android.view.DragEvent} object that has a
19029 * {@link android.view.DragEvent#getAction()} value of
19030 * {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
19033 * Your application can invoke startDrag() on any attached View object. The View object does not
19034 * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
19035 * be related to the View the user selected for dragging.
19037 * @param data A {@link android.content.ClipData} object pointing to the data to be
19038 * transferred by the drag and drop operation.
19039 * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
19041 * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
19042 * drop operation. This Object is put into every DragEvent object sent by the system during the
19045 * myLocalState is a lightweight mechanism for the sending information from the dragged View
19046 * to the target Views. For example, it can contain flags that differentiate between a
19047 * a copy operation and a move operation.
19049 * @param flags Flags that control the drag and drop operation. No flags are currently defined,
19050 * so the parameter should be set to 0.
19051 * @return {@code true} if the method completes successfully, or
19052 * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
19053 * do a drag, and so no drag operation is in progress.
19055 public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
19056 Object myLocalState, int flags) {
19057 if (ViewDebug.DEBUG_DRAG) {
19058 Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
19060 boolean okay = false;
19062 Point shadowSize = new Point();
19063 Point shadowTouchPoint = new Point();
19064 shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
19066 if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
19067 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
19068 throw new IllegalStateException("Drag shadow dimensions must not be negative");
19071 if (ViewDebug.DEBUG_DRAG) {
19072 Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
19073 + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
19075 Surface surface = new Surface();
19077 IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
19078 flags, shadowSize.x, shadowSize.y, surface);
19079 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
19080 + " surface=" + surface);
19081 if (token != null) {
19082 Canvas canvas = surface.lockCanvas(null);
19084 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
19085 shadowBuilder.onDrawShadow(canvas);
19087 surface.unlockCanvasAndPost(canvas);
19090 final ViewRootImpl root = getViewRootImpl();
19092 // Cache the local state object for delivery with DragEvents
19093 root.setLocalDragState(myLocalState);
19095 // repurpose 'shadowSize' for the last touch point
19096 root.getLastTouchPoint(shadowSize);
19098 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
19099 shadowSize.x, shadowSize.y,
19100 shadowTouchPoint.x, shadowTouchPoint.y, data);
19101 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
19103 // Off and running! Release our local surface instance; the drag
19104 // shadow surface is now managed by the system process.
19107 } catch (Exception e) {
19108 Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
19116 * Handles drag events sent by the system following a call to
19117 * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
19119 * When the system calls this method, it passes a
19120 * {@link android.view.DragEvent} object. A call to
19121 * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
19122 * in DragEvent. The method uses these to determine what is happening in the drag and drop
19124 * @param event The {@link android.view.DragEvent} sent by the system.
19125 * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
19126 * in DragEvent, indicating the type of drag event represented by this object.
19127 * @return {@code true} if the method was successful, otherwise {@code false}.
19129 * The method should return {@code true} in response to an action type of
19130 * {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
19134 * The method should also return {@code true} in response to an action type of
19135 * {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
19136 * {@code false} if it didn't.
19139 public boolean onDragEvent(DragEvent event) {
19144 * Detects if this View is enabled and has a drag event listener.
19145 * If both are true, then it calls the drag event listener with the
19146 * {@link android.view.DragEvent} it received. If the drag event listener returns
19147 * {@code true}, then dispatchDragEvent() returns {@code true}.
19149 * For all other cases, the method calls the
19150 * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
19151 * method and returns its result.
19154 * This ensures that a drag event is always consumed, even if the View does not have a drag
19155 * event listener. However, if the View has a listener and the listener returns true, then
19156 * onDragEvent() is not called.
19159 public boolean dispatchDragEvent(DragEvent event) {
19160 ListenerInfo li = mListenerInfo;
19161 //noinspection SimplifiableIfStatement
19162 if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
19163 && li.mOnDragListener.onDrag(this, event)) {
19166 return onDragEvent(event);
19169 boolean canAcceptDrag() {
19170 return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
19174 * This needs to be a better API (NOT ON VIEW) before it is exposed. If
19175 * it is ever exposed at all.
19178 public void onCloseSystemDialogs(String reason) {
19182 * Given a Drawable whose bounds have been set to draw into this view,
19183 * update a Region being computed for
19184 * {@link #gatherTransparentRegion(android.graphics.Region)} so
19185 * that any non-transparent parts of the Drawable are removed from the
19186 * given transparent region.
19188 * @param dr The Drawable whose transparency is to be applied to the region.
19189 * @param region A Region holding the current transparency information,
19190 * where any parts of the region that are set are considered to be
19191 * transparent. On return, this region will be modified to have the
19192 * transparency information reduced by the corresponding parts of the
19193 * Drawable that are not transparent.
19196 public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
19198 Log.i("View", "Getting transparent region for: " + this);
19200 final Region r = dr.getTransparentRegion();
19201 final Rect db = dr.getBounds();
19202 final AttachInfo attachInfo = mAttachInfo;
19203 if (r != null && attachInfo != null) {
19204 final int w = getRight()-getLeft();
19205 final int h = getBottom()-getTop();
19207 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
19208 r.op(0, 0, db.left, h, Region.Op.UNION);
19210 if (db.right < w) {
19211 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
19212 r.op(db.right, 0, w, h, Region.Op.UNION);
19215 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
19216 r.op(0, 0, w, db.top, Region.Op.UNION);
19218 if (db.bottom < h) {
19219 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
19220 r.op(0, db.bottom, w, h, Region.Op.UNION);
19222 final int[] location = attachInfo.mTransparentLocation;
19223 getLocationInWindow(location);
19224 r.translate(location[0], location[1]);
19225 region.op(r, Region.Op.INTERSECT);
19227 region.op(db, Region.Op.DIFFERENCE);
19231 private void checkForLongClick(int delayOffset) {
19232 if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
19233 mHasPerformedLongPress = false;
19235 if (mPendingCheckForLongPress == null) {
19236 mPendingCheckForLongPress = new CheckForLongPress();
19238 mPendingCheckForLongPress.rememberWindowAttachCount();
19239 postDelayed(mPendingCheckForLongPress,
19240 ViewConfiguration.getLongPressTimeout() - delayOffset);
19245 * Inflate a view from an XML resource. This convenience method wraps the {@link
19246 * LayoutInflater} class, which provides a full range of options for view inflation.
19248 * @param context The Context object for your activity or application.
19249 * @param resource The resource ID to inflate
19250 * @param root A view group that will be the parent. Used to properly inflate the
19251 * layout_* parameters.
19252 * @see LayoutInflater
19254 public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
19255 LayoutInflater factory = LayoutInflater.from(context);
19256 return factory.inflate(resource, root);
19260 * Scroll the view with standard behavior for scrolling beyond the normal
19261 * content boundaries. Views that call this method should override
19262 * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
19263 * results of an over-scroll operation.
19265 * Views can use this method to handle any touch or fling-based scrolling.
19267 * @param deltaX Change in X in pixels
19268 * @param deltaY Change in Y in pixels
19269 * @param scrollX Current X scroll value in pixels before applying deltaX
19270 * @param scrollY Current Y scroll value in pixels before applying deltaY
19271 * @param scrollRangeX Maximum content scroll range along the X axis
19272 * @param scrollRangeY Maximum content scroll range along the Y axis
19273 * @param maxOverScrollX Number of pixels to overscroll by in either direction
19274 * along the X axis.
19275 * @param maxOverScrollY Number of pixels to overscroll by in either direction
19276 * along the Y axis.
19277 * @param isTouchEvent true if this scroll operation is the result of a touch event.
19278 * @return true if scrolling was clamped to an over-scroll boundary along either
19279 * axis, false otherwise.
19281 @SuppressWarnings({"UnusedParameters"})
19282 protected boolean overScrollBy(int deltaX, int deltaY,
19283 int scrollX, int scrollY,
19284 int scrollRangeX, int scrollRangeY,
19285 int maxOverScrollX, int maxOverScrollY,
19286 boolean isTouchEvent) {
19287 final int overScrollMode = mOverScrollMode;
19288 final boolean canScrollHorizontal =
19289 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
19290 final boolean canScrollVertical =
19291 computeVerticalScrollRange() > computeVerticalScrollExtent();
19292 final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
19293 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
19294 final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
19295 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
19297 int newScrollX = scrollX + deltaX;
19298 if (!overScrollHorizontal) {
19299 maxOverScrollX = 0;
19302 int newScrollY = scrollY + deltaY;
19303 if (!overScrollVertical) {
19304 maxOverScrollY = 0;
19307 // Clamp values if at the limits and record
19308 final int left = -maxOverScrollX;
19309 final int right = maxOverScrollX + scrollRangeX;
19310 final int top = -maxOverScrollY;
19311 final int bottom = maxOverScrollY + scrollRangeY;
19313 boolean clampedX = false;
19314 if (newScrollX > right) {
19315 newScrollX = right;
19317 } else if (newScrollX < left) {
19322 boolean clampedY = false;
19323 if (newScrollY > bottom) {
19324 newScrollY = bottom;
19326 } else if (newScrollY < top) {
19331 onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
19333 return clampedX || clampedY;
19337 * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
19338 * respond to the results of an over-scroll operation.
19340 * @param scrollX New X scroll value in pixels
19341 * @param scrollY New Y scroll value in pixels
19342 * @param clampedX True if scrollX was clamped to an over-scroll boundary
19343 * @param clampedY True if scrollY was clamped to an over-scroll boundary
19345 protected void onOverScrolled(int scrollX, int scrollY,
19346 boolean clampedX, boolean clampedY) {
19347 // Intentionally empty.
19351 * Returns the over-scroll mode for this view. The result will be
19352 * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
19353 * (allow over-scrolling only if the view content is larger than the container),
19354 * or {@link #OVER_SCROLL_NEVER}.
19356 * @return This view's over-scroll mode.
19358 public int getOverScrollMode() {
19359 return mOverScrollMode;
19363 * Set the over-scroll mode for this view. Valid over-scroll modes are
19364 * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
19365 * (allow over-scrolling only if the view content is larger than the container),
19366 * or {@link #OVER_SCROLL_NEVER}.
19368 * Setting the over-scroll mode of a view will have an effect only if the
19369 * view is capable of scrolling.
19371 * @param overScrollMode The new over-scroll mode for this view.
19373 public void setOverScrollMode(int overScrollMode) {
19374 if (overScrollMode != OVER_SCROLL_ALWAYS &&
19375 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
19376 overScrollMode != OVER_SCROLL_NEVER) {
19377 throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
19379 mOverScrollMode = overScrollMode;
19383 * Enable or disable nested scrolling for this view.
19385 * <p>If this property is set to true the view will be permitted to initiate nested
19386 * scrolling operations with a compatible parent view in the current hierarchy. If this
19387 * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
19388 * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
19389 * the nested scroll.</p>
19391 * @param enabled true to enable nested scrolling, false to disable
19393 * @see #isNestedScrollingEnabled()
19395 public void setNestedScrollingEnabled(boolean enabled) {
19397 mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
19399 stopNestedScroll();
19400 mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
19405 * Returns true if nested scrolling is enabled for this view.
19407 * <p>If nested scrolling is enabled and this View class implementation supports it,
19408 * this view will act as a nested scrolling child view when applicable, forwarding data
19409 * about the scroll operation in progress to a compatible and cooperating nested scrolling
19412 * @return true if nested scrolling is enabled
19414 * @see #setNestedScrollingEnabled(boolean)
19416 public boolean isNestedScrollingEnabled() {
19417 return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
19418 PFLAG3_NESTED_SCROLLING_ENABLED;
19422 * Begin a nestable scroll operation along the given axes.
19424 * <p>A view starting a nested scroll promises to abide by the following contract:</p>
19426 * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
19427 * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
19428 * In the case of touch scrolling the nested scroll will be terminated automatically in
19429 * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
19430 * In the event of programmatic scrolling the caller must explicitly call
19431 * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
19433 * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
19434 * If it returns false the caller may ignore the rest of this contract until the next scroll.
19435 * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
19437 * <p>At each incremental step of the scroll the caller should invoke
19438 * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
19439 * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
19440 * parent at least partially consumed the scroll and the caller should adjust the amount it
19443 * <p>After applying the remainder of the scroll delta the caller should invoke
19444 * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
19445 * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
19446 * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
19449 * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
19450 * {@link #SCROLL_AXIS_VERTICAL}.
19451 * @return true if a cooperative parent was found and nested scrolling has been enabled for
19452 * the current gesture.
19454 * @see #stopNestedScroll()
19455 * @see #dispatchNestedPreScroll(int, int, int[], int[])
19456 * @see #dispatchNestedScroll(int, int, int, int, int[])
19458 public boolean startNestedScroll(int axes) {
19459 if (hasNestedScrollingParent()) {
19460 // Already in progress
19463 if (isNestedScrollingEnabled()) {
19464 ViewParent p = getParent();
19466 while (p != null) {
19468 if (p.onStartNestedScroll(child, this, axes)) {
19469 mNestedScrollingParent = p;
19470 p.onNestedScrollAccepted(child, this, axes);
19473 } catch (AbstractMethodError e) {
19474 Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
19475 "method onStartNestedScroll", e);
19476 // Allow the search upward to continue
19478 if (p instanceof View) {
19488 * Stop a nested scroll in progress.
19490 * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
19492 * @see #startNestedScroll(int)
19494 public void stopNestedScroll() {
19495 if (mNestedScrollingParent != null) {
19496 mNestedScrollingParent.onStopNestedScroll(this);
19497 mNestedScrollingParent = null;
19502 * Returns true if this view has a nested scrolling parent.
19504 * <p>The presence of a nested scrolling parent indicates that this view has initiated
19505 * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
19507 * @return whether this view has a nested scrolling parent
19509 public boolean hasNestedScrollingParent() {
19510 return mNestedScrollingParent != null;
19514 * Dispatch one step of a nested scroll in progress.
19516 * <p>Implementations of views that support nested scrolling should call this to report
19517 * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
19518 * is not currently in progress or nested scrolling is not
19519 * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
19521 * <p>Compatible View implementations should also call
19522 * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
19523 * consuming a component of the scroll event themselves.</p>
19525 * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
19526 * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
19527 * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
19528 * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
19529 * @param offsetInWindow Optional. If not null, on return this will contain the offset
19530 * in local view coordinates of this view from before this operation
19531 * to after it completes. View implementations may use this to adjust
19532 * expected input coordinate tracking.
19533 * @return true if the event was dispatched, false if it could not be dispatched.
19534 * @see #dispatchNestedPreScroll(int, int, int[], int[])
19536 public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
19537 int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
19538 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
19539 if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
19542 if (offsetInWindow != null) {
19543 getLocationInWindow(offsetInWindow);
19544 startX = offsetInWindow[0];
19545 startY = offsetInWindow[1];
19548 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
19549 dxUnconsumed, dyUnconsumed);
19551 if (offsetInWindow != null) {
19552 getLocationInWindow(offsetInWindow);
19553 offsetInWindow[0] -= startX;
19554 offsetInWindow[1] -= startY;
19557 } else if (offsetInWindow != null) {
19558 // No motion, no dispatch. Keep offsetInWindow up to date.
19559 offsetInWindow[0] = 0;
19560 offsetInWindow[1] = 0;
19567 * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
19569 * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
19570 * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
19571 * scrolling operation to consume some or all of the scroll operation before the child view
19574 * @param dx Horizontal scroll distance in pixels
19575 * @param dy Vertical scroll distance in pixels
19576 * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
19577 * and consumed[1] the consumed dy.
19578 * @param offsetInWindow Optional. If not null, on return this will contain the offset
19579 * in local view coordinates of this view from before this operation
19580 * to after it completes. View implementations may use this to adjust
19581 * expected input coordinate tracking.
19582 * @return true if the parent consumed some or all of the scroll delta
19583 * @see #dispatchNestedScroll(int, int, int, int, int[])
19585 public boolean dispatchNestedPreScroll(int dx, int dy,
19586 @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
19587 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
19588 if (dx != 0 || dy != 0) {
19591 if (offsetInWindow != null) {
19592 getLocationInWindow(offsetInWindow);
19593 startX = offsetInWindow[0];
19594 startY = offsetInWindow[1];
19597 if (consumed == null) {
19598 if (mTempNestedScrollConsumed == null) {
19599 mTempNestedScrollConsumed = new int[2];
19601 consumed = mTempNestedScrollConsumed;
19605 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
19607 if (offsetInWindow != null) {
19608 getLocationInWindow(offsetInWindow);
19609 offsetInWindow[0] -= startX;
19610 offsetInWindow[1] -= startY;
19612 return consumed[0] != 0 || consumed[1] != 0;
19613 } else if (offsetInWindow != null) {
19614 offsetInWindow[0] = 0;
19615 offsetInWindow[1] = 0;
19622 * Dispatch a fling to a nested scrolling parent.
19624 * <p>This method should be used to indicate that a nested scrolling child has detected
19625 * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
19626 * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
19627 * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
19628 * along a scrollable axis.</p>
19630 * <p>If a nested scrolling child view would normally fling but it is at the edge of
19631 * its own content, it can use this method to delegate the fling to its nested scrolling
19632 * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
19634 * @param velocityX Horizontal fling velocity in pixels per second
19635 * @param velocityY Vertical fling velocity in pixels per second
19636 * @param consumed true if the child consumed the fling, false otherwise
19637 * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
19639 public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
19640 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
19641 return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
19647 * Dispatch a fling to a nested scrolling parent before it is processed by this view.
19649 * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
19650 * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
19651 * offsets an opportunity for the parent view in a nested fling to fully consume the fling
19652 * before the child view consumes it. If this method returns <code>true</code>, a nested
19653 * parent view consumed the fling and this view should not scroll as a result.</p>
19655 * <p>For a better user experience, only one view in a nested scrolling chain should consume
19656 * the fling at a time. If a parent view consumed the fling this method will return false.
19657 * Custom view implementations should account for this in two ways:</p>
19660 * <li>If a custom view is paged and needs to settle to a fixed page-point, do not
19661 * call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
19662 * position regardless.</li>
19663 * <li>If a nested parent does consume the fling, this view should not scroll at all,
19664 * even to settle back to a valid idle position.</li>
19667 * <p>Views should also not offer fling velocities to nested parent views along an axis
19668 * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
19669 * should not offer a horizontal fling velocity to its parents since scrolling along that
19670 * axis is not permitted and carrying velocity along that motion does not make sense.</p>
19672 * @param velocityX Horizontal fling velocity in pixels per second
19673 * @param velocityY Vertical fling velocity in pixels per second
19674 * @return true if a nested scrolling parent consumed the fling
19676 public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
19677 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
19678 return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
19684 * Gets a scale factor that determines the distance the view should scroll
19685 * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
19686 * @return The vertical scroll scale factor.
19689 protected float getVerticalScrollFactor() {
19690 if (mVerticalScrollFactor == 0) {
19691 TypedValue outValue = new TypedValue();
19692 if (!mContext.getTheme().resolveAttribute(
19693 com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
19694 throw new IllegalStateException(
19695 "Expected theme to define listPreferredItemHeight.");
19697 mVerticalScrollFactor = outValue.getDimension(
19698 mContext.getResources().getDisplayMetrics());
19700 return mVerticalScrollFactor;
19704 * Gets a scale factor that determines the distance the view should scroll
19705 * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
19706 * @return The horizontal scroll scale factor.
19709 protected float getHorizontalScrollFactor() {
19710 // TODO: Should use something else.
19711 return getVerticalScrollFactor();
19715 * Return the value specifying the text direction or policy that was set with
19716 * {@link #setTextDirection(int)}.
19718 * @return the defined text direction. It can be one of:
19720 * {@link #TEXT_DIRECTION_INHERIT},
19721 * {@link #TEXT_DIRECTION_FIRST_STRONG},
19722 * {@link #TEXT_DIRECTION_ANY_RTL},
19723 * {@link #TEXT_DIRECTION_LTR},
19724 * {@link #TEXT_DIRECTION_RTL},
19725 * {@link #TEXT_DIRECTION_LOCALE},
19726 * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
19727 * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
19729 * @attr ref android.R.styleable#View_textDirection
19733 @ViewDebug.ExportedProperty(category = "text", mapping = {
19734 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
19735 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
19736 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
19737 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
19738 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
19739 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
19740 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
19741 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
19743 public int getRawTextDirection() {
19744 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
19748 * Set the text direction.
19750 * @param textDirection the direction to set. Should be one of:
19752 * {@link #TEXT_DIRECTION_INHERIT},
19753 * {@link #TEXT_DIRECTION_FIRST_STRONG},
19754 * {@link #TEXT_DIRECTION_ANY_RTL},
19755 * {@link #TEXT_DIRECTION_LTR},
19756 * {@link #TEXT_DIRECTION_RTL},
19757 * {@link #TEXT_DIRECTION_LOCALE}
19758 * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
19759 * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
19761 * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
19762 * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
19763 * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
19765 * @attr ref android.R.styleable#View_textDirection
19767 public void setTextDirection(int textDirection) {
19768 if (getRawTextDirection() != textDirection) {
19769 // Reset the current text direction and the resolved one
19770 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
19771 resetResolvedTextDirection();
19772 // Set the new text direction
19773 mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
19775 resolveTextDirection();
19777 onRtlPropertiesChanged(getLayoutDirection());
19785 * Return the resolved text direction.
19787 * @return the resolved text direction. Returns one of:
19789 * {@link #TEXT_DIRECTION_FIRST_STRONG},
19790 * {@link #TEXT_DIRECTION_ANY_RTL},
19791 * {@link #TEXT_DIRECTION_LTR},
19792 * {@link #TEXT_DIRECTION_RTL},
19793 * {@link #TEXT_DIRECTION_LOCALE},
19794 * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
19795 * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
19797 * @attr ref android.R.styleable#View_textDirection
19799 @ViewDebug.ExportedProperty(category = "text", mapping = {
19800 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
19801 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
19802 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
19803 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
19804 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
19805 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
19806 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
19807 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
19809 public int getTextDirection() {
19810 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
19814 * Resolve the text direction.
19816 * @return true if resolution has been done, false otherwise.
19820 public boolean resolveTextDirection() {
19821 // Reset any previous text direction resolution
19822 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
19824 if (hasRtlSupport()) {
19825 // Set resolved text direction flag depending on text direction flag
19826 final int textDirection = getRawTextDirection();
19827 switch(textDirection) {
19828 case TEXT_DIRECTION_INHERIT:
19829 if (!canResolveTextDirection()) {
19830 // We cannot do the resolution if there is no parent, so use the default one
19831 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19832 // Resolution will need to happen again later
19836 // Parent has not yet resolved, so we still return the default
19838 if (!mParent.isTextDirectionResolved()) {
19839 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19840 // Resolution will need to happen again later
19843 } catch (AbstractMethodError e) {
19844 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19845 " does not fully implement ViewParent", e);
19846 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
19847 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19851 // Set current resolved direction to the same value as the parent's one
19852 int parentResolvedDirection;
19854 parentResolvedDirection = mParent.getTextDirection();
19855 } catch (AbstractMethodError e) {
19856 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19857 " does not fully implement ViewParent", e);
19858 parentResolvedDirection = TEXT_DIRECTION_LTR;
19860 switch (parentResolvedDirection) {
19861 case TEXT_DIRECTION_FIRST_STRONG:
19862 case TEXT_DIRECTION_ANY_RTL:
19863 case TEXT_DIRECTION_LTR:
19864 case TEXT_DIRECTION_RTL:
19865 case TEXT_DIRECTION_LOCALE:
19866 case TEXT_DIRECTION_FIRST_STRONG_LTR:
19867 case TEXT_DIRECTION_FIRST_STRONG_RTL:
19869 (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
19872 // Default resolved direction is "first strong" heuristic
19873 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19876 case TEXT_DIRECTION_FIRST_STRONG:
19877 case TEXT_DIRECTION_ANY_RTL:
19878 case TEXT_DIRECTION_LTR:
19879 case TEXT_DIRECTION_RTL:
19880 case TEXT_DIRECTION_LOCALE:
19881 case TEXT_DIRECTION_FIRST_STRONG_LTR:
19882 case TEXT_DIRECTION_FIRST_STRONG_RTL:
19883 // Resolved direction is the same as text direction
19884 mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
19887 // Default resolved direction is "first strong" heuristic
19888 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19891 // Default resolved direction is "first strong" heuristic
19892 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19896 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
19901 * Check if text direction resolution can be done.
19903 * @return true if text direction resolution can be done otherwise return false.
19905 public boolean canResolveTextDirection() {
19906 switch (getRawTextDirection()) {
19907 case TEXT_DIRECTION_INHERIT:
19908 if (mParent != null) {
19910 return mParent.canResolveTextDirection();
19911 } catch (AbstractMethodError e) {
19912 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19913 " does not fully implement ViewParent", e);
19924 * Reset resolved text direction. Text direction will be resolved during a call to
19925 * {@link #onMeasure(int, int)}.
19929 public void resetResolvedTextDirection() {
19930 // Reset any previous text direction resolution
19931 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
19932 // Set to default value
19933 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19937 * @return true if text direction is inherited.
19941 public boolean isTextDirectionInherited() {
19942 return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
19946 * @return true if text direction is resolved.
19948 public boolean isTextDirectionResolved() {
19949 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
19953 * Return the value specifying the text alignment or policy that was set with
19954 * {@link #setTextAlignment(int)}.
19956 * @return the defined text alignment. It can be one of:
19958 * {@link #TEXT_ALIGNMENT_INHERIT},
19959 * {@link #TEXT_ALIGNMENT_GRAVITY},
19960 * {@link #TEXT_ALIGNMENT_CENTER},
19961 * {@link #TEXT_ALIGNMENT_TEXT_START},
19962 * {@link #TEXT_ALIGNMENT_TEXT_END},
19963 * {@link #TEXT_ALIGNMENT_VIEW_START},
19964 * {@link #TEXT_ALIGNMENT_VIEW_END}
19966 * @attr ref android.R.styleable#View_textAlignment
19970 @ViewDebug.ExportedProperty(category = "text", mapping = {
19971 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
19972 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
19973 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
19974 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
19975 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
19976 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
19977 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
19980 public int getRawTextAlignment() {
19981 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
19985 * Set the text alignment.
19987 * @param textAlignment The text alignment to set. Should be one of
19989 * {@link #TEXT_ALIGNMENT_INHERIT},
19990 * {@link #TEXT_ALIGNMENT_GRAVITY},
19991 * {@link #TEXT_ALIGNMENT_CENTER},
19992 * {@link #TEXT_ALIGNMENT_TEXT_START},
19993 * {@link #TEXT_ALIGNMENT_TEXT_END},
19994 * {@link #TEXT_ALIGNMENT_VIEW_START},
19995 * {@link #TEXT_ALIGNMENT_VIEW_END}
19997 * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
19998 * proceeds up the parent chain of the view to get the value. If there is no parent, then it
19999 * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
20001 * @attr ref android.R.styleable#View_textAlignment
20003 public void setTextAlignment(@TextAlignment int textAlignment) {
20004 if (textAlignment != getRawTextAlignment()) {
20005 // Reset the current and resolved text alignment
20006 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
20007 resetResolvedTextAlignment();
20008 // Set the new text alignment
20010 ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
20012 resolveTextAlignment();
20014 onRtlPropertiesChanged(getLayoutDirection());
20022 * Return the resolved text alignment.
20024 * @return the resolved text alignment. Returns one of:
20026 * {@link #TEXT_ALIGNMENT_GRAVITY},
20027 * {@link #TEXT_ALIGNMENT_CENTER},
20028 * {@link #TEXT_ALIGNMENT_TEXT_START},
20029 * {@link #TEXT_ALIGNMENT_TEXT_END},
20030 * {@link #TEXT_ALIGNMENT_VIEW_START},
20031 * {@link #TEXT_ALIGNMENT_VIEW_END}
20033 * @attr ref android.R.styleable#View_textAlignment
20035 @ViewDebug.ExportedProperty(category = "text", mapping = {
20036 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20037 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20038 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20039 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20040 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20041 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20042 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
20045 public int getTextAlignment() {
20046 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
20047 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
20051 * Resolve the text alignment.
20053 * @return true if resolution has been done, false otherwise.
20057 public boolean resolveTextAlignment() {
20058 // Reset any previous text alignment resolution
20059 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20061 if (hasRtlSupport()) {
20062 // Set resolved text alignment flag depending on text alignment flag
20063 final int textAlignment = getRawTextAlignment();
20064 switch (textAlignment) {
20065 case TEXT_ALIGNMENT_INHERIT:
20066 // Check if we can resolve the text alignment
20067 if (!canResolveTextAlignment()) {
20068 // We cannot do the resolution if there is no parent so use the default
20069 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20070 // Resolution will need to happen again later
20074 // Parent has not yet resolved, so we still return the default
20076 if (!mParent.isTextAlignmentResolved()) {
20077 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20078 // Resolution will need to happen again later
20081 } catch (AbstractMethodError e) {
20082 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20083 " does not fully implement ViewParent", e);
20084 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
20085 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20089 int parentResolvedTextAlignment;
20091 parentResolvedTextAlignment = mParent.getTextAlignment();
20092 } catch (AbstractMethodError e) {
20093 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20094 " does not fully implement ViewParent", e);
20095 parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
20097 switch (parentResolvedTextAlignment) {
20098 case TEXT_ALIGNMENT_GRAVITY:
20099 case TEXT_ALIGNMENT_TEXT_START:
20100 case TEXT_ALIGNMENT_TEXT_END:
20101 case TEXT_ALIGNMENT_CENTER:
20102 case TEXT_ALIGNMENT_VIEW_START:
20103 case TEXT_ALIGNMENT_VIEW_END:
20104 // Resolved text alignment is the same as the parent resolved
20107 (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20110 // Use default resolved text alignment
20111 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20114 case TEXT_ALIGNMENT_GRAVITY:
20115 case TEXT_ALIGNMENT_TEXT_START:
20116 case TEXT_ALIGNMENT_TEXT_END:
20117 case TEXT_ALIGNMENT_CENTER:
20118 case TEXT_ALIGNMENT_VIEW_START:
20119 case TEXT_ALIGNMENT_VIEW_END:
20120 // Resolved text alignment is the same as text alignment
20121 mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20124 // Use default resolved text alignment
20125 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20128 // Use default resolved text alignment
20129 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20132 // Set the resolved
20133 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20138 * Check if text alignment resolution can be done.
20140 * @return true if text alignment resolution can be done otherwise return false.
20142 public boolean canResolveTextAlignment() {
20143 switch (getRawTextAlignment()) {
20144 case TEXT_DIRECTION_INHERIT:
20145 if (mParent != null) {
20147 return mParent.canResolveTextAlignment();
20148 } catch (AbstractMethodError e) {
20149 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20150 " does not fully implement ViewParent", e);
20161 * Reset resolved text alignment. Text alignment will be resolved during a call to
20162 * {@link #onMeasure(int, int)}.
20166 public void resetResolvedTextAlignment() {
20167 // Reset any previous text alignment resolution
20168 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20170 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20174 * @return true if text alignment is inherited.
20178 public boolean isTextAlignmentInherited() {
20179 return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
20183 * @return true if text alignment is resolved.
20185 public boolean isTextAlignmentResolved() {
20186 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20190 * Generate a value suitable for use in {@link #setId(int)}.
20191 * This value will not collide with ID values generated at build time by aapt for R.id.
20193 * @return a generated ID value
20195 public static int generateViewId() {
20197 final int result = sNextGeneratedId.get();
20198 // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
20199 int newValue = result + 1;
20200 if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
20201 if (sNextGeneratedId.compareAndSet(result, newValue)) {
20208 * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
20209 * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
20210 * a normal View or a ViewGroup with
20211 * {@link android.view.ViewGroup#isTransitionGroup()} true.
20214 public void captureTransitioningViews(List<View> transitioningViews) {
20215 if (getVisibility() == View.VISIBLE) {
20216 transitioningViews.add(this);
20221 * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
20222 * @param namedElements Will contain all Views in the hierarchy having a transitionName.
20225 public void findNamedViews(Map<String, View> namedElements) {
20226 if (getVisibility() == VISIBLE || mGhostView != null) {
20227 String transitionName = getTransitionName();
20228 if (transitionName != null) {
20229 namedElements.put(transitionName, this);
20238 * A Property wrapper around the <code>alpha</code> functionality handled by the
20239 * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
20241 public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
20243 public void setValue(View object, float value) {
20244 object.setAlpha(value);
20248 public Float get(View object) {
20249 return object.getAlpha();
20254 * A Property wrapper around the <code>translationX</code> functionality handled by the
20255 * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
20257 public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
20259 public void setValue(View object, float value) {
20260 object.setTranslationX(value);
20264 public Float get(View object) {
20265 return object.getTranslationX();
20270 * A Property wrapper around the <code>translationY</code> functionality handled by the
20271 * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
20273 public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
20275 public void setValue(View object, float value) {
20276 object.setTranslationY(value);
20280 public Float get(View object) {
20281 return object.getTranslationY();
20286 * A Property wrapper around the <code>translationZ</code> functionality handled by the
20287 * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
20289 public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
20291 public void setValue(View object, float value) {
20292 object.setTranslationZ(value);
20296 public Float get(View object) {
20297 return object.getTranslationZ();
20302 * A Property wrapper around the <code>x</code> functionality handled by the
20303 * {@link View#setX(float)} and {@link View#getX()} methods.
20305 public static final Property<View, Float> X = new FloatProperty<View>("x") {
20307 public void setValue(View object, float value) {
20308 object.setX(value);
20312 public Float get(View object) {
20313 return object.getX();
20318 * A Property wrapper around the <code>y</code> functionality handled by the
20319 * {@link View#setY(float)} and {@link View#getY()} methods.
20321 public static final Property<View, Float> Y = new FloatProperty<View>("y") {
20323 public void setValue(View object, float value) {
20324 object.setY(value);
20328 public Float get(View object) {
20329 return object.getY();
20334 * A Property wrapper around the <code>z</code> functionality handled by the
20335 * {@link View#setZ(float)} and {@link View#getZ()} methods.
20337 public static final Property<View, Float> Z = new FloatProperty<View>("z") {
20339 public void setValue(View object, float value) {
20340 object.setZ(value);
20344 public Float get(View object) {
20345 return object.getZ();
20350 * A Property wrapper around the <code>rotation</code> functionality handled by the
20351 * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
20353 public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
20355 public void setValue(View object, float value) {
20356 object.setRotation(value);
20360 public Float get(View object) {
20361 return object.getRotation();
20366 * A Property wrapper around the <code>rotationX</code> functionality handled by the
20367 * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
20369 public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
20371 public void setValue(View object, float value) {
20372 object.setRotationX(value);
20376 public Float get(View object) {
20377 return object.getRotationX();
20382 * A Property wrapper around the <code>rotationY</code> functionality handled by the
20383 * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
20385 public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
20387 public void setValue(View object, float value) {
20388 object.setRotationY(value);
20392 public Float get(View object) {
20393 return object.getRotationY();
20398 * A Property wrapper around the <code>scaleX</code> functionality handled by the
20399 * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
20401 public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
20403 public void setValue(View object, float value) {
20404 object.setScaleX(value);
20408 public Float get(View object) {
20409 return object.getScaleX();
20414 * A Property wrapper around the <code>scaleY</code> functionality handled by the
20415 * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
20417 public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
20419 public void setValue(View object, float value) {
20420 object.setScaleY(value);
20424 public Float get(View object) {
20425 return object.getScaleY();
20430 * A MeasureSpec encapsulates the layout requirements passed from parent to child.
20431 * Each MeasureSpec represents a requirement for either the width or the height.
20432 * A MeasureSpec is comprised of a size and a mode. There are three possible
20435 * <dt>UNSPECIFIED</dt>
20437 * The parent has not imposed any constraint on the child. It can be whatever size
20443 * The parent has determined an exact size for the child. The child is going to be
20444 * given those bounds regardless of how big it wants to be.
20449 * The child can be as large as it wants up to the specified size.
20453 * MeasureSpecs are implemented as ints to reduce object allocation. This class
20454 * is provided to pack and unpack the <size, mode> tuple into the int.
20456 public static class MeasureSpec {
20457 private static final int MODE_SHIFT = 30;
20458 private static final int MODE_MASK = 0x3 << MODE_SHIFT;
20461 * Measure specification mode: The parent has not imposed any constraint
20462 * on the child. It can be whatever size it wants.
20464 public static final int UNSPECIFIED = 0 << MODE_SHIFT;
20467 * Measure specification mode: The parent has determined an exact size
20468 * for the child. The child is going to be given those bounds regardless
20469 * of how big it wants to be.
20471 public static final int EXACTLY = 1 << MODE_SHIFT;
20474 * Measure specification mode: The child can be as large as it wants up
20475 * to the specified size.
20477 public static final int AT_MOST = 2 << MODE_SHIFT;
20480 * Creates a measure specification based on the supplied size and mode.
20482 * The mode must always be one of the following:
20484 * <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
20485 * <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
20486 * <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
20489 * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
20490 * implementation was such that the order of arguments did not matter
20491 * and overflow in either value could impact the resulting MeasureSpec.
20492 * {@link android.widget.RelativeLayout} was affected by this bug.
20493 * Apps targeting API levels greater than 17 will get the fixed, more strict
20496 * @param size the size of the measure specification
20497 * @param mode the mode of the measure specification
20498 * @return the measure specification based on size and mode
20500 public static int makeMeasureSpec(int size, int mode) {
20501 if (sUseBrokenMakeMeasureSpec) {
20502 return size + mode;
20504 return (size & ~MODE_MASK) | (mode & MODE_MASK);
20509 * Extracts the mode from the supplied measure specification.
20511 * @param measureSpec the measure specification to extract the mode from
20512 * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
20513 * {@link android.view.View.MeasureSpec#AT_MOST} or
20514 * {@link android.view.View.MeasureSpec#EXACTLY}
20516 public static int getMode(int measureSpec) {
20517 return (measureSpec & MODE_MASK);
20521 * Extracts the size from the supplied measure specification.
20523 * @param measureSpec the measure specification to extract the size from
20524 * @return the size in pixels defined in the supplied measure specification
20526 public static int getSize(int measureSpec) {
20527 return (measureSpec & ~MODE_MASK);
20530 static int adjust(int measureSpec, int delta) {
20531 final int mode = getMode(measureSpec);
20532 int size = getSize(measureSpec);
20533 if (mode == UNSPECIFIED) {
20534 // No need to adjust size for UNSPECIFIED mode.
20535 return makeMeasureSpec(size, UNSPECIFIED);
20539 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
20540 ") spec: " + toString(measureSpec) + " delta: " + delta);
20543 return makeMeasureSpec(size, mode);
20547 * Returns a String representation of the specified measure
20550 * @param measureSpec the measure specification to convert to a String
20551 * @return a String with the following format: "MeasureSpec: MODE SIZE"
20553 public static String toString(int measureSpec) {
20554 int mode = getMode(measureSpec);
20555 int size = getSize(measureSpec);
20557 StringBuilder sb = new StringBuilder("MeasureSpec: ");
20559 if (mode == UNSPECIFIED)
20560 sb.append("UNSPECIFIED ");
20561 else if (mode == EXACTLY)
20562 sb.append("EXACTLY ");
20563 else if (mode == AT_MOST)
20564 sb.append("AT_MOST ");
20566 sb.append(mode).append(" ");
20569 return sb.toString();
20573 private final class CheckForLongPress implements Runnable {
20574 private int mOriginalWindowAttachCount;
20577 public void run() {
20578 if (isPressed() && (mParent != null)
20579 && mOriginalWindowAttachCount == mWindowAttachCount) {
20580 if (performLongClick()) {
20581 mHasPerformedLongPress = true;
20586 public void rememberWindowAttachCount() {
20587 mOriginalWindowAttachCount = mWindowAttachCount;
20591 private final class CheckForTap implements Runnable {
20596 public void run() {
20597 mPrivateFlags &= ~PFLAG_PREPRESSED;
20598 setPressed(true, x, y);
20599 checkForLongClick(ViewConfiguration.getTapTimeout());
20603 private final class PerformClick implements Runnable {
20605 public void run() {
20611 public void hackTurnOffWindowResizeAnim(boolean off) {
20612 mAttachInfo.mTurnOffWindowResizeAnim = off;
20616 * This method returns a ViewPropertyAnimator object, which can be used to animate
20617 * specific properties on this View.
20619 * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
20621 public ViewPropertyAnimator animate() {
20622 if (mAnimator == null) {
20623 mAnimator = new ViewPropertyAnimator(this);
20629 * Sets the name of the View to be used to identify Views in Transitions.
20630 * Names should be unique in the View hierarchy.
20632 * @param transitionName The name of the View to uniquely identify it for Transitions.
20634 public final void setTransitionName(String transitionName) {
20635 mTransitionName = transitionName;
20639 * Returns the name of the View to be used to identify Views in Transitions.
20640 * Names should be unique in the View hierarchy.
20642 * <p>This returns null if the View has not been given a name.</p>
20644 * @return The name used of the View to be used to identify Views in Transitions or null
20645 * if no name has been given.
20647 @ViewDebug.ExportedProperty
20648 public String getTransitionName() {
20649 return mTransitionName;
20653 * Interface definition for a callback to be invoked when a hardware key event is
20654 * dispatched to this view. The callback will be invoked before the key event is
20655 * given to the view. This is only useful for hardware keyboards; a software input
20656 * method has no obligation to trigger this listener.
20658 public interface OnKeyListener {
20660 * Called when a hardware key is dispatched to a view. This allows listeners to
20661 * get a chance to respond before the target view.
20662 * <p>Key presses in software keyboards will generally NOT trigger this method,
20663 * although some may elect to do so in some situations. Do not assume a
20664 * software input method has to be key-based; even if it is, it may use key presses
20665 * in a different way than you expect, so there is no way to reliably catch soft
20666 * input key presses.
20668 * @param v The view the key has been dispatched to.
20669 * @param keyCode The code for the physical key that was pressed
20670 * @param event The KeyEvent object containing full information about
20672 * @return True if the listener has consumed the event, false otherwise.
20674 boolean onKey(View v, int keyCode, KeyEvent event);
20678 * Interface definition for a callback to be invoked when a touch event is
20679 * dispatched to this view. The callback will be invoked before the touch
20680 * event is given to the view.
20682 public interface OnTouchListener {
20684 * Called when a touch event is dispatched to a view. This allows listeners to
20685 * get a chance to respond before the target view.
20687 * @param v The view the touch event has been dispatched to.
20688 * @param event The MotionEvent object containing full information about
20690 * @return True if the listener has consumed the event, false otherwise.
20692 boolean onTouch(View v, MotionEvent event);
20696 * Interface definition for a callback to be invoked when a hover event is
20697 * dispatched to this view. The callback will be invoked before the hover
20698 * event is given to the view.
20700 public interface OnHoverListener {
20702 * Called when a hover event is dispatched to a view. This allows listeners to
20703 * get a chance to respond before the target view.
20705 * @param v The view the hover event has been dispatched to.
20706 * @param event The MotionEvent object containing full information about
20708 * @return True if the listener has consumed the event, false otherwise.
20710 boolean onHover(View v, MotionEvent event);
20714 * Interface definition for a callback to be invoked when a generic motion event is
20715 * dispatched to this view. The callback will be invoked before the generic motion
20716 * event is given to the view.
20718 public interface OnGenericMotionListener {
20720 * Called when a generic motion event is dispatched to a view. This allows listeners to
20721 * get a chance to respond before the target view.
20723 * @param v The view the generic motion event has been dispatched to.
20724 * @param event The MotionEvent object containing full information about
20726 * @return True if the listener has consumed the event, false otherwise.
20728 boolean onGenericMotion(View v, MotionEvent event);
20732 * Interface definition for a callback to be invoked when a view has been clicked and held.
20734 public interface OnLongClickListener {
20736 * Called when a view has been clicked and held.
20738 * @param v The view that was clicked and held.
20740 * @return true if the callback consumed the long click, false otherwise.
20742 boolean onLongClick(View v);
20746 * Interface definition for a callback to be invoked when a drag is being dispatched
20747 * to this view. The callback will be invoked before the hosting view's own
20748 * onDrag(event) method. If the listener wants to fall back to the hosting view's
20749 * onDrag(event) behavior, it should return 'false' from this callback.
20751 * <div class="special reference">
20752 * <h3>Developer Guides</h3>
20753 * <p>For a guide to implementing drag and drop features, read the
20754 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
20757 public interface OnDragListener {
20759 * Called when a drag event is dispatched to a view. This allows listeners
20760 * to get a chance to override base View behavior.
20762 * @param v The View that received the drag event.
20763 * @param event The {@link android.view.DragEvent} object for the drag event.
20764 * @return {@code true} if the drag event was handled successfully, or {@code false}
20765 * if the drag event was not handled. Note that {@code false} will trigger the View
20766 * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
20768 boolean onDrag(View v, DragEvent event);
20772 * Interface definition for a callback to be invoked when the focus state of
20775 public interface OnFocusChangeListener {
20777 * Called when the focus state of a view has changed.
20779 * @param v The view whose state has changed.
20780 * @param hasFocus The new focus state of v.
20782 void onFocusChange(View v, boolean hasFocus);
20786 * Interface definition for a callback to be invoked when a view is clicked.
20788 public interface OnClickListener {
20790 * Called when a view has been clicked.
20792 * @param v The view that was clicked.
20794 void onClick(View v);
20798 * Interface definition for a callback to be invoked when the context menu
20799 * for this view is being built.
20801 public interface OnCreateContextMenuListener {
20803 * Called when the context menu for this view is being built. It is not
20804 * safe to hold onto the menu after this method returns.
20806 * @param menu The context menu that is being built
20807 * @param v The view for which the context menu is being built
20808 * @param menuInfo Extra information about the item for which the
20809 * context menu should be shown. This information will vary
20810 * depending on the class of v.
20812 void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
20816 * Interface definition for a callback to be invoked when the status bar changes
20817 * visibility. This reports <strong>global</strong> changes to the system UI
20818 * state, not what the application is requesting.
20820 * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
20822 public interface OnSystemUiVisibilityChangeListener {
20824 * Called when the status bar changes visibility because of a call to
20825 * {@link View#setSystemUiVisibility(int)}.
20827 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20828 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
20829 * This tells you the <strong>global</strong> state of these UI visibility
20830 * flags, not what your app is currently applying.
20832 public void onSystemUiVisibilityChange(int visibility);
20836 * Interface definition for a callback to be invoked when this view is attached
20837 * or detached from its window.
20839 public interface OnAttachStateChangeListener {
20841 * Called when the view is attached to a window.
20842 * @param v The view that was attached
20844 public void onViewAttachedToWindow(View v);
20846 * Called when the view is detached from a window.
20847 * @param v The view that was detached
20849 public void onViewDetachedFromWindow(View v);
20853 * Listener for applying window insets on a view in a custom way.
20855 * <p>Apps may choose to implement this interface if they want to apply custom policy
20856 * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
20858 * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
20859 * method will be called instead of the View's own
20860 * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
20861 * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
20862 * the View's normal behavior as part of its own.</p>
20864 public interface OnApplyWindowInsetsListener {
20866 * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
20867 * on a View, this listener method will be called instead of the view's own
20868 * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
20870 * @param v The view applying window insets
20871 * @param insets The insets to apply
20872 * @return The insets supplied, minus any insets that were consumed
20874 public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
20877 private final class UnsetPressedState implements Runnable {
20879 public void run() {
20885 * Base class for derived classes that want to save and restore their own
20886 * state in {@link android.view.View#onSaveInstanceState()}.
20888 public static class BaseSavedState extends AbsSavedState {
20889 String mStartActivityRequestWhoSaved;
20892 * Constructor used when reading from a parcel. Reads the state of the superclass.
20896 public BaseSavedState(Parcel source) {
20898 mStartActivityRequestWhoSaved = source.readString();
20902 * Constructor called by derived classes when creating their SavedState objects
20904 * @param superState The state of the superclass of this view
20906 public BaseSavedState(Parcelable superState) {
20911 public void writeToParcel(Parcel out, int flags) {
20912 super.writeToParcel(out, flags);
20913 out.writeString(mStartActivityRequestWhoSaved);
20916 public static final Parcelable.Creator<BaseSavedState> CREATOR =
20917 new Parcelable.Creator<BaseSavedState>() {
20918 public BaseSavedState createFromParcel(Parcel in) {
20919 return new BaseSavedState(in);
20922 public BaseSavedState[] newArray(int size) {
20923 return new BaseSavedState[size];
20929 * A set of information given to a view when it is attached to its parent
20932 final static class AttachInfo {
20933 interface Callbacks {
20934 void playSoundEffect(int effectId);
20935 boolean performHapticFeedback(int effectId, boolean always);
20939 * InvalidateInfo is used to post invalidate(int, int, int, int) messages
20940 * to a Handler. This class contains the target (View) to invalidate and
20941 * the coordinates of the dirty rectangle.
20943 * For performance purposes, this class also implements a pool of up to
20944 * POOL_LIMIT objects that get reused. This reduces memory allocations
20945 * whenever possible.
20947 static class InvalidateInfo {
20948 private static final int POOL_LIMIT = 10;
20950 private static final SynchronizedPool<InvalidateInfo> sPool =
20951 new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
20960 public static InvalidateInfo obtain() {
20961 InvalidateInfo instance = sPool.acquire();
20962 return (instance != null) ? instance : new InvalidateInfo();
20965 public void recycle() {
20967 sPool.release(this);
20971 final IWindowSession mSession;
20973 final IWindow mWindow;
20975 final IBinder mWindowToken;
20977 final Display mDisplay;
20979 final Callbacks mRootCallbacks;
20981 IWindowId mIWindowId;
20982 WindowId mWindowId;
20985 * The top view of the hierarchy.
20989 IBinder mPanelParentWindowToken;
20991 boolean mHardwareAccelerated;
20992 boolean mHardwareAccelerationRequested;
20993 HardwareRenderer mHardwareRenderer;
20994 List<RenderNode> mPendingAnimatingRenderNodes;
20997 * The state of the display to which the window is attached, as reported
20998 * by {@link Display#getState()}. Note that the display state constants
20999 * declared by {@link Display} do not exactly line up with the screen state
21000 * constants declared by {@link View} (there are more display states than
21003 int mDisplayState = Display.STATE_UNKNOWN;
21006 * Scale factor used by the compatibility mode
21008 float mApplicationScale;
21011 * Indicates whether the application is in compatibility mode
21013 boolean mScalingRequired;
21016 * If set, ViewRootImpl doesn't use its lame animation for when the window resizes.
21018 boolean mTurnOffWindowResizeAnim;
21021 * Left position of this view's window
21026 * Top position of this view's window
21031 * Indicates whether views need to use 32-bit drawing caches
21033 boolean mUse32BitDrawingCache;
21036 * For windows that are full-screen but using insets to layout inside
21037 * of the screen areas, these are the current insets to appear inside
21038 * the overscan area of the display.
21040 final Rect mOverscanInsets = new Rect();
21043 * For windows that are full-screen but using insets to layout inside
21044 * of the screen decorations, these are the current insets for the
21045 * content of the window.
21047 final Rect mContentInsets = new Rect();
21050 * For windows that are full-screen but using insets to layout inside
21051 * of the screen decorations, these are the current insets for the
21052 * actual visible parts of the window.
21054 final Rect mVisibleInsets = new Rect();
21057 * For windows that are full-screen but using insets to layout inside
21058 * of the screen decorations, these are the current insets for the
21059 * stable system windows.
21061 final Rect mStableInsets = new Rect();
21064 * The internal insets given by this window. This value is
21065 * supplied by the client (through
21066 * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
21067 * be given to the window manager when changed to be used in laying
21068 * out windows behind it.
21070 final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
21071 = new ViewTreeObserver.InternalInsetsInfo();
21074 * Set to true when mGivenInternalInsets is non-empty.
21076 boolean mHasNonEmptyGivenInternalInsets;
21079 * All views in the window's hierarchy that serve as scroll containers,
21080 * used to determine if the window can be resized or must be panned
21081 * to adjust for a soft input area.
21083 final ArrayList<View> mScrollContainers = new ArrayList<View>();
21085 final KeyEvent.DispatcherState mKeyDispatchState
21086 = new KeyEvent.DispatcherState();
21089 * Indicates whether the view's window currently has the focus.
21091 boolean mHasWindowFocus;
21094 * The current visibility of the window.
21096 int mWindowVisibility;
21099 * Indicates the time at which drawing started to occur.
21104 * Indicates whether or not ignoring the DIRTY_MASK flags.
21106 boolean mIgnoreDirtyState;
21109 * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
21110 * to avoid clearing that flag prematurely.
21112 boolean mSetIgnoreDirtyState = false;
21115 * Indicates whether the view's window is currently in touch mode.
21117 boolean mInTouchMode;
21120 * Indicates whether the view has requested unbuffered input dispatching for the current
21123 boolean mUnbufferedDispatchRequested;
21126 * Indicates that ViewAncestor should trigger a global layout change
21127 * the next time it performs a traversal
21129 boolean mRecomputeGlobalAttributes;
21132 * Always report new attributes at next traversal.
21134 boolean mForceReportNewAttributes;
21137 * Set during a traveral if any views want to keep the screen on.
21139 boolean mKeepScreenOn;
21142 * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
21144 int mSystemUiVisibility;
21147 * Hack to force certain system UI visibility flags to be cleared.
21149 int mDisabledSystemUiVisibility;
21152 * Last global system UI visibility reported by the window manager.
21154 int mGlobalSystemUiVisibility;
21157 * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
21160 boolean mHasSystemUiListeners;
21163 * Set if the window has requested to extend into the overscan region
21164 * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
21166 boolean mOverscanRequested;
21169 * Set if the visibility of any views has changed.
21171 boolean mViewVisibilityChanged;
21174 * Set to true if a view has been scrolled.
21176 boolean mViewScrollChanged;
21179 * Set to true if high contrast mode enabled
21181 boolean mHighContrastText;
21184 * Global to the view hierarchy used as a temporary for dealing with
21185 * x/y points in the transparent region computations.
21187 final int[] mTransparentLocation = new int[2];
21190 * Global to the view hierarchy used as a temporary for dealing with
21191 * x/y points in the ViewGroup.invalidateChild implementation.
21193 final int[] mInvalidateChildLocation = new int[2];
21196 * Global to the view hierarchy used as a temporary for dealng with
21197 * computing absolute on-screen location.
21199 final int[] mTmpLocation = new int[2];
21202 * Global to the view hierarchy used as a temporary for dealing with
21203 * x/y location when view is transformed.
21205 final float[] mTmpTransformLocation = new float[2];
21208 * The view tree observer used to dispatch global events like
21209 * layout, pre-draw, touch mode change, etc.
21211 final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
21214 * A Canvas used by the view hierarchy to perform bitmap caching.
21219 * The view root impl.
21221 final ViewRootImpl mViewRootImpl;
21224 * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
21225 * handler can be used to pump events in the UI events queue.
21227 final Handler mHandler;
21230 * Temporary for use in computing invalidate rectangles while
21231 * calling up the hierarchy.
21233 final Rect mTmpInvalRect = new Rect();
21236 * Temporary for use in computing hit areas with transformed views
21238 final RectF mTmpTransformRect = new RectF();
21241 * Temporary for use in computing hit areas with transformed views
21243 final RectF mTmpTransformRect1 = new RectF();
21246 * Temporary list of rectanges.
21248 final List<RectF> mTmpRectList = new ArrayList<>();
21251 * Temporary for use in transforming invalidation rect
21253 final Matrix mTmpMatrix = new Matrix();
21256 * Temporary for use in transforming invalidation rect
21258 final Transformation mTmpTransformation = new Transformation();
21261 * Temporary for use in querying outlines from OutlineProviders
21263 final Outline mTmpOutline = new Outline();
21266 * Temporary list for use in collecting focusable descendents of a view.
21268 final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
21271 * The id of the window for accessibility purposes.
21273 int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
21276 * Flags related to accessibility processing.
21278 * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
21279 * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
21281 int mAccessibilityFetchFlags;
21284 * The drawable for highlighting accessibility focus.
21286 Drawable mAccessibilityFocusDrawable;
21289 * Show where the margins, bounds and layout bounds are for each view.
21291 boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
21294 * Point used to compute visible regions.
21296 final Point mPoint = new Point();
21299 * Used to track which View originated a requestLayout() call, used when
21300 * requestLayout() is called during layout.
21302 View mViewRequestingLayout;
21305 * Creates a new set of attachment information with the specified
21306 * events handler and thread.
21308 * @param handler the events handler the view must use
21310 AttachInfo(IWindowSession session, IWindow window, Display display,
21311 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
21312 mSession = session;
21314 mWindowToken = window.asBinder();
21315 mDisplay = display;
21316 mViewRootImpl = viewRootImpl;
21317 mHandler = handler;
21318 mRootCallbacks = effectPlayer;
21323 * <p>ScrollabilityCache holds various fields used by a View when scrolling
21324 * is supported. This avoids keeping too many unused fields in most
21325 * instances of View.</p>
21327 private static class ScrollabilityCache implements Runnable {
21330 * Scrollbars are not visible
21332 public static final int OFF = 0;
21335 * Scrollbars are visible
21337 public static final int ON = 1;
21340 * Scrollbars are fading away
21342 public static final int FADING = 2;
21344 public boolean fadeScrollBars;
21346 public int fadingEdgeLength;
21347 public int scrollBarDefaultDelayBeforeFade;
21348 public int scrollBarFadeDuration;
21350 public int scrollBarSize;
21351 public ScrollBarDrawable scrollBar;
21352 public float[] interpolatorValues;
21355 public final Paint paint;
21356 public final Matrix matrix;
21357 public Shader shader;
21359 public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
21361 private static final float[] OPAQUE = { 255 };
21362 private static final float[] TRANSPARENT = { 0.0f };
21365 * When fading should start. This time moves into the future every time
21366 * a new scroll happens. Measured based on SystemClock.uptimeMillis()
21368 public long fadeStartTime;
21372 * The current state of the scrollbars: ON, OFF, or FADING
21374 public int state = OFF;
21376 private int mLastColor;
21378 public ScrollabilityCache(ViewConfiguration configuration, View host) {
21379 fadingEdgeLength = configuration.getScaledFadingEdgeLength();
21380 scrollBarSize = configuration.getScaledScrollBarSize();
21381 scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
21382 scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
21384 paint = new Paint();
21385 matrix = new Matrix();
21386 // use use a height of 1, and then wack the matrix each time we
21387 // actually use it.
21388 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
21389 paint.setShader(shader);
21390 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
21395 public void setFadeColor(int color) {
21396 if (color != mLastColor) {
21397 mLastColor = color;
21400 shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
21401 color & 0x00FFFFFF, Shader.TileMode.CLAMP);
21402 paint.setShader(shader);
21403 // Restore the default transfer mode (src_over)
21404 paint.setXfermode(null);
21406 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
21407 paint.setShader(shader);
21408 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
21413 public void run() {
21414 long now = AnimationUtils.currentAnimationTimeMillis();
21415 if (now >= fadeStartTime) {
21417 // the animation fades the scrollbars out by changing
21418 // the opacity (alpha) from fully opaque to fully
21420 int nextFrame = (int) now;
21421 int framesCount = 0;
21423 Interpolator interpolator = scrollBarInterpolator;
21426 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
21429 nextFrame += scrollBarFadeDuration;
21430 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
21434 // Kick off the fade animation
21435 host.invalidate(true);
21441 * Resuable callback for sending
21442 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
21444 private class SendViewScrolledAccessibilityEvent implements Runnable {
21445 public volatile boolean mIsPending;
21447 public void run() {
21448 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
21449 mIsPending = false;
21455 * This class represents a delegate that can be registered in a {@link View}
21456 * to enhance accessibility support via composition rather via inheritance.
21457 * It is specifically targeted to widget developers that extend basic View
21458 * classes i.e. classes in package android.view, that would like their
21459 * applications to be backwards compatible.
21461 * <div class="special reference">
21462 * <h3>Developer Guides</h3>
21463 * <p>For more information about making applications accessible, read the
21464 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
21465 * developer guide.</p>
21468 * A scenario in which a developer would like to use an accessibility delegate
21469 * is overriding a method introduced in a later API version then the minimal API
21470 * version supported by the application. For example, the method
21471 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
21472 * in API version 4 when the accessibility APIs were first introduced. If a
21473 * developer would like his application to run on API version 4 devices (assuming
21474 * all other APIs used by the application are version 4 or lower) and take advantage
21475 * of this method, instead of overriding the method which would break the application's
21476 * backwards compatibility, he can override the corresponding method in this
21477 * delegate and register the delegate in the target View if the API version of
21478 * the system is high enough i.e. the API version is same or higher to the API
21479 * version that introduced
21480 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
21483 * Here is an example implementation:
21486 * if (Build.VERSION.SDK_INT >= 14) {
21487 * // If the API version is equal of higher than the version in
21488 * // which onInitializeAccessibilityNodeInfo was introduced we
21489 * // register a delegate with a customized implementation.
21490 * View view = findViewById(R.id.view_id);
21491 * view.setAccessibilityDelegate(new AccessibilityDelegate() {
21492 * public void onInitializeAccessibilityNodeInfo(View host,
21493 * AccessibilityNodeInfo info) {
21494 * // Let the default implementation populate the info.
21495 * super.onInitializeAccessibilityNodeInfo(host, info);
21496 * // Set some other information.
21497 * info.setEnabled(host.isEnabled());
21501 * </code></pre></p>
21503 * This delegate contains methods that correspond to the accessibility methods
21504 * in View. If a delegate has been specified the implementation in View hands
21505 * off handling to the corresponding method in this delegate. The default
21506 * implementation the delegate methods behaves exactly as the corresponding
21507 * method in View for the case of no accessibility delegate been set. Hence,
21508 * to customize the behavior of a View method, clients can override only the
21509 * corresponding delegate method without altering the behavior of the rest
21510 * accessibility related methods of the host view.
21513 public static class AccessibilityDelegate {
21516 * Sends an accessibility event of the given type. If accessibility is not
21517 * enabled this method has no effect.
21519 * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
21520 * View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
21524 * @param host The View hosting the delegate.
21525 * @param eventType The type of the event to send.
21527 * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
21529 public void sendAccessibilityEvent(View host, int eventType) {
21530 host.sendAccessibilityEventInternal(eventType);
21534 * Performs the specified accessibility action on the view. For
21535 * possible accessibility actions look at {@link AccessibilityNodeInfo}.
21537 * The default implementation behaves as
21538 * {@link View#performAccessibilityAction(int, Bundle)
21539 * View#performAccessibilityAction(int, Bundle)} for the case of
21540 * no accessibility delegate been set.
21543 * @param action The action to perform.
21544 * @return Whether the action was performed.
21546 * @see View#performAccessibilityAction(int, Bundle)
21547 * View#performAccessibilityAction(int, Bundle)
21549 public boolean performAccessibilityAction(View host, int action, Bundle args) {
21550 return host.performAccessibilityActionInternal(action, args);
21554 * Sends an accessibility event. This method behaves exactly as
21555 * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
21556 * empty {@link AccessibilityEvent} and does not perform a check whether
21557 * accessibility is enabled.
21559 * The default implementation behaves as
21560 * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
21561 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
21562 * the case of no accessibility delegate been set.
21565 * @param host The View hosting the delegate.
21566 * @param event The event to send.
21568 * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
21569 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)
21571 public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
21572 host.sendAccessibilityEventUncheckedInternal(event);
21576 * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
21577 * to its children for adding their text content to the event.
21579 * The default implementation behaves as
21580 * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
21581 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
21582 * the case of no accessibility delegate been set.
21585 * @param host The View hosting the delegate.
21586 * @param event The event.
21587 * @return True if the event population was completed.
21589 * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
21590 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
21592 public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
21593 return host.dispatchPopulateAccessibilityEventInternal(event);
21597 * Gives a chance to the host View to populate the accessibility event with its
21600 * The default implementation behaves as
21601 * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
21602 * View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
21603 * the case of no accessibility delegate been set.
21606 * @param host The View hosting the delegate.
21607 * @param event The accessibility event which to populate.
21609 * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
21610 * View#onPopulateAccessibilityEvent(AccessibilityEvent)
21612 public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
21613 host.onPopulateAccessibilityEventInternal(event);
21617 * Initializes an {@link AccessibilityEvent} with information about the
21618 * the host View which is the event source.
21620 * The default implementation behaves as
21621 * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
21622 * View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
21623 * the case of no accessibility delegate been set.
21626 * @param host The View hosting the delegate.
21627 * @param event The event to initialize.
21629 * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
21630 * View#onInitializeAccessibilityEvent(AccessibilityEvent)
21632 public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
21633 host.onInitializeAccessibilityEventInternal(event);
21637 * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
21639 * The default implementation behaves as
21640 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
21641 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
21642 * the case of no accessibility delegate been set.
21645 * @param host The View hosting the delegate.
21646 * @param info The instance to initialize.
21648 * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
21649 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
21651 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
21652 host.onInitializeAccessibilityNodeInfoInternal(info);
21656 * Called when a child of the host View has requested sending an
21657 * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
21658 * to augment the event.
21660 * The default implementation behaves as
21661 * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
21662 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
21663 * the case of no accessibility delegate been set.
21666 * @param host The View hosting the delegate.
21667 * @param child The child which requests sending the event.
21668 * @param event The event to be sent.
21669 * @return True if the event should be sent
21671 * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
21672 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
21674 public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
21675 AccessibilityEvent event) {
21676 return host.onRequestSendAccessibilityEventInternal(child, event);
21680 * Gets the provider for managing a virtual view hierarchy rooted at this View
21681 * and reported to {@link android.accessibilityservice.AccessibilityService}s
21682 * that explore the window content.
21684 * The default implementation behaves as
21685 * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
21686 * the case of no accessibility delegate been set.
21689 * @return The provider.
21691 * @see AccessibilityNodeProvider
21693 public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
21698 * Returns an {@link AccessibilityNodeInfo} representing the host view from the
21699 * point of view of an {@link android.accessibilityservice.AccessibilityService}.
21700 * This method is responsible for obtaining an accessibility node info from a
21701 * pool of reusable instances and calling
21702 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
21703 * view to initialize the former.
21705 * <strong>Note:</strong> The client is responsible for recycling the obtained
21706 * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
21710 * The default implementation behaves as
21711 * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
21712 * the case of no accessibility delegate been set.
21714 * @return A populated {@link AccessibilityNodeInfo}.
21716 * @see AccessibilityNodeInfo
21720 public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
21721 return host.createAccessibilityNodeInfoInternal();
21725 private class MatchIdPredicate implements Predicate<View> {
21729 public boolean apply(View view) {
21730 return (view.mID == mId);
21734 private class MatchLabelForPredicate implements Predicate<View> {
21735 private int mLabeledId;
21738 public boolean apply(View view) {
21739 return (view.mLabelForId == mLabeledId);
21743 private class SendViewStateChangedAccessibilityEvent implements Runnable {
21744 private int mChangeTypes = 0;
21745 private boolean mPosted;
21746 private boolean mPostedWithDelay;
21747 private long mLastEventTimeMillis;
21750 public void run() {
21752 mPostedWithDelay = false;
21753 mLastEventTimeMillis = SystemClock.uptimeMillis();
21754 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
21755 final AccessibilityEvent event = AccessibilityEvent.obtain();
21756 event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
21757 event.setContentChangeTypes(mChangeTypes);
21758 sendAccessibilityEventUnchecked(event);
21763 public void runOrPost(int changeType) {
21764 mChangeTypes |= changeType;
21766 // If this is a live region or the child of a live region, collect
21767 // all events from this frame and send them on the next frame.
21768 if (inLiveRegion()) {
21769 // If we're already posted with a delay, remove that.
21770 if (mPostedWithDelay) {
21771 removeCallbacks(this);
21772 mPostedWithDelay = false;
21774 // Only post if we're not already posted.
21786 final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
21787 final long minEventIntevalMillis =
21788 ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
21789 if (timeSinceLastMillis >= minEventIntevalMillis) {
21790 removeCallbacks(this);
21793 postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
21794 mPostedWithDelay = true;
21799 private boolean inLiveRegion() {
21800 if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
21804 ViewParent parent = getParent();
21805 while (parent instanceof View) {
21806 if (((View) parent).getAccessibilityLiveRegion()
21807 != View.ACCESSIBILITY_LIVE_REGION_NONE) {
21810 parent = parent.getParent();
21817 * Dump all private flags in readable format, useful for documentation and
21820 private static void dumpFlags() {
21821 final HashMap<String, String> found = Maps.newHashMap();
21823 for (Field field : View.class.getDeclaredFields()) {
21824 final int modifiers = field.getModifiers();
21825 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
21826 if (field.getType().equals(int.class)) {
21827 final int value = field.getInt(null);
21828 dumpFlag(found, field.getName(), value);
21829 } else if (field.getType().equals(int[].class)) {
21830 final int[] values = (int[]) field.get(null);
21831 for (int i = 0; i < values.length; i++) {
21832 dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
21837 } catch (IllegalAccessException e) {
21838 throw new RuntimeException(e);
21841 final ArrayList<String> keys = Lists.newArrayList();
21842 keys.addAll(found.keySet());
21843 Collections.sort(keys);
21844 for (String key : keys) {
21845 Log.d(VIEW_LOG_TAG, found.get(key));
21849 private static void dumpFlag(HashMap<String, String> found, String name, int value) {
21850 // Sort flags by prefix, then by bits, always keeping unique keys
21851 final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
21852 final int prefix = name.indexOf('_');
21853 final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
21854 final String output = bits + " " + name;
21855 found.put(key, output);