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.IntRange;
28 import android.annotation.LayoutRes;
29 import android.annotation.NonNull;
30 import android.annotation.Nullable;
31 import android.annotation.Size;
32 import android.annotation.UiThread;
33 import android.content.ClipData;
34 import android.content.Context;
35 import android.content.ContextWrapper;
36 import android.content.Intent;
37 import android.content.res.ColorStateList;
38 import android.content.res.Configuration;
39 import android.content.res.Resources;
40 import android.content.res.TypedArray;
41 import android.graphics.Bitmap;
42 import android.graphics.Canvas;
43 import android.graphics.Insets;
44 import android.graphics.Interpolator;
45 import android.graphics.LinearGradient;
46 import android.graphics.Matrix;
47 import android.graphics.Outline;
48 import android.graphics.Paint;
49 import android.graphics.PixelFormat;
50 import android.graphics.Point;
51 import android.graphics.PorterDuff;
52 import android.graphics.PorterDuffXfermode;
53 import android.graphics.Rect;
54 import android.graphics.RectF;
55 import android.graphics.Region;
56 import android.graphics.Shader;
57 import android.graphics.drawable.ColorDrawable;
58 import android.graphics.drawable.Drawable;
59 import android.hardware.display.DisplayManagerGlobal;
60 import android.os.Build.VERSION_CODES;
61 import android.os.Bundle;
62 import android.os.Handler;
63 import android.os.IBinder;
64 import android.os.Parcel;
65 import android.os.Parcelable;
66 import android.os.RemoteException;
67 import android.os.SystemClock;
68 import android.os.SystemProperties;
69 import android.os.Trace;
70 import android.text.TextUtils;
71 import android.util.AttributeSet;
72 import android.util.FloatProperty;
73 import android.util.LayoutDirection;
74 import android.util.Log;
75 import android.util.LongSparseLongArray;
76 import android.util.Pools.SynchronizedPool;
77 import android.util.Property;
78 import android.util.SparseArray;
79 import android.util.StateSet;
80 import android.util.SuperNotCalledException;
81 import android.util.TypedValue;
82 import android.view.ContextMenu.ContextMenuInfo;
83 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
84 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
85 import android.view.AccessibilityIterators.TextSegmentIterator;
86 import android.view.AccessibilityIterators.WordTextSegmentIterator;
87 import android.view.accessibility.AccessibilityEvent;
88 import android.view.accessibility.AccessibilityEventSource;
89 import android.view.accessibility.AccessibilityManager;
90 import android.view.accessibility.AccessibilityNodeInfo;
91 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
92 import android.view.accessibility.AccessibilityNodeProvider;
93 import android.view.animation.Animation;
94 import android.view.animation.AnimationUtils;
95 import android.view.animation.Transformation;
96 import android.view.inputmethod.EditorInfo;
97 import android.view.inputmethod.InputConnection;
98 import android.view.inputmethod.InputMethodManager;
99 import android.widget.Checkable;
100 import android.widget.FrameLayout;
101 import android.widget.ScrollBarDrawable;
102 import static android.os.Build.VERSION_CODES.*;
103 import static java.lang.Math.max;
105 import com.android.internal.R;
106 import com.android.internal.util.Predicate;
107 import com.android.internal.view.menu.MenuBuilder;
108 import com.android.internal.widget.ScrollBarUtils;
109 import com.google.android.collect.Lists;
110 import com.google.android.collect.Maps;
112 import java.lang.NullPointerException;
113 import java.lang.annotation.Retention;
114 import java.lang.annotation.RetentionPolicy;
115 import java.lang.ref.WeakReference;
116 import java.lang.reflect.Field;
117 import java.lang.reflect.InvocationTargetException;
118 import java.lang.reflect.Method;
119 import java.lang.reflect.Modifier;
120 import java.util.ArrayList;
121 import java.util.Arrays;
122 import java.util.Collections;
123 import java.util.HashMap;
124 import java.util.List;
125 import java.util.Locale;
126 import java.util.Map;
127 import java.util.concurrent.CopyOnWriteArrayList;
128 import java.util.concurrent.atomic.AtomicInteger;
132 * This class represents the basic building block for user interface components. A View
133 * occupies a rectangular area on the screen and is responsible for drawing and
134 * event handling. View is the base class for <em>widgets</em>, which are
135 * used to create interactive UI components (buttons, text fields, etc.). The
136 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
137 * are invisible containers that hold other Views (or other ViewGroups) and define
138 * their layout properties.
141 * <div class="special reference">
142 * <h3>Developer Guides</h3>
143 * <p>For information about using this class to develop your application's user interface,
144 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
147 * <a name="Using"></a>
148 * <h3>Using Views</h3>
150 * All of the views in a window are arranged in a single tree. You can add views
151 * either from code or by specifying a tree of views in one or more XML layout
152 * files. There are many specialized subclasses of views that act as controls or
153 * are capable of displaying text, images, or other content.
156 * Once you have created a tree of views, there are typically a few types of
157 * common operations you may wish to perform:
159 * <li><strong>Set properties:</strong> for example setting the text of a
160 * {@link android.widget.TextView}. The available properties and the methods
161 * that set them will vary among the different subclasses of views. Note that
162 * properties that are known at build time can be set in the XML layout
164 * <li><strong>Set focus:</strong> The framework will handle moving focus in
165 * response to user input. To force focus to a specific view, call
166 * {@link #requestFocus}.</li>
167 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
168 * that will be notified when something interesting happens to the view. For
169 * example, all views will let you set a listener to be notified when the view
170 * gains or loses focus. You can register such a listener using
171 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
172 * Other view subclasses offer more specialized listeners. For example, a Button
173 * exposes a listener to notify clients when the button is clicked.</li>
174 * <li><strong>Set visibility:</strong> You can hide or show views using
175 * {@link #setVisibility(int)}.</li>
179 * Note: The Android framework is responsible for measuring, laying out and
180 * drawing views. You should not call methods that perform these actions on
181 * views yourself unless you are actually implementing a
182 * {@link android.view.ViewGroup}.
185 * <a name="Lifecycle"></a>
186 * <h3>Implementing a Custom View</h3>
189 * To implement a custom view, you will usually begin by providing overrides for
190 * some of the standard methods that the framework calls on all views. You do
191 * not need to override all of these methods. In fact, you can start by just
192 * overriding {@link #onDraw(android.graphics.Canvas)}.
193 * <table border="2" width="85%" align="center" cellpadding="5">
195 * <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
200 * <td rowspan="2">Creation</td>
201 * <td>Constructors</td>
202 * <td>There is a form of the constructor that are called when the view
203 * is created from code and a form that is called when the view is
204 * inflated from a layout file. The second form should parse and apply
205 * any attributes defined in the layout file.
209 * <td><code>{@link #onFinishInflate()}</code></td>
210 * <td>Called after a view and all of its children has been inflated
215 * <td rowspan="3">Layout</td>
216 * <td><code>{@link #onMeasure(int, int)}</code></td>
217 * <td>Called to determine the size requirements for this view and all
222 * <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
223 * <td>Called when this view should assign a size and position to all
228 * <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
229 * <td>Called when the size of this view has changed.
235 * <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
236 * <td>Called when the view should render its content.
241 * <td rowspan="4">Event processing</td>
242 * <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
243 * <td>Called when a new hardware key event occurs.
247 * <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
248 * <td>Called when a hardware key up event occurs.
252 * <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
253 * <td>Called when a trackball motion event occurs.
257 * <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
258 * <td>Called when a touch screen motion event occurs.
263 * <td rowspan="2">Focus</td>
264 * <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
265 * <td>Called when the view gains or loses focus.
270 * <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
271 * <td>Called when the window containing the view gains or loses focus.
276 * <td rowspan="3">Attaching</td>
277 * <td><code>{@link #onAttachedToWindow()}</code></td>
278 * <td>Called when the view is attached to a window.
283 * <td><code>{@link #onDetachedFromWindow}</code></td>
284 * <td>Called when the view is detached from its window.
289 * <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
290 * <td>Called when the visibility of the window containing the view
301 * Views may have an integer id associated with them. These ids are typically
302 * assigned in the layout XML files, and are used to find specific views within
303 * the view tree. A common pattern is to:
305 * <li>Define a Button in the layout file and assign it a unique ID.
308 * android:id="@+id/my_button"
309 * android:layout_width="wrap_content"
310 * android:layout_height="wrap_content"
311 * android:text="@string/my_button_text"/>
313 * <li>From the onCreate method of an Activity, find the Button
314 * <pre class="prettyprint">
315 * Button myButton = (Button) findViewById(R.id.my_button);
319 * View IDs need not be unique throughout the tree, but it is good practice to
320 * ensure that they are at least unique within the part of the tree you are
324 * <a name="Position"></a>
327 * The geometry of a view is that of a rectangle. A view has a location,
328 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
329 * two dimensions, expressed as a width and a height. The unit for location
330 * and dimensions is the pixel.
334 * It is possible to retrieve the location of a view by invoking the methods
335 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
336 * coordinate of the rectangle representing the view. The latter returns the
337 * top, or Y, coordinate of the rectangle representing the view. These methods
338 * both return the location of the view relative to its parent. For instance,
339 * when getLeft() returns 20, that means the view is located 20 pixels to the
340 * right of the left edge of its direct parent.
344 * In addition, several convenience methods are offered to avoid unnecessary
345 * computations, namely {@link #getRight()} and {@link #getBottom()}.
346 * These methods return the coordinates of the right and bottom edges of the
347 * rectangle representing the view. For instance, calling {@link #getRight()}
348 * is similar to the following computation: <code>getLeft() + getWidth()</code>
349 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
352 * <a name="SizePaddingMargins"></a>
353 * <h3>Size, padding and margins</h3>
355 * The size of a view is expressed with a width and a height. A view actually
356 * possess two pairs of width and height values.
360 * The first pair is known as <em>measured width</em> and
361 * <em>measured height</em>. These dimensions define how big a view wants to be
362 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
363 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
364 * and {@link #getMeasuredHeight()}.
368 * The second pair is simply known as <em>width</em> and <em>height</em>, or
369 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
370 * dimensions define the actual size of the view on screen, at drawing time and
371 * after layout. These values may, but do not have to, be different from the
372 * measured width and height. The width and height can be obtained by calling
373 * {@link #getWidth()} and {@link #getHeight()}.
377 * To measure its dimensions, a view takes into account its padding. The padding
378 * is expressed in pixels for the left, top, right and bottom parts of the view.
379 * Padding can be used to offset the content of the view by a specific amount of
380 * pixels. For instance, a left padding of 2 will push the view's content by
381 * 2 pixels to the right of the left edge. Padding can be set using the
382 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
383 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
384 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
385 * {@link #getPaddingEnd()}.
389 * Even though a view can define a padding, it does not provide any support for
390 * margins. However, view groups provide such a support. Refer to
391 * {@link android.view.ViewGroup} and
392 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
395 * <a name="Layout"></a>
398 * Layout is a two pass process: a measure pass and a layout pass. The measuring
399 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
400 * of the view tree. Each view pushes dimension specifications down the tree
401 * during the recursion. At the end of the measure pass, every view has stored
402 * its measurements. The second pass happens in
403 * {@link #layout(int,int,int,int)} and is also top-down. During
404 * this pass each parent is responsible for positioning all of its children
405 * using the sizes computed in the measure pass.
409 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
410 * {@link #getMeasuredHeight()} values must be set, along with those for all of
411 * that view's descendants. A view's measured width and measured height values
412 * must respect the constraints imposed by the view's parents. This guarantees
413 * that at the end of the measure pass, all parents accept all of their
414 * children's measurements. A parent view may call measure() more than once on
415 * its children. For example, the parent may measure each child once with
416 * unspecified dimensions to find out how big they want to be, then call
417 * measure() on them again with actual numbers if the sum of all the children's
418 * unconstrained sizes is too big or too small.
422 * The measure pass uses two classes to communicate dimensions. The
423 * {@link MeasureSpec} class is used by views to tell their parents how they
424 * want to be measured and positioned. The base LayoutParams class just
425 * describes how big the view wants to be for both width and height. For each
426 * dimension, it can specify one of:
428 * <li> an exact number
429 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
431 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
432 * enclose its content (plus padding).
434 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
435 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
440 * MeasureSpecs are used to push requirements down the tree from parent to
441 * child. A MeasureSpec can be in one of three modes:
443 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
444 * of a child view. For example, a LinearLayout may call measure() on its child
445 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
446 * tall the child view wants to be given a width of 240 pixels.
447 * <li>EXACTLY: This is used by the parent to impose an exact size on the
448 * child. The child must use this size, and guarantee that all of its
449 * descendants will fit within this size.
450 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
451 * child. The child must guarantee that it and all of its descendants will fit
457 * To initiate a layout, call {@link #requestLayout}. This method is typically
458 * called by a view on itself when it believes that is can no longer fit within
459 * its current bounds.
462 * <a name="Drawing"></a>
465 * Drawing is handled by walking the tree and recording the drawing commands of
466 * any View that needs to update. After this, the drawing commands of the
467 * entire tree are issued to screen, clipped to the newly damaged area.
471 * The tree is largely recorded and drawn in order, with parents drawn before
472 * (i.e., behind) their children, with siblings drawn in the order they appear
473 * in the tree. If you set a background drawable for a View, then the View will
474 * draw it before calling back to its <code>onDraw()</code> method. The child
475 * drawing order can be overridden with
476 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
477 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
481 * To force a view to draw, call {@link #invalidate()}.
484 * <a name="EventHandlingThreading"></a>
485 * <h3>Event Handling and Threading</h3>
487 * The basic cycle of a view is as follows:
489 * <li>An event comes in and is dispatched to the appropriate view. The view
490 * handles the event and notifies any listeners.</li>
491 * <li>If in the course of processing the event, the view's bounds may need
492 * to be changed, the view will call {@link #requestLayout()}.</li>
493 * <li>Similarly, if in the course of processing the event the view's appearance
494 * may need to be changed, the view will call {@link #invalidate()}.</li>
495 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
496 * the framework will take care of measuring, laying out, and drawing the tree
497 * as appropriate.</li>
501 * <p><em>Note: The entire view tree is single threaded. You must always be on
502 * the UI thread when calling any method on any view.</em>
503 * If you are doing work on other threads and want to update the state of a view
504 * from that thread, you should use a {@link Handler}.
507 * <a name="FocusHandling"></a>
508 * <h3>Focus Handling</h3>
510 * The framework will handle routine focus movement in response to user input.
511 * This includes changing the focus as views are removed or hidden, or as new
512 * views become available. Views indicate their willingness to take focus
513 * through the {@link #isFocusable} method. To change whether a view can take
514 * focus, call {@link #setFocusable(boolean)}. When in touch mode (see notes below)
515 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
516 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
519 * Focus movement is based on an algorithm which finds the nearest neighbor in a
520 * given direction. In rare cases, the default algorithm may not match the
521 * intended behavior of the developer. In these situations, you can provide
522 * explicit overrides by using these XML attributes in the layout file:
533 * To get a particular view to take focus, call {@link #requestFocus()}.
536 * <a name="TouchMode"></a>
537 * <h3>Touch Mode</h3>
539 * When a user is navigating a user interface via directional keys such as a D-pad, it is
540 * necessary to give focus to actionable items such as buttons so the user can see
541 * what will take input. If the device has touch capabilities, however, and the user
542 * begins interacting with the interface by touching it, it is no longer necessary to
543 * always highlight, or give focus to, a particular view. This motivates a mode
544 * for interaction named 'touch mode'.
547 * For a touch capable device, once the user touches the screen, the device
548 * will enter touch mode. From this point onward, only views for which
549 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
550 * Other views that are touchable, like buttons, will not take focus when touched; they will
551 * only fire the on click listeners.
554 * Any time a user hits a directional key, such as a D-pad direction, the view device will
555 * exit touch mode, and find a view to take focus, so that the user may resume interacting
556 * with the user interface without touching the screen again.
559 * The touch mode state is maintained across {@link android.app.Activity}s. Call
560 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
563 * <a name="Scrolling"></a>
566 * The framework provides basic support for views that wish to internally
567 * scroll their content. This includes keeping track of the X and Y scroll
568 * offset as well as mechanisms for drawing scrollbars. See
569 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
570 * {@link #awakenScrollBars()} for more details.
573 * <a name="Tags"></a>
576 * Unlike IDs, tags are not used to identify views. Tags are essentially an
577 * extra piece of information that can be associated with a view. They are most
578 * often used as a convenience to store data related to views in the views
579 * themselves rather than by putting them in a separate structure.
582 * Tags may be specified with character sequence values in layout XML as either
583 * a single tag using the {@link android.R.styleable#View_tag android:tag}
584 * attribute or multiple tags using the {@code <tag>} child element:
587 * android:tag="@string/mytag_value" />
589 * <tag android:id="@+id/mytag"
590 * android:value="@string/mytag_value" />
595 * Tags may also be specified with arbitrary objects from code using
596 * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
599 * <a name="Themes"></a>
602 * By default, Views are created using the theme of the Context object supplied
603 * to their constructor; however, a different theme may be specified by using
604 * the {@link android.R.styleable#View_theme android:theme} attribute in layout
605 * XML or by passing a {@link ContextThemeWrapper} to the constructor from
609 * When the {@link android.R.styleable#View_theme android:theme} attribute is
610 * used in XML, the specified theme is applied on top of the inflation
611 * context's theme (see {@link LayoutInflater}) and used for the view itself as
612 * well as any child elements.
615 * In the following example, both views will be created using the Material dark
616 * color scheme; however, because an overlay theme is used which only defines a
617 * subset of attributes, the value of
618 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
619 * the inflation context's theme (e.g. the Activity theme) will be preserved.
623 * android:theme="@android:theme/ThemeOverlay.Material.Dark">
625 * </LinearLayout>
629 * <a name="Properties"></a>
630 * <h3>Properties</h3>
632 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
633 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
634 * available both in the {@link Property} form as well as in similarly-named setter/getter
635 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
636 * be used to set persistent state associated with these rendering-related properties on the view.
637 * The properties and methods can also be used in conjunction with
638 * {@link android.animation.Animator Animator}-based animations, described more in the
639 * <a href="#Animation">Animation</a> section.
642 * <a name="Animation"></a>
645 * Starting with Android 3.0, the preferred way of animating views is to use the
646 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
647 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
648 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
649 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
650 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
651 * makes animating these View properties particularly easy and efficient.
654 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
655 * You can attach an {@link Animation} object to a view using
656 * {@link #setAnimation(Animation)} or
657 * {@link #startAnimation(Animation)}. The animation can alter the scale,
658 * rotation, translation and alpha of a view over time. If the animation is
659 * attached to a view that has children, the animation will affect the entire
660 * subtree rooted by that node. When an animation is started, the framework will
661 * take care of redrawing the appropriate views until the animation completes.
664 * <a name="Security"></a>
667 * Sometimes it is essential that an application be able to verify that an action
668 * is being performed with the full knowledge and consent of the user, such as
669 * granting a permission request, making a purchase or clicking on an advertisement.
670 * Unfortunately, a malicious application could try to spoof the user into
671 * performing these actions, unaware, by concealing the intended purpose of the view.
672 * As a remedy, the framework offers a touch filtering mechanism that can be used to
673 * improve the security of views that provide access to sensitive functionality.
675 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
676 * android:filterTouchesWhenObscured layout attribute to true. When enabled, the framework
677 * will discard touches that are received whenever the view's window is obscured by
678 * another visible window. As a result, the view will not receive touches whenever a
679 * toast, dialog or other window appears above the view's window.
681 * For more fine-grained control over security, consider overriding the
682 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
683 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
686 * @attr ref android.R.styleable#View_alpha
687 * @attr ref android.R.styleable#View_background
688 * @attr ref android.R.styleable#View_clickable
689 * @attr ref android.R.styleable#View_contentDescription
690 * @attr ref android.R.styleable#View_drawingCacheQuality
691 * @attr ref android.R.styleable#View_duplicateParentState
692 * @attr ref android.R.styleable#View_id
693 * @attr ref android.R.styleable#View_requiresFadingEdge
694 * @attr ref android.R.styleable#View_fadeScrollbars
695 * @attr ref android.R.styleable#View_fadingEdgeLength
696 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
697 * @attr ref android.R.styleable#View_fitsSystemWindows
698 * @attr ref android.R.styleable#View_isScrollContainer
699 * @attr ref android.R.styleable#View_focusable
700 * @attr ref android.R.styleable#View_focusableInTouchMode
701 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
702 * @attr ref android.R.styleable#View_keepScreenOn
703 * @attr ref android.R.styleable#View_layerType
704 * @attr ref android.R.styleable#View_layoutDirection
705 * @attr ref android.R.styleable#View_longClickable
706 * @attr ref android.R.styleable#View_minHeight
707 * @attr ref android.R.styleable#View_minWidth
708 * @attr ref android.R.styleable#View_nextFocusDown
709 * @attr ref android.R.styleable#View_nextFocusLeft
710 * @attr ref android.R.styleable#View_nextFocusRight
711 * @attr ref android.R.styleable#View_nextFocusUp
712 * @attr ref android.R.styleable#View_onClick
713 * @attr ref android.R.styleable#View_padding
714 * @attr ref android.R.styleable#View_paddingBottom
715 * @attr ref android.R.styleable#View_paddingLeft
716 * @attr ref android.R.styleable#View_paddingRight
717 * @attr ref android.R.styleable#View_paddingTop
718 * @attr ref android.R.styleable#View_paddingStart
719 * @attr ref android.R.styleable#View_paddingEnd
720 * @attr ref android.R.styleable#View_saveEnabled
721 * @attr ref android.R.styleable#View_rotation
722 * @attr ref android.R.styleable#View_rotationX
723 * @attr ref android.R.styleable#View_rotationY
724 * @attr ref android.R.styleable#View_scaleX
725 * @attr ref android.R.styleable#View_scaleY
726 * @attr ref android.R.styleable#View_scrollX
727 * @attr ref android.R.styleable#View_scrollY
728 * @attr ref android.R.styleable#View_scrollbarSize
729 * @attr ref android.R.styleable#View_scrollbarStyle
730 * @attr ref android.R.styleable#View_scrollbars
731 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
732 * @attr ref android.R.styleable#View_scrollbarFadeDuration
733 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
734 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
735 * @attr ref android.R.styleable#View_scrollbarThumbVertical
736 * @attr ref android.R.styleable#View_scrollbarTrackVertical
737 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
738 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
739 * @attr ref android.R.styleable#View_stateListAnimator
740 * @attr ref android.R.styleable#View_transitionName
741 * @attr ref android.R.styleable#View_soundEffectsEnabled
742 * @attr ref android.R.styleable#View_tag
743 * @attr ref android.R.styleable#View_textAlignment
744 * @attr ref android.R.styleable#View_textDirection
745 * @attr ref android.R.styleable#View_transformPivotX
746 * @attr ref android.R.styleable#View_transformPivotY
747 * @attr ref android.R.styleable#View_translationX
748 * @attr ref android.R.styleable#View_translationY
749 * @attr ref android.R.styleable#View_translationZ
750 * @attr ref android.R.styleable#View_visibility
751 * @attr ref android.R.styleable#View_theme
753 * @see android.view.ViewGroup
756 public class View implements Drawable.Callback, KeyEvent.Callback,
757 AccessibilityEventSource {
758 private static final boolean DBG = false;
761 * The logging tag used by this class with android.util.Log.
763 protected static final String VIEW_LOG_TAG = "View";
766 * When set to true, apps will draw debugging information about their layouts.
770 public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
773 * When set to true, this view will save its attribute data.
777 public static boolean mDebugViewAttributes = false;
780 * Used to mark a View that has no ID.
782 public static final int NO_ID = -1;
785 * Signals that compatibility booleans have been initialized according to
786 * target SDK versions.
788 private static boolean sCompatibilityDone = false;
791 * Use the old (broken) way of building MeasureSpecs.
793 private static boolean sUseBrokenMakeMeasureSpec = false;
796 * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
798 static boolean sUseZeroUnspecifiedMeasureSpec = false;
801 * Ignore any optimizations using the measure cache.
803 private static boolean sIgnoreMeasureCache = false;
806 * Ignore an optimization that skips unnecessary EXACTLY layout passes.
808 private static boolean sAlwaysRemeasureExactly = false;
811 * Relax constraints around whether setLayoutParams() must be called after
812 * modifying the layout params.
814 private static boolean sLayoutParamsAlwaysChanged = false;
817 * Allow setForeground/setBackground to be called (and ignored) on a textureview,
820 static boolean sTextureViewIgnoresDrawableSetters = false;
823 * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
824 * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
825 * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
826 * check is implemented for backwards compatibility.
830 protected static boolean sPreserveMarginParamsInLayoutParamConversion;
833 * Prior to N, when drag enters into child of a view that has already received an
834 * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
835 * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
836 * false from its event handler for these events.
837 * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
838 * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
839 * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
841 static boolean sCascadedDragDrop;
844 * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
847 private static final int NOT_FOCUSABLE = 0x00000000;
850 * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
853 private static final int FOCUSABLE = 0x00000001;
856 * Mask for use with setFlags indicating bits used for focus.
858 private static final int FOCUSABLE_MASK = 0x00000001;
861 * This view will adjust its padding to fit sytem windows (e.g. status bar)
863 private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
866 @IntDef({VISIBLE, INVISIBLE, GONE})
867 @Retention(RetentionPolicy.SOURCE)
868 public @interface Visibility {}
871 * This view is visible.
872 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
873 * android:visibility}.
875 public static final int VISIBLE = 0x00000000;
878 * This view is invisible, but it still takes up space for layout purposes.
879 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
880 * android:visibility}.
882 public static final int INVISIBLE = 0x00000004;
885 * This view is invisible, and it doesn't take any space for layout
886 * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
887 * android:visibility}.
889 public static final int GONE = 0x00000008;
892 * Mask for use with setFlags indicating bits used for visibility.
895 static final int VISIBILITY_MASK = 0x0000000C;
897 private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
900 * This view is enabled. Interpretation varies by subclass.
901 * Use with ENABLED_MASK when calling setFlags.
904 static final int ENABLED = 0x00000000;
907 * This view is disabled. Interpretation varies by subclass.
908 * Use with ENABLED_MASK when calling setFlags.
911 static final int DISABLED = 0x00000020;
914 * Mask for use with setFlags indicating bits used for indicating whether
915 * this view is enabled
918 static final int ENABLED_MASK = 0x00000020;
921 * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
922 * called and further optimizations will be performed. It is okay to have
923 * this flag set and a background. Use with DRAW_MASK when calling setFlags.
926 static final int WILL_NOT_DRAW = 0x00000080;
929 * Mask for use with setFlags indicating bits used for indicating whether
930 * this view is will draw
933 static final int DRAW_MASK = 0x00000080;
936 * <p>This view doesn't show scrollbars.</p>
939 static final int SCROLLBARS_NONE = 0x00000000;
942 * <p>This view shows horizontal scrollbars.</p>
945 static final int SCROLLBARS_HORIZONTAL = 0x00000100;
948 * <p>This view shows vertical scrollbars.</p>
951 static final int SCROLLBARS_VERTICAL = 0x00000200;
954 * <p>Mask for use with setFlags indicating bits used for indicating which
955 * scrollbars are enabled.</p>
958 static final int SCROLLBARS_MASK = 0x00000300;
961 * Indicates that the view should filter touches when its window is obscured.
962 * Refer to the class comments for more information about this security feature.
965 static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
968 * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
969 * that they are optional and should be skipped if the window has
970 * requested system UI flags that ignore those insets for layout.
972 static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
975 * <p>This view doesn't show fading edges.</p>
978 static final int FADING_EDGE_NONE = 0x00000000;
981 * <p>This view shows horizontal fading edges.</p>
984 static final int FADING_EDGE_HORIZONTAL = 0x00001000;
987 * <p>This view shows vertical fading edges.</p>
990 static final int FADING_EDGE_VERTICAL = 0x00002000;
993 * <p>Mask for use with setFlags indicating bits used for indicating which
994 * fading edges are enabled.</p>
997 static final int FADING_EDGE_MASK = 0x00003000;
1000 * <p>Indicates this view can be clicked. When clickable, a View reacts
1001 * to clicks by notifying the OnClickListener.<p>
1004 static final int CLICKABLE = 0x00004000;
1007 * <p>Indicates this view is caching its drawing into a bitmap.</p>
1010 static final int DRAWING_CACHE_ENABLED = 0x00008000;
1013 * <p>Indicates that no icicle should be saved for this view.<p>
1016 static final int SAVE_DISABLED = 0x000010000;
1019 * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1023 static final int SAVE_DISABLED_MASK = 0x000010000;
1026 * <p>Indicates that no drawing cache should ever be created for this view.<p>
1029 static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1032 * <p>Indicates this view can take / keep focus when int touch mode.</p>
1035 static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1038 @Retention(RetentionPolicy.SOURCE)
1039 @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1040 public @interface DrawingCacheQuality {}
1043 * <p>Enables low quality mode for the drawing cache.</p>
1045 public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1048 * <p>Enables high quality mode for the drawing cache.</p>
1050 public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1053 * <p>Enables automatic quality mode for the drawing cache.</p>
1055 public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1057 private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1058 DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1062 * <p>Mask for use with setFlags indicating bits used for the cache
1063 * quality property.</p>
1066 static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1070 * Indicates this view can be long clicked. When long clickable, a View
1071 * reacts to long clicks by notifying the OnLongClickListener or showing a
1076 static final int LONG_CLICKABLE = 0x00200000;
1079 * <p>Indicates that this view gets its drawable states from its direct parent
1080 * and ignores its original internal states.</p>
1084 static final int DUPLICATE_PARENT_STATE = 0x00400000;
1088 * Indicates this view can be context clicked. When context clickable, a View reacts to a
1089 * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1090 * OnContextClickListener.
1094 static final int CONTEXT_CLICKABLE = 0x00800000;
1099 SCROLLBARS_INSIDE_OVERLAY,
1100 SCROLLBARS_INSIDE_INSET,
1101 SCROLLBARS_OUTSIDE_OVERLAY,
1102 SCROLLBARS_OUTSIDE_INSET
1104 @Retention(RetentionPolicy.SOURCE)
1105 public @interface ScrollBarStyle {}
1108 * The scrollbar style to display the scrollbars inside the content area,
1109 * without increasing the padding. The scrollbars will be overlaid with
1110 * translucency on the view's content.
1112 public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1115 * The scrollbar style to display the scrollbars inside the padded area,
1116 * increasing the padding of the view. The scrollbars will not overlap the
1117 * content area of the view.
1119 public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1122 * The scrollbar style to display the scrollbars at the edge of the view,
1123 * without increasing the padding. The scrollbars will be overlaid with
1126 public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1129 * The scrollbar style to display the scrollbars at the edge of the view,
1130 * increasing the padding of the view. The scrollbars will only overlap the
1131 * background, if any.
1133 public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1136 * Mask to check if the scrollbar style is overlay or inset.
1139 static final int SCROLLBARS_INSET_MASK = 0x01000000;
1142 * Mask to check if the scrollbar style is inside or outside.
1145 static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1148 * Mask for scrollbar style.
1151 static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1154 * View flag indicating that the screen should remain on while the
1155 * window containing this view is visible to the user. This effectively
1156 * takes care of automatically setting the WindowManager's
1157 * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1159 public static final int KEEP_SCREEN_ON = 0x04000000;
1162 * View flag indicating whether this view should have sound effects enabled
1163 * for events such as clicking and touching.
1165 public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1168 * View flag indicating whether this view should have haptic feedback
1169 * enabled for events such as long presses.
1171 public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1174 * <p>Indicates that the view hierarchy should stop saving state when
1175 * it reaches this view. If state saving is initiated immediately at
1176 * the view, it will be allowed.
1179 static final int PARENT_SAVE_DISABLED = 0x20000000;
1182 * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1185 static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1188 @IntDef(flag = true,
1191 FOCUSABLES_TOUCH_MODE
1193 @Retention(RetentionPolicy.SOURCE)
1194 public @interface FocusableMode {}
1197 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1198 * should add all focusable Views regardless if they are focusable in touch mode.
1200 public static final int FOCUSABLES_ALL = 0x00000000;
1203 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1204 * should add only Views focusable in touch mode.
1206 public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1217 @Retention(RetentionPolicy.SOURCE)
1218 public @interface FocusDirection {}
1227 @Retention(RetentionPolicy.SOURCE)
1228 public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1231 * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1234 public static final int FOCUS_BACKWARD = 0x00000001;
1237 * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1240 public static final int FOCUS_FORWARD = 0x00000002;
1243 * Use with {@link #focusSearch(int)}. Move focus to the left.
1245 public static final int FOCUS_LEFT = 0x00000011;
1248 * Use with {@link #focusSearch(int)}. Move focus up.
1250 public static final int FOCUS_UP = 0x00000021;
1253 * Use with {@link #focusSearch(int)}. Move focus to the right.
1255 public static final int FOCUS_RIGHT = 0x00000042;
1258 * Use with {@link #focusSearch(int)}. Move focus down.
1260 public static final int FOCUS_DOWN = 0x00000082;
1263 * Bits of {@link #getMeasuredWidthAndState()} and
1264 * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1266 public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1269 * Bits of {@link #getMeasuredWidthAndState()} and
1270 * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1272 public static final int MEASURED_STATE_MASK = 0xff000000;
1275 * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1276 * for functions that combine both width and height into a single int,
1277 * such as {@link #getMeasuredState()} and the childState argument of
1278 * {@link #resolveSizeAndState(int, int, int)}.
1280 public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1283 * Bit of {@link #getMeasuredWidthAndState()} and
1284 * {@link #getMeasuredWidthAndState()} that indicates the measured size
1285 * is smaller that the space the view would like to have.
1287 public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1290 * Base View state sets
1294 * Indicates the view has no states set. States are used with
1295 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1296 * view depending on its state.
1298 * @see android.graphics.drawable.Drawable
1299 * @see #getDrawableState()
1301 protected static final int[] EMPTY_STATE_SET;
1303 * Indicates the view is enabled. States are used with
1304 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1305 * view depending on its state.
1307 * @see android.graphics.drawable.Drawable
1308 * @see #getDrawableState()
1310 protected static final int[] ENABLED_STATE_SET;
1312 * Indicates the view is focused. States are used with
1313 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1314 * view depending on its state.
1316 * @see android.graphics.drawable.Drawable
1317 * @see #getDrawableState()
1319 protected static final int[] FOCUSED_STATE_SET;
1321 * Indicates the view is selected. States are used with
1322 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1323 * view depending on its state.
1325 * @see android.graphics.drawable.Drawable
1326 * @see #getDrawableState()
1328 protected static final int[] SELECTED_STATE_SET;
1330 * Indicates the view is pressed. States are used with
1331 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1332 * view depending on its state.
1334 * @see android.graphics.drawable.Drawable
1335 * @see #getDrawableState()
1337 protected static final int[] PRESSED_STATE_SET;
1339 * Indicates the view's window has focus. States are used with
1340 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1341 * view depending on its state.
1343 * @see android.graphics.drawable.Drawable
1344 * @see #getDrawableState()
1346 protected static final int[] WINDOW_FOCUSED_STATE_SET;
1349 * Indicates the view is enabled and has the focus.
1351 * @see #ENABLED_STATE_SET
1352 * @see #FOCUSED_STATE_SET
1354 protected static final int[] ENABLED_FOCUSED_STATE_SET;
1356 * Indicates the view is enabled and selected.
1358 * @see #ENABLED_STATE_SET
1359 * @see #SELECTED_STATE_SET
1361 protected static final int[] ENABLED_SELECTED_STATE_SET;
1363 * Indicates the view is enabled and that its window has focus.
1365 * @see #ENABLED_STATE_SET
1366 * @see #WINDOW_FOCUSED_STATE_SET
1368 protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1370 * Indicates the view is focused and selected.
1372 * @see #FOCUSED_STATE_SET
1373 * @see #SELECTED_STATE_SET
1375 protected static final int[] FOCUSED_SELECTED_STATE_SET;
1377 * Indicates the view has the focus and that its window has the focus.
1379 * @see #FOCUSED_STATE_SET
1380 * @see #WINDOW_FOCUSED_STATE_SET
1382 protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1384 * Indicates the view is selected and that its window has the focus.
1386 * @see #SELECTED_STATE_SET
1387 * @see #WINDOW_FOCUSED_STATE_SET
1389 protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1392 * Indicates the view is enabled, focused and selected.
1394 * @see #ENABLED_STATE_SET
1395 * @see #FOCUSED_STATE_SET
1396 * @see #SELECTED_STATE_SET
1398 protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1400 * Indicates the view is enabled, focused and its window has the focus.
1402 * @see #ENABLED_STATE_SET
1403 * @see #FOCUSED_STATE_SET
1404 * @see #WINDOW_FOCUSED_STATE_SET
1406 protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1408 * Indicates the view is enabled, selected and its window has the focus.
1410 * @see #ENABLED_STATE_SET
1411 * @see #SELECTED_STATE_SET
1412 * @see #WINDOW_FOCUSED_STATE_SET
1414 protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1416 * Indicates the view is focused, selected and its window has the focus.
1418 * @see #FOCUSED_STATE_SET
1419 * @see #SELECTED_STATE_SET
1420 * @see #WINDOW_FOCUSED_STATE_SET
1422 protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1424 * Indicates the view is enabled, focused, selected and its window
1427 * @see #ENABLED_STATE_SET
1428 * @see #FOCUSED_STATE_SET
1429 * @see #SELECTED_STATE_SET
1430 * @see #WINDOW_FOCUSED_STATE_SET
1432 protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1434 * Indicates the view is pressed and its window has the focus.
1436 * @see #PRESSED_STATE_SET
1437 * @see #WINDOW_FOCUSED_STATE_SET
1439 protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1441 * Indicates the view is pressed and selected.
1443 * @see #PRESSED_STATE_SET
1444 * @see #SELECTED_STATE_SET
1446 protected static final int[] PRESSED_SELECTED_STATE_SET;
1448 * Indicates the view is pressed, selected and its window has the focus.
1450 * @see #PRESSED_STATE_SET
1451 * @see #SELECTED_STATE_SET
1452 * @see #WINDOW_FOCUSED_STATE_SET
1454 protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1456 * Indicates the view is pressed and focused.
1458 * @see #PRESSED_STATE_SET
1459 * @see #FOCUSED_STATE_SET
1461 protected static final int[] PRESSED_FOCUSED_STATE_SET;
1463 * Indicates the view is pressed, focused and its window has the focus.
1465 * @see #PRESSED_STATE_SET
1466 * @see #FOCUSED_STATE_SET
1467 * @see #WINDOW_FOCUSED_STATE_SET
1469 protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1471 * Indicates the view is pressed, focused and selected.
1473 * @see #PRESSED_STATE_SET
1474 * @see #SELECTED_STATE_SET
1475 * @see #FOCUSED_STATE_SET
1477 protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1479 * Indicates the view is pressed, focused, selected and its window has the focus.
1481 * @see #PRESSED_STATE_SET
1482 * @see #FOCUSED_STATE_SET
1483 * @see #SELECTED_STATE_SET
1484 * @see #WINDOW_FOCUSED_STATE_SET
1486 protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1488 * Indicates the view is pressed and enabled.
1490 * @see #PRESSED_STATE_SET
1491 * @see #ENABLED_STATE_SET
1493 protected static final int[] PRESSED_ENABLED_STATE_SET;
1495 * Indicates the view is pressed, enabled and its window has the focus.
1497 * @see #PRESSED_STATE_SET
1498 * @see #ENABLED_STATE_SET
1499 * @see #WINDOW_FOCUSED_STATE_SET
1501 protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1503 * Indicates the view is pressed, enabled and selected.
1505 * @see #PRESSED_STATE_SET
1506 * @see #ENABLED_STATE_SET
1507 * @see #SELECTED_STATE_SET
1509 protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1511 * Indicates the view is pressed, enabled, selected and its window has the
1514 * @see #PRESSED_STATE_SET
1515 * @see #ENABLED_STATE_SET
1516 * @see #SELECTED_STATE_SET
1517 * @see #WINDOW_FOCUSED_STATE_SET
1519 protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1521 * Indicates the view is pressed, enabled and focused.
1523 * @see #PRESSED_STATE_SET
1524 * @see #ENABLED_STATE_SET
1525 * @see #FOCUSED_STATE_SET
1527 protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1529 * Indicates the view is pressed, enabled, focused and its window has the
1532 * @see #PRESSED_STATE_SET
1533 * @see #ENABLED_STATE_SET
1534 * @see #FOCUSED_STATE_SET
1535 * @see #WINDOW_FOCUSED_STATE_SET
1537 protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1539 * Indicates the view is pressed, enabled, focused and selected.
1541 * @see #PRESSED_STATE_SET
1542 * @see #ENABLED_STATE_SET
1543 * @see #SELECTED_STATE_SET
1544 * @see #FOCUSED_STATE_SET
1546 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1548 * Indicates the view is pressed, enabled, focused, selected and its window
1551 * @see #PRESSED_STATE_SET
1552 * @see #ENABLED_STATE_SET
1553 * @see #SELECTED_STATE_SET
1554 * @see #FOCUSED_STATE_SET
1555 * @see #WINDOW_FOCUSED_STATE_SET
1557 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1560 EMPTY_STATE_SET = StateSet.get(0);
1562 WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1564 SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1565 SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1566 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1568 FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1569 FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1570 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1571 FOCUSED_SELECTED_STATE_SET = StateSet.get(
1572 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1573 FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1574 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1575 | StateSet.VIEW_STATE_FOCUSED);
1577 ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1578 ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1579 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1580 ENABLED_SELECTED_STATE_SET = StateSet.get(
1581 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1582 ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1583 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1584 | StateSet.VIEW_STATE_ENABLED);
1585 ENABLED_FOCUSED_STATE_SET = StateSet.get(
1586 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1587 ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1588 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1589 | StateSet.VIEW_STATE_ENABLED);
1590 ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1591 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1592 | StateSet.VIEW_STATE_ENABLED);
1593 ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1594 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1595 | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1597 PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1598 PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1599 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1600 PRESSED_SELECTED_STATE_SET = StateSet.get(
1601 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1602 PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1603 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1604 | StateSet.VIEW_STATE_PRESSED);
1605 PRESSED_FOCUSED_STATE_SET = StateSet.get(
1606 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1607 PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1608 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1609 | StateSet.VIEW_STATE_PRESSED);
1610 PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1611 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1612 | StateSet.VIEW_STATE_PRESSED);
1613 PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1614 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1615 | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1616 PRESSED_ENABLED_STATE_SET = StateSet.get(
1617 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1618 PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1619 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1620 | StateSet.VIEW_STATE_PRESSED);
1621 PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1622 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1623 | StateSet.VIEW_STATE_PRESSED);
1624 PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1625 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1626 | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1627 PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1628 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1629 | StateSet.VIEW_STATE_PRESSED);
1630 PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1631 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1632 | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1633 PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1634 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1635 | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1636 PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1637 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1638 | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1639 | StateSet.VIEW_STATE_PRESSED);
1643 * Accessibility event types that are dispatched for text population.
1645 private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1646 AccessibilityEvent.TYPE_VIEW_CLICKED
1647 | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1648 | AccessibilityEvent.TYPE_VIEW_SELECTED
1649 | AccessibilityEvent.TYPE_VIEW_FOCUSED
1650 | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1651 | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1652 | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1653 | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1654 | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1655 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1656 | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1659 * Temporary Rect currently for use in setBackground(). This will probably
1660 * be extended in the future to hold our own class with more than just
1663 static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1666 * Map used to store views' tags.
1668 private SparseArray<Object> mKeyedTags;
1671 * The next available accessibility id.
1673 private static int sNextAccessibilityViewId;
1676 * The animation currently associated with this view.
1679 protected Animation mCurrentAnimation = null;
1682 * Width as measured during measure pass.
1685 @ViewDebug.ExportedProperty(category = "measurement")
1689 * Height as measured during measure pass.
1692 @ViewDebug.ExportedProperty(category = "measurement")
1693 int mMeasuredHeight;
1696 * Flag to indicate that this view was marked INVALIDATED, or had its display list
1697 * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1698 * its display list. This flag, used only when hw accelerated, allows us to clear the
1699 * flag while retaining this information until it's needed (at getDisplayList() time and
1700 * in drawChild(), when we decide to draw a view's children's display lists into our own).
1704 boolean mRecreateDisplayList = false;
1707 * The view's identifier.
1714 @ViewDebug.ExportedProperty(resolveId = true)
1718 * The stable ID of this view for accessibility purposes.
1720 int mAccessibilityViewId = NO_ID;
1722 private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1724 SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1730 * @see #setTag(Object)
1733 protected Object mTag = null;
1735 // for mPrivateFlags:
1737 static final int PFLAG_WANTS_FOCUS = 0x00000001;
1739 static final int PFLAG_FOCUSED = 0x00000002;
1741 static final int PFLAG_SELECTED = 0x00000004;
1743 static final int PFLAG_IS_ROOT_NAMESPACE = 0x00000008;
1745 static final int PFLAG_HAS_BOUNDS = 0x00000010;
1747 static final int PFLAG_DRAWN = 0x00000020;
1749 * When this flag is set, this view is running an animation on behalf of its
1750 * children and should therefore not cancel invalidate requests, even if they
1751 * lie outside of this view's bounds.
1755 static final int PFLAG_DRAW_ANIMATION = 0x00000040;
1757 static final int PFLAG_SKIP_DRAW = 0x00000080;
1759 static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1761 static final int PFLAG_DRAWABLE_STATE_DIRTY = 0x00000400;
1763 static final int PFLAG_MEASURED_DIMENSION_SET = 0x00000800;
1765 static final int PFLAG_FORCE_LAYOUT = 0x00001000;
1767 static final int PFLAG_LAYOUT_REQUIRED = 0x00002000;
1769 private static final int PFLAG_PRESSED = 0x00004000;
1772 static final int PFLAG_DRAWING_CACHE_VALID = 0x00008000;
1774 * Flag used to indicate that this view should be drawn once more (and only once
1775 * more) after its animation has completed.
1778 static final int PFLAG_ANIMATION_STARTED = 0x00010000;
1780 private static final int PFLAG_SAVE_STATE_CALLED = 0x00020000;
1783 * Indicates that the View returned true when onSetAlpha() was called and that
1784 * the alpha must be restored.
1787 static final int PFLAG_ALPHA_SET = 0x00040000;
1790 * Set by {@link #setScrollContainer(boolean)}.
1792 static final int PFLAG_SCROLL_CONTAINER = 0x00080000;
1795 * Set by {@link #setScrollContainer(boolean)}.
1797 static final int PFLAG_SCROLL_CONTAINER_ADDED = 0x00100000;
1800 * View flag indicating whether this view was invalidated (fully or partially.)
1804 static final int PFLAG_DIRTY = 0x00200000;
1807 * View flag indicating whether this view was invalidated by an opaque
1808 * invalidate request.
1812 static final int PFLAG_DIRTY_OPAQUE = 0x00400000;
1815 * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1819 static final int PFLAG_DIRTY_MASK = 0x00600000;
1822 * Indicates whether the background is opaque.
1826 static final int PFLAG_OPAQUE_BACKGROUND = 0x00800000;
1829 * Indicates whether the scrollbars are opaque.
1833 static final int PFLAG_OPAQUE_SCROLLBARS = 0x01000000;
1836 * Indicates whether the view is opaque.
1840 static final int PFLAG_OPAQUE_MASK = 0x01800000;
1843 * Indicates a prepressed state;
1844 * the short time between ACTION_DOWN and recognizing
1845 * a 'real' press. Prepressed is used to recognize quick taps
1846 * even when they are shorter than ViewConfiguration.getTapTimeout().
1850 private static final int PFLAG_PREPRESSED = 0x02000000;
1853 * Indicates whether the view is temporarily detached.
1857 static final int PFLAG_CANCEL_NEXT_UP_EVENT = 0x04000000;
1860 * Indicates that we should awaken scroll bars once attached
1862 * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
1863 * during window attachment and it is no longer needed. Feel free to repurpose it.
1867 private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1870 * Indicates that the view has received HOVER_ENTER. Cleared on HOVER_EXIT.
1873 private static final int PFLAG_HOVERED = 0x10000000;
1876 * no longer needed, should be reused
1878 private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1881 static final int PFLAG_ACTIVATED = 0x40000000;
1884 * Indicates that this view was specifically invalidated, not just dirtied because some
1885 * child view was invalidated. The flag is used to determine when we need to recreate
1886 * a view's display list (as opposed to just returning a reference to its existing
1891 static final int PFLAG_INVALIDATED = 0x80000000;
1894 * Masks for mPrivateFlags2, as generated by dumpFlags():
1896 * |-------|-------|-------|-------|
1897 * 1 PFLAG2_DRAG_CAN_ACCEPT
1898 * 1 PFLAG2_DRAG_HOVERED
1899 * 11 PFLAG2_LAYOUT_DIRECTION_MASK
1900 * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1901 * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED
1902 * 11 PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1903 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[1]
1904 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[2]
1905 * 11 PFLAG2_TEXT_DIRECTION_FLAGS[3]
1906 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[4]
1907 * 1 1 PFLAG2_TEXT_DIRECTION_FLAGS[5]
1908 * 11 PFLAG2_TEXT_DIRECTION_FLAGS[6]
1909 * 111 PFLAG2_TEXT_DIRECTION_FLAGS[7]
1910 * 111 PFLAG2_TEXT_DIRECTION_MASK
1911 * 1 PFLAG2_TEXT_DIRECTION_RESOLVED
1912 * 1 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1913 * 111 PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1914 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1915 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1916 * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1917 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1918 * 1 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1919 * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1920 * 111 PFLAG2_TEXT_ALIGNMENT_MASK
1921 * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1922 * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1923 * 111 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1924 * 111 PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1925 * 11 PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1926 * 1 PFLAG2_ACCESSIBILITY_FOCUSED
1927 * 1 PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1928 * 1 PFLAG2_VIEW_QUICK_REJECTED
1929 * 1 PFLAG2_PADDING_RESOLVED
1930 * 1 PFLAG2_DRAWABLE_RESOLVED
1931 * 1 PFLAG2_HAS_TRANSIENT_STATE
1932 * |-------|-------|-------|-------|
1936 * Indicates that this view has reported that it can accept the current drag's content.
1937 * Cleared when the drag operation concludes.
1940 static final int PFLAG2_DRAG_CAN_ACCEPT = 0x00000001;
1943 * Indicates that this view is currently directly under the drag location in a
1944 * drag-and-drop operation involving content that it can accept. Cleared when
1945 * the drag exits the view, or when the drag operation concludes.
1948 static final int PFLAG2_DRAG_HOVERED = 0x00000002;
1952 LAYOUT_DIRECTION_LTR,
1953 LAYOUT_DIRECTION_RTL,
1954 LAYOUT_DIRECTION_INHERIT,
1955 LAYOUT_DIRECTION_LOCALE
1957 @Retention(RetentionPolicy.SOURCE)
1958 // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1959 public @interface LayoutDir {}
1963 LAYOUT_DIRECTION_LTR,
1964 LAYOUT_DIRECTION_RTL
1966 @Retention(RetentionPolicy.SOURCE)
1967 public @interface ResolvedLayoutDir {}
1970 * A flag to indicate that the layout direction of this view has not been defined yet.
1973 public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
1976 * Horizontal layout direction of this view is from Left to Right.
1977 * Use with {@link #setLayoutDirection}.
1979 public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1982 * Horizontal layout direction of this view is from Right to Left.
1983 * Use with {@link #setLayoutDirection}.
1985 public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1988 * Horizontal layout direction of this view is inherited from its parent.
1989 * Use with {@link #setLayoutDirection}.
1991 public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1994 * Horizontal layout direction of this view is from deduced from the default language
1995 * script for the locale. Use with {@link #setLayoutDirection}.
1997 public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2000 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2003 static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2006 * Mask for use with private flags indicating bits used for horizontal layout direction.
2009 static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2012 * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2013 * right-to-left direction.
2016 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2019 * Indicates whether the view horizontal layout direction has been resolved.
2022 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2025 * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2028 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2029 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2032 * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2036 private static final int[] LAYOUT_DIRECTION_FLAGS = {
2037 LAYOUT_DIRECTION_LTR,
2038 LAYOUT_DIRECTION_RTL,
2039 LAYOUT_DIRECTION_INHERIT,
2040 LAYOUT_DIRECTION_LOCALE
2044 * Default horizontal layout direction.
2046 private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2049 * Default horizontal layout direction.
2052 static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2055 * Text direction is inherited through {@link ViewGroup}
2057 public static final int TEXT_DIRECTION_INHERIT = 0;
2060 * Text direction is using "first strong algorithm". The first strong directional character
2061 * determines the paragraph direction. If there is no strong directional character, the
2062 * paragraph direction is the view's resolved layout direction.
2064 public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2067 * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2068 * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2069 * If there are neither, the paragraph direction is the view's resolved layout direction.
2071 public static final int TEXT_DIRECTION_ANY_RTL = 2;
2074 * Text direction is forced to LTR.
2076 public static final int TEXT_DIRECTION_LTR = 3;
2079 * Text direction is forced to RTL.
2081 public static final int TEXT_DIRECTION_RTL = 4;
2084 * Text direction is coming from the system Locale.
2086 public static final int TEXT_DIRECTION_LOCALE = 5;
2089 * Text direction is using "first strong algorithm". The first strong directional character
2090 * determines the paragraph direction. If there is no strong directional character, the
2091 * paragraph direction is LTR.
2093 public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2096 * Text direction is using "first strong algorithm". The first strong directional character
2097 * determines the paragraph direction. If there is no strong directional character, the
2098 * paragraph direction is RTL.
2100 public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2103 * Default text direction is inherited
2105 private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2108 * Default resolved text direction
2111 static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2114 * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2117 static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2120 * Mask for use with private flags indicating bits used for text direction.
2123 static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2124 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2127 * Array of text direction flags for mapping attribute "textDirection" to correct
2131 private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2132 TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2133 TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2134 TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2135 TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2136 TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2137 TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2138 TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2139 TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2143 * Indicates whether the view text direction has been resolved.
2146 static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2147 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2150 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2153 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2156 * Mask for use with private flags indicating bits used for resolved text direction.
2159 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2160 << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2163 * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2166 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2167 TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2171 TEXT_ALIGNMENT_INHERIT,
2172 TEXT_ALIGNMENT_GRAVITY,
2173 TEXT_ALIGNMENT_CENTER,
2174 TEXT_ALIGNMENT_TEXT_START,
2175 TEXT_ALIGNMENT_TEXT_END,
2176 TEXT_ALIGNMENT_VIEW_START,
2177 TEXT_ALIGNMENT_VIEW_END
2179 @Retention(RetentionPolicy.SOURCE)
2180 public @interface TextAlignment {}
2183 * Default text alignment. The text alignment of this View is inherited from its parent.
2184 * Use with {@link #setTextAlignment(int)}
2186 public static final int TEXT_ALIGNMENT_INHERIT = 0;
2189 * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2190 * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2192 * Use with {@link #setTextAlignment(int)}
2194 public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2197 * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2199 * Use with {@link #setTextAlignment(int)}
2201 public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2204 * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2206 * Use with {@link #setTextAlignment(int)}
2208 public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2211 * Center the paragraph, e.g. ALIGN_CENTER.
2213 * Use with {@link #setTextAlignment(int)}
2215 public static final int TEXT_ALIGNMENT_CENTER = 4;
2218 * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2219 * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2221 * Use with {@link #setTextAlignment(int)}
2223 public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2226 * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2227 * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2229 * Use with {@link #setTextAlignment(int)}
2231 public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2234 * Default text alignment is inherited
2236 private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2239 * Default resolved text alignment
2242 static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2245 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2248 static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2251 * Mask for use with private flags indicating bits used for text alignment.
2254 static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2257 * Array of text direction flags for mapping attribute "textAlignment" to correct
2261 private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2262 TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2263 TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2264 TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2265 TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2266 TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2267 TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2268 TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2272 * Indicates whether the view text alignment has been resolved.
2275 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2278 * Bit shift to get the resolved text alignment.
2281 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2284 * Mask for use with private flags indicating bits used for text alignment.
2287 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2288 << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2291 * Indicates whether if the view text alignment has been resolved to gravity
2293 private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2294 TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2296 // Accessiblity constants for mPrivateFlags2
2299 * Shift for the bits in {@link #mPrivateFlags2} related to the
2300 * "importantForAccessibility" attribute.
2302 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2305 * Automatically determine whether a view is important for accessibility.
2307 public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2310 * The view is important for accessibility.
2312 public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2315 * The view is not important for accessibility.
2317 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2320 * The view is not important for accessibility, nor are any of its
2323 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2326 * The default whether the view is important for accessibility.
2328 static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2331 * Mask for obtainig the bits which specify how to determine
2332 * whether a view is important for accessibility.
2334 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2335 | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2336 | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2337 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2340 * Shift for the bits in {@link #mPrivateFlags2} related to the
2341 * "accessibilityLiveRegion" attribute.
2343 static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2346 * Live region mode specifying that accessibility services should not
2347 * automatically announce changes to this view. This is the default live
2348 * region mode for most views.
2350 * Use with {@link #setAccessibilityLiveRegion(int)}.
2352 public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2355 * Live region mode specifying that accessibility services should announce
2356 * changes to this view.
2358 * Use with {@link #setAccessibilityLiveRegion(int)}.
2360 public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2363 * Live region mode specifying that accessibility services should interrupt
2364 * ongoing speech to immediately announce changes to this view.
2366 * Use with {@link #setAccessibilityLiveRegion(int)}.
2368 public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2371 * The default whether the view is important for accessibility.
2373 static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2376 * Mask for obtaining the bits which specify a view's accessibility live
2379 static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2380 | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2381 << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2384 * Flag indicating whether a view has accessibility focus.
2386 static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2389 * Flag whether the accessibility state of the subtree rooted at this view changed.
2391 static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2394 * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2395 * is used to check whether later changes to the view's transform should invalidate the
2396 * view to force the quickReject test to run again.
2398 static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2401 * Flag indicating that start/end padding has been resolved into left/right padding
2402 * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2403 * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2404 * during measurement. In some special cases this is required such as when an adapter-based
2405 * view measures prospective children without attaching them to a window.
2407 static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2410 * Flag indicating that the start/end drawables has been resolved into left/right ones.
2412 static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2415 * Indicates that the view is tracking some sort of transient state
2416 * that the app should not need to be aware of, but that the framework
2417 * should take special care to preserve.
2419 static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2422 * Group of bits indicating that RTL properties resolution is done.
2424 static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2425 PFLAG2_TEXT_DIRECTION_RESOLVED |
2426 PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2427 PFLAG2_PADDING_RESOLVED |
2428 PFLAG2_DRAWABLE_RESOLVED;
2430 // There are a couple of flags left in mPrivateFlags2
2432 /* End of masks for mPrivateFlags2 */
2435 * Masks for mPrivateFlags3, as generated by dumpFlags():
2437 * |-------|-------|-------|-------|
2438 * 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2439 * 1 PFLAG3_VIEW_IS_ANIMATING_ALPHA
2440 * 1 PFLAG3_IS_LAID_OUT
2441 * 1 PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2442 * 1 PFLAG3_CALLED_SUPER
2443 * 1 PFLAG3_APPLYING_INSETS
2444 * 1 PFLAG3_FITTING_SYSTEM_WINDOWS
2445 * 1 PFLAG3_NESTED_SCROLLING_ENABLED
2446 * 1 PFLAG3_SCROLL_INDICATOR_TOP
2447 * 1 PFLAG3_SCROLL_INDICATOR_BOTTOM
2448 * 1 PFLAG3_SCROLL_INDICATOR_LEFT
2449 * 1 PFLAG3_SCROLL_INDICATOR_RIGHT
2450 * 1 PFLAG3_SCROLL_INDICATOR_START
2451 * 1 PFLAG3_SCROLL_INDICATOR_END
2452 * 1 PFLAG3_ASSIST_BLOCKED
2453 * 1 PFLAG3_POINTER_ICON_NULL
2454 * 1 PFLAG3_POINTER_ICON_VALUE_START
2455 * 11111111 PFLAG3_POINTER_ICON_MASK
2456 * 1 PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2457 * 1 PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2458 * 1 PFLAG3_TEMPORARY_DETACH
2459 * 1 PFLAG3_NO_REVEAL_ON_FOCUS
2460 * |-------|-------|-------|-------|
2464 * Flag indicating that view has a transform animation set on it. This is used to track whether
2465 * an animation is cleared between successive frames, in order to tell the associated
2466 * DisplayList to clear its animation matrix.
2468 static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2471 * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2472 * animation is cleared between successive frames, in order to tell the associated
2473 * DisplayList to restore its alpha value.
2475 static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2478 * Flag indicating that the view has been through at least one layout since it
2479 * was last attached to a window.
2481 static final int PFLAG3_IS_LAID_OUT = 0x4;
2484 * Flag indicating that a call to measure() was skipped and should be done
2485 * instead when layout() is invoked.
2487 static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2490 * Flag indicating that an overridden method correctly called down to
2491 * the superclass implementation as required by the API spec.
2493 static final int PFLAG3_CALLED_SUPER = 0x10;
2496 * Flag indicating that we're in the process of applying window insets.
2498 static final int PFLAG3_APPLYING_INSETS = 0x20;
2501 * Flag indicating that we're in the process of fitting system windows using the old method.
2503 static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2506 * Flag indicating that nested scrolling is enabled for this view.
2507 * The view will optionally cooperate with views up its parent chain to allow for
2508 * integrated nested scrolling along the same axis.
2510 static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2513 * Flag indicating that the bottom scroll indicator should be displayed
2514 * when this view can scroll up.
2516 static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2519 * Flag indicating that the bottom scroll indicator should be displayed
2520 * when this view can scroll down.
2522 static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2525 * Flag indicating that the left scroll indicator should be displayed
2526 * when this view can scroll left.
2528 static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2531 * Flag indicating that the right scroll indicator should be displayed
2532 * when this view can scroll right.
2534 static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2537 * Flag indicating that the start scroll indicator should be displayed
2538 * when this view can scroll in the start direction.
2540 static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2543 * Flag indicating that the end scroll indicator should be displayed
2544 * when this view can scroll in the end direction.
2546 static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2548 static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2550 static final int SCROLL_INDICATORS_NONE = 0x0000;
2553 * Mask for use with setFlags indicating bits used for indicating which
2554 * scroll indicators are enabled.
2556 static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2557 | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2558 | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2559 | PFLAG3_SCROLL_INDICATOR_END;
2562 * Left-shift required to translate between public scroll indicator flags
2563 * and internal PFLAGS3 flags. When used as a right-shift, translates
2564 * PFLAGS3 flags to public flags.
2566 static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2569 @Retention(RetentionPolicy.SOURCE)
2570 @IntDef(flag = true,
2572 SCROLL_INDICATOR_TOP,
2573 SCROLL_INDICATOR_BOTTOM,
2574 SCROLL_INDICATOR_LEFT,
2575 SCROLL_INDICATOR_RIGHT,
2576 SCROLL_INDICATOR_START,
2577 SCROLL_INDICATOR_END,
2579 public @interface ScrollIndicators {}
2582 * Scroll indicator direction for the top edge of the view.
2584 * @see #setScrollIndicators(int)
2585 * @see #setScrollIndicators(int, int)
2586 * @see #getScrollIndicators()
2588 public static final int SCROLL_INDICATOR_TOP =
2589 PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2592 * Scroll indicator direction for the bottom edge of the view.
2594 * @see #setScrollIndicators(int)
2595 * @see #setScrollIndicators(int, int)
2596 * @see #getScrollIndicators()
2598 public static final int SCROLL_INDICATOR_BOTTOM =
2599 PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2602 * Scroll indicator direction for the left edge of the view.
2604 * @see #setScrollIndicators(int)
2605 * @see #setScrollIndicators(int, int)
2606 * @see #getScrollIndicators()
2608 public static final int SCROLL_INDICATOR_LEFT =
2609 PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2612 * Scroll indicator direction for the right edge of the view.
2614 * @see #setScrollIndicators(int)
2615 * @see #setScrollIndicators(int, int)
2616 * @see #getScrollIndicators()
2618 public static final int SCROLL_INDICATOR_RIGHT =
2619 PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2622 * Scroll indicator direction for the starting edge of the view.
2624 * Resolved according to the view's layout direction, see
2625 * {@link #getLayoutDirection()} for more information.
2627 * @see #setScrollIndicators(int)
2628 * @see #setScrollIndicators(int, int)
2629 * @see #getScrollIndicators()
2631 public static final int SCROLL_INDICATOR_START =
2632 PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2635 * Scroll indicator direction for the ending edge of the view.
2637 * Resolved according to the view's layout direction, see
2638 * {@link #getLayoutDirection()} for more information.
2640 * @see #setScrollIndicators(int)
2641 * @see #setScrollIndicators(int, int)
2642 * @see #getScrollIndicators()
2644 public static final int SCROLL_INDICATOR_END =
2645 PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2648 * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2649 * into this view.<p>
2651 static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2654 * The mask for use with private flags indicating bits used for pointer icon shapes.
2656 static final int PFLAG3_POINTER_ICON_MASK = 0x7f8000;
2659 * Left-shift used for pointer icon shape values in private flags.
2661 static final int PFLAG3_POINTER_ICON_LSHIFT = 15;
2664 * Value indicating no specific pointer icons.
2666 private static final int PFLAG3_POINTER_ICON_NOT_SPECIFIED = 0 << PFLAG3_POINTER_ICON_LSHIFT;
2669 * Value indicating {@link PointerIcon.TYPE_NULL}.
2671 private static final int PFLAG3_POINTER_ICON_NULL = 1 << PFLAG3_POINTER_ICON_LSHIFT;
2674 * The base value for other pointer icon shapes.
2676 private static final int PFLAG3_POINTER_ICON_VALUE_START = 2 << PFLAG3_POINTER_ICON_LSHIFT;
2679 * Whether this view has rendered elements that overlap (see {@link
2680 * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
2681 * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
2682 * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
2683 * determined by whatever {@link #hasOverlappingRendering()} returns.
2685 private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
2688 * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
2689 * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
2691 private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
2694 * Flag indicating that the view is temporarily detached from the parent view.
2696 * @see #onStartTemporaryDetach()
2697 * @see #onFinishTemporaryDetach()
2699 static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
2702 * Flag indicating that the view does not wish to be revealed within its parent
2703 * hierarchy when it gains focus. Expressed in the negative since the historical
2704 * default behavior is to reveal on focus; this flag suppresses that behavior.
2706 * @see #setRevealOnFocusHint(boolean)
2707 * @see #getRevealOnFocusHint()
2709 private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
2711 /* End of masks for mPrivateFlags3 */
2714 * Always allow a user to over-scroll this view, provided it is a
2715 * view that can scroll.
2717 * @see #getOverScrollMode()
2718 * @see #setOverScrollMode(int)
2720 public static final int OVER_SCROLL_ALWAYS = 0;
2723 * Allow a user to over-scroll this view only if the content is large
2724 * enough to meaningfully scroll, provided it is a view that can scroll.
2726 * @see #getOverScrollMode()
2727 * @see #setOverScrollMode(int)
2729 public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2732 * Never allow a user to over-scroll this view.
2734 * @see #getOverScrollMode()
2735 * @see #setOverScrollMode(int)
2737 public static final int OVER_SCROLL_NEVER = 2;
2740 * Special constant for {@link #setSystemUiVisibility(int)}: View has
2741 * requested the system UI (status bar) to be visible (the default).
2743 * @see #setSystemUiVisibility(int)
2745 public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2748 * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2749 * system UI to enter an unobtrusive "low profile" mode.
2751 * <p>This is for use in games, book readers, video players, or any other
2752 * "immersive" application where the usual system chrome is deemed too distracting.
2754 * <p>In low profile mode, the status bar and/or navigation icons may dim.
2756 * @see #setSystemUiVisibility(int)
2758 public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2761 * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2762 * system navigation be temporarily hidden.
2764 * <p>This is an even less obtrusive state than that called for by
2765 * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2766 * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2767 * those to disappear. This is useful (in conjunction with the
2768 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2769 * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2770 * window flags) for displaying content using every last pixel on the display.
2772 * <p>There is a limitation: because navigation controls are so important, the least user
2773 * interaction will cause them to reappear immediately. When this happens, both
2774 * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2775 * so that both elements reappear at the same time.
2777 * @see #setSystemUiVisibility(int)
2779 public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2782 * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2783 * into the normal fullscreen mode so that its content can take over the screen
2784 * while still allowing the user to interact with the application.
2786 * <p>This has the same visual effect as
2787 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2788 * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2789 * meaning that non-critical screen decorations (such as the status bar) will be
2790 * hidden while the user is in the View's window, focusing the experience on
2791 * that content. Unlike the window flag, if you are using ActionBar in
2792 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2793 * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2794 * hide the action bar.
2796 * <p>This approach to going fullscreen is best used over the window flag when
2797 * it is a transient state -- that is, the application does this at certain
2798 * points in its user interaction where it wants to allow the user to focus
2799 * on content, but not as a continuous state. For situations where the application
2800 * would like to simply stay full screen the entire time (such as a game that
2801 * wants to take over the screen), the
2802 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2803 * is usually a better approach. The state set here will be removed by the system
2804 * in various situations (such as the user moving to another application) like
2805 * the other system UI states.
2807 * <p>When using this flag, the application should provide some easy facility
2808 * for the user to go out of it. A common example would be in an e-book
2809 * reader, where tapping on the screen brings back whatever screen and UI
2810 * decorations that had been hidden while the user was immersed in reading
2813 * @see #setSystemUiVisibility(int)
2815 public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2818 * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2819 * flags, we would like a stable view of the content insets given to
2820 * {@link #fitSystemWindows(Rect)}. This means that the insets seen there
2821 * will always represent the worst case that the application can expect
2822 * as a continuous state. In the stock Android UI this is the space for
2823 * the system bar, nav bar, and status bar, but not more transient elements
2824 * such as an input method.
2826 * The stable layout your UI sees is based on the system UI modes you can
2827 * switch to. That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2828 * then you will get a stable layout for changes of the
2829 * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2830 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2831 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2832 * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2833 * with a stable layout. (Note that you should avoid using
2834 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2836 * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2837 * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2838 * then a hidden status bar will be considered a "stable" state for purposes
2839 * here. This allows your UI to continually hide the status bar, while still
2840 * using the system UI flags to hide the action bar while still retaining
2841 * a stable layout. Note that changing the window fullscreen flag will never
2842 * provide a stable layout for a clean transition.
2844 * <p>If you are using ActionBar in
2845 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2846 * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2847 * insets it adds to those given to the application.
2849 public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2852 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2853 * to be laid out as if it has requested
2854 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't. This
2855 * allows it to avoid artifacts when switching in and out of that mode, at
2856 * the expense that some of its user interface may be covered by screen
2857 * decorations when they are shown. You can perform layout of your inner
2858 * UI elements to account for the navigation system UI through the
2859 * {@link #fitSystemWindows(Rect)} method.
2861 public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2864 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2865 * to be laid out as if it has requested
2866 * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't. This
2867 * allows it to avoid artifacts when switching in and out of that mode, at
2868 * the expense that some of its user interface may be covered by screen
2869 * decorations when they are shown. You can perform layout of your inner
2870 * UI elements to account for non-fullscreen system UI through the
2871 * {@link #fitSystemWindows(Rect)} method.
2873 public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2876 * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2877 * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. If this flag is
2878 * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2880 * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2881 * has an effect when used in combination with that flag.</p>
2883 public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2886 * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2887 * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2888 * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. Use this flag to create an immersive
2889 * experience while also hiding the system bars. If this flag is not set,
2890 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2891 * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2892 * if the user swipes from the top of the screen.
2893 * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2894 * system gestures, such as swiping from the top of the screen. These transient system bars
2895 * will overlay app’s content, may have some degree of transparency, and will automatically
2896 * hide after a short timeout.
2897 * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2898 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2899 * with one or both of those flags.</p>
2901 public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2904 * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2905 * is compatible with light status bar backgrounds.
2907 * <p>For this to take effect, the window must request
2908 * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2909 * FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2910 * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2911 * FLAG_TRANSLUCENT_STATUS}.
2913 * @see android.R.attr#windowLightStatusBar
2915 public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2918 * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2920 public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2923 * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2925 public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2930 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2931 * out of the public fields to keep the undefined bits out of the developer's way.
2933 * Flag to make the status bar not expandable. Unless you also
2934 * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2936 public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2941 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2942 * out of the public fields to keep the undefined bits out of the developer's way.
2944 * Flag to hide notification icons and scrolling ticker text.
2946 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2951 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2952 * out of the public fields to keep the undefined bits out of the developer's way.
2954 * Flag to disable incoming notification alerts. This will not block
2955 * icons, but it will block sound, vibrating and other visual or aural notifications.
2957 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2962 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2963 * out of the public fields to keep the undefined bits out of the developer's way.
2965 * Flag to hide only the scrolling ticker. Note that
2966 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2967 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2969 public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2974 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2975 * out of the public fields to keep the undefined bits out of the developer's way.
2977 * Flag to hide the center system info area.
2979 public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2984 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2985 * out of the public fields to keep the undefined bits out of the developer's way.
2987 * Flag to hide only the home button. Don't use this
2988 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2990 public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2995 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2996 * out of the public fields to keep the undefined bits out of the developer's way.
2998 * Flag to hide only the back button. Don't use this
2999 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3001 public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3006 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3007 * out of the public fields to keep the undefined bits out of the developer's way.
3009 * Flag to hide only the clock. You might use this if your activity has
3010 * its own clock making the status bar's clock redundant.
3012 public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3017 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3018 * out of the public fields to keep the undefined bits out of the developer's way.
3020 * Flag to hide only the recent apps button. Don't use this
3021 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3023 public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3028 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3029 * out of the public fields to keep the undefined bits out of the developer's way.
3031 * Flag to disable the global search gesture. Don't use this
3032 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3034 public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3039 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3040 * out of the public fields to keep the undefined bits out of the developer's way.
3042 * Flag to specify that the status bar is displayed in transient mode.
3044 public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3049 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3050 * out of the public fields to keep the undefined bits out of the developer's way.
3052 * Flag to specify that the navigation bar is displayed in transient mode.
3054 public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3059 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3060 * out of the public fields to keep the undefined bits out of the developer's way.
3062 * Flag to specify that the hidden status bar would like to be shown.
3064 public static final int STATUS_BAR_UNHIDE = 0x10000000;
3069 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3070 * out of the public fields to keep the undefined bits out of the developer's way.
3072 * Flag to specify that the hidden navigation bar would like to be shown.
3074 public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3079 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3080 * out of the public fields to keep the undefined bits out of the developer's way.
3082 * Flag to specify that the status bar is displayed in translucent mode.
3084 public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3089 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3090 * out of the public fields to keep the undefined bits out of the developer's way.
3092 * Flag to specify that the navigation bar is displayed in translucent mode.
3094 public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3099 * Makes navigation bar transparent (but not the status bar).
3101 public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3106 * Makes status bar transparent (but not the navigation bar).
3108 public static final int STATUS_BAR_TRANSPARENT = 0x0000008;
3113 * Makes both status bar and navigation bar transparent.
3115 public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3116 | STATUS_BAR_TRANSPARENT;
3121 public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3124 * These are the system UI flags that can be cleared by events outside
3125 * of an application. Currently this is just the ability to tap on the
3126 * screen while hiding the navigation bar to have it return.
3129 public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3130 SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3131 | SYSTEM_UI_FLAG_FULLSCREEN;
3134 * Flags that can impact the layout in relation to system UI.
3136 public static final int SYSTEM_UI_LAYOUT_FLAGS =
3137 SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3138 | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3141 @IntDef(flag = true,
3142 value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3143 @Retention(RetentionPolicy.SOURCE)
3144 public @interface FindViewFlags {}
3147 * Find views that render the specified text.
3149 * @see #findViewsWithText(ArrayList, CharSequence, int)
3151 public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3154 * Find find views that contain the specified content description.
3156 * @see #findViewsWithText(ArrayList, CharSequence, int)
3158 public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3161 * Find views that contain {@link AccessibilityNodeProvider}. Such
3162 * a View is a root of virtual view hierarchy and may contain the searched
3163 * text. If this flag is set Views with providers are automatically
3164 * added and it is a responsibility of the client to call the APIs of
3165 * the provider to determine whether the virtual tree rooted at this View
3166 * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3167 * representing the virtual views with this text.
3169 * @see #findViewsWithText(ArrayList, CharSequence, int)
3173 public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3176 * The undefined cursor position.
3180 public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3183 * Indicates that the screen has changed state and is now off.
3185 * @see #onScreenStateChanged(int)
3187 public static final int SCREEN_STATE_OFF = 0x0;
3190 * Indicates that the screen has changed state and is now on.
3192 * @see #onScreenStateChanged(int)
3194 public static final int SCREEN_STATE_ON = 0x1;
3197 * Indicates no axis of view scrolling.
3199 public static final int SCROLL_AXIS_NONE = 0;
3202 * Indicates scrolling along the horizontal axis.
3204 public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3207 * Indicates scrolling along the vertical axis.
3209 public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3212 * Controls the over-scroll mode for this view.
3213 * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3214 * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3215 * and {@link #OVER_SCROLL_NEVER}.
3217 private int mOverScrollMode;
3220 * The parent this view is attached to.
3225 protected ViewParent mParent;
3230 AttachInfo mAttachInfo;
3235 @ViewDebug.ExportedProperty(flagMapping = {
3236 @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3237 name = "FORCE_LAYOUT"),
3238 @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3239 name = "LAYOUT_REQUIRED"),
3240 @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3241 name = "DRAWING_CACHE_INVALID", outputIf = false),
3242 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3243 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3244 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3245 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3246 }, formatToHexString = true)
3252 * This view's request for the visibility of the status bar.
3255 @ViewDebug.ExportedProperty(flagMapping = {
3256 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3257 equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3258 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3259 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3260 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3261 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3262 @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3263 equals = SYSTEM_UI_FLAG_VISIBLE,
3264 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3265 }, formatToHexString = true)
3266 int mSystemUiVisibility;
3269 * Reference count for transient state.
3270 * @see #setHasTransientState(boolean)
3272 int mTransientStateCount = 0;
3275 * Count of how many windows this view has been attached to.
3277 int mWindowAttachCount;
3280 * The layout parameters associated with this view and used by the parent
3281 * {@link android.view.ViewGroup} to determine how this view should be
3285 protected ViewGroup.LayoutParams mLayoutParams;
3288 * The view flags hold various views states.
3291 @ViewDebug.ExportedProperty(formatToHexString = true)
3294 static class TransformationInfo {
3296 * The transform matrix for the View. This transform is calculated internally
3297 * based on the translation, rotation, and scale properties.
3299 * Do *not* use this variable directly; instead call getMatrix(), which will
3300 * load the value from the View's RenderNode.
3302 private final Matrix mMatrix = new Matrix();
3305 * The inverse transform matrix for the View. This transform is calculated
3306 * internally based on the translation, rotation, and scale properties.
3308 * Do *not* use this variable directly; instead call getInverseMatrix(),
3309 * which will load the value from the View's RenderNode.
3311 private Matrix mInverseMatrix;
3314 * The opacity of the View. This is a value from 0 to 1, where 0 means
3315 * completely transparent and 1 means completely opaque.
3317 @ViewDebug.ExportedProperty
3321 * The opacity of the view as manipulated by the Fade transition. This is a hidden
3322 * property only used by transitions, which is composited with the other alpha
3323 * values to calculate the final visual alpha value.
3325 float mTransitionAlpha = 1f;
3328 TransformationInfo mTransformationInfo;
3331 * Current clip bounds. to which all drawing of this view are constrained.
3333 Rect mClipBounds = null;
3335 private boolean mLastIsOpaque;
3338 * The distance in pixels from the left edge of this view's parent
3339 * to the left edge of this view.
3342 @ViewDebug.ExportedProperty(category = "layout")
3343 protected int mLeft;
3345 * The distance in pixels from the left edge of this view's parent
3346 * to the right edge of this view.
3349 @ViewDebug.ExportedProperty(category = "layout")
3350 protected int mRight;
3352 * The distance in pixels from the top edge of this view's parent
3353 * to the top edge of this view.
3356 @ViewDebug.ExportedProperty(category = "layout")
3359 * The distance in pixels from the top edge of this view's parent
3360 * to the bottom edge of this view.
3363 @ViewDebug.ExportedProperty(category = "layout")
3364 protected int mBottom;
3367 * The offset, in pixels, by which the content of this view is scrolled
3371 @ViewDebug.ExportedProperty(category = "scrolling")
3372 protected int mScrollX;
3374 * The offset, in pixels, by which the content of this view is scrolled
3378 @ViewDebug.ExportedProperty(category = "scrolling")
3379 protected int mScrollY;
3382 * The left padding in pixels, that is the distance in pixels between the
3383 * left edge of this view and the left edge of its content.
3386 @ViewDebug.ExportedProperty(category = "padding")
3387 protected int mPaddingLeft = 0;
3389 * The right padding in pixels, that is the distance in pixels between the
3390 * right edge of this view and the right edge of its content.
3393 @ViewDebug.ExportedProperty(category = "padding")
3394 protected int mPaddingRight = 0;
3396 * The top padding in pixels, that is the distance in pixels between the
3397 * top edge of this view and the top edge of its content.
3400 @ViewDebug.ExportedProperty(category = "padding")
3401 protected int mPaddingTop;
3403 * The bottom padding in pixels, that is the distance in pixels between the
3404 * bottom edge of this view and the bottom edge of its content.
3407 @ViewDebug.ExportedProperty(category = "padding")
3408 protected int mPaddingBottom;
3411 * The layout insets in pixels, that is the distance in pixels between the
3412 * visible edges of this view its bounds.
3414 private Insets mLayoutInsets;
3417 * Briefly describes the view and is primarily used for accessibility support.
3419 private CharSequence mContentDescription;
3422 * Specifies the id of a view for which this view serves as a label for
3423 * accessibility purposes.
3425 private int mLabelForId = View.NO_ID;
3428 * Predicate for matching labeled view id with its label for
3429 * accessibility purposes.
3431 private MatchLabelForPredicate mMatchLabelForPredicate;
3434 * Specifies a view before which this one is visited in accessibility traversal.
3436 private int mAccessibilityTraversalBeforeId = NO_ID;
3439 * Specifies a view after which this one is visited in accessibility traversal.
3441 private int mAccessibilityTraversalAfterId = NO_ID;
3444 * Predicate for matching a view by its id.
3446 private MatchIdPredicate mMatchIdPredicate;
3449 * Cache the paddingRight set by the user to append to the scrollbar's size.
3453 @ViewDebug.ExportedProperty(category = "padding")
3454 protected int mUserPaddingRight;
3457 * Cache the paddingBottom set by the user to append to the scrollbar's size.
3461 @ViewDebug.ExportedProperty(category = "padding")
3462 protected int mUserPaddingBottom;
3465 * Cache the paddingLeft set by the user to append to the scrollbar's size.
3469 @ViewDebug.ExportedProperty(category = "padding")
3470 protected int mUserPaddingLeft;
3473 * Cache the paddingStart set by the user to append to the scrollbar's size.
3476 @ViewDebug.ExportedProperty(category = "padding")
3477 int mUserPaddingStart;
3480 * Cache the paddingEnd set by the user to append to the scrollbar's size.
3483 @ViewDebug.ExportedProperty(category = "padding")
3484 int mUserPaddingEnd;
3487 * Cache initial left padding.
3491 int mUserPaddingLeftInitial;
3494 * Cache initial right padding.
3498 int mUserPaddingRightInitial;
3501 * Default undefined padding
3503 private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3506 * Cache if a left padding has been defined
3508 private boolean mLeftPaddingDefined = false;
3511 * Cache if a right padding has been defined
3513 private boolean mRightPaddingDefined = false;
3518 int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3522 int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3524 private LongSparseLongArray mMeasureCache;
3526 @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3527 private Drawable mBackground;
3528 private TintInfo mBackgroundTint;
3530 @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3531 private ForegroundInfo mForegroundInfo;
3533 private Drawable mScrollIndicatorDrawable;
3536 * RenderNode used for backgrounds.
3538 * When non-null and valid, this is expected to contain an up-to-date copy
3539 * of the background drawable. It is cleared on temporary detach, and reset
3542 private RenderNode mBackgroundRenderNode;
3544 private int mBackgroundResource;
3545 private boolean mBackgroundSizeChanged;
3547 private String mTransitionName;
3549 static class TintInfo {
3550 ColorStateList mTintList;
3551 PorterDuff.Mode mTintMode;
3552 boolean mHasTintMode;
3553 boolean mHasTintList;
3556 private static class ForegroundInfo {
3557 private Drawable mDrawable;
3558 private TintInfo mTintInfo;
3559 private int mGravity = Gravity.FILL;
3560 private boolean mInsidePadding = true;
3561 private boolean mBoundsChanged = true;
3562 private final Rect mSelfBounds = new Rect();
3563 private final Rect mOverlayBounds = new Rect();
3566 static class ListenerInfo {
3568 * Listener used to dispatch focus change events.
3569 * This field should be made private, so it is hidden from the SDK.
3572 protected OnFocusChangeListener mOnFocusChangeListener;
3575 * Listeners for layout change events.
3577 private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3579 protected OnScrollChangeListener mOnScrollChangeListener;
3582 * Listeners for attach events.
3584 private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3587 * Listener used to dispatch click events.
3588 * This field should be made private, so it is hidden from the SDK.
3591 public OnClickListener mOnClickListener;
3594 * Listener used to dispatch long click events.
3595 * This field should be made private, so it is hidden from the SDK.
3598 protected OnLongClickListener mOnLongClickListener;
3601 * Listener used to dispatch context click events. This field should be made private, so it
3602 * is hidden from the SDK.
3605 protected OnContextClickListener mOnContextClickListener;
3608 * Listener used to build the context menu.
3609 * This field should be made private, so it is hidden from the SDK.
3612 protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3614 private OnKeyListener mOnKeyListener;
3616 private OnTouchListener mOnTouchListener;
3618 private OnHoverListener mOnHoverListener;
3620 private OnGenericMotionListener mOnGenericMotionListener;
3622 private OnDragListener mOnDragListener;
3624 private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3626 OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3629 ListenerInfo mListenerInfo;
3631 // Temporary values used to hold (x,y) coordinates when delegating from the
3632 // two-arg performLongClick() method to the legacy no-arg version.
3633 private float mLongClickX = Float.NaN;
3634 private float mLongClickY = Float.NaN;
3637 * The application environment this view lives in.
3638 * This field should be made private, so it is hidden from the SDK.
3641 @ViewDebug.ExportedProperty(deepExport = true)
3642 protected Context mContext;
3644 private final Resources mResources;
3646 private ScrollabilityCache mScrollCache;
3648 private int[] mDrawableState = null;
3650 ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3653 * Animator that automatically runs based on state changes.
3655 private StateListAnimator mStateListAnimator;
3658 * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3659 * the user may specify which view to go to next.
3661 private int mNextFocusLeftId = View.NO_ID;
3664 * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3665 * the user may specify which view to go to next.
3667 private int mNextFocusRightId = View.NO_ID;
3670 * When this view has focus and the next focus is {@link #FOCUS_UP},
3671 * the user may specify which view to go to next.
3673 private int mNextFocusUpId = View.NO_ID;
3676 * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3677 * the user may specify which view to go to next.
3679 private int mNextFocusDownId = View.NO_ID;
3682 * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3683 * the user may specify which view to go to next.
3685 int mNextFocusForwardId = View.NO_ID;
3687 private CheckForLongPress mPendingCheckForLongPress;
3688 private CheckForTap mPendingCheckForTap = null;
3689 private PerformClick mPerformClick;
3690 private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3692 private UnsetPressedState mUnsetPressedState;
3695 * Whether the long press's action has been invoked. The tap's action is invoked on the
3696 * up event while a long press is invoked as soon as the long press duration is reached, so
3697 * a long press could be performed before the tap is checked, in which case the tap's action
3698 * should not be invoked.
3700 private boolean mHasPerformedLongPress;
3703 * Whether a context click button is currently pressed down. This is true when the stylus is
3704 * touching the screen and the primary button has been pressed, or if a mouse's right button is
3705 * pressed. This is false once the button is released or if the stylus has been lifted.
3707 private boolean mInContextButtonPress;
3710 * Whether the next up event should be ignored for the purposes of gesture recognition. This is
3711 * true after a stylus button press has occured, when the next up event should not be recognized
3714 private boolean mIgnoreNextUpEvent;
3717 * The minimum height of the view. We'll try our best to have the height
3718 * of this view to at least this amount.
3720 @ViewDebug.ExportedProperty(category = "measurement")
3721 private int mMinHeight;
3724 * The minimum width of the view. We'll try our best to have the width
3725 * of this view to at least this amount.
3727 @ViewDebug.ExportedProperty(category = "measurement")
3728 private int mMinWidth;
3731 * The delegate to handle touch events that are physically in this view
3732 * but should be handled by another view.
3734 private TouchDelegate mTouchDelegate = null;
3737 * Solid color to use as a background when creating the drawing cache. Enables
3738 * the cache to use 16 bit bitmaps instead of 32 bit.
3740 private int mDrawingCacheBackgroundColor = 0;
3743 * Special tree observer used when mAttachInfo is null.
3745 private ViewTreeObserver mFloatingTreeObserver;
3748 * Cache the touch slop from the context that created the view.
3750 private int mTouchSlop;
3753 * Object that handles automatic animation of view properties.
3755 private ViewPropertyAnimator mAnimator = null;
3758 * List of registered FrameMetricsObservers.
3760 private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
3763 * Flag indicating that a drag can cross window boundaries. When
3764 * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3765 * with this flag set, all visible applications with targetSdkVersion >=
3766 * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
3767 * in the drag operation and receive the dragged content.
3769 * <p>If this is the only flag set, then the drag recipient will only have access to text data
3770 * and intents contained in the {@link ClipData} object. Access to URIs contained in the
3771 * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
3773 public static final int DRAG_FLAG_GLOBAL = 1 << 8; // 256
3776 * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3777 * request read access to the content URI(s) contained in the {@link ClipData} object.
3778 * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
3780 public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
3783 * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3784 * request write access to the content URI(s) contained in the {@link ClipData} object.
3785 * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
3787 public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
3790 * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3791 * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
3792 * reboots until explicitly revoked with
3793 * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}.
3794 * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
3796 public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
3797 Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
3800 * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3801 * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
3802 * match against the original granted URI.
3803 * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
3805 public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
3806 Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
3809 * Flag indicating that the drag shadow will be opaque. When
3810 * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3811 * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
3813 public static final int DRAG_FLAG_OPAQUE = 1 << 9;
3816 * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3818 private float mVerticalScrollFactor;
3821 * Position of the vertical scroll bar.
3823 private int mVerticalScrollbarPosition;
3826 * Position the scroll bar at the default position as determined by the system.
3828 public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3831 * Position the scroll bar along the left edge.
3833 public static final int SCROLLBAR_POSITION_LEFT = 1;
3836 * Position the scroll bar along the right edge.
3838 public static final int SCROLLBAR_POSITION_RIGHT = 2;
3841 * Indicates that the view does not have a layer.
3843 * @see #getLayerType()
3844 * @see #setLayerType(int, android.graphics.Paint)
3845 * @see #LAYER_TYPE_SOFTWARE
3846 * @see #LAYER_TYPE_HARDWARE
3848 public static final int LAYER_TYPE_NONE = 0;
3851 * <p>Indicates that the view has a software layer. A software layer is backed
3852 * by a bitmap and causes the view to be rendered using Android's software
3853 * rendering pipeline, even if hardware acceleration is enabled.</p>
3855 * <p>Software layers have various usages:</p>
3856 * <p>When the application is not using hardware acceleration, a software layer
3857 * is useful to apply a specific color filter and/or blending mode and/or
3858 * translucency to a view and all its children.</p>
3859 * <p>When the application is using hardware acceleration, a software layer
3860 * is useful to render drawing primitives not supported by the hardware
3861 * accelerated pipeline. It can also be used to cache a complex view tree
3862 * into a texture and reduce the complexity of drawing operations. For instance,
3863 * when animating a complex view tree with a translation, a software layer can
3864 * be used to render the view tree only once.</p>
3865 * <p>Software layers should be avoided when the affected view tree updates
3866 * often. Every update will require to re-render the software layer, which can
3867 * potentially be slow (particularly when hardware acceleration is turned on
3868 * since the layer will have to be uploaded into a hardware texture after every
3871 * @see #getLayerType()
3872 * @see #setLayerType(int, android.graphics.Paint)
3873 * @see #LAYER_TYPE_NONE
3874 * @see #LAYER_TYPE_HARDWARE
3876 public static final int LAYER_TYPE_SOFTWARE = 1;
3879 * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3880 * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3881 * OpenGL hardware) and causes the view to be rendered using Android's hardware
3882 * rendering pipeline, but only if hardware acceleration is turned on for the
3883 * view hierarchy. When hardware acceleration is turned off, hardware layers
3884 * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3886 * <p>A hardware layer is useful to apply a specific color filter and/or
3887 * blending mode and/or translucency to a view and all its children.</p>
3888 * <p>A hardware layer can be used to cache a complex view tree into a
3889 * texture and reduce the complexity of drawing operations. For instance,
3890 * when animating a complex view tree with a translation, a hardware layer can
3891 * be used to render the view tree only once.</p>
3892 * <p>A hardware layer can also be used to increase the rendering quality when
3893 * rotation transformations are applied on a view. It can also be used to
3894 * prevent potential clipping issues when applying 3D transforms on a view.</p>
3896 * @see #getLayerType()
3897 * @see #setLayerType(int, android.graphics.Paint)
3898 * @see #LAYER_TYPE_NONE
3899 * @see #LAYER_TYPE_SOFTWARE
3901 public static final int LAYER_TYPE_HARDWARE = 2;
3903 @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3904 @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3905 @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3906 @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3908 int mLayerType = LAYER_TYPE_NONE;
3912 * Set to true when drawing cache is enabled and cannot be created.
3916 public boolean mCachingFailed;
3917 private Bitmap mDrawingCache;
3918 private Bitmap mUnscaledDrawingCache;
3921 * RenderNode holding View properties, potentially holding a DisplayList of View content.
3923 * When non-null and valid, this is expected to contain an up-to-date copy
3924 * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3927 final RenderNode mRenderNode;
3930 * Set to true when the view is sending hover accessibility events because it
3931 * is the innermost hovered view.
3933 private boolean mSendingHoverAccessibilityEvents;
3936 * Delegate for injecting accessibility functionality.
3938 AccessibilityDelegate mAccessibilityDelegate;
3941 * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3942 * and add/remove objects to/from the overlay directly through the Overlay methods.
3944 ViewOverlay mOverlay;
3947 * The currently active parent view for receiving delegated nested scrolling events.
3948 * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3949 * by {@link #stopNestedScroll()} at the same point where we clear
3950 * requestDisallowInterceptTouchEvent.
3952 private ViewParent mNestedScrollingParent;
3955 * Consistency verifier for debugging purposes.
3958 protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3959 InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3960 new InputEventConsistencyVerifier(this, 0) : null;
3962 private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3964 private int[] mTempNestedScrollConsumed;
3967 * An overlay is going to draw this View instead of being drawn as part of this
3968 * View's parent. mGhostView is the View in the Overlay that must be invalidated
3969 * when this view is invalidated.
3971 GhostView mGhostView;
3974 * Holds pairs of adjacent attribute data: attribute name followed by its value.
3977 @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3978 public String[] mAttributes;
3981 * Maps a Resource id to its name.
3983 private static SparseArray<String> mAttributeMap;
3986 * Queue of pending runnables. Used to postpone calls to post() until this
3987 * view is attached and has a handler.
3989 private HandlerActionQueue mRunQueue;
3992 * The pointer icon when the mouse hovers on this view. The default is null.
3994 private PointerIcon mPointerIcon;
3999 String mStartActivityRequestWho;
4002 private RoundScrollbarRenderer mRoundScrollbarRenderer;
4005 * Simple constructor to use when creating a view from code.
4007 * @param context The Context the view is running in, through which it can
4008 * access the current theme, resources, etc.
4010 public View(Context context) {
4012 mResources = context != null ? context.getResources() : null;
4013 mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
4014 // Set some flags defaults
4016 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4017 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4018 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4019 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4020 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4021 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4022 mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4023 setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4024 mUserPaddingStart = UNDEFINED_PADDING;
4025 mUserPaddingEnd = UNDEFINED_PADDING;
4026 mRenderNode = RenderNode.create(getClass().getName(), this);
4028 if (!sCompatibilityDone && context != null) {
4029 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4031 // Older apps may need this compatibility hack for measurement.
4032 sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
4034 // Older apps expect onMeasure() to always be called on a layout pass, regardless
4035 // of whether a layout was requested on that View.
4036 sIgnoreMeasureCache = targetSdkVersion < KITKAT;
4038 Canvas.sCompatibilityRestore = targetSdkVersion < M;
4040 // In M and newer, our widgets can pass a "hint" value in the size
4041 // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4042 // know what the expected parent size is going to be, so e.g. list items can size
4043 // themselves at 1/3 the size of their container. It breaks older apps though,
4044 // specifically apps that use some popular open source libraries.
4045 sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
4047 // Old versions of the platform would give different results from
4048 // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4049 // modes, so we always need to run an additional EXACTLY pass.
4050 sAlwaysRemeasureExactly = targetSdkVersion <= M;
4052 // Prior to N, layout params could change without requiring a
4053 // subsequent call to setLayoutParams() and they would usually
4054 // work. Partial layout breaks this assumption.
4055 sLayoutParamsAlwaysChanged = targetSdkVersion <= M;
4057 // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4058 // On N+, we throw, but that breaks compatibility with apps that use these methods.
4059 sTextureViewIgnoresDrawableSetters = targetSdkVersion <= M;
4061 // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4062 // in apps so we target check it to avoid breaking existing apps.
4063 sPreserveMarginParamsInLayoutParamConversion = targetSdkVersion >= N;
4065 sCascadedDragDrop = targetSdkVersion < N;
4067 sCompatibilityDone = true;
4072 * Constructor that is called when inflating a view from XML. This is called
4073 * when a view is being constructed from an XML file, supplying attributes
4074 * that were specified in the XML file. This version uses a default style of
4075 * 0, so the only attribute values applied are those in the Context's Theme
4076 * and the given AttributeSet.
4079 * The method onFinishInflate() will be called after all children have been
4082 * @param context The Context the view is running in, through which it can
4083 * access the current theme, resources, etc.
4084 * @param attrs The attributes of the XML tag that is inflating the view.
4085 * @see #View(Context, AttributeSet, int)
4087 public View(Context context, @Nullable AttributeSet attrs) {
4088 this(context, attrs, 0);
4092 * Perform inflation from XML and apply a class-specific base style from a
4093 * theme attribute. This constructor of View allows subclasses to use their
4094 * own base style when they are inflating. For example, a Button class's
4095 * constructor would call this version of the super class constructor and
4096 * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4097 * allows the theme's button style to modify all of the base view attributes
4098 * (in particular its background) as well as the Button class's attributes.
4100 * @param context The Context the view is running in, through which it can
4101 * access the current theme, resources, etc.
4102 * @param attrs The attributes of the XML tag that is inflating the view.
4103 * @param defStyleAttr An attribute in the current theme that contains a
4104 * reference to a style resource that supplies default values for
4105 * the view. Can be 0 to not look for defaults.
4106 * @see #View(Context, AttributeSet)
4108 public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4109 this(context, attrs, defStyleAttr, 0);
4113 * Perform inflation from XML and apply a class-specific base style from a
4114 * theme attribute or style resource. This constructor of View allows
4115 * subclasses to use their own base style when they are inflating.
4117 * When determining the final value of a particular attribute, there are
4118 * four inputs that come into play:
4120 * <li>Any attribute values in the given AttributeSet.
4121 * <li>The style resource specified in the AttributeSet (named "style").
4122 * <li>The default style specified by <var>defStyleAttr</var>.
4123 * <li>The default style specified by <var>defStyleRes</var>.
4124 * <li>The base values in this theme.
4127 * Each of these inputs is considered in-order, with the first listed taking
4128 * precedence over the following ones. In other words, if in the
4129 * AttributeSet you have supplied <code><Button * textColor="#ff000000"></code>
4130 * , then the button's text will <em>always</em> be black, regardless of
4131 * what is specified in any of the styles.
4133 * @param context The Context the view is running in, through which it can
4134 * access the current theme, resources, etc.
4135 * @param attrs The attributes of the XML tag that is inflating the view.
4136 * @param defStyleAttr An attribute in the current theme that contains a
4137 * reference to a style resource that supplies default values for
4138 * the view. Can be 0 to not look for defaults.
4139 * @param defStyleRes A resource identifier of a style resource that
4140 * supplies default values for the view, used only if
4141 * defStyleAttr is 0 or can not be found in the theme. Can be 0
4142 * to not look for defaults.
4143 * @see #View(Context, AttributeSet, int)
4145 public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4148 final TypedArray a = context.obtainStyledAttributes(
4149 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4151 if (mDebugViewAttributes) {
4152 saveAttributeData(attrs, a);
4155 Drawable background = null;
4157 int leftPadding = -1;
4158 int topPadding = -1;
4159 int rightPadding = -1;
4160 int bottomPadding = -1;
4161 int startPadding = UNDEFINED_PADDING;
4162 int endPadding = UNDEFINED_PADDING;
4166 int viewFlagValues = 0;
4167 int viewFlagMasks = 0;
4169 boolean setScrollContainer = false;
4177 float elevation = 0;
4179 float rotationX = 0;
4180 float rotationY = 0;
4183 boolean transformSet = false;
4185 int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4186 int overScrollMode = mOverScrollMode;
4187 boolean initializeScrollbars = false;
4188 boolean initializeScrollIndicators = false;
4190 boolean startPaddingDefined = false;
4191 boolean endPaddingDefined = false;
4192 boolean leftPaddingDefined = false;
4193 boolean rightPaddingDefined = false;
4195 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4197 final int N = a.getIndexCount();
4198 for (int i = 0; i < N; i++) {
4199 int attr = a.getIndex(i);
4201 case com.android.internal.R.styleable.View_background:
4202 background = a.getDrawable(attr);
4204 case com.android.internal.R.styleable.View_padding:
4205 padding = a.getDimensionPixelSize(attr, -1);
4206 mUserPaddingLeftInitial = padding;
4207 mUserPaddingRightInitial = padding;
4208 leftPaddingDefined = true;
4209 rightPaddingDefined = true;
4211 case com.android.internal.R.styleable.View_paddingLeft:
4212 leftPadding = a.getDimensionPixelSize(attr, -1);
4213 mUserPaddingLeftInitial = leftPadding;
4214 leftPaddingDefined = true;
4216 case com.android.internal.R.styleable.View_paddingTop:
4217 topPadding = a.getDimensionPixelSize(attr, -1);
4219 case com.android.internal.R.styleable.View_paddingRight:
4220 rightPadding = a.getDimensionPixelSize(attr, -1);
4221 mUserPaddingRightInitial = rightPadding;
4222 rightPaddingDefined = true;
4224 case com.android.internal.R.styleable.View_paddingBottom:
4225 bottomPadding = a.getDimensionPixelSize(attr, -1);
4227 case com.android.internal.R.styleable.View_paddingStart:
4228 startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4229 startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4231 case com.android.internal.R.styleable.View_paddingEnd:
4232 endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4233 endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4235 case com.android.internal.R.styleable.View_scrollX:
4236 x = a.getDimensionPixelOffset(attr, 0);
4238 case com.android.internal.R.styleable.View_scrollY:
4239 y = a.getDimensionPixelOffset(attr, 0);
4241 case com.android.internal.R.styleable.View_alpha:
4242 setAlpha(a.getFloat(attr, 1f));
4244 case com.android.internal.R.styleable.View_transformPivotX:
4245 setPivotX(a.getDimension(attr, 0));
4247 case com.android.internal.R.styleable.View_transformPivotY:
4248 setPivotY(a.getDimension(attr, 0));
4250 case com.android.internal.R.styleable.View_translationX:
4251 tx = a.getDimension(attr, 0);
4252 transformSet = true;
4254 case com.android.internal.R.styleable.View_translationY:
4255 ty = a.getDimension(attr, 0);
4256 transformSet = true;
4258 case com.android.internal.R.styleable.View_translationZ:
4259 tz = a.getDimension(attr, 0);
4260 transformSet = true;
4262 case com.android.internal.R.styleable.View_elevation:
4263 elevation = a.getDimension(attr, 0);
4264 transformSet = true;
4266 case com.android.internal.R.styleable.View_rotation:
4267 rotation = a.getFloat(attr, 0);
4268 transformSet = true;
4270 case com.android.internal.R.styleable.View_rotationX:
4271 rotationX = a.getFloat(attr, 0);
4272 transformSet = true;
4274 case com.android.internal.R.styleable.View_rotationY:
4275 rotationY = a.getFloat(attr, 0);
4276 transformSet = true;
4278 case com.android.internal.R.styleable.View_scaleX:
4279 sx = a.getFloat(attr, 1f);
4280 transformSet = true;
4282 case com.android.internal.R.styleable.View_scaleY:
4283 sy = a.getFloat(attr, 1f);
4284 transformSet = true;
4286 case com.android.internal.R.styleable.View_id:
4287 mID = a.getResourceId(attr, NO_ID);
4289 case com.android.internal.R.styleable.View_tag:
4290 mTag = a.getText(attr);
4292 case com.android.internal.R.styleable.View_fitsSystemWindows:
4293 if (a.getBoolean(attr, false)) {
4294 viewFlagValues |= FITS_SYSTEM_WINDOWS;
4295 viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4298 case com.android.internal.R.styleable.View_focusable:
4299 if (a.getBoolean(attr, false)) {
4300 viewFlagValues |= FOCUSABLE;
4301 viewFlagMasks |= FOCUSABLE_MASK;
4304 case com.android.internal.R.styleable.View_focusableInTouchMode:
4305 if (a.getBoolean(attr, false)) {
4306 viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4307 viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4310 case com.android.internal.R.styleable.View_clickable:
4311 if (a.getBoolean(attr, false)) {
4312 viewFlagValues |= CLICKABLE;
4313 viewFlagMasks |= CLICKABLE;
4316 case com.android.internal.R.styleable.View_longClickable:
4317 if (a.getBoolean(attr, false)) {
4318 viewFlagValues |= LONG_CLICKABLE;
4319 viewFlagMasks |= LONG_CLICKABLE;
4322 case com.android.internal.R.styleable.View_contextClickable:
4323 if (a.getBoolean(attr, false)) {
4324 viewFlagValues |= CONTEXT_CLICKABLE;
4325 viewFlagMasks |= CONTEXT_CLICKABLE;
4328 case com.android.internal.R.styleable.View_saveEnabled:
4329 if (!a.getBoolean(attr, true)) {
4330 viewFlagValues |= SAVE_DISABLED;
4331 viewFlagMasks |= SAVE_DISABLED_MASK;
4334 case com.android.internal.R.styleable.View_duplicateParentState:
4335 if (a.getBoolean(attr, false)) {
4336 viewFlagValues |= DUPLICATE_PARENT_STATE;
4337 viewFlagMasks |= DUPLICATE_PARENT_STATE;
4340 case com.android.internal.R.styleable.View_visibility:
4341 final int visibility = a.getInt(attr, 0);
4342 if (visibility != 0) {
4343 viewFlagValues |= VISIBILITY_FLAGS[visibility];
4344 viewFlagMasks |= VISIBILITY_MASK;
4347 case com.android.internal.R.styleable.View_layoutDirection:
4348 // Clear any layout direction flags (included resolved bits) already set
4350 ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4351 // Set the layout direction flags depending on the value of the attribute
4352 final int layoutDirection = a.getInt(attr, -1);
4353 final int value = (layoutDirection != -1) ?
4354 LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4355 mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4357 case com.android.internal.R.styleable.View_drawingCacheQuality:
4358 final int cacheQuality = a.getInt(attr, 0);
4359 if (cacheQuality != 0) {
4360 viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4361 viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4364 case com.android.internal.R.styleable.View_contentDescription:
4365 setContentDescription(a.getString(attr));
4367 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4368 setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4370 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4371 setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4373 case com.android.internal.R.styleable.View_labelFor:
4374 setLabelFor(a.getResourceId(attr, NO_ID));
4376 case com.android.internal.R.styleable.View_soundEffectsEnabled:
4377 if (!a.getBoolean(attr, true)) {
4378 viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4379 viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4382 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4383 if (!a.getBoolean(attr, true)) {
4384 viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4385 viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4388 case R.styleable.View_scrollbars:
4389 final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4390 if (scrollbars != SCROLLBARS_NONE) {
4391 viewFlagValues |= scrollbars;
4392 viewFlagMasks |= SCROLLBARS_MASK;
4393 initializeScrollbars = true;
4396 //noinspection deprecation
4397 case R.styleable.View_fadingEdge:
4398 if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
4399 // Ignore the attribute starting with ICS
4402 // With builds < ICS, fall through and apply fading edges
4403 case R.styleable.View_requiresFadingEdge:
4404 final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4405 if (fadingEdge != FADING_EDGE_NONE) {
4406 viewFlagValues |= fadingEdge;
4407 viewFlagMasks |= FADING_EDGE_MASK;
4408 initializeFadingEdgeInternal(a);
4411 case R.styleable.View_scrollbarStyle:
4412 scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4413 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4414 viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4415 viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4418 case R.styleable.View_isScrollContainer:
4419 setScrollContainer = true;
4420 if (a.getBoolean(attr, false)) {
4421 setScrollContainer(true);
4424 case com.android.internal.R.styleable.View_keepScreenOn:
4425 if (a.getBoolean(attr, false)) {
4426 viewFlagValues |= KEEP_SCREEN_ON;
4427 viewFlagMasks |= KEEP_SCREEN_ON;
4430 case R.styleable.View_filterTouchesWhenObscured:
4431 if (a.getBoolean(attr, false)) {
4432 viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4433 viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4436 case R.styleable.View_nextFocusLeft:
4437 mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4439 case R.styleable.View_nextFocusRight:
4440 mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4442 case R.styleable.View_nextFocusUp:
4443 mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4445 case R.styleable.View_nextFocusDown:
4446 mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4448 case R.styleable.View_nextFocusForward:
4449 mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4451 case R.styleable.View_minWidth:
4452 mMinWidth = a.getDimensionPixelSize(attr, 0);
4454 case R.styleable.View_minHeight:
4455 mMinHeight = a.getDimensionPixelSize(attr, 0);
4457 case R.styleable.View_onClick:
4458 if (context.isRestricted()) {
4459 throw new IllegalStateException("The android:onClick attribute cannot "
4460 + "be used within a restricted context");
4463 final String handlerName = a.getString(attr);
4464 if (handlerName != null) {
4465 setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4468 case R.styleable.View_overScrollMode:
4469 overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4471 case R.styleable.View_verticalScrollbarPosition:
4472 mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4474 case R.styleable.View_layerType:
4475 setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4477 case R.styleable.View_textDirection:
4478 // Clear any text direction flag already set
4479 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4480 // Set the text direction flags depending on the value of the attribute
4481 final int textDirection = a.getInt(attr, -1);
4482 if (textDirection != -1) {
4483 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4486 case R.styleable.View_textAlignment:
4487 // Clear any text alignment flag already set
4488 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4489 // Set the text alignment flag depending on the value of the attribute
4490 final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4491 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4493 case R.styleable.View_importantForAccessibility:
4494 setImportantForAccessibility(a.getInt(attr,
4495 IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4497 case R.styleable.View_accessibilityLiveRegion:
4498 setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4500 case R.styleable.View_transitionName:
4501 setTransitionName(a.getString(attr));
4503 case R.styleable.View_nestedScrollingEnabled:
4504 setNestedScrollingEnabled(a.getBoolean(attr, false));
4506 case R.styleable.View_stateListAnimator:
4507 setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4508 a.getResourceId(attr, 0)));
4510 case R.styleable.View_backgroundTint:
4511 // This will get applied later during setBackground().
4512 if (mBackgroundTint == null) {
4513 mBackgroundTint = new TintInfo();
4515 mBackgroundTint.mTintList = a.getColorStateList(
4516 R.styleable.View_backgroundTint);
4517 mBackgroundTint.mHasTintList = true;
4519 case R.styleable.View_backgroundTintMode:
4520 // This will get applied later during setBackground().
4521 if (mBackgroundTint == null) {
4522 mBackgroundTint = new TintInfo();
4524 mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4525 R.styleable.View_backgroundTintMode, -1), null);
4526 mBackgroundTint.mHasTintMode = true;
4528 case R.styleable.View_outlineProvider:
4529 setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4530 PROVIDER_BACKGROUND));
4532 case R.styleable.View_foreground:
4533 if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4534 setForeground(a.getDrawable(attr));
4537 case R.styleable.View_foregroundGravity:
4538 if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4539 setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4542 case R.styleable.View_foregroundTintMode:
4543 if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4544 setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4547 case R.styleable.View_foregroundTint:
4548 if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4549 setForegroundTintList(a.getColorStateList(attr));
4552 case R.styleable.View_foregroundInsidePadding:
4553 if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4554 if (mForegroundInfo == null) {
4555 mForegroundInfo = new ForegroundInfo();
4557 mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4558 mForegroundInfo.mInsidePadding);
4561 case R.styleable.View_scrollIndicators:
4562 final int scrollIndicators =
4563 (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4564 & SCROLL_INDICATORS_PFLAG3_MASK;
4565 if (scrollIndicators != 0) {
4566 mPrivateFlags3 |= scrollIndicators;
4567 initializeScrollIndicators = true;
4570 case R.styleable.View_pointerIcon:
4571 final int resourceId = a.getResourceId(attr, 0);
4572 if (resourceId != 0) {
4573 setPointerIcon(PointerIcon.load(
4574 context.getResources(), resourceId));
4576 final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
4577 if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
4578 setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
4582 case R.styleable.View_forceHasOverlappingRendering:
4583 if (a.peekValue(attr) != null) {
4584 forceHasOverlappingRendering(a.getBoolean(attr, true));
4591 setOverScrollMode(overScrollMode);
4593 // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4594 // the resolved layout direction). Those cached values will be used later during padding
4596 mUserPaddingStart = startPadding;
4597 mUserPaddingEnd = endPadding;
4599 if (background != null) {
4600 setBackground(background);
4603 // setBackground above will record that padding is currently provided by the background.
4604 // If we have padding specified via xml, record that here instead and use it.
4605 mLeftPaddingDefined = leftPaddingDefined;
4606 mRightPaddingDefined = rightPaddingDefined;
4609 leftPadding = padding;
4610 topPadding = padding;
4611 rightPadding = padding;
4612 bottomPadding = padding;
4613 mUserPaddingLeftInitial = padding;
4614 mUserPaddingRightInitial = padding;
4617 if (isRtlCompatibilityMode()) {
4618 // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4619 // left / right padding are used if defined (meaning here nothing to do). If they are not
4620 // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4621 // start / end and resolve them as left / right (layout direction is not taken into account).
4622 // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4623 // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4625 if (!mLeftPaddingDefined && startPaddingDefined) {
4626 leftPadding = startPadding;
4628 mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4629 if (!mRightPaddingDefined && endPaddingDefined) {
4630 rightPadding = endPadding;
4632 mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4634 // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4635 // values defined. Otherwise, left /right values are used.
4636 // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4637 // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4639 final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4641 if (mLeftPaddingDefined && !hasRelativePadding) {
4642 mUserPaddingLeftInitial = leftPadding;
4644 if (mRightPaddingDefined && !hasRelativePadding) {
4645 mUserPaddingRightInitial = rightPadding;
4650 mUserPaddingLeftInitial,
4651 topPadding >= 0 ? topPadding : mPaddingTop,
4652 mUserPaddingRightInitial,
4653 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4655 if (viewFlagMasks != 0) {
4656 setFlags(viewFlagValues, viewFlagMasks);
4659 if (initializeScrollbars) {
4660 initializeScrollbarsInternal(a);
4663 if (initializeScrollIndicators) {
4664 initializeScrollIndicatorsInternal();
4669 // Needs to be called after mViewFlags is set
4670 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4674 if (x != 0 || y != 0) {
4679 setTranslationX(tx);
4680 setTranslationY(ty);
4681 setTranslationZ(tz);
4682 setElevation(elevation);
4683 setRotation(rotation);
4684 setRotationX(rotationX);
4685 setRotationY(rotationY);
4690 if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4691 setScrollContainer(true);
4694 computeOpaqueFlags();
4698 * An implementation of OnClickListener that attempts to lazily load a
4699 * named click handling method from a parent or ancestor context.
4701 private static class DeclaredOnClickListener implements OnClickListener {
4702 private final View mHostView;
4703 private final String mMethodName;
4705 private Method mResolvedMethod;
4706 private Context mResolvedContext;
4708 public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4709 mHostView = hostView;
4710 mMethodName = methodName;
4714 public void onClick(@NonNull View v) {
4715 if (mResolvedMethod == null) {
4716 resolveMethod(mHostView.getContext(), mMethodName);
4720 mResolvedMethod.invoke(mResolvedContext, v);
4721 } catch (IllegalAccessException e) {
4722 throw new IllegalStateException(
4723 "Could not execute non-public method for android:onClick", e);
4724 } catch (InvocationTargetException e) {
4725 throw new IllegalStateException(
4726 "Could not execute method for android:onClick", e);
4731 private void resolveMethod(@Nullable Context context, @NonNull String name) {
4732 while (context != null) {
4734 if (!context.isRestricted()) {
4735 final Method method = context.getClass().getMethod(mMethodName, View.class);
4736 if (method != null) {
4737 mResolvedMethod = method;
4738 mResolvedContext = context;
4742 } catch (NoSuchMethodException e) {
4743 // Failed to find method, keep searching up the hierarchy.
4746 if (context instanceof ContextWrapper) {
4747 context = ((ContextWrapper) context).getBaseContext();
4749 // Can't search up the hierarchy, null out and fail.
4754 final int id = mHostView.getId();
4755 final String idText = id == NO_ID ? "" : " with id '"
4756 + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4757 throw new IllegalStateException("Could not find method " + mMethodName
4758 + "(View) in a parent or ancestor Context for android:onClick "
4759 + "attribute defined on view " + mHostView.getClass() + idText);
4764 * Non-public constructor for use in testing
4768 mRenderNode = RenderNode.create(getClass().getName(), this);
4771 private static SparseArray<String> getAttributeMap() {
4772 if (mAttributeMap == null) {
4773 mAttributeMap = new SparseArray<>();
4775 return mAttributeMap;
4778 private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4779 final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4780 final int indexCount = t.getIndexCount();
4781 final String[] attributes = new String[(attrsCount + indexCount) * 2];
4785 // Store raw XML attributes.
4786 for (int j = 0; j < attrsCount; ++j) {
4787 attributes[i] = attrs.getAttributeName(j);
4788 attributes[i + 1] = attrs.getAttributeValue(j);
4792 // Store resolved styleable attributes.
4793 final Resources res = t.getResources();
4794 final SparseArray<String> attributeMap = getAttributeMap();
4795 for (int j = 0; j < indexCount; ++j) {
4796 final int index = t.getIndex(j);
4797 if (!t.hasValueOrEmpty(index)) {
4798 // Value is undefined. Skip it.
4802 final int resourceId = t.getResourceId(index, 0);
4803 if (resourceId == 0) {
4804 // Value is not a reference. Skip it.
4808 String resourceName = attributeMap.get(resourceId);
4809 if (resourceName == null) {
4811 resourceName = res.getResourceName(resourceId);
4812 } catch (Resources.NotFoundException e) {
4813 resourceName = "0x" + Integer.toHexString(resourceId);
4815 attributeMap.put(resourceId, resourceName);
4818 attributes[i] = resourceName;
4819 attributes[i + 1] = t.getString(index);
4823 // Trim to fit contents.
4824 final String[] trimmed = new String[i];
4825 System.arraycopy(attributes, 0, trimmed, 0, i);
4826 mAttributes = trimmed;
4829 public String toString() {
4830 StringBuilder out = new StringBuilder(128);
4831 out.append(getClass().getName());
4833 out.append(Integer.toHexString(System.identityHashCode(this)));
4835 switch (mViewFlags&VISIBILITY_MASK) {
4836 case VISIBLE: out.append('V'); break;
4837 case INVISIBLE: out.append('I'); break;
4838 case GONE: out.append('G'); break;
4839 default: out.append('.'); break;
4841 out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4842 out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4843 out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4844 out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4845 out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4846 out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4847 out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4848 out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
4850 out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4851 out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4852 out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4853 if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4856 out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4858 out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4859 out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4860 out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4861 out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4869 out.append(mBottom);
4870 final int id = getId();
4873 out.append(Integer.toHexString(id));
4874 final Resources r = mResources;
4875 if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
4878 switch (id&0xff000000) {
4886 pkgname = r.getResourcePackageName(id);
4889 String typename = r.getResourceTypeName(id);
4890 String entryname = r.getResourceEntryName(id);
4892 out.append(pkgname);
4894 out.append(typename);
4896 out.append(entryname);
4897 } catch (Resources.NotFoundException e) {
4902 return out.toString();
4907 * Initializes the fading edges from a given set of styled attributes. This
4908 * method should be called by subclasses that need fading edges and when an
4909 * instance of these subclasses is created programmatically rather than
4910 * being inflated from XML. This method is automatically called when the XML
4914 * @param a the styled attributes set to initialize the fading edges from
4918 protected void initializeFadingEdge(TypedArray a) {
4919 // This method probably shouldn't have been included in the SDK to begin with.
4920 // It relies on 'a' having been initialized using an attribute filter array that is
4921 // not publicly available to the SDK. The old method has been renamed
4922 // to initializeFadingEdgeInternal and hidden for framework use only;
4923 // this one initializes using defaults to make it safe to call for apps.
4925 TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4927 initializeFadingEdgeInternal(arr);
4934 * Initializes the fading edges from a given set of styled attributes. This
4935 * method should be called by subclasses that need fading edges and when an
4936 * instance of these subclasses is created programmatically rather than
4937 * being inflated from XML. This method is automatically called when the XML
4941 * @param a the styled attributes set to initialize the fading edges from
4942 * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4944 protected void initializeFadingEdgeInternal(TypedArray a) {
4947 mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4948 R.styleable.View_fadingEdgeLength,
4949 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4953 * Returns the size of the vertical faded edges used to indicate that more
4954 * content in this view is visible.
4956 * @return The size in pixels of the vertical faded edge or 0 if vertical
4957 * faded edges are not enabled for this view.
4958 * @attr ref android.R.styleable#View_fadingEdgeLength
4960 public int getVerticalFadingEdgeLength() {
4961 if (isVerticalFadingEdgeEnabled()) {
4962 ScrollabilityCache cache = mScrollCache;
4963 if (cache != null) {
4964 return cache.fadingEdgeLength;
4971 * Set the size of the faded edge used to indicate that more content in this
4972 * view is available. Will not change whether the fading edge is enabled; use
4973 * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4974 * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4975 * for the vertical or horizontal fading edges.
4977 * @param length The size in pixels of the faded edge used to indicate that more
4978 * content in this view is visible.
4980 public void setFadingEdgeLength(int length) {
4982 mScrollCache.fadingEdgeLength = length;
4986 * Returns the size of the horizontal faded edges used to indicate that more
4987 * content in this view is visible.
4989 * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4990 * faded edges are not enabled for this view.
4991 * @attr ref android.R.styleable#View_fadingEdgeLength
4993 public int getHorizontalFadingEdgeLength() {
4994 if (isHorizontalFadingEdgeEnabled()) {
4995 ScrollabilityCache cache = mScrollCache;
4996 if (cache != null) {
4997 return cache.fadingEdgeLength;
5004 * Returns the width of the vertical scrollbar.
5006 * @return The width in pixels of the vertical scrollbar or 0 if there
5007 * is no vertical scrollbar.
5009 public int getVerticalScrollbarWidth() {
5010 ScrollabilityCache cache = mScrollCache;
5011 if (cache != null) {
5012 ScrollBarDrawable scrollBar = cache.scrollBar;
5013 if (scrollBar != null) {
5014 int size = scrollBar.getSize(true);
5016 size = cache.scrollBarSize;
5026 * Returns the height of the horizontal scrollbar.
5028 * @return The height in pixels of the horizontal scrollbar or 0 if
5029 * there is no horizontal scrollbar.
5031 protected int getHorizontalScrollbarHeight() {
5032 ScrollabilityCache cache = mScrollCache;
5033 if (cache != null) {
5034 ScrollBarDrawable scrollBar = cache.scrollBar;
5035 if (scrollBar != null) {
5036 int size = scrollBar.getSize(false);
5038 size = cache.scrollBarSize;
5049 * Initializes the scrollbars from a given set of styled attributes. This
5050 * method should be called by subclasses that need scrollbars and when an
5051 * instance of these subclasses is created programmatically rather than
5052 * being inflated from XML. This method is automatically called when the XML
5056 * @param a the styled attributes set to initialize the scrollbars from
5060 protected void initializeScrollbars(TypedArray a) {
5061 // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5062 // using the View filter array which is not available to the SDK. As such, internal
5063 // framework usage now uses initializeScrollbarsInternal and we grab a default
5064 // TypedArray with the right filter instead here.
5065 TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5067 initializeScrollbarsInternal(arr);
5069 // We ignored the method parameter. Recycle the one we actually did use.
5075 * Initializes the scrollbars from a given set of styled attributes. This
5076 * method should be called by subclasses that need scrollbars and when an
5077 * instance of these subclasses is created programmatically rather than
5078 * being inflated from XML. This method is automatically called when the XML
5082 * @param a the styled attributes set to initialize the scrollbars from
5085 protected void initializeScrollbarsInternal(TypedArray a) {
5088 final ScrollabilityCache scrollabilityCache = mScrollCache;
5090 if (scrollabilityCache.scrollBar == null) {
5091 scrollabilityCache.scrollBar = new ScrollBarDrawable();
5092 scrollabilityCache.scrollBar.setState(getDrawableState());
5093 scrollabilityCache.scrollBar.setCallback(this);
5096 final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5098 if (!fadeScrollbars) {
5099 scrollabilityCache.state = ScrollabilityCache.ON;
5101 scrollabilityCache.fadeScrollBars = fadeScrollbars;
5104 scrollabilityCache.scrollBarFadeDuration = a.getInt(
5105 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5106 .getScrollBarFadeDuration());
5107 scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5108 R.styleable.View_scrollbarDefaultDelayBeforeFade,
5109 ViewConfiguration.getScrollDefaultDelay());
5112 scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5113 com.android.internal.R.styleable.View_scrollbarSize,
5114 ViewConfiguration.get(mContext).getScaledScrollBarSize());
5116 Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5117 scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5119 Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5120 if (thumb != null) {
5121 scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5124 boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5127 scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5130 track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5131 scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5133 thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5134 if (thumb != null) {
5135 scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5138 alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5141 scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5144 // Apply layout direction to the new Drawables if needed
5145 final int layoutDirection = getLayoutDirection();
5146 if (track != null) {
5147 track.setLayoutDirection(layoutDirection);
5149 if (thumb != null) {
5150 thumb.setLayoutDirection(layoutDirection);
5153 // Re-apply user/background padding so that scrollbar(s) get added
5157 private void initializeScrollIndicatorsInternal() {
5158 // Some day maybe we'll break this into top/left/start/etc. and let the
5159 // client control it. Until then, you can have any scroll indicator you
5160 // want as long as it's a 1dp foreground-colored rectangle.
5161 if (mScrollIndicatorDrawable == null) {
5162 mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5168 * Initalizes the scrollability cache if necessary.
5171 private void initScrollCache() {
5172 if (mScrollCache == null) {
5173 mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5177 private ScrollabilityCache getScrollCache() {
5179 return mScrollCache;
5183 * Set the position of the vertical scroll bar. Should be one of
5184 * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5185 * {@link #SCROLLBAR_POSITION_RIGHT}.
5187 * @param position Where the vertical scroll bar should be positioned.
5189 public void setVerticalScrollbarPosition(int position) {
5190 if (mVerticalScrollbarPosition != position) {
5191 mVerticalScrollbarPosition = position;
5192 computeOpaqueFlags();
5198 * @return The position where the vertical scroll bar will show, if applicable.
5199 * @see #setVerticalScrollbarPosition(int)
5201 public int getVerticalScrollbarPosition() {
5202 return mVerticalScrollbarPosition;
5205 boolean isOnScrollbar(float x, float y) {
5206 if (mScrollCache == null) {
5211 if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5212 final Rect bounds = mScrollCache.mScrollBarBounds;
5213 getVerticalScrollBarBounds(bounds);
5214 if (bounds.contains((int)x, (int)y)) {
5218 if (isHorizontalScrollBarEnabled()) {
5219 final Rect bounds = mScrollCache.mScrollBarBounds;
5220 getHorizontalScrollBarBounds(bounds);
5221 if (bounds.contains((int)x, (int)y)) {
5228 boolean isOnScrollbarThumb(float x, float y) {
5229 return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5232 private boolean isOnVerticalScrollbarThumb(float x, float y) {
5233 if (mScrollCache == null) {
5236 if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5239 final Rect bounds = mScrollCache.mScrollBarBounds;
5240 getVerticalScrollBarBounds(bounds);
5241 final int range = computeVerticalScrollRange();
5242 final int offset = computeVerticalScrollOffset();
5243 final int extent = computeVerticalScrollExtent();
5244 final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5246 final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5247 extent, range, offset);
5248 final int thumbTop = bounds.top + thumbOffset;
5249 if (x >= bounds.left && x <= bounds.right && y >= thumbTop
5250 && y <= thumbTop + thumbLength) {
5257 private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5258 if (mScrollCache == null) {
5261 if (isHorizontalScrollBarEnabled()) {
5264 final Rect bounds = mScrollCache.mScrollBarBounds;
5265 getHorizontalScrollBarBounds(bounds);
5266 final int range = computeHorizontalScrollRange();
5267 final int offset = computeHorizontalScrollOffset();
5268 final int extent = computeHorizontalScrollExtent();
5269 final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5271 final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5272 extent, range, offset);
5273 final int thumbLeft = bounds.left + thumbOffset;
5274 if (x >= thumbLeft && x <= thumbLeft + thumbLength && y >= bounds.top
5275 && y <= bounds.bottom) {
5282 boolean isDraggingScrollBar() {
5283 return mScrollCache != null
5284 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5288 * Sets the state of all scroll indicators.
5290 * See {@link #setScrollIndicators(int, int)} for usage information.
5292 * @param indicators a bitmask of indicators that should be enabled, or
5293 * {@code 0} to disable all indicators
5294 * @see #setScrollIndicators(int, int)
5295 * @see #getScrollIndicators()
5296 * @attr ref android.R.styleable#View_scrollIndicators
5298 public void setScrollIndicators(@ScrollIndicators int indicators) {
5299 setScrollIndicators(indicators,
5300 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5304 * Sets the state of the scroll indicators specified by the mask. To change
5305 * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5307 * When a scroll indicator is enabled, it will be displayed if the view
5308 * can scroll in the direction of the indicator.
5310 * Multiple indicator types may be enabled or disabled by passing the
5311 * logical OR of the desired types. If multiple types are specified, they
5312 * will all be set to the same enabled state.
5314 * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5316 * @param indicators the indicator direction, or the logical OR of multiple
5317 * indicator directions. One or more of:
5319 * <li>{@link #SCROLL_INDICATOR_TOP}</li>
5320 * <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5321 * <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5322 * <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5323 * <li>{@link #SCROLL_INDICATOR_START}</li>
5324 * <li>{@link #SCROLL_INDICATOR_END}</li>
5326 * @see #setScrollIndicators(int)
5327 * @see #getScrollIndicators()
5328 * @attr ref android.R.styleable#View_scrollIndicators
5330 public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5331 // Shift and sanitize mask.
5332 mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5333 mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5335 // Shift and mask indicators.
5336 indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5339 // Merge with non-masked flags.
5340 final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5342 if (mPrivateFlags3 != updatedFlags) {
5343 mPrivateFlags3 = updatedFlags;
5345 if (indicators != 0) {
5346 initializeScrollIndicatorsInternal();
5353 * Returns a bitmask representing the enabled scroll indicators.
5355 * For example, if the top and left scroll indicators are enabled and all
5356 * other indicators are disabled, the return value will be
5357 * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5359 * To check whether the bottom scroll indicator is enabled, use the value
5360 * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5362 * @return a bitmask representing the enabled scroll indicators
5365 public int getScrollIndicators() {
5366 return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5367 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5370 ListenerInfo getListenerInfo() {
5371 if (mListenerInfo != null) {
5372 return mListenerInfo;
5374 mListenerInfo = new ListenerInfo();
5375 return mListenerInfo;
5379 * Register a callback to be invoked when the scroll X or Y positions of
5382 * <b>Note:</b> Some views handle scrolling independently from View and may
5383 * have their own separate listeners for scroll-type events. For example,
5384 * {@link android.widget.ListView ListView} allows clients to register an
5385 * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5386 * to listen for changes in list scroll position.
5388 * @param l The listener to notify when the scroll X or Y position changes.
5389 * @see android.view.View#getScrollX()
5390 * @see android.view.View#getScrollY()
5392 public void setOnScrollChangeListener(OnScrollChangeListener l) {
5393 getListenerInfo().mOnScrollChangeListener = l;
5397 * Register a callback to be invoked when focus of this view changed.
5399 * @param l The callback that will run.
5401 public void setOnFocusChangeListener(OnFocusChangeListener l) {
5402 getListenerInfo().mOnFocusChangeListener = l;
5406 * Add a listener that will be called when the bounds of the view change due to
5407 * layout processing.
5409 * @param listener The listener that will be called when layout bounds change.
5411 public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5412 ListenerInfo li = getListenerInfo();
5413 if (li.mOnLayoutChangeListeners == null) {
5414 li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5416 if (!li.mOnLayoutChangeListeners.contains(listener)) {
5417 li.mOnLayoutChangeListeners.add(listener);
5422 * Remove a listener for layout changes.
5424 * @param listener The listener for layout bounds change.
5426 public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5427 ListenerInfo li = mListenerInfo;
5428 if (li == null || li.mOnLayoutChangeListeners == null) {
5431 li.mOnLayoutChangeListeners.remove(listener);
5435 * Add a listener for attach state changes.
5437 * This listener will be called whenever this view is attached or detached
5438 * from a window. Remove the listener using
5439 * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5441 * @param listener Listener to attach
5442 * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5444 public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5445 ListenerInfo li = getListenerInfo();
5446 if (li.mOnAttachStateChangeListeners == null) {
5447 li.mOnAttachStateChangeListeners
5448 = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5450 li.mOnAttachStateChangeListeners.add(listener);
5454 * Remove a listener for attach state changes. The listener will receive no further
5455 * notification of window attach/detach events.
5457 * @param listener Listener to remove
5458 * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5460 public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5461 ListenerInfo li = mListenerInfo;
5462 if (li == null || li.mOnAttachStateChangeListeners == null) {
5465 li.mOnAttachStateChangeListeners.remove(listener);
5469 * Returns the focus-change callback registered for this view.
5471 * @return The callback, or null if one is not registered.
5473 public OnFocusChangeListener getOnFocusChangeListener() {
5474 ListenerInfo li = mListenerInfo;
5475 return li != null ? li.mOnFocusChangeListener : null;
5479 * Register a callback to be invoked when this view is clicked. If this view is not
5480 * clickable, it becomes clickable.
5482 * @param l The callback that will run
5484 * @see #setClickable(boolean)
5486 public void setOnClickListener(@Nullable OnClickListener l) {
5487 if (!isClickable()) {
5490 getListenerInfo().mOnClickListener = l;
5494 * Return whether this view has an attached OnClickListener. Returns
5495 * true if there is a listener, false if there is none.
5497 public boolean hasOnClickListeners() {
5498 ListenerInfo li = mListenerInfo;
5499 return (li != null && li.mOnClickListener != null);
5503 * Register a callback to be invoked when this view is clicked and held. If this view is not
5504 * long clickable, it becomes long clickable.
5506 * @param l The callback that will run
5508 * @see #setLongClickable(boolean)
5510 public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5511 if (!isLongClickable()) {
5512 setLongClickable(true);
5514 getListenerInfo().mOnLongClickListener = l;
5518 * Register a callback to be invoked when this view is context clicked. If the view is not
5519 * context clickable, it becomes context clickable.
5521 * @param l The callback that will run
5522 * @see #setContextClickable(boolean)
5524 public void setOnContextClickListener(@Nullable OnContextClickListener l) {
5525 if (!isContextClickable()) {
5526 setContextClickable(true);
5528 getListenerInfo().mOnContextClickListener = l;
5532 * Register a callback to be invoked when the context menu for this view is
5533 * being built. If this view is not long clickable, it becomes long clickable.
5535 * @param l The callback that will run
5538 public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5539 if (!isLongClickable()) {
5540 setLongClickable(true);
5542 getListenerInfo().mOnCreateContextMenuListener = l;
5546 * Set an observer to collect stats for each frame rendered for this view.
5550 public void addFrameMetricsListener(Window window,
5551 Window.OnFrameMetricsAvailableListener listener,
5553 if (mAttachInfo != null) {
5554 if (mAttachInfo.mHardwareRenderer != null) {
5555 if (mFrameMetricsObservers == null) {
5556 mFrameMetricsObservers = new ArrayList<>();
5559 FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5560 handler.getLooper(), listener);
5561 mFrameMetricsObservers.add(fmo);
5562 mAttachInfo.mHardwareRenderer.addFrameMetricsObserver(fmo);
5564 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5567 if (mFrameMetricsObservers == null) {
5568 mFrameMetricsObservers = new ArrayList<>();
5571 FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5572 handler.getLooper(), listener);
5573 mFrameMetricsObservers.add(fmo);
5578 * Remove observer configured to collect frame stats for this view.
5582 public void removeFrameMetricsListener(
5583 Window.OnFrameMetricsAvailableListener listener) {
5584 ThreadedRenderer renderer = getHardwareRenderer();
5585 FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
5587 throw new IllegalArgumentException(
5588 "attempt to remove OnFrameMetricsAvailableListener that was never added");
5591 if (mFrameMetricsObservers != null) {
5592 mFrameMetricsObservers.remove(fmo);
5593 if (renderer != null) {
5594 renderer.removeFrameMetricsObserver(fmo);
5599 private void registerPendingFrameMetricsObservers() {
5600 if (mFrameMetricsObservers != null) {
5601 ThreadedRenderer renderer = getHardwareRenderer();
5602 if (renderer != null) {
5603 for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
5604 renderer.addFrameMetricsObserver(fmo);
5607 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5612 private FrameMetricsObserver findFrameMetricsObserver(
5613 Window.OnFrameMetricsAvailableListener listener) {
5614 for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
5615 FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
5616 if (observer.mListener == listener) {
5625 * Call this view's OnClickListener, if it is defined. Performs all normal
5626 * actions associated with clicking: reporting accessibility event, playing
5629 * @return True there was an assigned OnClickListener that was called, false
5630 * otherwise is returned.
5632 public boolean performClick() {
5633 final boolean result;
5634 final ListenerInfo li = mListenerInfo;
5635 if (li != null && li.mOnClickListener != null) {
5636 playSoundEffect(SoundEffectConstants.CLICK);
5637 li.mOnClickListener.onClick(this);
5643 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5648 * Directly call any attached OnClickListener. Unlike {@link #performClick()},
5649 * this only calls the listener, and does not do any associated clicking
5650 * actions like reporting an accessibility event.
5652 * @return True there was an assigned OnClickListener that was called, false
5653 * otherwise is returned.
5655 public boolean callOnClick() {
5656 ListenerInfo li = mListenerInfo;
5657 if (li != null && li.mOnClickListener != null) {
5658 li.mOnClickListener.onClick(this);
5665 * Calls this view's OnLongClickListener, if it is defined. Invokes the
5666 * context menu if the OnLongClickListener did not consume the event.
5668 * @return {@code true} if one of the above receivers consumed the event,
5669 * {@code false} otherwise
5671 public boolean performLongClick() {
5672 return performLongClickInternal(mLongClickX, mLongClickY);
5676 * Calls this view's OnLongClickListener, if it is defined. Invokes the
5677 * context menu if the OnLongClickListener did not consume the event,
5678 * anchoring it to an (x,y) coordinate.
5680 * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5681 * to disable anchoring
5682 * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5683 * to disable anchoring
5684 * @return {@code true} if one of the above receivers consumed the event,
5685 * {@code false} otherwise
5687 public boolean performLongClick(float x, float y) {
5690 final boolean handled = performLongClick();
5691 mLongClickX = Float.NaN;
5692 mLongClickY = Float.NaN;
5697 * Calls this view's OnLongClickListener, if it is defined. Invokes the
5698 * context menu if the OnLongClickListener did not consume the event,
5699 * optionally anchoring it to an (x,y) coordinate.
5701 * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5702 * to disable anchoring
5703 * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5704 * to disable anchoring
5705 * @return {@code true} if one of the above receivers consumed the event,
5706 * {@code false} otherwise
5708 private boolean performLongClickInternal(float x, float y) {
5709 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5711 boolean handled = false;
5712 final ListenerInfo li = mListenerInfo;
5713 if (li != null && li.mOnLongClickListener != null) {
5714 handled = li.mOnLongClickListener.onLongClick(View.this);
5717 final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
5718 handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
5721 performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5727 * Call this view's OnContextClickListener, if it is defined.
5729 * @param x the x coordinate of the context click
5730 * @param y the y coordinate of the context click
5731 * @return True if there was an assigned OnContextClickListener that consumed the event, false
5734 public boolean performContextClick(float x, float y) {
5735 return performContextClick();
5739 * Call this view's OnContextClickListener, if it is defined.
5741 * @return True if there was an assigned OnContextClickListener that consumed the event, false
5744 public boolean performContextClick() {
5745 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
5747 boolean handled = false;
5748 ListenerInfo li = mListenerInfo;
5749 if (li != null && li.mOnContextClickListener != null) {
5750 handled = li.mOnContextClickListener.onContextClick(View.this);
5753 performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
5759 * Performs button-related actions during a touch down event.
5761 * @param event The event.
5762 * @return True if the down was consumed.
5766 protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5767 if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
5768 (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5769 showContextMenu(event.getX(), event.getY());
5770 mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5777 * Shows the context menu for this view.
5779 * @return {@code true} if the context menu was shown, {@code false}
5781 * @see #showContextMenu(float, float)
5783 public boolean showContextMenu() {
5784 return getParent().showContextMenuForChild(this);
5788 * Shows the context menu for this view anchored to the specified
5789 * view-relative coordinate.
5791 * @param x the X coordinate in pixels relative to the view to which the
5792 * menu should be anchored, or {@link Float#NaN} to disable anchoring
5793 * @param y the Y coordinate in pixels relative to the view to which the
5794 * menu should be anchored, or {@link Float#NaN} to disable anchoring
5795 * @return {@code true} if the context menu was shown, {@code false}
5798 public boolean showContextMenu(float x, float y) {
5799 return getParent().showContextMenuForChild(this, x, y);
5803 * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
5805 * @param callback Callback that will control the lifecycle of the action mode
5806 * @return The new action mode if it is started, null otherwise
5809 * @see #startActionMode(android.view.ActionMode.Callback, int)
5811 public ActionMode startActionMode(ActionMode.Callback callback) {
5812 return startActionMode(callback, ActionMode.TYPE_PRIMARY);
5816 * Start an action mode with the given type.
5818 * @param callback Callback that will control the lifecycle of the action mode
5819 * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
5820 * @return The new action mode if it is started, null otherwise
5824 public ActionMode startActionMode(ActionMode.Callback callback, int type) {
5825 ViewParent parent = getParent();
5826 if (parent == null) return null;
5828 return parent.startActionModeForChild(this, callback, type);
5829 } catch (AbstractMethodError ame) {
5830 // Older implementations of custom views might not implement this.
5831 return parent.startActionModeForChild(this, callback);
5836 * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
5837 * Context, creating a unique View identifier to retrieve the result.
5839 * @param intent The Intent to be started.
5840 * @param requestCode The request code to use.
5843 public void startActivityForResult(Intent intent, int requestCode) {
5844 mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
5845 getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
5849 * If this View corresponds to the calling who, dispatches the activity result.
5850 * @param who The identifier for the targeted View to receive the result.
5851 * @param requestCode The integer request code originally supplied to
5852 * startActivityForResult(), allowing you to identify who this
5854 * @param resultCode The integer result code returned by the child activity
5855 * through its setResult().
5856 * @param data An Intent, which can return result data to the caller
5857 * (various data can be attached to Intent "extras").
5858 * @return {@code true} if the activity result was dispatched.
5861 public boolean dispatchActivityResult(
5862 String who, int requestCode, int resultCode, Intent data) {
5863 if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
5864 onActivityResult(requestCode, resultCode, data);
5865 mStartActivityRequestWho = null;
5872 * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
5874 * @param requestCode The integer request code originally supplied to
5875 * startActivityForResult(), allowing you to identify who this
5877 * @param resultCode The integer result code returned by the child activity
5878 * through its setResult().
5879 * @param data An Intent, which can return result data to the caller
5880 * (various data can be attached to Intent "extras").
5883 public void onActivityResult(int requestCode, int resultCode, Intent data) {
5888 * Register a callback to be invoked when a hardware key is pressed in this view.
5889 * Key presses in software input methods will generally not trigger the methods of
5891 * @param l the key listener to attach to this view
5893 public void setOnKeyListener(OnKeyListener l) {
5894 getListenerInfo().mOnKeyListener = l;
5898 * Register a callback to be invoked when a touch event is sent to this view.
5899 * @param l the touch listener to attach to this view
5901 public void setOnTouchListener(OnTouchListener l) {
5902 getListenerInfo().mOnTouchListener = l;
5906 * Register a callback to be invoked when a generic motion event is sent to this view.
5907 * @param l the generic motion listener to attach to this view
5909 public void setOnGenericMotionListener(OnGenericMotionListener l) {
5910 getListenerInfo().mOnGenericMotionListener = l;
5914 * Register a callback to be invoked when a hover event is sent to this view.
5915 * @param l the hover listener to attach to this view
5917 public void setOnHoverListener(OnHoverListener l) {
5918 getListenerInfo().mOnHoverListener = l;
5922 * Register a drag event listener callback object for this View. The parameter is
5923 * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
5924 * View, the system calls the
5925 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
5926 * @param l An implementation of {@link android.view.View.OnDragListener}.
5928 public void setOnDragListener(OnDragListener l) {
5929 getListenerInfo().mOnDragListener = l;
5933 * Give this view focus. This will cause
5934 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
5936 * Note: this does not check whether this {@link View} should get focus, it just
5937 * gives it focus no matter what. It should only be called internally by framework
5938 * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
5940 * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
5941 * {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
5942 * focus moved when requestFocus() is called. It may not always
5943 * apply, in which case use the default View.FOCUS_DOWN.
5944 * @param previouslyFocusedRect The rectangle of the view that had focus
5945 * prior in this View's coordinate system.
5947 void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
5949 System.out.println(this + " requestFocus()");
5952 if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
5953 mPrivateFlags |= PFLAG_FOCUSED;
5955 View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
5957 if (mParent != null) {
5958 mParent.requestChildFocus(this, this);
5961 if (mAttachInfo != null) {
5962 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
5965 onFocusChanged(true, direction, previouslyFocusedRect);
5966 refreshDrawableState();
5971 * Sets this view's preference for reveal behavior when it gains focus.
5973 * <p>When set to true, this is a signal to ancestor views in the hierarchy that
5974 * this view would prefer to be brought fully into view when it gains focus.
5975 * For example, a text field that a user is meant to type into. Other views such
5976 * as scrolling containers may prefer to opt-out of this behavior.</p>
5978 * <p>The default value for views is true, though subclasses may change this
5979 * based on their preferred behavior.</p>
5981 * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
5983 * @see #getRevealOnFocusHint()
5985 public final void setRevealOnFocusHint(boolean revealOnFocus) {
5986 if (revealOnFocus) {
5987 mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
5989 mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
5994 * Returns this view's preference for reveal behavior when it gains focus.
5996 * <p>When this method returns true for a child view requesting focus, ancestor
5997 * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
5998 * should make a best effort to make the newly focused child fully visible to the user.
5999 * When it returns false, ancestor views should preferably not disrupt scroll positioning or
6000 * other properties affecting visibility to the user as part of the focus change.</p>
6002 * @return true if this view would prefer to become fully visible when it gains focus,
6003 * false if it would prefer not to disrupt scroll positioning
6005 * @see #setRevealOnFocusHint(boolean)
6007 public final boolean getRevealOnFocusHint() {
6008 return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
6012 * Populates <code>outRect</code> with the hotspot bounds. By default,
6013 * the hotspot bounds are identical to the screen bounds.
6015 * @param outRect rect to populate with hotspot bounds
6016 * @hide Only for internal use by views and widgets.
6018 public void getHotspotBounds(Rect outRect) {
6019 final Drawable background = getBackground();
6020 if (background != null) {
6021 background.getHotspotBounds(outRect);
6023 getBoundsOnScreen(outRect);
6028 * Request that a rectangle of this view be visible on the screen,
6029 * scrolling if necessary just enough.
6031 * <p>A View should call this if it maintains some notion of which part
6032 * of its content is interesting. For example, a text editing view
6033 * should call this when its cursor moves.
6034 * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6035 * It should not be affected by which part of the View is currently visible or its scroll
6038 * @param rectangle The rectangle in the View's content coordinate space
6039 * @return Whether any parent scrolled.
6041 public boolean requestRectangleOnScreen(Rect rectangle) {
6042 return requestRectangleOnScreen(rectangle, false);
6046 * Request that a rectangle of this view be visible on the screen,
6047 * scrolling if necessary just enough.
6049 * <p>A View should call this if it maintains some notion of which part
6050 * of its content is interesting. For example, a text editing view
6051 * should call this when its cursor moves.
6052 * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6053 * It should not be affected by which part of the View is currently visible or its scroll
6055 * <p>When <code>immediate</code> is set to true, scrolling will not be
6058 * @param rectangle The rectangle in the View's content coordinate space
6059 * @param immediate True to forbid animated scrolling, false otherwise
6060 * @return Whether any parent scrolled.
6062 public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6063 if (mParent == null) {
6069 RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6070 position.set(rectangle);
6072 ViewParent parent = mParent;
6073 boolean scrolled = false;
6074 while (parent != null) {
6075 rectangle.set((int) position.left, (int) position.top,
6076 (int) position.right, (int) position.bottom);
6078 scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6080 if (!(parent instanceof View)) {
6084 // move it from child's content coordinate space to parent's content coordinate space
6085 position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6087 child = (View) parent;
6088 parent = child.getParent();
6095 * Called when this view wants to give up focus. If focus is cleared
6096 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6098 * <strong>Note:</strong> When a View clears focus the framework is trying
6099 * to give focus to the first focusable View from the top. Hence, if this
6100 * View is the first from the top that can take focus, then all callbacks
6101 * related to clearing focus will be invoked after which the framework will
6102 * give focus to this view.
6105 public void clearFocus() {
6107 System.out.println(this + " clearFocus()");
6110 clearFocusInternal(null, true, true);
6114 * Clears focus from the view, optionally propagating the change up through
6115 * the parent hierarchy and requesting that the root view place new focus.
6117 * @param propagate whether to propagate the change up through the parent
6119 * @param refocus when propagate is true, specifies whether to request the
6120 * root view place new focus
6122 void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6123 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6124 mPrivateFlags &= ~PFLAG_FOCUSED;
6126 if (propagate && mParent != null) {
6127 mParent.clearChildFocus(this);
6130 onFocusChanged(false, 0, null);
6131 refreshDrawableState();
6133 if (propagate && (!refocus || !rootViewRequestFocus())) {
6134 notifyGlobalFocusCleared(this);
6139 void notifyGlobalFocusCleared(View oldFocus) {
6140 if (oldFocus != null && mAttachInfo != null) {
6141 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6145 boolean rootViewRequestFocus() {
6146 final View root = getRootView();
6147 return root != null && root.requestFocus();
6151 * Called internally by the view system when a new view is getting focus.
6152 * This is what clears the old focus.
6154 * <b>NOTE:</b> The parent view's focused child must be updated manually
6155 * after calling this method. Otherwise, the view hierarchy may be left in
6156 * an inconstent state.
6158 void unFocus(View focused) {
6160 System.out.println(this + " unFocus()");
6163 clearFocusInternal(focused, false, false);
6167 * Returns true if this view has focus itself, or is the ancestor of the
6168 * view that has focus.
6170 * @return True if this view has or contains focus, false otherwise.
6172 @ViewDebug.ExportedProperty(category = "focus")
6173 public boolean hasFocus() {
6174 return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6178 * Returns true if this view is focusable or if it contains a reachable View
6179 * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
6180 * is a View whose parents do not block descendants focus.
6182 * Only {@link #VISIBLE} views are considered focusable.
6184 * @return True if the view is focusable or if the view contains a focusable
6185 * View, false otherwise.
6187 * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6188 * @see ViewGroup#getTouchscreenBlocksFocus()
6190 public boolean hasFocusable() {
6191 if (!isFocusableInTouchMode()) {
6192 for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6193 final ViewGroup g = (ViewGroup) p;
6194 if (g.shouldBlockFocusForTouchscreen()) {
6199 return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
6203 * Called by the view system when the focus state of this view changes.
6204 * When the focus change event is caused by directional navigation, direction
6205 * and previouslyFocusedRect provide insight into where the focus is coming from.
6206 * When overriding, be sure to call up through to the super class so that
6207 * the standard focus handling will occur.
6209 * @param gainFocus True if the View has focus; false otherwise.
6210 * @param direction The direction focus has moved when requestFocus()
6211 * is called to give this view focus. Values are
6212 * {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6213 * {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6214 * It may not always apply, in which case use the default.
6215 * @param previouslyFocusedRect The rectangle, in this view's coordinate
6216 * system, of the previously focused view. If applicable, this will be
6217 * passed in as finer grained information about where the focus is coming
6218 * from (in addition to direction). Will be <code>null</code> otherwise.
6221 protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6222 @Nullable Rect previouslyFocusedRect) {
6224 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6226 notifyViewAccessibilityStateChangedIfNeeded(
6227 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6230 InputMethodManager imm = InputMethodManager.peekInstance();
6235 if (imm != null && mAttachInfo != null
6236 && mAttachInfo.mHasWindowFocus) {
6240 } else if (imm != null && mAttachInfo != null
6241 && mAttachInfo.mHasWindowFocus) {
6246 ListenerInfo li = mListenerInfo;
6247 if (li != null && li.mOnFocusChangeListener != null) {
6248 li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6251 if (mAttachInfo != null) {
6252 mAttachInfo.mKeyDispatchState.reset(this);
6257 * Sends an accessibility event of the given type. If accessibility is
6258 * not enabled this method has no effect. The default implementation calls
6259 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6260 * to populate information about the event source (this View), then calls
6261 * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6262 * populate the text content of the event source including its descendants,
6264 * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6265 * on its parent to request sending of the event to interested parties.
6267 * If an {@link AccessibilityDelegate} has been specified via calling
6268 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6269 * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
6270 * responsible for handling this call.
6273 * @param eventType The type of the event to send, as defined by several types from
6274 * {@link android.view.accessibility.AccessibilityEvent}, such as
6275 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
6276 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
6278 * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6279 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6280 * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
6281 * @see AccessibilityDelegate
6283 public void sendAccessibilityEvent(int eventType) {
6284 if (mAccessibilityDelegate != null) {
6285 mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
6287 sendAccessibilityEventInternal(eventType);
6292 * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6293 * {@link AccessibilityEvent} to make an announcement which is related to some
6294 * sort of a context change for which none of the events representing UI transitions
6295 * is a good fit. For example, announcing a new page in a book. If accessibility
6296 * is not enabled this method does nothing.
6298 * @param text The announcement text.
6300 public void announceForAccessibility(CharSequence text) {
6301 if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6302 AccessibilityEvent event = AccessibilityEvent.obtain(
6303 AccessibilityEvent.TYPE_ANNOUNCEMENT);
6304 onInitializeAccessibilityEvent(event);
6305 event.getText().add(text);
6306 event.setContentDescription(null);
6307 mParent.requestSendAccessibilityEvent(this, event);
6312 * @see #sendAccessibilityEvent(int)
6314 * Note: Called from the default {@link AccessibilityDelegate}.
6318 public void sendAccessibilityEventInternal(int eventType) {
6319 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6320 sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
6325 * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
6326 * takes as an argument an empty {@link AccessibilityEvent} and does not
6327 * perform a check whether accessibility is enabled.
6329 * If an {@link AccessibilityDelegate} has been specified via calling
6330 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6331 * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
6332 * is responsible for handling this call.
6335 * @param event The event to send.
6337 * @see #sendAccessibilityEvent(int)
6339 public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
6340 if (mAccessibilityDelegate != null) {
6341 mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
6343 sendAccessibilityEventUncheckedInternal(event);
6348 * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
6350 * Note: Called from the default {@link AccessibilityDelegate}.
6354 public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
6358 onInitializeAccessibilityEvent(event);
6359 // Only a subset of accessibility events populates text content.
6360 if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
6361 dispatchPopulateAccessibilityEvent(event);
6363 // In the beginning we called #isShown(), so we know that getParent() is not null.
6364 getParent().requestSendAccessibilityEvent(this, event);
6368 * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
6369 * to its children for adding their text content to the event. Note that the
6370 * event text is populated in a separate dispatch path since we add to the
6371 * event not only the text of the source but also the text of all its descendants.
6372 * A typical implementation will call
6373 * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
6374 * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6375 * on each child. Override this method if custom population of the event text
6376 * content is required.
6378 * If an {@link AccessibilityDelegate} has been specified via calling
6379 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6380 * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
6381 * is responsible for handling this call.
6384 * <em>Note:</em> Accessibility events of certain types are not dispatched for
6385 * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
6388 * @param event The event.
6390 * @return True if the event population was completed.
6392 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6393 if (mAccessibilityDelegate != null) {
6394 return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
6396 return dispatchPopulateAccessibilityEventInternal(event);
6401 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6403 * Note: Called from the default {@link AccessibilityDelegate}.
6407 public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6408 onPopulateAccessibilityEvent(event);
6413 * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6414 * giving a chance to this View to populate the accessibility event with its
6415 * text content. While this method is free to modify event
6416 * attributes other than text content, doing so should normally be performed in
6417 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
6419 * Example: Adding formatted date string to an accessibility event in addition
6420 * to the text added by the super implementation:
6421 * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6422 * super.onPopulateAccessibilityEvent(event);
6423 * final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
6424 * String selectedDateUtterance = DateUtils.formatDateTime(mContext,
6425 * mCurrentDate.getTimeInMillis(), flags);
6426 * event.getText().add(selectedDateUtterance);
6429 * If an {@link AccessibilityDelegate} has been specified via calling
6430 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6431 * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
6432 * is responsible for handling this call.
6434 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6435 * information to the event, in case the default implementation has basic information to add.
6438 * @param event The accessibility event which to populate.
6440 * @see #sendAccessibilityEvent(int)
6441 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6444 public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6445 if (mAccessibilityDelegate != null) {
6446 mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
6448 onPopulateAccessibilityEventInternal(event);
6453 * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
6455 * Note: Called from the default {@link AccessibilityDelegate}.
6459 public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6463 * Initializes an {@link AccessibilityEvent} with information about
6464 * this View which is the event source. In other words, the source of
6465 * an accessibility event is the view whose state change triggered firing
6468 * Example: Setting the password property of an event in addition
6469 * to properties set by the super implementation:
6470 * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6471 * super.onInitializeAccessibilityEvent(event);
6472 * event.setPassword(true);
6475 * If an {@link AccessibilityDelegate} has been specified via calling
6476 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6477 * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
6478 * is responsible for handling this call.
6480 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6481 * information to the event, in case the default implementation has basic information to add.
6483 * @param event The event to initialize.
6485 * @see #sendAccessibilityEvent(int)
6486 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6489 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6490 if (mAccessibilityDelegate != null) {
6491 mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
6493 onInitializeAccessibilityEventInternal(event);
6498 * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6500 * Note: Called from the default {@link AccessibilityDelegate}.
6504 public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
6505 event.setSource(this);
6506 event.setClassName(getAccessibilityClassName());
6507 event.setPackageName(getContext().getPackageName());
6508 event.setEnabled(isEnabled());
6509 event.setContentDescription(mContentDescription);
6511 switch (event.getEventType()) {
6512 case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
6513 ArrayList<View> focusablesTempList = (mAttachInfo != null)
6514 ? mAttachInfo.mTempArrayList : new ArrayList<View>();
6515 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
6516 event.setItemCount(focusablesTempList.size());
6517 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
6518 if (mAttachInfo != null) {
6519 focusablesTempList.clear();
6522 case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
6523 CharSequence text = getIterableTextForAccessibility();
6524 if (text != null && text.length() > 0) {
6525 event.setFromIndex(getAccessibilitySelectionStart());
6526 event.setToIndex(getAccessibilitySelectionEnd());
6527 event.setItemCount(text.length());
6534 * Returns an {@link AccessibilityNodeInfo} representing this view from the
6535 * point of view of an {@link android.accessibilityservice.AccessibilityService}.
6536 * This method is responsible for obtaining an accessibility node info from a
6537 * pool of reusable instances and calling
6538 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
6539 * initialize the former.
6541 * Note: The client is responsible for recycling the obtained instance by calling
6542 * {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
6545 * @return A populated {@link AccessibilityNodeInfo}.
6547 * @see AccessibilityNodeInfo
6549 public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6550 if (mAccessibilityDelegate != null) {
6551 return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6553 return createAccessibilityNodeInfoInternal();
6558 * @see #createAccessibilityNodeInfo()
6562 public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6563 AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6564 if (provider != null) {
6565 return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
6567 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6568 onInitializeAccessibilityNodeInfo(info);
6574 * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6575 * The base implementation sets:
6577 * <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6578 * <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6579 * <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6580 * <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6581 * <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6582 * <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6583 * <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6584 * <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6585 * <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6586 * <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6587 * <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6588 * <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6589 * <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
6592 * Subclasses should override this method, call the super implementation,
6593 * and set additional attributes.
6596 * If an {@link AccessibilityDelegate} has been specified via calling
6597 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6598 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6599 * is responsible for handling this call.
6602 * @param info The instance to initialize.
6605 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6606 if (mAccessibilityDelegate != null) {
6607 mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6609 onInitializeAccessibilityNodeInfoInternal(info);
6614 * Gets the location of this view in screen coordinates.
6616 * @param outRect The output location
6619 public void getBoundsOnScreen(Rect outRect) {
6620 getBoundsOnScreen(outRect, false);
6624 * Gets the location of this view in screen coordinates.
6626 * @param outRect The output location
6627 * @param clipToParent Whether to clip child bounds to the parent ones.
6630 public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6631 if (mAttachInfo == null) {
6635 RectF position = mAttachInfo.mTmpTransformRect;
6636 position.set(0, 0, mRight - mLeft, mBottom - mTop);
6638 if (!hasIdentityMatrix()) {
6639 getMatrix().mapRect(position);
6642 position.offset(mLeft, mTop);
6644 ViewParent parent = mParent;
6645 while (parent instanceof View) {
6646 View parentView = (View) parent;
6648 position.offset(-parentView.mScrollX, -parentView.mScrollY);
6651 position.left = Math.max(position.left, 0);
6652 position.top = Math.max(position.top, 0);
6653 position.right = Math.min(position.right, parentView.getWidth());
6654 position.bottom = Math.min(position.bottom, parentView.getHeight());
6657 if (!parentView.hasIdentityMatrix()) {
6658 parentView.getMatrix().mapRect(position);
6661 position.offset(parentView.mLeft, parentView.mTop);
6663 parent = parentView.mParent;
6666 if (parent instanceof ViewRootImpl) {
6667 ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6668 position.offset(0, -viewRootImpl.mCurScrollY);
6671 position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6673 outRect.set(Math.round(position.left), Math.round(position.top),
6674 Math.round(position.right), Math.round(position.bottom));
6678 * Return the class name of this object to be used for accessibility purposes.
6679 * Subclasses should only override this if they are implementing something that
6680 * should be seen as a completely new class of view when used by accessibility,
6681 * unrelated to the class it is deriving from. This is used to fill in
6682 * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6684 public CharSequence getAccessibilityClassName() {
6685 return View.class.getName();
6689 * Called when assist structure is being retrieved from a view as part of
6690 * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6691 * @param structure Fill in with structured view data. The default implementation
6692 * fills in all data that can be inferred from the view itself.
6694 public void onProvideStructure(ViewStructure structure) {
6696 if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
6697 && (id&0x0000ffff) != 0) {
6698 String pkg, type, entry;
6700 final Resources res = getResources();
6701 entry = res.getResourceEntryName(id);
6702 type = res.getResourceTypeName(id);
6703 pkg = res.getResourcePackageName(id);
6704 } catch (Resources.NotFoundException e) {
6705 entry = type = pkg = null;
6707 structure.setId(id, pkg, type, entry);
6709 structure.setId(id, null, null, null);
6711 structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6712 if (!hasIdentityMatrix()) {
6713 structure.setTransformation(getMatrix());
6715 structure.setElevation(getZ());
6716 structure.setVisibility(getVisibility());
6717 structure.setEnabled(isEnabled());
6718 if (isClickable()) {
6719 structure.setClickable(true);
6721 if (isFocusable()) {
6722 structure.setFocusable(true);
6725 structure.setFocused(true);
6727 if (isAccessibilityFocused()) {
6728 structure.setAccessibilityFocused(true);
6731 structure.setSelected(true);
6733 if (isActivated()) {
6734 structure.setActivated(true);
6736 if (isLongClickable()) {
6737 structure.setLongClickable(true);
6739 if (this instanceof Checkable) {
6740 structure.setCheckable(true);
6741 if (((Checkable)this).isChecked()) {
6742 structure.setChecked(true);
6745 if (isContextClickable()) {
6746 structure.setContextClickable(true);
6748 structure.setClassName(getAccessibilityClassName().toString());
6749 structure.setContentDescription(getContentDescription());
6753 * Called when assist structure is being retrieved from a view as part of
6754 * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
6755 * generate additional virtual structure under this view. The defaullt implementation
6756 * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
6757 * view's virtual accessibility nodes, if any. You can override this for a more
6758 * optimal implementation providing this data.
6760 public void onProvideVirtualStructure(ViewStructure structure) {
6761 AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6762 if (provider != null) {
6763 AccessibilityNodeInfo info = createAccessibilityNodeInfo();
6764 structure.setChildCount(1);
6765 ViewStructure root = structure.newChild(0);
6766 populateVirtualStructure(root, provider, info);
6771 private void populateVirtualStructure(ViewStructure structure,
6772 AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
6773 structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
6775 Rect rect = structure.getTempRect();
6776 info.getBoundsInParent(rect);
6777 structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
6778 structure.setVisibility(VISIBLE);
6779 structure.setEnabled(info.isEnabled());
6780 if (info.isClickable()) {
6781 structure.setClickable(true);
6783 if (info.isFocusable()) {
6784 structure.setFocusable(true);
6786 if (info.isFocused()) {
6787 structure.setFocused(true);
6789 if (info.isAccessibilityFocused()) {
6790 structure.setAccessibilityFocused(true);
6792 if (info.isSelected()) {
6793 structure.setSelected(true);
6795 if (info.isLongClickable()) {
6796 structure.setLongClickable(true);
6798 if (info.isCheckable()) {
6799 structure.setCheckable(true);
6800 if (info.isChecked()) {
6801 structure.setChecked(true);
6804 if (info.isContextClickable()) {
6805 structure.setContextClickable(true);
6807 CharSequence cname = info.getClassName();
6808 structure.setClassName(cname != null ? cname.toString() : null);
6809 structure.setContentDescription(info.getContentDescription());
6810 if (info.getText() != null || info.getError() != null) {
6811 structure.setText(info.getText(), info.getTextSelectionStart(),
6812 info.getTextSelectionEnd());
6814 final int NCHILDREN = info.getChildCount();
6815 if (NCHILDREN > 0) {
6816 structure.setChildCount(NCHILDREN);
6817 for (int i=0; i<NCHILDREN; i++) {
6818 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
6819 AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
6820 ViewStructure child = structure.newChild(i);
6821 populateVirtualStructure(child, provider, cinfo);
6828 * Dispatch creation of {@link ViewStructure} down the hierarchy. The default
6829 * implementation calls {@link #onProvideStructure} and
6830 * {@link #onProvideVirtualStructure}.
6832 public void dispatchProvideStructure(ViewStructure structure) {
6833 if (!isAssistBlocked()) {
6834 onProvideStructure(structure);
6835 onProvideVirtualStructure(structure);
6837 structure.setClassName(getAccessibilityClassName().toString());
6838 structure.setAssistBlocked(true);
6843 * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
6845 * Note: Called from the default {@link AccessibilityDelegate}.
6849 public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
6850 if (mAttachInfo == null) {
6854 Rect bounds = mAttachInfo.mTmpInvalRect;
6856 getDrawingRect(bounds);
6857 info.setBoundsInParent(bounds);
6859 getBoundsOnScreen(bounds, true);
6860 info.setBoundsInScreen(bounds);
6862 ViewParent parent = getParentForAccessibility();
6863 if (parent instanceof View) {
6864 info.setParent((View) parent);
6867 if (mID != View.NO_ID) {
6868 View rootView = getRootView();
6869 if (rootView == null) {
6873 View label = rootView.findLabelForView(this, mID);
6874 if (label != null) {
6875 info.setLabeledBy(label);
6878 if ((mAttachInfo.mAccessibilityFetchFlags
6879 & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
6880 && Resources.resourceHasPackage(mID)) {
6882 String viewId = getResources().getResourceName(mID);
6883 info.setViewIdResourceName(viewId);
6884 } catch (Resources.NotFoundException nfe) {
6890 if (mLabelForId != View.NO_ID) {
6891 View rootView = getRootView();
6892 if (rootView == null) {
6895 View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
6896 if (labeled != null) {
6897 info.setLabelFor(labeled);
6901 if (mAccessibilityTraversalBeforeId != View.NO_ID) {
6902 View rootView = getRootView();
6903 if (rootView == null) {
6906 View next = rootView.findViewInsideOutShouldExist(this,
6907 mAccessibilityTraversalBeforeId);
6908 if (next != null && next.includeForAccessibility()) {
6909 info.setTraversalBefore(next);
6913 if (mAccessibilityTraversalAfterId != View.NO_ID) {
6914 View rootView = getRootView();
6915 if (rootView == null) {
6918 View next = rootView.findViewInsideOutShouldExist(this,
6919 mAccessibilityTraversalAfterId);
6920 if (next != null && next.includeForAccessibility()) {
6921 info.setTraversalAfter(next);
6925 info.setVisibleToUser(isVisibleToUser());
6927 if ((mAttachInfo != null) && ((mAttachInfo.mAccessibilityFetchFlags
6928 & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0)) {
6929 info.setImportantForAccessibility(isImportantForAccessibility());
6931 info.setImportantForAccessibility(true);
6934 info.setPackageName(mContext.getPackageName());
6935 info.setClassName(getAccessibilityClassName());
6936 info.setContentDescription(getContentDescription());
6938 info.setEnabled(isEnabled());
6939 info.setClickable(isClickable());
6940 info.setFocusable(isFocusable());
6941 info.setFocused(isFocused());
6942 info.setAccessibilityFocused(isAccessibilityFocused());
6943 info.setSelected(isSelected());
6944 info.setLongClickable(isLongClickable());
6945 info.setContextClickable(isContextClickable());
6946 info.setLiveRegion(getAccessibilityLiveRegion());
6948 // TODO: These make sense only if we are in an AdapterView but all
6949 // views can be selected. Maybe from accessibility perspective
6950 // we should report as selectable view in an AdapterView.
6951 info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
6952 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
6954 if (isFocusable()) {
6956 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
6958 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
6962 if (!isAccessibilityFocused()) {
6963 info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
6965 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
6968 if (isClickable() && isEnabled()) {
6969 info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
6972 if (isLongClickable() && isEnabled()) {
6973 info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
6976 if (isContextClickable() && isEnabled()) {
6977 info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
6980 CharSequence text = getIterableTextForAccessibility();
6981 if (text != null && text.length() > 0) {
6982 info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
6984 info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
6985 info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
6986 info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
6987 info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
6988 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
6989 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
6992 info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
6993 populateAccessibilityNodeInfoDrawingOrderInParent(info);
6997 * Determine the order in which this view will be drawn relative to its siblings for a11y
6999 * @param info The info whose drawing order should be populated
7001 private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
7003 * If the view's bounds haven't been set yet, layout has not completed. In that situation,
7004 * drawing order may not be well-defined, and some Views with custom drawing order may
7005 * not be initialized sufficiently to respond properly getChildDrawingOrder.
7007 if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
7008 info.setDrawingOrder(0);
7011 int drawingOrderInParent = 1;
7012 // Iterate up the hierarchy if parents are not important for a11y
7013 View viewAtDrawingLevel = this;
7014 final ViewParent parent = getParentForAccessibility();
7015 while (viewAtDrawingLevel != parent) {
7016 final ViewParent currentParent = viewAtDrawingLevel.getParent();
7017 if (!(currentParent instanceof ViewGroup)) {
7018 // Should only happen for the Decor
7019 drawingOrderInParent = 0;
7022 final ViewGroup parentGroup = (ViewGroup) currentParent;
7023 final int childCount = parentGroup.getChildCount();
7024 if (childCount > 1) {
7025 List<View> preorderedList = parentGroup.buildOrderedChildList();
7026 if (preorderedList != null) {
7027 final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
7028 for (int i = 0; i < childDrawIndex; i++) {
7029 drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
7032 final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
7033 final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
7034 final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
7035 .getChildDrawingOrder(childCount, childIndex) : childIndex;
7036 final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
7037 if (childDrawIndex != 0) {
7038 for (int i = 0; i < numChildrenToIterate; i++) {
7039 final int otherDrawIndex = (customOrder ?
7040 parentGroup.getChildDrawingOrder(childCount, i) : i);
7041 if (otherDrawIndex < childDrawIndex) {
7042 drawingOrderInParent +=
7043 numViewsForAccessibility(parentGroup.getChildAt(i));
7050 viewAtDrawingLevel = (View) currentParent;
7052 info.setDrawingOrder(drawingOrderInParent);
7055 private static int numViewsForAccessibility(View view) {
7057 if (view.includeForAccessibility()) {
7059 } else if (view instanceof ViewGroup) {
7060 return ((ViewGroup) view).getNumChildrenForAccessibility();
7066 private View findLabelForView(View view, int labeledId) {
7067 if (mMatchLabelForPredicate == null) {
7068 mMatchLabelForPredicate = new MatchLabelForPredicate();
7070 mMatchLabelForPredicate.mLabeledId = labeledId;
7071 return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
7075 * Computes whether this view is visible to the user. Such a view is
7076 * attached, visible, all its predecessors are visible, it is not clipped
7077 * entirely by its predecessors, and has an alpha greater than zero.
7079 * @return Whether the view is visible on the screen.
7083 protected boolean isVisibleToUser() {
7084 return isVisibleToUser(null);
7088 * Computes whether the given portion of this view is visible to the user.
7089 * Such a view is attached, visible, all its predecessors are visible,
7090 * has an alpha greater than zero, and the specified portion is not
7091 * clipped entirely by its predecessors.
7093 * @param boundInView the portion of the view to test; coordinates should be relative; may be
7094 * <code>null</code>, and the entire view will be tested in this case.
7095 * When <code>true</code> is returned by the function, the actual visible
7096 * region will be stored in this parameter; that is, if boundInView is fully
7097 * contained within the view, no modification will be made, otherwise regions
7098 * outside of the visible area of the view will be clipped.
7100 * @return Whether the specified portion of the view is visible on the screen.
7104 protected boolean isVisibleToUser(Rect boundInView) {
7105 if (mAttachInfo != null) {
7106 // Attached to invisible window means this view is not visible.
7107 if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
7110 // An invisible predecessor or one with alpha zero means
7111 // that this view is not visible to the user.
7112 Object current = this;
7113 while (current instanceof View) {
7114 View view = (View) current;
7115 // We have attach info so this view is attached and there is no
7116 // need to check whether we reach to ViewRootImpl on the way up.
7117 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
7118 view.getVisibility() != VISIBLE) {
7121 current = view.mParent;
7123 // Check if the view is entirely covered by its predecessors.
7124 Rect visibleRect = mAttachInfo.mTmpInvalRect;
7125 Point offset = mAttachInfo.mPoint;
7126 if (!getGlobalVisibleRect(visibleRect, offset)) {
7129 // Check if the visible portion intersects the rectangle of interest.
7130 if (boundInView != null) {
7131 visibleRect.offset(-offset.x, -offset.y);
7132 return boundInView.intersect(visibleRect);
7140 * Returns the delegate for implementing accessibility support via
7141 * composition. For more details see {@link AccessibilityDelegate}.
7143 * @return The delegate, or null if none set.
7147 public AccessibilityDelegate getAccessibilityDelegate() {
7148 return mAccessibilityDelegate;
7152 * Sets a delegate for implementing accessibility support via composition
7153 * (as opposed to inheritance). For more details, see
7154 * {@link AccessibilityDelegate}.
7156 * <strong>Note:</strong> On platform versions prior to
7157 * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
7158 * views in the {@code android.widget.*} package are called <i>before</i>
7159 * host methods. This prevents certain properties such as class name from
7160 * being modified by overriding
7161 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
7162 * as any changes will be overwritten by the host class.
7164 * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
7165 * methods are called <i>after</i> host methods, which all properties to be
7166 * modified without being overwritten by the host class.
7168 * @param delegate the object to which accessibility method calls should be
7170 * @see AccessibilityDelegate
7172 public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
7173 mAccessibilityDelegate = delegate;
7177 * Gets the provider for managing a virtual view hierarchy rooted at this View
7178 * and reported to {@link android.accessibilityservice.AccessibilityService}s
7179 * that explore the window content.
7181 * If this method returns an instance, this instance is responsible for managing
7182 * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
7183 * View including the one representing the View itself. Similarly the returned
7184 * instance is responsible for performing accessibility actions on any virtual
7185 * view or the root view itself.
7188 * If an {@link AccessibilityDelegate} has been specified via calling
7189 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7190 * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
7191 * is responsible for handling this call.
7194 * @return The provider.
7196 * @see AccessibilityNodeProvider
7198 public AccessibilityNodeProvider getAccessibilityNodeProvider() {
7199 if (mAccessibilityDelegate != null) {
7200 return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
7207 * Gets the unique identifier of this view on the screen for accessibility purposes.
7208 * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
7210 * @return The view accessibility id.
7214 public int getAccessibilityViewId() {
7215 if (mAccessibilityViewId == NO_ID) {
7216 mAccessibilityViewId = sNextAccessibilityViewId++;
7218 return mAccessibilityViewId;
7222 * Gets the unique identifier of the window in which this View reseides.
7224 * @return The window accessibility id.
7228 public int getAccessibilityWindowId() {
7229 return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
7230 : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
7234 * Returns the {@link View}'s content description.
7236 * <strong>Note:</strong> Do not override this method, as it will have no
7237 * effect on the content description presented to accessibility services.
7238 * You must call {@link #setContentDescription(CharSequence)} to modify the
7239 * content description.
7241 * @return the content description
7242 * @see #setContentDescription(CharSequence)
7243 * @attr ref android.R.styleable#View_contentDescription
7245 @ViewDebug.ExportedProperty(category = "accessibility")
7246 public CharSequence getContentDescription() {
7247 return mContentDescription;
7251 * Sets the {@link View}'s content description.
7253 * A content description briefly describes the view and is primarily used
7254 * for accessibility support to determine how a view should be presented to
7255 * the user. In the case of a view with no textual representation, such as
7256 * {@link android.widget.ImageButton}, a useful content description
7257 * explains what the view does. For example, an image button with a phone
7258 * icon that is used to place a call may use "Call" as its content
7259 * description. An image of a floppy disk that is used to save a file may
7262 * @param contentDescription The content description.
7263 * @see #getContentDescription()
7264 * @attr ref android.R.styleable#View_contentDescription
7266 @RemotableViewMethod
7267 public void setContentDescription(CharSequence contentDescription) {
7268 if (mContentDescription == null) {
7269 if (contentDescription == null) {
7272 } else if (mContentDescription.equals(contentDescription)) {
7275 mContentDescription = contentDescription;
7276 final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
7277 if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
7278 setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
7279 notifySubtreeAccessibilityStateChangedIfNeeded();
7281 notifyViewAccessibilityStateChangedIfNeeded(
7282 AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
7287 * Sets the id of a view before which this one is visited in accessibility traversal.
7288 * A screen-reader must visit the content of this view before the content of the one
7289 * it precedes. For example, if view B is set to be before view A, then a screen-reader
7290 * will traverse the entire content of B before traversing the entire content of A,
7291 * regardles of what traversal strategy it is using.
7293 * Views that do not have specified before/after relationships are traversed in order
7294 * determined by the screen-reader.
7297 * Setting that this view is before a view that is not important for accessibility
7298 * or if this view is not important for accessibility will have no effect as the
7299 * screen-reader is not aware of unimportant views.
7302 * @param beforeId The id of a view this one precedes in accessibility traversal.
7304 * @attr ref android.R.styleable#View_accessibilityTraversalBefore
7306 * @see #setImportantForAccessibility(int)
7308 @RemotableViewMethod
7309 public void setAccessibilityTraversalBefore(int beforeId) {
7310 if (mAccessibilityTraversalBeforeId == beforeId) {
7313 mAccessibilityTraversalBeforeId = beforeId;
7314 notifyViewAccessibilityStateChangedIfNeeded(
7315 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7319 * Gets the id of a view before which this one is visited in accessibility traversal.
7321 * @return The id of a view this one precedes in accessibility traversal if
7322 * specified, otherwise {@link #NO_ID}.
7324 * @see #setAccessibilityTraversalBefore(int)
7326 public int getAccessibilityTraversalBefore() {
7327 return mAccessibilityTraversalBeforeId;
7331 * Sets the id of a view after which this one is visited in accessibility traversal.
7332 * A screen-reader must visit the content of the other view before the content of this
7333 * one. For example, if view B is set to be after view A, then a screen-reader
7334 * will traverse the entire content of A before traversing the entire content of B,
7335 * regardles of what traversal strategy it is using.
7337 * Views that do not have specified before/after relationships are traversed in order
7338 * determined by the screen-reader.
7341 * Setting that this view is after a view that is not important for accessibility
7342 * or if this view is not important for accessibility will have no effect as the
7343 * screen-reader is not aware of unimportant views.
7346 * @param afterId The id of a view this one succedees in accessibility traversal.
7348 * @attr ref android.R.styleable#View_accessibilityTraversalAfter
7350 * @see #setImportantForAccessibility(int)
7352 @RemotableViewMethod
7353 public void setAccessibilityTraversalAfter(int afterId) {
7354 if (mAccessibilityTraversalAfterId == afterId) {
7357 mAccessibilityTraversalAfterId = afterId;
7358 notifyViewAccessibilityStateChangedIfNeeded(
7359 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7363 * Gets the id of a view after which this one is visited in accessibility traversal.
7365 * @return The id of a view this one succeedes in accessibility traversal if
7366 * specified, otherwise {@link #NO_ID}.
7368 * @see #setAccessibilityTraversalAfter(int)
7370 public int getAccessibilityTraversalAfter() {
7371 return mAccessibilityTraversalAfterId;
7375 * Gets the id of a view for which this view serves as a label for
7376 * accessibility purposes.
7378 * @return The labeled view id.
7380 @ViewDebug.ExportedProperty(category = "accessibility")
7381 public int getLabelFor() {
7386 * Sets the id of a view for which this view serves as a label for
7387 * accessibility purposes.
7389 * @param id The labeled view id.
7391 @RemotableViewMethod
7392 public void setLabelFor(@IdRes int id) {
7393 if (mLabelForId == id) {
7397 if (mLabelForId != View.NO_ID
7398 && mID == View.NO_ID) {
7399 mID = generateViewId();
7401 notifyViewAccessibilityStateChangedIfNeeded(
7402 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7406 * Invoked whenever this view loses focus, either by losing window focus or by losing
7407 * focus within its window. This method can be used to clear any state tied to the
7408 * focus. For instance, if a button is held pressed with the trackball and the window
7409 * loses focus, this method can be used to cancel the press.
7411 * Subclasses of View overriding this method should always call super.onFocusLost().
7413 * @see #onFocusChanged(boolean, int, android.graphics.Rect)
7414 * @see #onWindowFocusChanged(boolean)
7416 * @hide pending API council approval
7419 protected void onFocusLost() {
7420 resetPressedState();
7423 private void resetPressedState() {
7424 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7431 if (!mHasPerformedLongPress) {
7432 removeLongPressCallback();
7438 * Returns true if this view has focus
7440 * @return True if this view has focus, false otherwise.
7442 @ViewDebug.ExportedProperty(category = "focus")
7443 public boolean isFocused() {
7444 return (mPrivateFlags & PFLAG_FOCUSED) != 0;
7448 * Find the view in the hierarchy rooted at this view that currently has
7451 * @return The view that currently has focus, or null if no focused view can
7454 public View findFocus() {
7455 return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
7459 * Indicates whether this view is one of the set of scrollable containers in
7462 * @return whether this view is one of the set of scrollable containers in
7465 * @attr ref android.R.styleable#View_isScrollContainer
7467 public boolean isScrollContainer() {
7468 return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
7472 * Change whether this view is one of the set of scrollable containers in
7473 * its window. This will be used to determine whether the window can
7474 * resize or must pan when a soft input area is open -- scrollable
7475 * containers allow the window to use resize mode since the container
7476 * will appropriately shrink.
7478 * @attr ref android.R.styleable#View_isScrollContainer
7480 public void setScrollContainer(boolean isScrollContainer) {
7481 if (isScrollContainer) {
7482 if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
7483 mAttachInfo.mScrollContainers.add(this);
7484 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
7486 mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
7488 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
7489 mAttachInfo.mScrollContainers.remove(this);
7491 mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
7496 * Returns the quality of the drawing cache.
7498 * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7499 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7501 * @see #setDrawingCacheQuality(int)
7502 * @see #setDrawingCacheEnabled(boolean)
7503 * @see #isDrawingCacheEnabled()
7505 * @attr ref android.R.styleable#View_drawingCacheQuality
7507 @DrawingCacheQuality
7508 public int getDrawingCacheQuality() {
7509 return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
7513 * Set the drawing cache quality of this view. This value is used only when the
7514 * drawing cache is enabled
7516 * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7517 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7519 * @see #getDrawingCacheQuality()
7520 * @see #setDrawingCacheEnabled(boolean)
7521 * @see #isDrawingCacheEnabled()
7523 * @attr ref android.R.styleable#View_drawingCacheQuality
7525 public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
7526 setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
7530 * Returns whether the screen should remain on, corresponding to the current
7531 * value of {@link #KEEP_SCREEN_ON}.
7533 * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
7535 * @see #setKeepScreenOn(boolean)
7537 * @attr ref android.R.styleable#View_keepScreenOn
7539 public boolean getKeepScreenOn() {
7540 return (mViewFlags & KEEP_SCREEN_ON) != 0;
7544 * Controls whether the screen should remain on, modifying the
7545 * value of {@link #KEEP_SCREEN_ON}.
7547 * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
7549 * @see #getKeepScreenOn()
7551 * @attr ref android.R.styleable#View_keepScreenOn
7553 public void setKeepScreenOn(boolean keepScreenOn) {
7554 setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
7558 * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7559 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7561 * @attr ref android.R.styleable#View_nextFocusLeft
7563 public int getNextFocusLeftId() {
7564 return mNextFocusLeftId;
7568 * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7569 * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
7570 * decide automatically.
7572 * @attr ref android.R.styleable#View_nextFocusLeft
7574 public void setNextFocusLeftId(int nextFocusLeftId) {
7575 mNextFocusLeftId = nextFocusLeftId;
7579 * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7580 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7582 * @attr ref android.R.styleable#View_nextFocusRight
7584 public int getNextFocusRightId() {
7585 return mNextFocusRightId;
7589 * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7590 * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
7591 * decide automatically.
7593 * @attr ref android.R.styleable#View_nextFocusRight
7595 public void setNextFocusRightId(int nextFocusRightId) {
7596 mNextFocusRightId = nextFocusRightId;
7600 * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7601 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7603 * @attr ref android.R.styleable#View_nextFocusUp
7605 public int getNextFocusUpId() {
7606 return mNextFocusUpId;
7610 * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7611 * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
7612 * decide automatically.
7614 * @attr ref android.R.styleable#View_nextFocusUp
7616 public void setNextFocusUpId(int nextFocusUpId) {
7617 mNextFocusUpId = nextFocusUpId;
7621 * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7622 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7624 * @attr ref android.R.styleable#View_nextFocusDown
7626 public int getNextFocusDownId() {
7627 return mNextFocusDownId;
7631 * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7632 * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
7633 * decide automatically.
7635 * @attr ref android.R.styleable#View_nextFocusDown
7637 public void setNextFocusDownId(int nextFocusDownId) {
7638 mNextFocusDownId = nextFocusDownId;
7642 * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7643 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7645 * @attr ref android.R.styleable#View_nextFocusForward
7647 public int getNextFocusForwardId() {
7648 return mNextFocusForwardId;
7652 * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7653 * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
7654 * decide automatically.
7656 * @attr ref android.R.styleable#View_nextFocusForward
7658 public void setNextFocusForwardId(int nextFocusForwardId) {
7659 mNextFocusForwardId = nextFocusForwardId;
7663 * Returns the visibility of this view and all of its ancestors
7665 * @return True if this view and all of its ancestors are {@link #VISIBLE}
7667 public boolean isShown() {
7668 View current = this;
7669 //noinspection ConstantConditions
7671 if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7674 ViewParent parent = current.mParent;
7675 if (parent == null) {
7676 return false; // We are not attached to the view root
7678 if (!(parent instanceof View)) {
7681 current = (View) parent;
7682 } while (current != null);
7688 * Called by the view hierarchy when the content insets for a window have
7689 * changed, to allow it to adjust its content to fit within those windows.
7690 * The content insets tell you the space that the status bar, input method,
7691 * and other system windows infringe on the application's window.
7693 * <p>You do not normally need to deal with this function, since the default
7694 * window decoration given to applications takes care of applying it to the
7695 * content of the window. If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
7696 * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
7697 * and your content can be placed under those system elements. You can then
7698 * use this method within your view hierarchy if you have parts of your UI
7699 * which you would like to ensure are not being covered.
7701 * <p>The default implementation of this method simply applies the content
7702 * insets to the view's padding, consuming that content (modifying the
7703 * insets to be 0), and returning true. This behavior is off by default, but can
7704 * be enabled through {@link #setFitsSystemWindows(boolean)}.
7706 * <p>This function's traversal down the hierarchy is depth-first. The same content
7707 * insets object is propagated down the hierarchy, so any changes made to it will
7708 * be seen by all following views (including potentially ones above in
7709 * the hierarchy since this is a depth-first traversal). The first view
7710 * that returns true will abort the entire traversal.
7712 * <p>The default implementation works well for a situation where it is
7713 * used with a container that covers the entire window, allowing it to
7714 * apply the appropriate insets to its content on all edges. If you need
7715 * a more complicated layout (such as two different views fitting system
7716 * windows, one on the top of the window, and one on the bottom),
7717 * you can override the method and handle the insets however you would like.
7718 * Note that the insets provided by the framework are always relative to the
7719 * far edges of the window, not accounting for the location of the called view
7720 * within that window. (In fact when this method is called you do not yet know
7721 * where the layout will place the view, as it is done before layout happens.)
7723 * <p>Note: unlike many View methods, there is no dispatch phase to this
7724 * call. If you are overriding it in a ViewGroup and want to allow the
7725 * call to continue to your children, you must be sure to call the super
7728 * <p>Here is a sample layout that makes use of fitting system windows
7729 * to have controls for a video view placed inside of the window decorations
7730 * that it hides and shows. This can be used with code like the second
7731 * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
7733 * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
7735 * @param insets Current content insets of the window. Prior to
7736 * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
7737 * the insets or else you and Android will be unhappy.
7739 * @return {@code true} if this view applied the insets and it should not
7740 * continue propagating further down the hierarchy, {@code false} otherwise.
7741 * @see #getFitsSystemWindows()
7742 * @see #setFitsSystemWindows(boolean)
7743 * @see #setSystemUiVisibility(int)
7745 * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
7746 * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
7747 * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
7748 * to implement handling their own insets.
7750 protected boolean fitSystemWindows(Rect insets) {
7751 if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
7752 if (insets == null) {
7753 // Null insets by definition have already been consumed.
7754 // This call cannot apply insets since there are none to apply,
7758 // If we're not in the process of dispatching the newer apply insets call,
7759 // that means we're not in the compatibility path. Dispatch into the newer
7760 // apply insets path and take things from there.
7762 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
7763 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
7765 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
7768 // We're being called from the newer apply insets path.
7769 // Perform the standard fallback behavior.
7770 return fitSystemWindowsInt(insets);
7774 private boolean fitSystemWindowsInt(Rect insets) {
7775 if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
7776 mUserPaddingStart = UNDEFINED_PADDING;
7777 mUserPaddingEnd = UNDEFINED_PADDING;
7778 Rect localInsets = sThreadLocal.get();
7779 if (localInsets == null) {
7780 localInsets = new Rect();
7781 sThreadLocal.set(localInsets);
7783 boolean res = computeFitSystemWindows(insets, localInsets);
7784 mUserPaddingLeftInitial = localInsets.left;
7785 mUserPaddingRightInitial = localInsets.right;
7786 internalSetPadding(localInsets.left, localInsets.top,
7787 localInsets.right, localInsets.bottom);
7794 * Called when the view should apply {@link WindowInsets} according to its internal policy.
7796 * <p>This method should be overridden by views that wish to apply a policy different from or
7797 * in addition to the default behavior. Clients that wish to force a view subtree
7798 * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
7800 * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
7801 * it will be called during dispatch instead of this method. The listener may optionally
7802 * call this method from its own implementation if it wishes to apply the view's default
7803 * insets policy in addition to its own.</p>
7805 * <p>Implementations of this method should either return the insets parameter unchanged
7806 * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
7807 * that this view applied itself. This allows new inset types added in future platform
7808 * versions to pass through existing implementations unchanged without being erroneously
7811 * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
7812 * property is set then the view will consume the system window insets and apply them
7813 * as padding for the view.</p>
7815 * @param insets Insets to apply
7816 * @return The supplied insets with any applied insets consumed
7818 public WindowInsets onApplyWindowInsets(WindowInsets insets) {
7819 if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
7820 // We weren't called from within a direct call to fitSystemWindows,
7821 // call into it as a fallback in case we're in a class that overrides it
7822 // and has logic to perform.
7823 if (fitSystemWindows(insets.getSystemWindowInsets())) {
7824 return insets.consumeSystemWindowInsets();
7827 // We were called from within a direct call to fitSystemWindows.
7828 if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
7829 return insets.consumeSystemWindowInsets();
7836 * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
7837 * window insets to this view. The listener's
7838 * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
7839 * method will be called instead of the view's
7840 * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
7842 * @param listener Listener to set
7844 * @see #onApplyWindowInsets(WindowInsets)
7846 public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
7847 getListenerInfo().mOnApplyWindowInsetsListener = listener;
7851 * Request to apply the given window insets to this view or another view in its subtree.
7853 * <p>This method should be called by clients wishing to apply insets corresponding to areas
7854 * obscured by window decorations or overlays. This can include the status and navigation bars,
7855 * action bars, input methods and more. New inset categories may be added in the future.
7856 * The method returns the insets provided minus any that were applied by this view or its
7859 * <p>Clients wishing to provide custom behavior should override the
7860 * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
7861 * {@link OnApplyWindowInsetsListener} via the
7862 * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
7865 * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
7868 * @param insets Insets to apply
7869 * @return The provided insets minus the insets that were consumed
7871 public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
7873 mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
7874 if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
7875 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
7877 return onApplyWindowInsets(insets);
7880 mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
7885 * Compute the view's coordinate within the surface.
7887 * <p>Computes the coordinates of this view in its surface. The argument
7888 * must be an array of two integers. After the method returns, the array
7889 * contains the x and y location in that order.</p>
7891 * @param location an array of two integers in which to hold the coordinates
7893 public void getLocationInSurface(@Size(2) int[] location) {
7894 getLocationInWindow(location);
7895 if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
7896 location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
7897 location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
7902 * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
7903 * only available if the view is attached.
7905 * @return WindowInsets from the top of the view hierarchy or null if View is detached
7907 public WindowInsets getRootWindowInsets() {
7908 if (mAttachInfo != null) {
7909 return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
7915 * @hide Compute the insets that should be consumed by this view and the ones
7916 * that should propagate to those under it.
7918 protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
7919 if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7920 || mAttachInfo == null
7921 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
7922 && !mAttachInfo.mOverscanRequested)) {
7923 outLocalInsets.set(inoutInsets);
7924 inoutInsets.set(0, 0, 0, 0);
7927 // The application wants to take care of fitting system window for
7928 // the content... however we still need to take care of any overscan here.
7929 final Rect overscan = mAttachInfo.mOverscanInsets;
7930 outLocalInsets.set(overscan);
7931 inoutInsets.left -= overscan.left;
7932 inoutInsets.top -= overscan.top;
7933 inoutInsets.right -= overscan.right;
7934 inoutInsets.bottom -= overscan.bottom;
7940 * Compute insets that should be consumed by this view and the ones that should propagate
7941 * to those under it.
7943 * @param in Insets currently being processed by this View, likely received as a parameter
7944 * to {@link #onApplyWindowInsets(WindowInsets)}.
7945 * @param outLocalInsets A Rect that will receive the insets that should be consumed
7947 * @return Insets that should be passed along to views under this one
7949 public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
7950 if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7951 || mAttachInfo == null
7952 || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
7953 outLocalInsets.set(in.getSystemWindowInsets());
7954 return in.consumeSystemWindowInsets();
7956 outLocalInsets.set(0, 0, 0, 0);
7962 * Sets whether or not this view should account for system screen decorations
7963 * such as the status bar and inset its content; that is, controlling whether
7964 * the default implementation of {@link #fitSystemWindows(Rect)} will be
7965 * executed. See that method for more details.
7967 * <p>Note that if you are providing your own implementation of
7968 * {@link #fitSystemWindows(Rect)}, then there is no need to set this
7969 * flag to true -- your implementation will be overriding the default
7970 * implementation that checks this flag.
7972 * @param fitSystemWindows If true, then the default implementation of
7973 * {@link #fitSystemWindows(Rect)} will be executed.
7975 * @attr ref android.R.styleable#View_fitsSystemWindows
7976 * @see #getFitsSystemWindows()
7977 * @see #fitSystemWindows(Rect)
7978 * @see #setSystemUiVisibility(int)
7980 public void setFitsSystemWindows(boolean fitSystemWindows) {
7981 setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
7985 * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
7986 * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
7989 * @return {@code true} if the default implementation of
7990 * {@link #fitSystemWindows(Rect)} will be executed.
7992 * @attr ref android.R.styleable#View_fitsSystemWindows
7993 * @see #setFitsSystemWindows(boolean)
7994 * @see #fitSystemWindows(Rect)
7995 * @see #setSystemUiVisibility(int)
7997 @ViewDebug.ExportedProperty
7998 public boolean getFitsSystemWindows() {
7999 return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
8003 public boolean fitsSystemWindows() {
8004 return getFitsSystemWindows();
8008 * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
8009 * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
8011 public void requestFitSystemWindows() {
8012 if (mParent != null) {
8013 mParent.requestFitSystemWindows();
8018 * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
8020 public void requestApplyInsets() {
8021 requestFitSystemWindows();
8025 * For use by PhoneWindow to make its own system window fitting optional.
8028 public void makeOptionalFitsSystemWindows() {
8029 setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
8033 * Returns the outsets, which areas of the device that aren't a surface, but we would like to
8034 * treat them as such.
8037 public void getOutsets(Rect outOutsetRect) {
8038 if (mAttachInfo != null) {
8039 outOutsetRect.set(mAttachInfo.mOutsets);
8041 outOutsetRect.setEmpty();
8046 * Returns the visibility status for this view.
8048 * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8049 * @attr ref android.R.styleable#View_visibility
8051 @ViewDebug.ExportedProperty(mapping = {
8052 @ViewDebug.IntToString(from = VISIBLE, to = "VISIBLE"),
8053 @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
8054 @ViewDebug.IntToString(from = GONE, to = "GONE")
8057 public int getVisibility() {
8058 return mViewFlags & VISIBILITY_MASK;
8062 * Set the visibility state of this view.
8064 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8065 * @attr ref android.R.styleable#View_visibility
8067 @RemotableViewMethod
8068 public void setVisibility(@Visibility int visibility) {
8069 setFlags(visibility, VISIBILITY_MASK);
8073 * Returns the enabled status for this view. The interpretation of the
8074 * enabled state varies by subclass.
8076 * @return True if this view is enabled, false otherwise.
8078 @ViewDebug.ExportedProperty
8079 public boolean isEnabled() {
8080 return (mViewFlags & ENABLED_MASK) == ENABLED;
8084 * Set the enabled state of this view. The interpretation of the enabled
8085 * state varies by subclass.
8087 * @param enabled True if this view is enabled, false otherwise.
8089 @RemotableViewMethod
8090 public void setEnabled(boolean enabled) {
8091 if (enabled == isEnabled()) return;
8093 setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
8096 * The View most likely has to change its appearance, so refresh
8097 * the drawable state.
8099 refreshDrawableState();
8101 // Invalidate too, since the default behavior for views is to be
8102 // be drawn at 50% alpha rather than to change the drawable.
8106 cancelPendingInputEvents();
8111 * Set whether this view can receive the focus.
8113 * Setting this to false will also ensure that this view is not focusable
8116 * @param focusable If true, this view can receive the focus.
8118 * @see #setFocusableInTouchMode(boolean)
8119 * @attr ref android.R.styleable#View_focusable
8121 public void setFocusable(boolean focusable) {
8123 setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
8125 setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
8129 * Set whether this view can receive focus while in touch mode.
8131 * Setting this to true will also ensure that this view is focusable.
8133 * @param focusableInTouchMode If true, this view can receive the focus while
8136 * @see #setFocusable(boolean)
8137 * @attr ref android.R.styleable#View_focusableInTouchMode
8139 public void setFocusableInTouchMode(boolean focusableInTouchMode) {
8140 // Focusable in touch mode should always be set before the focusable flag
8141 // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
8142 // which, in touch mode, will not successfully request focus on this view
8143 // because the focusable in touch mode flag is not set
8144 setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
8145 if (focusableInTouchMode) {
8146 setFlags(FOCUSABLE, FOCUSABLE_MASK);
8151 * Set whether this view should have sound effects enabled for events such as
8152 * clicking and touching.
8154 * <p>You may wish to disable sound effects for a view if you already play sounds,
8155 * for instance, a dial key that plays dtmf tones.
8157 * @param soundEffectsEnabled whether sound effects are enabled for this view.
8158 * @see #isSoundEffectsEnabled()
8159 * @see #playSoundEffect(int)
8160 * @attr ref android.R.styleable#View_soundEffectsEnabled
8162 public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
8163 setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
8167 * @return whether this view should have sound effects enabled for events such as
8168 * clicking and touching.
8170 * @see #setSoundEffectsEnabled(boolean)
8171 * @see #playSoundEffect(int)
8172 * @attr ref android.R.styleable#View_soundEffectsEnabled
8174 @ViewDebug.ExportedProperty
8175 public boolean isSoundEffectsEnabled() {
8176 return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
8180 * Set whether this view should have haptic feedback for events such as
8183 * <p>You may wish to disable haptic feedback if your view already controls
8184 * its own haptic feedback.
8186 * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
8187 * @see #isHapticFeedbackEnabled()
8188 * @see #performHapticFeedback(int)
8189 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8191 public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
8192 setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
8196 * @return whether this view should have haptic feedback enabled for events
8199 * @see #setHapticFeedbackEnabled(boolean)
8200 * @see #performHapticFeedback(int)
8201 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8203 @ViewDebug.ExportedProperty
8204 public boolean isHapticFeedbackEnabled() {
8205 return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
8209 * Returns the layout direction for this view.
8211 * @return One of {@link #LAYOUT_DIRECTION_LTR},
8212 * {@link #LAYOUT_DIRECTION_RTL},
8213 * {@link #LAYOUT_DIRECTION_INHERIT} or
8214 * {@link #LAYOUT_DIRECTION_LOCALE}.
8216 * @attr ref android.R.styleable#View_layoutDirection
8220 @ViewDebug.ExportedProperty(category = "layout", mapping = {
8221 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "LTR"),
8222 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RTL"),
8223 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
8224 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE, to = "LOCALE")
8227 public int getRawLayoutDirection() {
8228 return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
8232 * Set the layout direction for this view. This will propagate a reset of layout direction
8233 * resolution to the view's children and resolve layout direction for this view.
8235 * @param layoutDirection the layout direction to set. Should be one of:
8237 * {@link #LAYOUT_DIRECTION_LTR},
8238 * {@link #LAYOUT_DIRECTION_RTL},
8239 * {@link #LAYOUT_DIRECTION_INHERIT},
8240 * {@link #LAYOUT_DIRECTION_LOCALE}.
8242 * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
8243 * proceeds up the parent chain of the view to get the value. If there is no parent, then it
8244 * will return the default {@link #LAYOUT_DIRECTION_LTR}.
8246 * @attr ref android.R.styleable#View_layoutDirection
8248 @RemotableViewMethod
8249 public void setLayoutDirection(@LayoutDir int layoutDirection) {
8250 if (getRawLayoutDirection() != layoutDirection) {
8251 // Reset the current layout direction and the resolved one
8252 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
8253 resetRtlProperties();
8254 // Set the new layout direction (filtered)
8256 ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
8257 // We need to resolve all RTL properties as they all depend on layout direction
8258 resolveRtlPropertiesIfNeeded();
8265 * Returns the resolved layout direction for this view.
8267 * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
8268 * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
8270 * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
8271 * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
8273 * @attr ref android.R.styleable#View_layoutDirection
8275 @ViewDebug.ExportedProperty(category = "layout", mapping = {
8276 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
8277 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
8280 public int getLayoutDirection() {
8281 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
8282 if (targetSdkVersion < JELLY_BEAN_MR1) {
8283 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
8284 return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
8286 return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
8287 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
8291 * Indicates whether or not this view's layout is right-to-left. This is resolved from
8292 * layout attribute and/or the inherited value from the parent
8294 * @return true if the layout is right-to-left.
8298 @ViewDebug.ExportedProperty(category = "layout")
8299 public boolean isLayoutRtl() {
8300 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
8304 * Indicates whether the view is currently tracking transient state that the
8305 * app should not need to concern itself with saving and restoring, but that
8306 * the framework should take special note to preserve when possible.
8308 * <p>A view with transient state cannot be trivially rebound from an external
8309 * data source, such as an adapter binding item views in a list. This may be
8310 * because the view is performing an animation, tracking user selection
8311 * of content, or similar.</p>
8313 * @return true if the view has transient state
8315 @ViewDebug.ExportedProperty(category = "layout")
8316 public boolean hasTransientState() {
8317 return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
8321 * Set whether this view is currently tracking transient state that the
8322 * framework should attempt to preserve when possible. This flag is reference counted,
8323 * so every call to setHasTransientState(true) should be paired with a later call
8324 * to setHasTransientState(false).
8326 * <p>A view with transient state cannot be trivially rebound from an external
8327 * data source, such as an adapter binding item views in a list. This may be
8328 * because the view is performing an animation, tracking user selection
8329 * of content, or similar.</p>
8331 * @param hasTransientState true if this view has transient state
8333 public void setHasTransientState(boolean hasTransientState) {
8334 mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
8335 mTransientStateCount - 1;
8336 if (mTransientStateCount < 0) {
8337 mTransientStateCount = 0;
8338 Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
8339 "unmatched pair of setHasTransientState calls");
8340 } else if ((hasTransientState && mTransientStateCount == 1) ||
8341 (!hasTransientState && mTransientStateCount == 0)) {
8342 // update flag if we've just incremented up from 0 or decremented down to 0
8343 mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
8344 (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
8345 if (mParent != null) {
8347 mParent.childHasTransientStateChanged(this, hasTransientState);
8348 } catch (AbstractMethodError e) {
8349 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8350 " does not fully implement ViewParent", e);
8357 * Returns true if this view is currently attached to a window.
8359 public boolean isAttachedToWindow() {
8360 return mAttachInfo != null;
8364 * Returns true if this view has been through at least one layout since it
8365 * was last attached to or detached from a window.
8367 public boolean isLaidOut() {
8368 return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
8372 * If this view doesn't do any drawing on its own, set this flag to
8373 * allow further optimizations. By default, this flag is not set on
8374 * View, but could be set on some View subclasses such as ViewGroup.
8376 * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
8377 * you should clear this flag.
8379 * @param willNotDraw whether or not this View draw on its own
8381 public void setWillNotDraw(boolean willNotDraw) {
8382 setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
8386 * Returns whether or not this View draws on its own.
8388 * @return true if this view has nothing to draw, false otherwise
8390 @ViewDebug.ExportedProperty(category = "drawing")
8391 public boolean willNotDraw() {
8392 return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
8396 * When a View's drawing cache is enabled, drawing is redirected to an
8397 * offscreen bitmap. Some views, like an ImageView, must be able to
8398 * bypass this mechanism if they already draw a single bitmap, to avoid
8399 * unnecessary usage of the memory.
8401 * @param willNotCacheDrawing true if this view does not cache its
8402 * drawing, false otherwise
8404 public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
8405 setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
8409 * Returns whether or not this View can cache its drawing or not.
8411 * @return true if this view does not cache its drawing, false otherwise
8413 @ViewDebug.ExportedProperty(category = "drawing")
8414 public boolean willNotCacheDrawing() {
8415 return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
8419 * Indicates whether this view reacts to click events or not.
8421 * @return true if the view is clickable, false otherwise
8423 * @see #setClickable(boolean)
8424 * @attr ref android.R.styleable#View_clickable
8426 @ViewDebug.ExportedProperty
8427 public boolean isClickable() {
8428 return (mViewFlags & CLICKABLE) == CLICKABLE;
8432 * Enables or disables click events for this view. When a view
8433 * is clickable it will change its state to "pressed" on every click.
8434 * Subclasses should set the view clickable to visually react to
8437 * @param clickable true to make the view clickable, false otherwise
8439 * @see #isClickable()
8440 * @attr ref android.R.styleable#View_clickable
8442 public void setClickable(boolean clickable) {
8443 setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
8447 * Indicates whether this view reacts to long click events or not.
8449 * @return true if the view is long clickable, false otherwise
8451 * @see #setLongClickable(boolean)
8452 * @attr ref android.R.styleable#View_longClickable
8454 public boolean isLongClickable() {
8455 return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
8459 * Enables or disables long click events for this view. When a view is long
8460 * clickable it reacts to the user holding down the button for a longer
8461 * duration than a tap. This event can either launch the listener or a
8464 * @param longClickable true to make the view long clickable, false otherwise
8465 * @see #isLongClickable()
8466 * @attr ref android.R.styleable#View_longClickable
8468 public void setLongClickable(boolean longClickable) {
8469 setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
8473 * Indicates whether this view reacts to context clicks or not.
8475 * @return true if the view is context clickable, false otherwise
8476 * @see #setContextClickable(boolean)
8477 * @attr ref android.R.styleable#View_contextClickable
8479 public boolean isContextClickable() {
8480 return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
8484 * Enables or disables context clicking for this view. This event can launch the listener.
8486 * @param contextClickable true to make the view react to a context click, false otherwise
8487 * @see #isContextClickable()
8488 * @attr ref android.R.styleable#View_contextClickable
8490 public void setContextClickable(boolean contextClickable) {
8491 setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
8495 * Sets the pressed state for this view and provides a touch coordinate for
8496 * animation hinting.
8498 * @param pressed Pass true to set the View's internal state to "pressed",
8499 * or false to reverts the View's internal state from a
8500 * previously set "pressed" state.
8501 * @param x The x coordinate of the touch that caused the press
8502 * @param y The y coordinate of the touch that caused the press
8504 private void setPressed(boolean pressed, float x, float y) {
8506 drawableHotspotChanged(x, y);
8509 setPressed(pressed);
8513 * Sets the pressed state for this view.
8515 * @see #isClickable()
8516 * @see #setClickable(boolean)
8518 * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
8519 * the View's internal state from a previously set "pressed" state.
8521 public void setPressed(boolean pressed) {
8522 final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
8525 mPrivateFlags |= PFLAG_PRESSED;
8527 mPrivateFlags &= ~PFLAG_PRESSED;
8531 refreshDrawableState();
8533 dispatchSetPressed(pressed);
8537 * Dispatch setPressed to all of this View's children.
8539 * @see #setPressed(boolean)
8541 * @param pressed The new pressed state
8543 protected void dispatchSetPressed(boolean pressed) {
8547 * Indicates whether the view is currently in pressed state. Unless
8548 * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
8549 * the pressed state.
8551 * @see #setPressed(boolean)
8552 * @see #isClickable()
8553 * @see #setClickable(boolean)
8555 * @return true if the view is currently pressed, false otherwise
8557 @ViewDebug.ExportedProperty
8558 public boolean isPressed() {
8559 return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
8564 * Indicates whether this view will participate in data collection through
8565 * {@link ViewStructure}. If true, it will not provide any data
8566 * for itself or its children. If false, the normal data collection will be allowed.
8568 * @return Returns false if assist data collection is not blocked, else true.
8570 * @see #setAssistBlocked(boolean)
8571 * @attr ref android.R.styleable#View_assistBlocked
8573 public boolean isAssistBlocked() {
8574 return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
8579 * Controls whether assist data collection from this view and its children is enabled
8580 * (that is, whether {@link #onProvideStructure} and
8581 * {@link #onProvideVirtualStructure} will be called). The default value is false,
8582 * allowing normal assist collection. Setting this to false will disable assist collection.
8584 * @param enabled Set to true to <em>disable</em> assist data collection, or false
8585 * (the default) to allow it.
8587 * @see #isAssistBlocked()
8588 * @see #onProvideStructure
8589 * @see #onProvideVirtualStructure
8590 * @attr ref android.R.styleable#View_assistBlocked
8592 public void setAssistBlocked(boolean enabled) {
8594 mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
8596 mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
8601 * Indicates whether this view will save its state (that is,
8602 * whether its {@link #onSaveInstanceState} method will be called).
8604 * @return Returns true if the view state saving is enabled, else false.
8606 * @see #setSaveEnabled(boolean)
8607 * @attr ref android.R.styleable#View_saveEnabled
8609 public boolean isSaveEnabled() {
8610 return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
8614 * Controls whether the saving of this view's state is
8615 * enabled (that is, whether its {@link #onSaveInstanceState} method
8616 * will be called). Note that even if freezing is enabled, the
8617 * view still must have an id assigned to it (via {@link #setId(int)})
8618 * for its state to be saved. This flag can only disable the
8619 * saving of this view; any child views may still have their state saved.
8621 * @param enabled Set to false to <em>disable</em> state saving, or true
8622 * (the default) to allow it.
8624 * @see #isSaveEnabled()
8626 * @see #onSaveInstanceState()
8627 * @attr ref android.R.styleable#View_saveEnabled
8629 public void setSaveEnabled(boolean enabled) {
8630 setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
8634 * Gets whether the framework should discard touches when the view's
8635 * window is obscured by another visible window.
8636 * Refer to the {@link View} security documentation for more details.
8638 * @return True if touch filtering is enabled.
8640 * @see #setFilterTouchesWhenObscured(boolean)
8641 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8643 @ViewDebug.ExportedProperty
8644 public boolean getFilterTouchesWhenObscured() {
8645 return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
8649 * Sets whether the framework should discard touches when the view's
8650 * window is obscured by another visible window.
8651 * Refer to the {@link View} security documentation for more details.
8653 * @param enabled True if touch filtering should be enabled.
8655 * @see #getFilterTouchesWhenObscured
8656 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8658 public void setFilterTouchesWhenObscured(boolean enabled) {
8659 setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
8660 FILTER_TOUCHES_WHEN_OBSCURED);
8664 * Indicates whether the entire hierarchy under this view will save its
8665 * state when a state saving traversal occurs from its parent. The default
8666 * is true; if false, these views will not be saved unless
8667 * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8669 * @return Returns true if the view state saving from parent is enabled, else false.
8671 * @see #setSaveFromParentEnabled(boolean)
8673 public boolean isSaveFromParentEnabled() {
8674 return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
8678 * Controls whether the entire hierarchy under this view will save its
8679 * state when a state saving traversal occurs from its parent. The default
8680 * is true; if false, these views will not be saved unless
8681 * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8683 * @param enabled Set to false to <em>disable</em> state saving, or true
8684 * (the default) to allow it.
8686 * @see #isSaveFromParentEnabled()
8688 * @see #onSaveInstanceState()
8690 public void setSaveFromParentEnabled(boolean enabled) {
8691 setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
8696 * Returns whether this View is able to take focus.
8698 * @return True if this view can take focus, or false otherwise.
8699 * @attr ref android.R.styleable#View_focusable
8701 @ViewDebug.ExportedProperty(category = "focus")
8702 public final boolean isFocusable() {
8703 return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
8707 * When a view is focusable, it may not want to take focus when in touch mode.
8708 * For example, a button would like focus when the user is navigating via a D-pad
8709 * so that the user can click on it, but once the user starts touching the screen,
8710 * the button shouldn't take focus
8711 * @return Whether the view is focusable in touch mode.
8712 * @attr ref android.R.styleable#View_focusableInTouchMode
8714 @ViewDebug.ExportedProperty
8715 public final boolean isFocusableInTouchMode() {
8716 return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
8720 * Find the nearest view in the specified direction that can take focus.
8721 * This does not actually give focus to that view.
8723 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8725 * @return The nearest focusable in the specified direction, or null if none
8728 public View focusSearch(@FocusRealDirection int direction) {
8729 if (mParent != null) {
8730 return mParent.focusSearch(this, direction);
8737 * This method is the last chance for the focused view and its ancestors to
8738 * respond to an arrow key. This is called when the focused view did not
8739 * consume the key internally, nor could the view system find a new view in
8740 * the requested direction to give focus to.
8742 * @param focused The currently focused view.
8743 * @param direction The direction focus wants to move. One of FOCUS_UP,
8744 * FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
8745 * @return True if the this view consumed this unhandled move.
8747 public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
8752 * If a user manually specified the next view id for a particular direction,
8753 * use the root to look up the view.
8754 * @param root The root view of the hierarchy containing this view.
8755 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
8756 * or FOCUS_BACKWARD.
8757 * @return The user specified next view, or null if there is none.
8759 View findUserSetNextFocus(View root, @FocusDirection int direction) {
8760 switch (direction) {
8762 if (mNextFocusLeftId == View.NO_ID) return null;
8763 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
8765 if (mNextFocusRightId == View.NO_ID) return null;
8766 return findViewInsideOutShouldExist(root, mNextFocusRightId);
8768 if (mNextFocusUpId == View.NO_ID) return null;
8769 return findViewInsideOutShouldExist(root, mNextFocusUpId);
8771 if (mNextFocusDownId == View.NO_ID) return null;
8772 return findViewInsideOutShouldExist(root, mNextFocusDownId);
8774 if (mNextFocusForwardId == View.NO_ID) return null;
8775 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
8776 case FOCUS_BACKWARD: {
8777 if (mID == View.NO_ID) return null;
8779 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
8781 public boolean apply(View t) {
8782 return t.mNextFocusForwardId == id;
8790 private View findViewInsideOutShouldExist(View root, int id) {
8791 if (mMatchIdPredicate == null) {
8792 mMatchIdPredicate = new MatchIdPredicate();
8794 mMatchIdPredicate.mId = id;
8795 View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
8796 if (result == null) {
8797 Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
8803 * Find and return all focusable views that are descendants of this view,
8804 * possibly including this view if it is focusable itself.
8806 * @param direction The direction of the focus
8807 * @return A list of focusable views
8809 public ArrayList<View> getFocusables(@FocusDirection int direction) {
8810 ArrayList<View> result = new ArrayList<View>(24);
8811 addFocusables(result, direction);
8816 * Add any focusable views that are descendants of this view (possibly
8817 * including this view if it is focusable itself) to views. If we are in touch mode,
8818 * only add views that are also focusable in touch mode.
8820 * @param views Focusable views found so far
8821 * @param direction The direction of the focus
8823 public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
8824 addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
8828 * Adds any focusable views that are descendants of this view (possibly
8829 * including this view if it is focusable itself) to views. This method
8830 * adds all focusable views regardless if we are in touch mode or
8831 * only views focusable in touch mode if we are in touch mode or
8832 * only views that can take accessibility focus if accessibility is enabled
8833 * depending on the focusable mode parameter.
8835 * @param views Focusable views found so far or null if all we are interested is
8836 * the number of focusables.
8837 * @param direction The direction of the focus.
8838 * @param focusableMode The type of focusables to be added.
8840 * @see #FOCUSABLES_ALL
8841 * @see #FOCUSABLES_TOUCH_MODE
8843 public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
8844 @FocusableMode int focusableMode) {
8845 if (views == null) {
8848 if (!isFocusable()) {
8851 if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
8852 && !isFocusableInTouchMode()) {
8859 * Finds the Views that contain given text. The containment is case insensitive.
8860 * The search is performed by either the text that the View renders or the content
8861 * description that describes the view for accessibility purposes and the view does
8862 * not render or both. Clients can specify how the search is to be performed via
8863 * passing the {@link #FIND_VIEWS_WITH_TEXT} and
8864 * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
8866 * @param outViews The output list of matching Views.
8867 * @param searched The text to match against.
8869 * @see #FIND_VIEWS_WITH_TEXT
8870 * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
8871 * @see #setContentDescription(CharSequence)
8873 public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
8874 @FindViewFlags int flags) {
8875 if (getAccessibilityNodeProvider() != null) {
8876 if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
8879 } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
8880 && (searched != null && searched.length() > 0)
8881 && (mContentDescription != null && mContentDescription.length() > 0)) {
8882 String searchedLowerCase = searched.toString().toLowerCase();
8883 String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
8884 if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
8891 * Find and return all touchable views that are descendants of this view,
8892 * possibly including this view if it is touchable itself.
8894 * @return A list of touchable views
8896 public ArrayList<View> getTouchables() {
8897 ArrayList<View> result = new ArrayList<View>();
8898 addTouchables(result);
8903 * Add any touchable views that are descendants of this view (possibly
8904 * including this view if it is touchable itself) to views.
8906 * @param views Touchable views found so far
8908 public void addTouchables(ArrayList<View> views) {
8909 final int viewFlags = mViewFlags;
8911 if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
8912 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
8913 && (viewFlags & ENABLED_MASK) == ENABLED) {
8919 * Returns whether this View is accessibility focused.
8921 * @return True if this View is accessibility focused.
8923 public boolean isAccessibilityFocused() {
8924 return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
8928 * Call this to try to give accessibility focus to this view.
8930 * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
8931 * returns false or the view is no visible or the view already has accessibility
8934 * See also {@link #focusSearch(int)}, which is what you call to say that you
8935 * have focus, and you want your parent to look for the next one.
8937 * @return Whether this view actually took accessibility focus.
8941 public boolean requestAccessibilityFocus() {
8942 AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
8943 if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
8946 if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8949 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
8950 mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
8951 ViewRootImpl viewRootImpl = getViewRootImpl();
8952 if (viewRootImpl != null) {
8953 viewRootImpl.setAccessibilityFocus(this, null);
8956 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
8963 * Call this to try to clear accessibility focus of this view.
8965 * See also {@link #focusSearch(int)}, which is what you call to say that you
8966 * have focus, and you want your parent to look for the next one.
8970 public void clearAccessibilityFocus() {
8971 clearAccessibilityFocusNoCallbacks(0);
8973 // Clear the global reference of accessibility focus if this view or
8974 // any of its descendants had accessibility focus. This will NOT send
8975 // an event or update internal state if focus is cleared from a
8976 // descendant view, which may leave views in inconsistent states.
8977 final ViewRootImpl viewRootImpl = getViewRootImpl();
8978 if (viewRootImpl != null) {
8979 final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
8980 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8981 viewRootImpl.setAccessibilityFocus(null, null);
8986 private void sendAccessibilityHoverEvent(int eventType) {
8987 // Since we are not delivering to a client accessibility events from not
8988 // important views (unless the clinet request that) we need to fire the
8989 // event from the deepest view exposed to the client. As a consequence if
8990 // the user crosses a not exposed view the client will see enter and exit
8991 // of the exposed predecessor followed by and enter and exit of that same
8992 // predecessor when entering and exiting the not exposed descendant. This
8993 // is fine since the client has a clear idea which view is hovered at the
8994 // price of a couple more events being sent. This is a simple and
8995 // working solution.
8998 if (source.includeForAccessibility()) {
8999 source.sendAccessibilityEvent(eventType);
9002 ViewParent parent = source.getParent();
9003 if (parent instanceof View) {
9004 source = (View) parent;
9012 * Clears accessibility focus without calling any callback methods
9013 * normally invoked in {@link #clearAccessibilityFocus()}. This method
9014 * is used separately from that one for clearing accessibility focus when
9015 * giving this focus to another view.
9017 * @param action The action, if any, that led to focus being cleared. Set to
9018 * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
9021 void clearAccessibilityFocusNoCallbacks(int action) {
9022 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
9023 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
9025 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
9026 AccessibilityEvent event = AccessibilityEvent.obtain(
9027 AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
9028 event.setAction(action);
9029 if (mAccessibilityDelegate != null) {
9030 mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
9032 sendAccessibilityEventUnchecked(event);
9039 * Call this to try to give focus to a specific view or to one of its
9042 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9043 * false), or if it is focusable and it is not focusable in touch mode
9044 * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9046 * See also {@link #focusSearch(int)}, which is what you call to say that you
9047 * have focus, and you want your parent to look for the next one.
9049 * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
9050 * {@link #FOCUS_DOWN} and <code>null</code>.
9052 * @return Whether this view or one of its descendants actually took focus.
9054 public final boolean requestFocus() {
9055 return requestFocus(View.FOCUS_DOWN);
9059 * Call this to try to give focus to a specific view or to one of its
9060 * descendants and give it a hint about what direction focus is heading.
9062 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9063 * false), or if it is focusable and it is not focusable in touch mode
9064 * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9066 * See also {@link #focusSearch(int)}, which is what you call to say that you
9067 * have focus, and you want your parent to look for the next one.
9069 * This is equivalent to calling {@link #requestFocus(int, Rect)} with
9070 * <code>null</code> set for the previously focused rectangle.
9072 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9073 * @return Whether this view or one of its descendants actually took focus.
9075 public final boolean requestFocus(int direction) {
9076 return requestFocus(direction, null);
9080 * Call this to try to give focus to a specific view or to one of its descendants
9081 * and give it hints about the direction and a specific rectangle that the focus
9082 * is coming from. The rectangle can help give larger views a finer grained hint
9083 * about where focus is coming from, and therefore, where to show selection, or
9084 * forward focus change internally.
9086 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9087 * false), or if it is focusable and it is not focusable in touch mode
9088 * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9090 * A View will not take focus if it is not visible.
9092 * A View will not take focus if one of its parents has
9093 * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
9094 * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
9096 * See also {@link #focusSearch(int)}, which is what you call to say that you
9097 * have focus, and you want your parent to look for the next one.
9099 * You may wish to override this method if your custom {@link View} has an internal
9100 * {@link View} that it wishes to forward the request to.
9102 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9103 * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
9104 * to give a finer grained hint about where focus is coming from. May be null
9105 * if there is no hint.
9106 * @return Whether this view or one of its descendants actually took focus.
9108 public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
9109 return requestFocusNoSearch(direction, previouslyFocusedRect);
9112 private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
9113 // need to be focusable
9114 if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
9115 (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
9119 // need to be focusable in touch mode if in touch mode
9120 if (isInTouchMode() &&
9121 (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
9125 // need to not have any parents blocking us
9126 if (hasAncestorThatBlocksDescendantFocus()) {
9130 handleFocusGainInternal(direction, previouslyFocusedRect);
9135 * Call this to try to give focus to a specific view or to one of its descendants. This is a
9136 * special variant of {@link #requestFocus() } that will allow views that are not focusable in
9137 * touch mode to request focus when they are touched.
9139 * @return Whether this view or one of its descendants actually took focus.
9141 * @see #isInTouchMode()
9144 public final boolean requestFocusFromTouch() {
9145 // Leave touch mode if we need to
9146 if (isInTouchMode()) {
9147 ViewRootImpl viewRoot = getViewRootImpl();
9148 if (viewRoot != null) {
9149 viewRoot.ensureTouchMode(false);
9152 return requestFocus(View.FOCUS_DOWN);
9156 * @return Whether any ancestor of this view blocks descendant focus.
9158 private boolean hasAncestorThatBlocksDescendantFocus() {
9159 final boolean focusableInTouchMode = isFocusableInTouchMode();
9160 ViewParent ancestor = mParent;
9161 while (ancestor instanceof ViewGroup) {
9162 final ViewGroup vgAncestor = (ViewGroup) ancestor;
9163 if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
9164 || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
9167 ancestor = vgAncestor.getParent();
9174 * Gets the mode for determining whether this View is important for accessibility
9175 * which is if it fires accessibility events and if it is reported to
9176 * accessibility services that query the screen.
9178 * @return The mode for determining whether a View is important for accessibility.
9180 * @attr ref android.R.styleable#View_importantForAccessibility
9182 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9183 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9184 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9185 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9187 @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
9188 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
9189 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
9190 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
9191 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
9192 to = "noHideDescendants")
9194 public int getImportantForAccessibility() {
9195 return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9196 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9200 * Sets the live region mode for this view. This indicates to accessibility
9201 * services whether they should automatically notify the user about changes
9202 * to the view's content description or text, or to the content descriptions
9203 * or text of the view's children (where applicable).
9205 * For example, in a login screen with a TextView that displays an "incorrect
9206 * password" notification, that view should be marked as a live region with
9207 * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9209 * To disable change notifications for this view, use
9210 * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
9211 * mode for most views.
9213 * To indicate that the user should be notified of changes, use
9214 * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9216 * If the view's changes should interrupt ongoing speech and notify the user
9217 * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
9219 * @param mode The live region mode for this view, one of:
9221 * <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
9222 * <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
9223 * <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
9225 * @attr ref android.R.styleable#View_accessibilityLiveRegion
9227 public void setAccessibilityLiveRegion(int mode) {
9228 if (mode != getAccessibilityLiveRegion()) {
9229 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9230 mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
9231 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9232 notifyViewAccessibilityStateChangedIfNeeded(
9233 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9238 * Gets the live region mode for this View.
9240 * @return The live region mode for the view.
9242 * @attr ref android.R.styleable#View_accessibilityLiveRegion
9244 * @see #setAccessibilityLiveRegion(int)
9246 public int getAccessibilityLiveRegion() {
9247 return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
9248 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
9252 * Sets how to determine whether this view is important for accessibility
9253 * which is if it fires accessibility events and if it is reported to
9254 * accessibility services that query the screen.
9256 * @param mode How to determine whether this view is important for accessibility.
9258 * @attr ref android.R.styleable#View_importantForAccessibility
9260 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9261 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9262 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9263 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9265 public void setImportantForAccessibility(int mode) {
9266 final int oldMode = getImportantForAccessibility();
9267 if (mode != oldMode) {
9268 final boolean hideDescendants =
9269 mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
9271 // If this node or its descendants are no longer important, try to
9272 // clear accessibility focus.
9273 if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
9274 final View focusHost = findAccessibilityFocusHost(hideDescendants);
9275 if (focusHost != null) {
9276 focusHost.clearAccessibilityFocus();
9280 // If we're moving between AUTO and another state, we might not need
9281 // to send a subtree changed notification. We'll store the computed
9282 // importance, since we'll need to check it later to make sure.
9283 final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
9284 || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
9285 final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
9286 mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9287 mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
9288 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9289 if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
9290 notifySubtreeAccessibilityStateChangedIfNeeded();
9292 notifyViewAccessibilityStateChangedIfNeeded(
9293 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9299 * Returns the view within this view's hierarchy that is hosting
9300 * accessibility focus.
9302 * @param searchDescendants whether to search for focus in descendant views
9303 * @return the view hosting accessibility focus, or {@code null}
9305 private View findAccessibilityFocusHost(boolean searchDescendants) {
9306 if (isAccessibilityFocusedViewOrHost()) {
9310 if (searchDescendants) {
9311 final ViewRootImpl viewRoot = getViewRootImpl();
9312 if (viewRoot != null) {
9313 final View focusHost = viewRoot.getAccessibilityFocusedHost();
9314 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
9324 * Computes whether this view should be exposed for accessibility. In
9325 * general, views that are interactive or provide information are exposed
9326 * while views that serve only as containers are hidden.
9328 * If an ancestor of this view has importance
9329 * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
9330 * returns <code>false</code>.
9332 * Otherwise, the value is computed according to the view's
9333 * {@link #getImportantForAccessibility()} value:
9335 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
9336 * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
9338 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
9339 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
9340 * view satisfies any of the following:
9342 * <li>Is actionable, e.g. {@link #isClickable()},
9343 * {@link #isLongClickable()}, or {@link #isFocusable()}
9344 * <li>Has an {@link AccessibilityDelegate}
9345 * <li>Has an interaction listener, e.g. {@link OnTouchListener},
9346 * {@link OnKeyListener}, etc.
9347 * <li>Is an accessibility live region, e.g.
9348 * {@link #getAccessibilityLiveRegion()} is not
9349 * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
9353 * @return Whether the view is exposed for accessibility.
9354 * @see #setImportantForAccessibility(int)
9355 * @see #getImportantForAccessibility()
9357 public boolean isImportantForAccessibility() {
9358 final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9359 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9360 if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
9361 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
9365 // Check parent mode to ensure we're not hidden.
9366 ViewParent parent = mParent;
9367 while (parent instanceof View) {
9368 if (((View) parent).getImportantForAccessibility()
9369 == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
9372 parent = parent.getParent();
9375 return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
9376 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
9377 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
9381 * Gets the parent for accessibility purposes. Note that the parent for
9382 * accessibility is not necessary the immediate parent. It is the first
9383 * predecessor that is important for accessibility.
9385 * @return The parent for accessibility purposes.
9387 public ViewParent getParentForAccessibility() {
9388 if (mParent instanceof View) {
9389 View parentView = (View) mParent;
9390 if (parentView.includeForAccessibility()) {
9393 return mParent.getParentForAccessibility();
9400 * Adds the children of this View relevant for accessibility to the given list
9401 * as output. Since some Views are not important for accessibility the added
9402 * child views are not necessarily direct children of this view, rather they are
9403 * the first level of descendants important for accessibility.
9405 * @param outChildren The output list that will receive children for accessibility.
9407 public void addChildrenForAccessibility(ArrayList<View> outChildren) {
9412 * Whether to regard this view for accessibility. A view is regarded for
9413 * accessibility if it is important for accessibility or the querying
9414 * accessibility service has explicitly requested that view not
9415 * important for accessibility are regarded.
9417 * @return Whether to regard the view for accessibility.
9421 public boolean includeForAccessibility() {
9422 if (mAttachInfo != null) {
9423 return (mAttachInfo.mAccessibilityFetchFlags
9424 & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
9425 || isImportantForAccessibility();
9431 * Returns whether the View is considered actionable from
9432 * accessibility perspective. Such view are important for
9435 * @return True if the view is actionable for accessibility.
9439 public boolean isActionableForAccessibility() {
9440 return (isClickable() || isLongClickable() || isFocusable());
9444 * Returns whether the View has registered callbacks which makes it
9445 * important for accessibility.
9447 * @return True if the view is actionable for accessibility.
9449 private boolean hasListenersForAccessibility() {
9450 ListenerInfo info = getListenerInfo();
9451 return mTouchDelegate != null || info.mOnKeyListener != null
9452 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
9453 || info.mOnHoverListener != null || info.mOnDragListener != null;
9457 * Notifies that the accessibility state of this view changed. The change
9458 * is local to this view and does not represent structural changes such
9459 * as children and parent. For example, the view became focusable. The
9460 * notification is at at most once every
9461 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9462 * to avoid unnecessary load to the system. Also once a view has a pending
9463 * notification this method is a NOP until the notification has been sent.
9467 public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
9468 if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9471 if (mSendViewStateChangedAccessibilityEvent == null) {
9472 mSendViewStateChangedAccessibilityEvent =
9473 new SendViewStateChangedAccessibilityEvent();
9475 mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
9479 * Notifies that the accessibility state of this view changed. The change
9480 * is *not* local to this view and does represent structural changes such
9481 * as children and parent. For example, the view size changed. The
9482 * notification is at at most once every
9483 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9484 * to avoid unnecessary load to the system. Also once a view has a pending
9485 * notification this method is a NOP until the notification has been sent.
9489 public void notifySubtreeAccessibilityStateChangedIfNeeded() {
9490 if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9493 if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
9494 mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9495 if (mParent != null) {
9497 mParent.notifySubtreeAccessibilityStateChanged(
9498 this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
9499 } catch (AbstractMethodError e) {
9500 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9501 " does not fully implement ViewParent", e);
9508 * Change the visibility of the View without triggering any other changes. This is
9509 * important for transitions, where visibility changes should not adjust focus or
9510 * trigger a new layout. This is only used when the visibility has already been changed
9511 * and we need a transient value during an animation. When the animation completes,
9512 * the original visibility value is always restored.
9514 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9517 public void setTransitionVisibility(@Visibility int visibility) {
9518 mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
9522 * Reset the flag indicating the accessibility state of the subtree rooted
9523 * at this view changed.
9525 void resetSubtreeAccessibilityStateChanged() {
9526 mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9530 * Report an accessibility action to this view's parents for delegated processing.
9532 * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
9533 * call this method to delegate an accessibility action to a supporting parent. If the parent
9534 * returns true from its
9535 * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
9536 * method this method will return true to signify that the action was consumed.</p>
9538 * <p>This method is useful for implementing nested scrolling child views. If
9539 * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
9540 * a custom view implementation may invoke this method to allow a parent to consume the
9541 * scroll first. If this method returns true the custom view should skip its own scrolling
9544 * @param action Accessibility action to delegate
9545 * @param arguments Optional action arguments
9546 * @return true if the action was consumed by a parent
9548 public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
9549 for (ViewParent p = getParent(); p != null; p = p.getParent()) {
9550 if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
9558 * Performs the specified accessibility action on the view. For
9559 * possible accessibility actions look at {@link AccessibilityNodeInfo}.
9561 * If an {@link AccessibilityDelegate} has been specified via calling
9562 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9563 * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
9564 * is responsible for handling this call.
9567 * <p>The default implementation will delegate
9568 * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
9569 * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
9570 * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
9572 * @param action The action to perform.
9573 * @param arguments Optional action arguments.
9574 * @return Whether the action was performed.
9576 public boolean performAccessibilityAction(int action, Bundle arguments) {
9577 if (mAccessibilityDelegate != null) {
9578 return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
9580 return performAccessibilityActionInternal(action, arguments);
9585 * @see #performAccessibilityAction(int, Bundle)
9587 * Note: Called from the default {@link AccessibilityDelegate}.
9591 public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
9592 if (isNestedScrollingEnabled()
9593 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
9594 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
9595 || action == R.id.accessibilityActionScrollUp
9596 || action == R.id.accessibilityActionScrollLeft
9597 || action == R.id.accessibilityActionScrollDown
9598 || action == R.id.accessibilityActionScrollRight)) {
9599 if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
9605 case AccessibilityNodeInfo.ACTION_CLICK: {
9606 if (isClickable()) {
9611 case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
9612 if (isLongClickable()) {
9617 case AccessibilityNodeInfo.ACTION_FOCUS: {
9619 // Get out of touch mode since accessibility
9620 // wants to move focus around.
9621 getViewRootImpl().ensureTouchMode(false);
9622 return requestFocus();
9625 case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
9628 return !isFocused();
9631 case AccessibilityNodeInfo.ACTION_SELECT: {
9632 if (!isSelected()) {
9634 return isSelected();
9637 case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
9640 return !isSelected();
9643 case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
9644 if (!isAccessibilityFocused()) {
9645 return requestAccessibilityFocus();
9648 case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
9649 if (isAccessibilityFocused()) {
9650 clearAccessibilityFocus();
9654 case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
9655 if (arguments != null) {
9656 final int granularity = arguments.getInt(
9657 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9658 final boolean extendSelection = arguments.getBoolean(
9659 AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9660 return traverseAtGranularity(granularity, true, extendSelection);
9663 case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
9664 if (arguments != null) {
9665 final int granularity = arguments.getInt(
9666 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9667 final boolean extendSelection = arguments.getBoolean(
9668 AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9669 return traverseAtGranularity(granularity, false, extendSelection);
9672 case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
9673 CharSequence text = getIterableTextForAccessibility();
9677 final int start = (arguments != null) ? arguments.getInt(
9678 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
9679 final int end = (arguments != null) ? arguments.getInt(
9680 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
9681 // Only cursor position can be specified (selection length == 0)
9682 if ((getAccessibilitySelectionStart() != start
9683 || getAccessibilitySelectionEnd() != end)
9684 && (start == end)) {
9685 setAccessibilitySelection(start, end);
9686 notifyViewAccessibilityStateChangedIfNeeded(
9687 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9691 case R.id.accessibilityActionShowOnScreen: {
9692 if (mAttachInfo != null) {
9693 final Rect r = mAttachInfo.mTmpInvalRect;
9695 return requestRectangleOnScreen(r, true);
9698 case R.id.accessibilityActionContextClick: {
9699 if (isContextClickable()) {
9700 performContextClick();
9708 private boolean traverseAtGranularity(int granularity, boolean forward,
9709 boolean extendSelection) {
9710 CharSequence text = getIterableTextForAccessibility();
9711 if (text == null || text.length() == 0) {
9714 TextSegmentIterator iterator = getIteratorForGranularity(granularity);
9715 if (iterator == null) {
9718 int current = getAccessibilitySelectionEnd();
9719 if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9720 current = forward ? 0 : text.length();
9722 final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
9723 if (range == null) {
9726 final int segmentStart = range[0];
9727 final int segmentEnd = range[1];
9730 if (extendSelection && isAccessibilitySelectionExtendable()) {
9731 selectionStart = getAccessibilitySelectionStart();
9732 if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9733 selectionStart = forward ? segmentStart : segmentEnd;
9735 selectionEnd = forward ? segmentEnd : segmentStart;
9737 selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
9739 setAccessibilitySelection(selectionStart, selectionEnd);
9740 final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
9741 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
9742 sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
9747 * Gets the text reported for accessibility purposes.
9749 * @return The accessibility text.
9753 public CharSequence getIterableTextForAccessibility() {
9754 return getContentDescription();
9758 * Gets whether accessibility selection can be extended.
9760 * @return If selection is extensible.
9764 public boolean isAccessibilitySelectionExtendable() {
9771 public int getAccessibilitySelectionStart() {
9772 return mAccessibilityCursorPosition;
9778 public int getAccessibilitySelectionEnd() {
9779 return getAccessibilitySelectionStart();
9785 public void setAccessibilitySelection(int start, int end) {
9786 if (start == end && end == mAccessibilityCursorPosition) {
9789 if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
9790 mAccessibilityCursorPosition = start;
9792 mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
9794 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
9797 private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
9798 int fromIndex, int toIndex) {
9799 if (mParent == null) {
9802 AccessibilityEvent event = AccessibilityEvent.obtain(
9803 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
9804 onInitializeAccessibilityEvent(event);
9805 onPopulateAccessibilityEvent(event);
9806 event.setFromIndex(fromIndex);
9807 event.setToIndex(toIndex);
9808 event.setAction(action);
9809 event.setMovementGranularity(granularity);
9810 mParent.requestSendAccessibilityEvent(this, event);
9816 public TextSegmentIterator getIteratorForGranularity(int granularity) {
9817 switch (granularity) {
9818 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
9819 CharSequence text = getIterableTextForAccessibility();
9820 if (text != null && text.length() > 0) {
9821 CharacterTextSegmentIterator iterator =
9822 CharacterTextSegmentIterator.getInstance(
9823 mContext.getResources().getConfiguration().locale);
9824 iterator.initialize(text.toString());
9828 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
9829 CharSequence text = getIterableTextForAccessibility();
9830 if (text != null && text.length() > 0) {
9831 WordTextSegmentIterator iterator =
9832 WordTextSegmentIterator.getInstance(
9833 mContext.getResources().getConfiguration().locale);
9834 iterator.initialize(text.toString());
9838 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
9839 CharSequence text = getIterableTextForAccessibility();
9840 if (text != null && text.length() > 0) {
9841 ParagraphTextSegmentIterator iterator =
9842 ParagraphTextSegmentIterator.getInstance();
9843 iterator.initialize(text.toString());
9852 * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
9853 * and {@link #onFinishTemporaryDetach()}.
9855 * <p>This method always returns {@code true} when called directly or indirectly from
9856 * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
9857 * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
9859 * <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
9860 * <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
9864 * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
9865 * and {@link #onFinishTemporaryDetach()}.
9867 public final boolean isTemporarilyDetached() {
9868 return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
9872 * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
9876 public void dispatchStartTemporaryDetach() {
9877 mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
9878 onStartTemporaryDetach();
9882 * This is called when a container is going to temporarily detach a child, with
9883 * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
9884 * It will either be followed by {@link #onFinishTemporaryDetach()} or
9885 * {@link #onDetachedFromWindow()} when the container is done.
9887 public void onStartTemporaryDetach() {
9888 removeUnsetPressCallback();
9889 mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
9893 * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
9897 public void dispatchFinishTemporaryDetach() {
9898 mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
9899 onFinishTemporaryDetach();
9900 if (hasWindowFocus() && hasFocus()) {
9901 InputMethodManager.getInstance().focusIn(this);
9906 * Called after {@link #onStartTemporaryDetach} when the container is done
9907 * changing the view.
9909 public void onFinishTemporaryDetach() {
9913 * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
9914 * for this view's window. Returns null if the view is not currently attached
9915 * to the window. Normally you will not need to use this directly, but
9916 * just use the standard high-level event callbacks like
9917 * {@link #onKeyDown(int, KeyEvent)}.
9919 public KeyEvent.DispatcherState getKeyDispatcherState() {
9920 return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
9924 * Dispatch a key event before it is processed by any input method
9925 * associated with the view hierarchy. This can be used to intercept
9926 * key events in special situations before the IME consumes them; a
9927 * typical example would be handling the BACK key to update the application's
9928 * UI instead of allowing the IME to see it and close itself.
9930 * @param event The key event to be dispatched.
9931 * @return True if the event was handled, false otherwise.
9933 public boolean dispatchKeyEventPreIme(KeyEvent event) {
9934 return onKeyPreIme(event.getKeyCode(), event);
9938 * Dispatch a key event to the next view on the focus path. This path runs
9939 * from the top of the view tree down to the currently focused view. If this
9940 * view has focus, it will dispatch to itself. Otherwise it will dispatch
9941 * the next node down the focus path. This method also fires any key
9944 * @param event The key event to be dispatched.
9945 * @return True if the event was handled, false otherwise.
9947 public boolean dispatchKeyEvent(KeyEvent event) {
9948 if (mInputEventConsistencyVerifier != null) {
9949 mInputEventConsistencyVerifier.onKeyEvent(event, 0);
9952 // Give any attached key listener a first crack at the event.
9953 //noinspection SimplifiableIfStatement
9954 ListenerInfo li = mListenerInfo;
9955 if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
9956 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
9960 if (event.dispatch(this, mAttachInfo != null
9961 ? mAttachInfo.mKeyDispatchState : null, this)) {
9965 if (mInputEventConsistencyVerifier != null) {
9966 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9972 * Dispatches a key shortcut event.
9974 * @param event The key event to be dispatched.
9975 * @return True if the event was handled by the view, false otherwise.
9977 public boolean dispatchKeyShortcutEvent(KeyEvent event) {
9978 return onKeyShortcut(event.getKeyCode(), event);
9982 * Pass the touch screen motion event down to the target view, or this
9983 * view if it is the target.
9985 * @param event The motion event to be dispatched.
9986 * @return True if the event was handled by the view, false otherwise.
9988 public boolean dispatchTouchEvent(MotionEvent event) {
9989 // If the event should be handled by accessibility focus first.
9990 if (event.isTargetAccessibilityFocus()) {
9991 // We don't have focus or no virtual descendant has it, do not handle the event.
9992 if (!isAccessibilityFocusedViewOrHost()) {
9995 // We have focus and got the event, then use normal event dispatch.
9996 event.setTargetAccessibilityFocus(false);
9999 boolean result = false;
10001 if (mInputEventConsistencyVerifier != null) {
10002 mInputEventConsistencyVerifier.onTouchEvent(event, 0);
10005 final int actionMasked = event.getActionMasked();
10006 if (actionMasked == MotionEvent.ACTION_DOWN) {
10007 // Defensive cleanup for new gesture
10008 stopNestedScroll();
10011 if (onFilterTouchEventForSecurity(event)) {
10012 if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
10015 //noinspection SimplifiableIfStatement
10016 ListenerInfo li = mListenerInfo;
10017 if (li != null && li.mOnTouchListener != null
10018 && (mViewFlags & ENABLED_MASK) == ENABLED
10019 && li.mOnTouchListener.onTouch(this, event)) {
10023 if (!result && onTouchEvent(event)) {
10028 if (!result && mInputEventConsistencyVerifier != null) {
10029 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10032 // Clean up after nested scrolls if this is the end of a gesture;
10033 // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
10035 if (actionMasked == MotionEvent.ACTION_UP ||
10036 actionMasked == MotionEvent.ACTION_CANCEL ||
10037 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
10038 stopNestedScroll();
10044 boolean isAccessibilityFocusedViewOrHost() {
10045 return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
10046 .getAccessibilityFocusedHost() == this);
10050 * Filter the touch event to apply security policies.
10052 * @param event The motion event to be filtered.
10053 * @return True if the event should be dispatched, false if the event should be dropped.
10055 * @see #getFilterTouchesWhenObscured
10057 public boolean onFilterTouchEventForSecurity(MotionEvent event) {
10058 //noinspection RedundantIfStatement
10059 if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
10060 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
10061 // Window is obscured, drop this touch.
10068 * Pass a trackball motion event down to the focused view.
10070 * @param event The motion event to be dispatched.
10071 * @return True if the event was handled by the view, false otherwise.
10073 public boolean dispatchTrackballEvent(MotionEvent event) {
10074 if (mInputEventConsistencyVerifier != null) {
10075 mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
10078 return onTrackballEvent(event);
10082 * Dispatch a generic motion event.
10084 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10085 * are delivered to the view under the pointer. All other generic motion events are
10086 * delivered to the focused view. Hover events are handled specially and are delivered
10087 * to {@link #onHoverEvent(MotionEvent)}.
10090 * @param event The motion event to be dispatched.
10091 * @return True if the event was handled by the view, false otherwise.
10093 public boolean dispatchGenericMotionEvent(MotionEvent event) {
10094 if (mInputEventConsistencyVerifier != null) {
10095 mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
10098 final int source = event.getSource();
10099 if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
10100 final int action = event.getAction();
10101 if (action == MotionEvent.ACTION_HOVER_ENTER
10102 || action == MotionEvent.ACTION_HOVER_MOVE
10103 || action == MotionEvent.ACTION_HOVER_EXIT) {
10104 if (dispatchHoverEvent(event)) {
10107 } else if (dispatchGenericPointerEvent(event)) {
10110 } else if (dispatchGenericFocusedEvent(event)) {
10114 if (dispatchGenericMotionEventInternal(event)) {
10118 if (mInputEventConsistencyVerifier != null) {
10119 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10124 private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
10125 //noinspection SimplifiableIfStatement
10126 ListenerInfo li = mListenerInfo;
10127 if (li != null && li.mOnGenericMotionListener != null
10128 && (mViewFlags & ENABLED_MASK) == ENABLED
10129 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
10133 if (onGenericMotionEvent(event)) {
10137 final int actionButton = event.getActionButton();
10138 switch (event.getActionMasked()) {
10139 case MotionEvent.ACTION_BUTTON_PRESS:
10140 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
10141 && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10142 || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10143 if (performContextClick(event.getX(), event.getY())) {
10144 mInContextButtonPress = true;
10145 setPressed(true, event.getX(), event.getY());
10146 removeTapCallback();
10147 removeLongPressCallback();
10153 case MotionEvent.ACTION_BUTTON_RELEASE:
10154 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10155 || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10156 mInContextButtonPress = false;
10157 mIgnoreNextUpEvent = true;
10162 if (mInputEventConsistencyVerifier != null) {
10163 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10169 * Dispatch a hover event.
10171 * Do not call this method directly.
10172 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10175 * @param event The motion event to be dispatched.
10176 * @return True if the event was handled by the view, false otherwise.
10178 protected boolean dispatchHoverEvent(MotionEvent event) {
10179 ListenerInfo li = mListenerInfo;
10180 //noinspection SimplifiableIfStatement
10181 if (li != null && li.mOnHoverListener != null
10182 && (mViewFlags & ENABLED_MASK) == ENABLED
10183 && li.mOnHoverListener.onHover(this, event)) {
10187 return onHoverEvent(event);
10191 * Returns true if the view has a child to which it has recently sent
10192 * {@link MotionEvent#ACTION_HOVER_ENTER}. If this view is hovered and
10193 * it does not have a hovered child, then it must be the innermost hovered view.
10196 protected boolean hasHoveredChild() {
10201 * Dispatch a generic motion event to the view under the first pointer.
10203 * Do not call this method directly.
10204 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10207 * @param event The motion event to be dispatched.
10208 * @return True if the event was handled by the view, false otherwise.
10210 protected boolean dispatchGenericPointerEvent(MotionEvent event) {
10215 * Dispatch a generic motion event to the currently focused view.
10217 * Do not call this method directly.
10218 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10221 * @param event The motion event to be dispatched.
10222 * @return True if the event was handled by the view, false otherwise.
10224 protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
10229 * Dispatch a pointer event.
10231 * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
10232 * other events to {@link #onGenericMotionEvent(MotionEvent)}. This separation of concerns
10233 * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
10234 * and should not be expected to handle other pointing device features.
10237 * @param event The motion event to be dispatched.
10238 * @return True if the event was handled by the view, false otherwise.
10241 public final boolean dispatchPointerEvent(MotionEvent event) {
10242 if (event.isTouchEvent()) {
10243 return dispatchTouchEvent(event);
10245 return dispatchGenericMotionEvent(event);
10250 * Called when the window containing this view gains or loses window focus.
10251 * ViewGroups should override to route to their children.
10253 * @param hasFocus True if the window containing this view now has focus,
10256 public void dispatchWindowFocusChanged(boolean hasFocus) {
10257 onWindowFocusChanged(hasFocus);
10261 * Called when the window containing this view gains or loses focus. Note
10262 * that this is separate from view focus: to receive key events, both
10263 * your view and its window must have focus. If a window is displayed
10264 * on top of yours that takes input focus, then your own window will lose
10265 * focus but the view focus will remain unchanged.
10267 * @param hasWindowFocus True if the window containing this view now has
10268 * focus, false otherwise.
10270 public void onWindowFocusChanged(boolean hasWindowFocus) {
10271 InputMethodManager imm = InputMethodManager.peekInstance();
10272 if (!hasWindowFocus) {
10276 if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10277 imm.focusOut(this);
10279 removeLongPressCallback();
10280 removeTapCallback();
10282 } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10285 refreshDrawableState();
10289 * Returns true if this view is in a window that currently has window focus.
10290 * Note that this is not the same as the view itself having focus.
10292 * @return True if this view is in a window that currently has window focus.
10294 public boolean hasWindowFocus() {
10295 return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
10299 * Dispatch a view visibility change down the view hierarchy.
10300 * ViewGroups should override to route to their children.
10301 * @param changedView The view whose visibility changed. Could be 'this' or
10302 * an ancestor view.
10303 * @param visibility The new visibility of changedView: {@link #VISIBLE},
10304 * {@link #INVISIBLE} or {@link #GONE}.
10306 protected void dispatchVisibilityChanged(@NonNull View changedView,
10307 @Visibility int visibility) {
10308 onVisibilityChanged(changedView, visibility);
10312 * Called when the visibility of the view or an ancestor of the view has
10315 * @param changedView The view whose visibility changed. May be
10316 * {@code this} or an ancestor view.
10317 * @param visibility The new visibility, one of {@link #VISIBLE},
10318 * {@link #INVISIBLE} or {@link #GONE}.
10320 protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
10324 * Dispatch a hint about whether this view is displayed. For instance, when
10325 * a View moves out of the screen, it might receives a display hint indicating
10326 * the view is not displayed. Applications should not <em>rely</em> on this hint
10327 * as there is no guarantee that they will receive one.
10329 * @param hint A hint about whether or not this view is displayed:
10330 * {@link #VISIBLE} or {@link #INVISIBLE}.
10332 public void dispatchDisplayHint(@Visibility int hint) {
10333 onDisplayHint(hint);
10337 * Gives this view a hint about whether is displayed or not. For instance, when
10338 * a View moves out of the screen, it might receives a display hint indicating
10339 * the view is not displayed. Applications should not <em>rely</em> on this hint
10340 * as there is no guarantee that they will receive one.
10342 * @param hint A hint about whether or not this view is displayed:
10343 * {@link #VISIBLE} or {@link #INVISIBLE}.
10345 protected void onDisplayHint(@Visibility int hint) {
10349 * Dispatch a window visibility change down the view hierarchy.
10350 * ViewGroups should override to route to their children.
10352 * @param visibility The new visibility of the window.
10354 * @see #onWindowVisibilityChanged(int)
10356 public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
10357 onWindowVisibilityChanged(visibility);
10361 * Called when the window containing has change its visibility
10362 * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}). Note
10363 * that this tells you whether or not your window is being made visible
10364 * to the window manager; this does <em>not</em> tell you whether or not
10365 * your window is obscured by other windows on the screen, even if it
10366 * is itself visible.
10368 * @param visibility The new visibility of the window.
10370 protected void onWindowVisibilityChanged(@Visibility int visibility) {
10371 if (visibility == VISIBLE) {
10372 initialAwakenScrollBars();
10377 * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
10378 * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
10379 * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
10381 * @param isVisible true if this view's visibility to the user is uninterrupted by its
10382 * ancestors or by window visibility
10383 * @return true if this view is visible to the user, not counting clipping or overlapping
10385 boolean dispatchVisibilityAggregated(boolean isVisible) {
10386 final boolean thisVisible = getVisibility() == VISIBLE;
10387 // If we're not visible but something is telling us we are, ignore it.
10388 if (thisVisible || !isVisible) {
10389 onVisibilityAggregated(isVisible);
10391 return thisVisible && isVisible;
10395 * Called when the user-visibility of this View is potentially affected by a change
10396 * to this view itself, an ancestor view or the window this view is attached to.
10398 * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
10399 * and this view's window is also visible
10402 public void onVisibilityAggregated(boolean isVisible) {
10403 if (isVisible && mAttachInfo != null) {
10404 initialAwakenScrollBars();
10407 final Drawable dr = mBackground;
10408 if (dr != null && isVisible != dr.isVisible()) {
10409 dr.setVisible(isVisible, false);
10411 final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
10412 if (fg != null && isVisible != fg.isVisible()) {
10413 fg.setVisible(isVisible, false);
10418 * Returns the current visibility of the window this view is attached to
10419 * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
10421 * @return Returns the current visibility of the view's window.
10424 public int getWindowVisibility() {
10425 return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
10429 * Retrieve the overall visible display size in which the window this view is
10430 * attached to has been positioned in. This takes into account screen
10431 * decorations above the window, for both cases where the window itself
10432 * is being position inside of them or the window is being placed under
10433 * then and covered insets are used for the window to position its content
10434 * inside. In effect, this tells you the available area where content can
10435 * be placed and remain visible to users.
10437 * <p>This function requires an IPC back to the window manager to retrieve
10438 * the requested information, so should not be used in performance critical
10439 * code like drawing.
10441 * @param outRect Filled in with the visible display frame. If the view
10442 * is not attached to a window, this is simply the raw display size.
10444 public void getWindowVisibleDisplayFrame(Rect outRect) {
10445 if (mAttachInfo != null) {
10447 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
10448 } catch (RemoteException e) {
10451 // XXX This is really broken, and probably all needs to be done
10452 // in the window manager, and we need to know more about whether
10453 // we want the area behind or in front of the IME.
10454 final Rect insets = mAttachInfo.mVisibleInsets;
10455 outRect.left += insets.left;
10456 outRect.top += insets.top;
10457 outRect.right -= insets.right;
10458 outRect.bottom -= insets.bottom;
10461 // The view is not attached to a display so we don't have a context.
10462 // Make a best guess about the display size.
10463 Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
10464 d.getRectSize(outRect);
10468 * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
10469 * is currently in without any insets.
10473 public void getWindowDisplayFrame(Rect outRect) {
10474 if (mAttachInfo != null) {
10476 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
10477 } catch (RemoteException e) {
10482 // The view is not attached to a display so we don't have a context.
10483 // Make a best guess about the display size.
10484 Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
10485 d.getRectSize(outRect);
10489 * Dispatch a notification about a resource configuration change down
10490 * the view hierarchy.
10491 * ViewGroups should override to route to their children.
10493 * @param newConfig The new resource configuration.
10495 * @see #onConfigurationChanged(android.content.res.Configuration)
10497 public void dispatchConfigurationChanged(Configuration newConfig) {
10498 onConfigurationChanged(newConfig);
10502 * Called when the current configuration of the resources being used
10503 * by the application have changed. You can use this to decide when
10504 * to reload resources that can changed based on orientation and other
10505 * configuration characteristics. You only need to use this if you are
10506 * not relying on the normal {@link android.app.Activity} mechanism of
10507 * recreating the activity instance upon a configuration change.
10509 * @param newConfig The new resource configuration.
10511 protected void onConfigurationChanged(Configuration newConfig) {
10515 * Private function to aggregate all per-view attributes in to the view
10518 void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10519 performCollectViewAttributes(attachInfo, visibility);
10522 void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10523 if ((visibility & VISIBILITY_MASK) == VISIBLE) {
10524 if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
10525 attachInfo.mKeepScreenOn = true;
10527 attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
10528 ListenerInfo li = mListenerInfo;
10529 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
10530 attachInfo.mHasSystemUiListeners = true;
10535 void needGlobalAttributesUpdate(boolean force) {
10536 final AttachInfo ai = mAttachInfo;
10537 if (ai != null && !ai.mRecomputeGlobalAttributes) {
10538 if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
10539 || ai.mHasSystemUiListeners) {
10540 ai.mRecomputeGlobalAttributes = true;
10546 * Returns whether the device is currently in touch mode. Touch mode is entered
10547 * once the user begins interacting with the device by touch, and affects various
10548 * things like whether focus is always visible to the user.
10550 * @return Whether the device is in touch mode.
10552 @ViewDebug.ExportedProperty
10553 public boolean isInTouchMode() {
10554 if (mAttachInfo != null) {
10555 return mAttachInfo.mInTouchMode;
10557 return ViewRootImpl.isInTouchMode();
10562 * Returns the context the view is running in, through which it can
10563 * access the current theme, resources, etc.
10565 * @return The view's Context.
10567 @ViewDebug.CapturedViewProperty
10568 public final Context getContext() {
10573 * Handle a key event before it is processed by any input method
10574 * associated with the view hierarchy. This can be used to intercept
10575 * key events in special situations before the IME consumes them; a
10576 * typical example would be handling the BACK key to update the application's
10577 * UI instead of allowing the IME to see it and close itself.
10579 * @param keyCode The value in event.getKeyCode().
10580 * @param event Description of the key event.
10581 * @return If you handled the event, return true. If you want to allow the
10582 * event to be handled by the next receiver, return false.
10584 public boolean onKeyPreIme(int keyCode, KeyEvent event) {
10589 * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
10590 * KeyEvent.Callback.onKeyDown()}: perform press of the view
10591 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
10592 * is released, if the view is enabled and clickable.
10594 * Key presses in software keyboards will generally NOT trigger this
10595 * listener, although some may elect to do so in some situations. Do not
10596 * rely on this to catch software key presses.
10598 * @param keyCode a key code that represents the button pressed, from
10599 * {@link android.view.KeyEvent}
10600 * @param event the KeyEvent object that defines the button action
10602 public boolean onKeyDown(int keyCode, KeyEvent event) {
10603 if (KeyEvent.isConfirmKey(keyCode)) {
10604 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10608 // Long clickable items don't necessarily have to be clickable.
10609 if (((mViewFlags & CLICKABLE) == CLICKABLE
10610 || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
10611 && (event.getRepeatCount() == 0)) {
10612 // For the purposes of menu anchoring and drawable hotspots,
10613 // key events are considered to be at the center of the view.
10614 final float x = getWidth() / 2f;
10615 final float y = getHeight() / 2f;
10616 setPressed(true, x, y);
10617 checkForLongClick(0, x, y);
10626 * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
10627 * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
10629 * <p>Key presses in software keyboards will generally NOT trigger this listener,
10630 * although some may elect to do so in some situations. Do not rely on this to
10631 * catch software key presses.
10633 public boolean onKeyLongPress(int keyCode, KeyEvent event) {
10638 * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
10639 * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
10640 * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
10641 * or {@link KeyEvent#KEYCODE_SPACE} is released.
10642 * <p>Key presses in software keyboards will generally NOT trigger this listener,
10643 * although some may elect to do so in some situations. Do not rely on this to
10644 * catch software key presses.
10646 * @param keyCode A key code that represents the button pressed, from
10647 * {@link android.view.KeyEvent}.
10648 * @param event The KeyEvent object that defines the button action.
10650 public boolean onKeyUp(int keyCode, KeyEvent event) {
10651 if (KeyEvent.isConfirmKey(keyCode)) {
10652 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10655 if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
10658 if (!mHasPerformedLongPress) {
10659 // This is a tap, so remove the longpress check
10660 removeLongPressCallback();
10661 return performClick();
10669 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
10670 * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
10672 * <p>Key presses in software keyboards will generally NOT trigger this listener,
10673 * although some may elect to do so in some situations. Do not rely on this to
10674 * catch software key presses.
10676 * @param keyCode A key code that represents the button pressed, from
10677 * {@link android.view.KeyEvent}.
10678 * @param repeatCount The number of times the action was made.
10679 * @param event The KeyEvent object that defines the button action.
10681 public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
10686 * Called on the focused view when a key shortcut event is not handled.
10687 * Override this method to implement local key shortcuts for the View.
10688 * Key shortcuts can also be implemented by setting the
10689 * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
10691 * @param keyCode The value in event.getKeyCode().
10692 * @param event Description of the key event.
10693 * @return If you handled the event, return true. If you want to allow the
10694 * event to be handled by the next receiver, return false.
10696 public boolean onKeyShortcut(int keyCode, KeyEvent event) {
10701 * Check whether the called view is a text editor, in which case it
10702 * would make sense to automatically display a soft input window for
10703 * it. Subclasses should override this if they implement
10704 * {@link #onCreateInputConnection(EditorInfo)} to return true if
10705 * a call on that method would return a non-null InputConnection, and
10706 * they are really a first-class editor that the user would normally
10707 * start typing on when the go into a window containing your view.
10709 * <p>The default implementation always returns false. This does
10710 * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
10711 * will not be called or the user can not otherwise perform edits on your
10712 * view; it is just a hint to the system that this is not the primary
10713 * purpose of this view.
10715 * @return Returns true if this view is a text editor, else false.
10717 public boolean onCheckIsTextEditor() {
10722 * Create a new InputConnection for an InputMethod to interact
10723 * with the view. The default implementation returns null, since it doesn't
10724 * support input methods. You can override this to implement such support.
10725 * This is only needed for views that take focus and text input.
10727 * <p>When implementing this, you probably also want to implement
10728 * {@link #onCheckIsTextEditor()} to indicate you will return a
10729 * non-null InputConnection.</p>
10731 * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
10732 * object correctly and in its entirety, so that the connected IME can rely
10733 * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
10734 * and {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
10735 * must be filled in with the correct cursor position for IMEs to work correctly
10736 * with your application.</p>
10738 * @param outAttrs Fill in with attribute information about the connection.
10740 public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
10745 * Called by the {@link android.view.inputmethod.InputMethodManager}
10746 * when a view who is not the current
10747 * input connection target is trying to make a call on the manager. The
10748 * default implementation returns false; you can override this to return
10749 * true for certain views if you are performing InputConnection proxying
10751 * @param view The View that is making the InputMethodManager call.
10752 * @return Return true to allow the call, false to reject.
10754 public boolean checkInputConnectionProxy(View view) {
10759 * Show the context menu for this view. It is not safe to hold on to the
10760 * menu after returning from this method.
10762 * You should normally not overload this method. Overload
10763 * {@link #onCreateContextMenu(ContextMenu)} or define an
10764 * {@link OnCreateContextMenuListener} to add items to the context menu.
10766 * @param menu The context menu to populate
10768 public void createContextMenu(ContextMenu menu) {
10769 ContextMenuInfo menuInfo = getContextMenuInfo();
10771 // Sets the current menu info so all items added to menu will have
10772 // my extra info set.
10773 ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
10775 onCreateContextMenu(menu);
10776 ListenerInfo li = mListenerInfo;
10777 if (li != null && li.mOnCreateContextMenuListener != null) {
10778 li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
10781 // Clear the extra information so subsequent items that aren't mine don't
10782 // have my extra info.
10783 ((MenuBuilder)menu).setCurrentMenuInfo(null);
10785 if (mParent != null) {
10786 mParent.createContextMenu(menu);
10791 * Views should implement this if they have extra information to associate
10792 * with the context menu. The return result is supplied as a parameter to
10793 * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
10796 * @return Extra information about the item for which the context menu
10797 * should be shown. This information will vary across different
10798 * subclasses of View.
10800 protected ContextMenuInfo getContextMenuInfo() {
10805 * Views should implement this if the view itself is going to add items to
10806 * the context menu.
10808 * @param menu the context menu to populate
10810 protected void onCreateContextMenu(ContextMenu menu) {
10814 * Implement this method to handle trackball motion events. The
10815 * <em>relative</em> movement of the trackball since the last event
10816 * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
10817 * {@link MotionEvent#getY MotionEvent.getY()}. These are normalized so
10818 * that a movement of 1 corresponds to the user pressing one DPAD key (so
10819 * they will often be fractional values, representing the more fine-grained
10820 * movement information available from a trackball).
10822 * @param event The motion event.
10823 * @return True if the event was handled, false otherwise.
10825 public boolean onTrackballEvent(MotionEvent event) {
10830 * Implement this method to handle generic motion events.
10832 * Generic motion events describe joystick movements, mouse hovers, track pad
10833 * touches, scroll wheel movements and other input events. The
10834 * {@link MotionEvent#getSource() source} of the motion event specifies
10835 * the class of input that was received. Implementations of this method
10836 * must examine the bits in the source before processing the event.
10837 * The following code example shows how this is done.
10839 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10840 * are delivered to the view under the pointer. All other generic motion events are
10841 * delivered to the focused view.
10843 * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
10844 * if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
10845 * if (event.getAction() == MotionEvent.ACTION_MOVE) {
10846 * // process the joystick movement...
10850 * if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
10851 * switch (event.getAction()) {
10852 * case MotionEvent.ACTION_HOVER_MOVE:
10853 * // process the mouse hover movement...
10855 * case MotionEvent.ACTION_SCROLL:
10856 * // process the scroll wheel movement...
10860 * return super.onGenericMotionEvent(event);
10863 * @param event The generic motion event being processed.
10864 * @return True if the event was handled, false otherwise.
10866 public boolean onGenericMotionEvent(MotionEvent event) {
10871 * Implement this method to handle hover events.
10873 * This method is called whenever a pointer is hovering into, over, or out of the
10874 * bounds of a view and the view is not currently being touched.
10875 * Hover events are represented as pointer events with action
10876 * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
10877 * or {@link MotionEvent#ACTION_HOVER_EXIT}.
10880 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
10881 * when the pointer enters the bounds of the view.</li>
10882 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
10883 * when the pointer has already entered the bounds of the view and has moved.</li>
10884 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
10885 * when the pointer has exited the bounds of the view or when the pointer is
10886 * about to go down due to a button click, tap, or similar user action that
10887 * causes the view to be touched.</li>
10890 * The view should implement this method to return true to indicate that it is
10891 * handling the hover event, such as by changing its drawable state.
10893 * The default implementation calls {@link #setHovered} to update the hovered state
10894 * of the view when a hover enter or hover exit event is received, if the view
10895 * is enabled and is clickable. The default implementation also sends hover
10896 * accessibility events.
10899 * @param event The motion event that describes the hover.
10900 * @return True if the view handled the hover event.
10904 * @see #onHoverChanged
10906 public boolean onHoverEvent(MotionEvent event) {
10907 // The root view may receive hover (or touch) events that are outside the bounds of
10908 // the window. This code ensures that we only send accessibility events for
10909 // hovers that are actually within the bounds of the root view.
10910 final int action = event.getActionMasked();
10911 if (!mSendingHoverAccessibilityEvents) {
10912 if ((action == MotionEvent.ACTION_HOVER_ENTER
10913 || action == MotionEvent.ACTION_HOVER_MOVE)
10914 && !hasHoveredChild()
10915 && pointInView(event.getX(), event.getY())) {
10916 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
10917 mSendingHoverAccessibilityEvents = true;
10920 if (action == MotionEvent.ACTION_HOVER_EXIT
10921 || (action == MotionEvent.ACTION_MOVE
10922 && !pointInView(event.getX(), event.getY()))) {
10923 mSendingHoverAccessibilityEvents = false;
10924 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
10928 if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
10929 && event.isFromSource(InputDevice.SOURCE_MOUSE)
10930 && isOnScrollbar(event.getX(), event.getY())) {
10931 awakenScrollBars();
10933 if (isHoverable()) {
10935 case MotionEvent.ACTION_HOVER_ENTER:
10938 case MotionEvent.ACTION_HOVER_EXIT:
10943 // Dispatch the event to onGenericMotionEvent before returning true.
10944 // This is to provide compatibility with existing applications that
10945 // handled HOVER_MOVE events in onGenericMotionEvent and that would
10946 // break because of the new default handling for hoverable views
10947 // in onHoverEvent.
10948 // Note that onGenericMotionEvent will be called by default when
10949 // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
10950 dispatchGenericMotionEventInternal(event);
10951 // The event was already handled by calling setHovered(), so always
10960 * Returns true if the view should handle {@link #onHoverEvent}
10961 * by calling {@link #setHovered} to change its hovered state.
10963 * @return True if the view is hoverable.
10965 private boolean isHoverable() {
10966 final int viewFlags = mViewFlags;
10967 if ((viewFlags & ENABLED_MASK) == DISABLED) {
10971 return (viewFlags & CLICKABLE) == CLICKABLE
10972 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10973 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
10977 * Returns true if the view is currently hovered.
10979 * @return True if the view is currently hovered.
10982 * @see #onHoverChanged
10984 @ViewDebug.ExportedProperty
10985 public boolean isHovered() {
10986 return (mPrivateFlags & PFLAG_HOVERED) != 0;
10990 * Sets whether the view is currently hovered.
10992 * Calling this method also changes the drawable state of the view. This
10993 * enables the view to react to hover by using different drawable resources
10994 * to change its appearance.
10996 * The {@link #onHoverChanged} method is called when the hovered state changes.
10999 * @param hovered True if the view is hovered.
11002 * @see #onHoverChanged
11004 public void setHovered(boolean hovered) {
11006 if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
11007 mPrivateFlags |= PFLAG_HOVERED;
11008 refreshDrawableState();
11009 onHoverChanged(true);
11012 if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
11013 mPrivateFlags &= ~PFLAG_HOVERED;
11014 refreshDrawableState();
11015 onHoverChanged(false);
11021 * Implement this method to handle hover state changes.
11023 * This method is called whenever the hover state changes as a result of a
11024 * call to {@link #setHovered}.
11027 * @param hovered The current hover state, as returned by {@link #isHovered}.
11032 public void onHoverChanged(boolean hovered) {
11036 * Handles scroll bar dragging by mouse input.
11039 * @param event The motion event.
11041 * @return true if the event was handled as a scroll bar dragging, false otherwise.
11043 protected boolean handleScrollBarDragging(MotionEvent event) {
11044 if (mScrollCache == null) {
11047 final float x = event.getX();
11048 final float y = event.getY();
11049 final int action = event.getAction();
11050 if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
11051 && action != MotionEvent.ACTION_DOWN)
11052 || !event.isFromSource(InputDevice.SOURCE_MOUSE)
11053 || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
11054 mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11059 case MotionEvent.ACTION_MOVE:
11060 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
11063 if (mScrollCache.mScrollBarDraggingState
11064 == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
11065 final Rect bounds = mScrollCache.mScrollBarBounds;
11066 getVerticalScrollBarBounds(bounds);
11067 final int range = computeVerticalScrollRange();
11068 final int offset = computeVerticalScrollOffset();
11069 final int extent = computeVerticalScrollExtent();
11071 final int thumbLength = ScrollBarUtils.getThumbLength(
11072 bounds.height(), bounds.width(), extent, range);
11073 final int thumbOffset = ScrollBarUtils.getThumbOffset(
11074 bounds.height(), thumbLength, extent, range, offset);
11076 final float diff = y - mScrollCache.mScrollBarDraggingPos;
11077 final float maxThumbOffset = bounds.height() - thumbLength;
11078 final float newThumbOffset =
11079 Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11080 final int height = getHeight();
11081 if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11082 && height > 0 && extent > 0) {
11083 final int newY = Math.round((range - extent)
11084 / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
11085 if (newY != getScrollY()) {
11086 mScrollCache.mScrollBarDraggingPos = y;
11092 if (mScrollCache.mScrollBarDraggingState
11093 == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
11094 final Rect bounds = mScrollCache.mScrollBarBounds;
11095 getHorizontalScrollBarBounds(bounds);
11096 final int range = computeHorizontalScrollRange();
11097 final int offset = computeHorizontalScrollOffset();
11098 final int extent = computeHorizontalScrollExtent();
11100 final int thumbLength = ScrollBarUtils.getThumbLength(
11101 bounds.width(), bounds.height(), extent, range);
11102 final int thumbOffset = ScrollBarUtils.getThumbOffset(
11103 bounds.width(), thumbLength, extent, range, offset);
11105 final float diff = x - mScrollCache.mScrollBarDraggingPos;
11106 final float maxThumbOffset = bounds.width() - thumbLength;
11107 final float newThumbOffset =
11108 Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11109 final int width = getWidth();
11110 if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11111 && width > 0 && extent > 0) {
11112 final int newX = Math.round((range - extent)
11113 / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
11114 if (newX != getScrollX()) {
11115 mScrollCache.mScrollBarDraggingPos = x;
11121 case MotionEvent.ACTION_DOWN:
11122 if (mScrollCache.state == ScrollabilityCache.OFF) {
11125 if (isOnVerticalScrollbarThumb(x, y)) {
11126 mScrollCache.mScrollBarDraggingState =
11127 ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
11128 mScrollCache.mScrollBarDraggingPos = y;
11131 if (isOnHorizontalScrollbarThumb(x, y)) {
11132 mScrollCache.mScrollBarDraggingState =
11133 ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
11134 mScrollCache.mScrollBarDraggingPos = x;
11138 mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11143 * Implement this method to handle touch screen motion events.
11145 * If this method is used to detect click actions, it is recommended that
11146 * the actions be performed by implementing and calling
11147 * {@link #performClick()}. This will ensure consistent system behavior,
11150 * <li>obeying click sound preferences
11151 * <li>dispatching OnClickListener calls
11152 * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
11153 * accessibility features are enabled
11156 * @param event The motion event.
11157 * @return True if the event was handled, false otherwise.
11159 public boolean onTouchEvent(MotionEvent event) {
11160 final float x = event.getX();
11161 final float y = event.getY();
11162 final int viewFlags = mViewFlags;
11163 final int action = event.getAction();
11165 if ((viewFlags & ENABLED_MASK) == DISABLED) {
11166 if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
11169 // A disabled view that is clickable still consumes the touch
11170 // events, it just doesn't respond to them.
11171 return (((viewFlags & CLICKABLE) == CLICKABLE
11172 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
11173 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
11175 if (mTouchDelegate != null) {
11176 if (mTouchDelegate.onTouchEvent(event)) {
11181 if (((viewFlags & CLICKABLE) == CLICKABLE ||
11182 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
11183 (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
11185 case MotionEvent.ACTION_UP:
11186 boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
11187 if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
11188 // take focus if we don't have it already and we should in
11190 boolean focusTaken = false;
11191 if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
11192 focusTaken = requestFocus();
11196 // The button is being released before we actually
11197 // showed it as pressed. Make it show the pressed
11198 // state now (before scheduling the click) to ensure
11199 // the user sees it.
11200 setPressed(true, x, y);
11203 if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
11204 // This is a tap, so remove the longpress check
11205 removeLongPressCallback();
11207 // Only perform take click actions if we were in the pressed state
11209 // Use a Runnable and post this rather than calling
11210 // performClick directly. This lets other visual state
11211 // of the view update before click actions start.
11212 if (mPerformClick == null) {
11213 mPerformClick = new PerformClick();
11215 if (!post(mPerformClick)) {
11221 if (mUnsetPressedState == null) {
11222 mUnsetPressedState = new UnsetPressedState();
11226 postDelayed(mUnsetPressedState,
11227 ViewConfiguration.getPressedStateDuration());
11228 } else if (!post(mUnsetPressedState)) {
11229 // If the post failed, unpress right now
11230 mUnsetPressedState.run();
11233 removeTapCallback();
11235 mIgnoreNextUpEvent = false;
11238 case MotionEvent.ACTION_DOWN:
11239 mHasPerformedLongPress = false;
11241 if (performButtonActionOnTouchDown(event)) {
11245 // Walk up the hierarchy to determine if we're inside a scrolling container.
11246 boolean isInScrollingContainer = isInScrollingContainer();
11248 // For views inside a scrolling container, delay the pressed feedback for
11249 // a short period in case this is a scroll.
11250 if (isInScrollingContainer) {
11251 mPrivateFlags |= PFLAG_PREPRESSED;
11252 if (mPendingCheckForTap == null) {
11253 mPendingCheckForTap = new CheckForTap();
11255 mPendingCheckForTap.x = event.getX();
11256 mPendingCheckForTap.y = event.getY();
11257 postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
11259 // Not inside a scrolling container, so show the feedback right away
11260 setPressed(true, x, y);
11261 checkForLongClick(0, x, y);
11265 case MotionEvent.ACTION_CANCEL:
11267 removeTapCallback();
11268 removeLongPressCallback();
11269 mInContextButtonPress = false;
11270 mHasPerformedLongPress = false;
11271 mIgnoreNextUpEvent = false;
11274 case MotionEvent.ACTION_MOVE:
11275 drawableHotspotChanged(x, y);
11277 // Be lenient about moving outside of buttons
11278 if (!pointInView(x, y, mTouchSlop)) {
11280 removeTapCallback();
11281 if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
11282 // Remove any future long press/tap checks
11283 removeLongPressCallback();
11300 public boolean isInScrollingContainer() {
11301 ViewParent p = getParent();
11302 while (p != null && p instanceof ViewGroup) {
11303 if (((ViewGroup) p).shouldDelayChildPressedState()) {
11312 * Remove the longpress detection timer.
11314 private void removeLongPressCallback() {
11315 if (mPendingCheckForLongPress != null) {
11316 removeCallbacks(mPendingCheckForLongPress);
11321 * Remove the pending click action
11323 private void removePerformClickCallback() {
11324 if (mPerformClick != null) {
11325 removeCallbacks(mPerformClick);
11330 * Remove the prepress detection timer.
11332 private void removeUnsetPressCallback() {
11333 if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
11335 removeCallbacks(mUnsetPressedState);
11340 * Remove the tap detection timer.
11342 private void removeTapCallback() {
11343 if (mPendingCheckForTap != null) {
11344 mPrivateFlags &= ~PFLAG_PREPRESSED;
11345 removeCallbacks(mPendingCheckForTap);
11350 * Cancels a pending long press. Your subclass can use this if you
11351 * want the context menu to come up if the user presses and holds
11352 * at the same place, but you don't want it to come up if they press
11353 * and then move around enough to cause scrolling.
11355 public void cancelLongPress() {
11356 removeLongPressCallback();
11359 * The prepressed state handled by the tap callback is a display
11360 * construct, but the tap callback will post a long press callback
11361 * less its own timeout. Remove it here.
11363 removeTapCallback();
11367 * Remove the pending callback for sending a
11368 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
11370 private void removeSendViewScrolledAccessibilityEventCallback() {
11371 if (mSendViewScrolledAccessibilityEvent != null) {
11372 removeCallbacks(mSendViewScrolledAccessibilityEvent);
11373 mSendViewScrolledAccessibilityEvent.mIsPending = false;
11378 * Sets the TouchDelegate for this View.
11380 public void setTouchDelegate(TouchDelegate delegate) {
11381 mTouchDelegate = delegate;
11385 * Gets the TouchDelegate for this View.
11387 public TouchDelegate getTouchDelegate() {
11388 return mTouchDelegate;
11392 * Request unbuffered dispatch of the given stream of MotionEvents to this View.
11394 * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
11395 * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
11396 * available. This method should only be called for touch events.
11398 * <p class="note">This api is not intended for most applications. Buffered dispatch
11399 * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
11400 * streams will not improve your input latency. Side effects include: increased latency,
11401 * jittery scrolls and inability to take advantage of system resampling. Talk to your input
11402 * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
11405 public final void requestUnbufferedDispatch(MotionEvent event) {
11406 final int action = event.getAction();
11407 if (mAttachInfo == null
11408 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
11409 || !event.isTouchEvent()) {
11412 mAttachInfo.mUnbufferedDispatchRequested = true;
11416 * Set flags controlling behavior of this view.
11418 * @param flags Constant indicating the value which should be set
11419 * @param mask Constant indicating the bit range that should be changed
11421 void setFlags(int flags, int mask) {
11422 final boolean accessibilityEnabled =
11423 AccessibilityManager.getInstance(mContext).isEnabled();
11424 final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
11426 int old = mViewFlags;
11427 mViewFlags = (mViewFlags & ~mask) | (flags & mask);
11429 int changed = mViewFlags ^ old;
11430 if (changed == 0) {
11433 int privateFlags = mPrivateFlags;
11435 /* Check if the FOCUSABLE bit has changed */
11436 if (((changed & FOCUSABLE_MASK) != 0) &&
11437 ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
11438 if (((old & FOCUSABLE_MASK) == FOCUSABLE)
11439 && ((privateFlags & PFLAG_FOCUSED) != 0)) {
11440 /* Give up focus if we are no longer focusable */
11442 } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
11443 && ((privateFlags & PFLAG_FOCUSED) == 0)) {
11445 * Tell the view system that we are now available to take focus
11446 * if no one else already has it.
11448 if (mParent != null) mParent.focusableViewAvailable(this);
11452 final int newVisibility = flags & VISIBILITY_MASK;
11453 if (newVisibility == VISIBLE) {
11454 if ((changed & VISIBILITY_MASK) != 0) {
11456 * If this view is becoming visible, invalidate it in case it changed while
11457 * it was not visible. Marking it drawn ensures that the invalidation will
11460 mPrivateFlags |= PFLAG_DRAWN;
11463 needGlobalAttributesUpdate(true);
11465 // a view becoming visible is worth notifying the parent
11466 // about in case nothing has focus. even if this specific view
11467 // isn't focusable, it may contain something that is, so let
11468 // the root view try to give this focus if nothing else does.
11469 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
11470 mParent.focusableViewAvailable(this);
11475 /* Check if the GONE bit has changed */
11476 if ((changed & GONE) != 0) {
11477 needGlobalAttributesUpdate(false);
11480 if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
11481 if (hasFocus()) clearFocus();
11482 clearAccessibilityFocus();
11483 destroyDrawingCache();
11484 if (mParent instanceof View) {
11485 // GONE views noop invalidation, so invalidate the parent
11486 ((View) mParent).invalidate(true);
11488 // Mark the view drawn to ensure that it gets invalidated properly the next
11489 // time it is visible and gets invalidated
11490 mPrivateFlags |= PFLAG_DRAWN;
11492 if (mAttachInfo != null) {
11493 mAttachInfo.mViewVisibilityChanged = true;
11497 /* Check if the VISIBLE bit has changed */
11498 if ((changed & INVISIBLE) != 0) {
11499 needGlobalAttributesUpdate(false);
11501 * If this view is becoming invisible, set the DRAWN flag so that
11502 * the next invalidate() will not be skipped.
11504 mPrivateFlags |= PFLAG_DRAWN;
11506 if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
11507 // root view becoming invisible shouldn't clear focus and accessibility focus
11508 if (getRootView() != this) {
11509 if (hasFocus()) clearFocus();
11510 clearAccessibilityFocus();
11513 if (mAttachInfo != null) {
11514 mAttachInfo.mViewVisibilityChanged = true;
11518 if ((changed & VISIBILITY_MASK) != 0) {
11519 // If the view is invisible, cleanup its display list to free up resources
11520 if (newVisibility != VISIBLE && mAttachInfo != null) {
11524 if (mParent instanceof ViewGroup) {
11525 ((ViewGroup) mParent).onChildVisibilityChanged(this,
11526 (changed & VISIBILITY_MASK), newVisibility);
11527 ((View) mParent).invalidate(true);
11528 } else if (mParent != null) {
11529 mParent.invalidateChild(this, null);
11532 if (mAttachInfo != null) {
11533 dispatchVisibilityChanged(this, newVisibility);
11535 // Aggregated visibility changes are dispatched to attached views
11536 // in visible windows where the parent is currently shown/drawn
11537 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
11538 // discounting clipping or overlapping. This makes it a good place
11539 // to change animation states.
11540 if (mParent != null && getWindowVisibility() == VISIBLE &&
11541 ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
11542 dispatchVisibilityAggregated(newVisibility == VISIBLE);
11544 notifySubtreeAccessibilityStateChangedIfNeeded();
11548 if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
11549 destroyDrawingCache();
11552 if ((changed & DRAWING_CACHE_ENABLED) != 0) {
11553 destroyDrawingCache();
11554 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11555 invalidateParentCaches();
11558 if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
11559 destroyDrawingCache();
11560 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11563 if ((changed & DRAW_MASK) != 0) {
11564 if ((mViewFlags & WILL_NOT_DRAW) != 0) {
11565 if (mBackground != null
11566 || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
11567 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
11569 mPrivateFlags |= PFLAG_SKIP_DRAW;
11572 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
11578 if ((changed & KEEP_SCREEN_ON) != 0) {
11579 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
11580 mParent.recomputeViewAttributes(this);
11584 if (accessibilityEnabled) {
11585 if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
11586 || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
11587 || (changed & CONTEXT_CLICKABLE) != 0) {
11588 if (oldIncludeForAccessibility != includeForAccessibility()) {
11589 notifySubtreeAccessibilityStateChangedIfNeeded();
11591 notifyViewAccessibilityStateChangedIfNeeded(
11592 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11594 } else if ((changed & ENABLED_MASK) != 0) {
11595 notifyViewAccessibilityStateChangedIfNeeded(
11596 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11602 * Change the view's z order in the tree, so it's on top of other sibling
11603 * views. This ordering change may affect layout, if the parent container
11604 * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
11605 * to {@link android.os.Build.VERSION_CODES#KITKAT} this
11606 * method should be followed by calls to {@link #requestLayout()} and
11607 * {@link View#invalidate()} on the view's parent to force the parent to redraw
11608 * with the new child ordering.
11610 * @see ViewGroup#bringChildToFront(View)
11612 public void bringToFront() {
11613 if (mParent != null) {
11614 mParent.bringChildToFront(this);
11619 * This is called in response to an internal scroll in this view (i.e., the
11620 * view scrolled its own contents). This is typically as a result of
11621 * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
11624 * @param l Current horizontal scroll origin.
11625 * @param t Current vertical scroll origin.
11626 * @param oldl Previous horizontal scroll origin.
11627 * @param oldt Previous vertical scroll origin.
11629 protected void onScrollChanged(int l, int t, int oldl, int oldt) {
11630 notifySubtreeAccessibilityStateChangedIfNeeded();
11632 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
11633 postSendViewScrolledAccessibilityEventCallback();
11636 mBackgroundSizeChanged = true;
11637 if (mForegroundInfo != null) {
11638 mForegroundInfo.mBoundsChanged = true;
11641 final AttachInfo ai = mAttachInfo;
11643 ai.mViewScrollChanged = true;
11646 if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
11647 mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
11652 * Interface definition for a callback to be invoked when the scroll
11653 * X or Y positions of a view change.
11655 * <b>Note:</b> Some views handle scrolling independently from View and may
11656 * have their own separate listeners for scroll-type events. For example,
11657 * {@link android.widget.ListView ListView} allows clients to register an
11658 * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
11659 * to listen for changes in list scroll position.
11661 * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
11663 public interface OnScrollChangeListener {
11665 * Called when the scroll position of a view changes.
11667 * @param v The view whose scroll position has changed.
11668 * @param scrollX Current horizontal scroll origin.
11669 * @param scrollY Current vertical scroll origin.
11670 * @param oldScrollX Previous horizontal scroll origin.
11671 * @param oldScrollY Previous vertical scroll origin.
11673 void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
11677 * Interface definition for a callback to be invoked when the layout bounds of a view
11678 * changes due to layout processing.
11680 public interface OnLayoutChangeListener {
11682 * Called when the layout bounds of a view changes due to layout processing.
11684 * @param v The view whose bounds have changed.
11685 * @param left The new value of the view's left property.
11686 * @param top The new value of the view's top property.
11687 * @param right The new value of the view's right property.
11688 * @param bottom The new value of the view's bottom property.
11689 * @param oldLeft The previous value of the view's left property.
11690 * @param oldTop The previous value of the view's top property.
11691 * @param oldRight The previous value of the view's right property.
11692 * @param oldBottom The previous value of the view's bottom property.
11694 void onLayoutChange(View v, int left, int top, int right, int bottom,
11695 int oldLeft, int oldTop, int oldRight, int oldBottom);
11699 * This is called during layout when the size of this view has changed. If
11700 * you were just added to the view hierarchy, you're called with the old
11703 * @param w Current width of this view.
11704 * @param h Current height of this view.
11705 * @param oldw Old width of this view.
11706 * @param oldh Old height of this view.
11708 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
11712 * Called by draw to draw the child views. This may be overridden
11713 * by derived classes to gain control just before its children are drawn
11714 * (but after its own view has been drawn).
11715 * @param canvas the canvas on which to draw the view
11717 protected void dispatchDraw(Canvas canvas) {
11722 * Gets the parent of this view. Note that the parent is a
11723 * ViewParent and not necessarily a View.
11725 * @return Parent of this view.
11727 public final ViewParent getParent() {
11732 * Set the horizontal scrolled position of your view. This will cause a call to
11733 * {@link #onScrollChanged(int, int, int, int)} and the view will be
11735 * @param value the x position to scroll to
11737 public void setScrollX(int value) {
11738 scrollTo(value, mScrollY);
11742 * Set the vertical scrolled position of your view. This will cause a call to
11743 * {@link #onScrollChanged(int, int, int, int)} and the view will be
11745 * @param value the y position to scroll to
11747 public void setScrollY(int value) {
11748 scrollTo(mScrollX, value);
11752 * Return the scrolled left position of this view. This is the left edge of
11753 * the displayed part of your view. You do not need to draw any pixels
11754 * farther left, since those are outside of the frame of your view on
11757 * @return The left edge of the displayed part of your view, in pixels.
11759 public final int getScrollX() {
11764 * Return the scrolled top position of this view. This is the top edge of
11765 * the displayed part of your view. You do not need to draw any pixels above
11766 * it, since those are outside of the frame of your view on screen.
11768 * @return The top edge of the displayed part of your view, in pixels.
11770 public final int getScrollY() {
11775 * Return the width of the your view.
11777 * @return The width of your view, in pixels.
11779 @ViewDebug.ExportedProperty(category = "layout")
11780 public final int getWidth() {
11781 return mRight - mLeft;
11785 * Return the height of your view.
11787 * @return The height of your view, in pixels.
11789 @ViewDebug.ExportedProperty(category = "layout")
11790 public final int getHeight() {
11791 return mBottom - mTop;
11795 * Return the visible drawing bounds of your view. Fills in the output
11796 * rectangle with the values from getScrollX(), getScrollY(),
11797 * getWidth(), and getHeight(). These bounds do not account for any
11798 * transformation properties currently set on the view, such as
11799 * {@link #setScaleX(float)} or {@link #setRotation(float)}.
11801 * @param outRect The (scrolled) drawing bounds of the view.
11803 public void getDrawingRect(Rect outRect) {
11804 outRect.left = mScrollX;
11805 outRect.top = mScrollY;
11806 outRect.right = mScrollX + (mRight - mLeft);
11807 outRect.bottom = mScrollY + (mBottom - mTop);
11811 * Like {@link #getMeasuredWidthAndState()}, but only returns the
11812 * raw width component (that is the result is masked by
11813 * {@link #MEASURED_SIZE_MASK}).
11815 * @return The raw measured width of this view.
11817 public final int getMeasuredWidth() {
11818 return mMeasuredWidth & MEASURED_SIZE_MASK;
11822 * Return the full width measurement information for this view as computed
11823 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask
11824 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11825 * This should be used during measurement and layout calculations only. Use
11826 * {@link #getWidth()} to see how wide a view is after layout.
11828 * @return The measured width of this view as a bit mask.
11830 @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11831 @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11832 name = "MEASURED_STATE_TOO_SMALL"),
11834 public final int getMeasuredWidthAndState() {
11835 return mMeasuredWidth;
11839 * Like {@link #getMeasuredHeightAndState()}, but only returns the
11840 * raw width component (that is the result is masked by
11841 * {@link #MEASURED_SIZE_MASK}).
11843 * @return The raw measured height of this view.
11845 public final int getMeasuredHeight() {
11846 return mMeasuredHeight & MEASURED_SIZE_MASK;
11850 * Return the full height measurement information for this view as computed
11851 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask
11852 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11853 * This should be used during measurement and layout calculations only. Use
11854 * {@link #getHeight()} to see how wide a view is after layout.
11856 * @return The measured width of this view as a bit mask.
11858 @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11859 @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11860 name = "MEASURED_STATE_TOO_SMALL"),
11862 public final int getMeasuredHeightAndState() {
11863 return mMeasuredHeight;
11867 * Return only the state bits of {@link #getMeasuredWidthAndState()}
11868 * and {@link #getMeasuredHeightAndState()}, combined into one integer.
11869 * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
11870 * and the height component is at the shifted bits
11871 * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
11873 public final int getMeasuredState() {
11874 return (mMeasuredWidth&MEASURED_STATE_MASK)
11875 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
11876 & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
11880 * The transform matrix of this view, which is calculated based on the current
11881 * rotation, scale, and pivot properties.
11883 * @see #getRotation()
11884 * @see #getScaleX()
11885 * @see #getScaleY()
11886 * @see #getPivotX()
11887 * @see #getPivotY()
11888 * @return The current transform matrix for the view
11890 public Matrix getMatrix() {
11891 ensureTransformationInfo();
11892 final Matrix matrix = mTransformationInfo.mMatrix;
11893 mRenderNode.getMatrix(matrix);
11898 * Returns true if the transform matrix is the identity matrix.
11899 * Recomputes the matrix if necessary.
11901 * @return True if the transform matrix is the identity matrix, false otherwise.
11903 final boolean hasIdentityMatrix() {
11904 return mRenderNode.hasIdentityMatrix();
11907 void ensureTransformationInfo() {
11908 if (mTransformationInfo == null) {
11909 mTransformationInfo = new TransformationInfo();
11914 * Utility method to retrieve the inverse of the current mMatrix property.
11915 * We cache the matrix to avoid recalculating it when transform properties
11916 * have not changed.
11918 * @return The inverse of the current matrix of this view.
11921 public final Matrix getInverseMatrix() {
11922 ensureTransformationInfo();
11923 if (mTransformationInfo.mInverseMatrix == null) {
11924 mTransformationInfo.mInverseMatrix = new Matrix();
11926 final Matrix matrix = mTransformationInfo.mInverseMatrix;
11927 mRenderNode.getInverseMatrix(matrix);
11932 * Gets the distance along the Z axis from the camera to this view.
11934 * @see #setCameraDistance(float)
11936 * @return The distance along the Z axis.
11938 public float getCameraDistance() {
11939 final float dpi = mResources.getDisplayMetrics().densityDpi;
11940 return -(mRenderNode.getCameraDistance() * dpi);
11944 * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
11945 * views are drawn) from the camera to this view. The camera's distance
11946 * affects 3D transformations, for instance rotations around the X and Y
11947 * axis. If the rotationX or rotationY properties are changed and this view is
11948 * large (more than half the size of the screen), it is recommended to always
11949 * use a camera distance that's greater than the height (X axis rotation) or
11950 * the width (Y axis rotation) of this view.</p>
11952 * <p>The distance of the camera from the view plane can have an affect on the
11953 * perspective distortion of the view when it is rotated around the x or y axis.
11954 * For example, a large distance will result in a large viewing angle, and there
11955 * will not be much perspective distortion of the view as it rotates. A short
11956 * distance may cause much more perspective distortion upon rotation, and can
11957 * also result in some drawing artifacts if the rotated view ends up partially
11958 * behind the camera (which is why the recommendation is to use a distance at
11959 * least as far as the size of the view, if the view is to be rotated.)</p>
11961 * <p>The distance is expressed in "depth pixels." The default distance depends
11962 * on the screen density. For instance, on a medium density display, the
11963 * default distance is 1280. On a high density display, the default distance
11966 * <p>If you want to specify a distance that leads to visually consistent
11967 * results across various densities, use the following formula:</p>
11969 * float scale = context.getResources().getDisplayMetrics().density;
11970 * view.setCameraDistance(distance * scale);
11973 * <p>The density scale factor of a high density display is 1.5,
11974 * and 1920 = 1280 * 1.5.</p>
11976 * @param distance The distance in "depth pixels", if negative the opposite
11979 * @see #setRotationX(float)
11980 * @see #setRotationY(float)
11982 public void setCameraDistance(float distance) {
11983 final float dpi = mResources.getDisplayMetrics().densityDpi;
11985 invalidateViewProperty(true, false);
11986 mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
11987 invalidateViewProperty(false, false);
11989 invalidateParentIfNeededAndWasQuickRejected();
11993 * The degrees that the view is rotated around the pivot point.
11995 * @see #setRotation(float)
11996 * @see #getPivotX()
11997 * @see #getPivotY()
11999 * @return The degrees of rotation.
12001 @ViewDebug.ExportedProperty(category = "drawing")
12002 public float getRotation() {
12003 return mRenderNode.getRotation();
12007 * Sets the degrees that the view is rotated around the pivot point. Increasing values
12008 * result in clockwise rotation.
12010 * @param rotation The degrees of rotation.
12012 * @see #getRotation()
12013 * @see #getPivotX()
12014 * @see #getPivotY()
12015 * @see #setRotationX(float)
12016 * @see #setRotationY(float)
12018 * @attr ref android.R.styleable#View_rotation
12020 public void setRotation(float rotation) {
12021 if (rotation != getRotation()) {
12022 // Double-invalidation is necessary to capture view's old and new areas
12023 invalidateViewProperty(true, false);
12024 mRenderNode.setRotation(rotation);
12025 invalidateViewProperty(false, true);
12027 invalidateParentIfNeededAndWasQuickRejected();
12028 notifySubtreeAccessibilityStateChangedIfNeeded();
12033 * The degrees that the view is rotated around the vertical axis through the pivot point.
12035 * @see #getPivotX()
12036 * @see #getPivotY()
12037 * @see #setRotationY(float)
12039 * @return The degrees of Y rotation.
12041 @ViewDebug.ExportedProperty(category = "drawing")
12042 public float getRotationY() {
12043 return mRenderNode.getRotationY();
12047 * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
12048 * Increasing values result in counter-clockwise rotation from the viewpoint of looking
12051 * When rotating large views, it is recommended to adjust the camera distance
12052 * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12054 * @param rotationY The degrees of Y rotation.
12056 * @see #getRotationY()
12057 * @see #getPivotX()
12058 * @see #getPivotY()
12059 * @see #setRotation(float)
12060 * @see #setRotationX(float)
12061 * @see #setCameraDistance(float)
12063 * @attr ref android.R.styleable#View_rotationY
12065 public void setRotationY(float rotationY) {
12066 if (rotationY != getRotationY()) {
12067 invalidateViewProperty(true, false);
12068 mRenderNode.setRotationY(rotationY);
12069 invalidateViewProperty(false, true);
12071 invalidateParentIfNeededAndWasQuickRejected();
12072 notifySubtreeAccessibilityStateChangedIfNeeded();
12077 * The degrees that the view is rotated around the horizontal axis through the pivot point.
12079 * @see #getPivotX()
12080 * @see #getPivotY()
12081 * @see #setRotationX(float)
12083 * @return The degrees of X rotation.
12085 @ViewDebug.ExportedProperty(category = "drawing")
12086 public float getRotationX() {
12087 return mRenderNode.getRotationX();
12091 * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
12092 * Increasing values result in clockwise rotation from the viewpoint of looking down the
12095 * When rotating large views, it is recommended to adjust the camera distance
12096 * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12098 * @param rotationX The degrees of X rotation.
12100 * @see #getRotationX()
12101 * @see #getPivotX()
12102 * @see #getPivotY()
12103 * @see #setRotation(float)
12104 * @see #setRotationY(float)
12105 * @see #setCameraDistance(float)
12107 * @attr ref android.R.styleable#View_rotationX
12109 public void setRotationX(float rotationX) {
12110 if (rotationX != getRotationX()) {
12111 invalidateViewProperty(true, false);
12112 mRenderNode.setRotationX(rotationX);
12113 invalidateViewProperty(false, true);
12115 invalidateParentIfNeededAndWasQuickRejected();
12116 notifySubtreeAccessibilityStateChangedIfNeeded();
12121 * The amount that the view is scaled in x around the pivot point, as a proportion of
12122 * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
12124 * <p>By default, this is 1.0f.
12126 * @see #getPivotX()
12127 * @see #getPivotY()
12128 * @return The scaling factor.
12130 @ViewDebug.ExportedProperty(category = "drawing")
12131 public float getScaleX() {
12132 return mRenderNode.getScaleX();
12136 * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
12137 * the view's unscaled width. A value of 1 means that no scaling is applied.
12139 * @param scaleX The scaling factor.
12140 * @see #getPivotX()
12141 * @see #getPivotY()
12143 * @attr ref android.R.styleable#View_scaleX
12145 public void setScaleX(float scaleX) {
12146 if (scaleX != getScaleX()) {
12147 invalidateViewProperty(true, false);
12148 mRenderNode.setScaleX(scaleX);
12149 invalidateViewProperty(false, true);
12151 invalidateParentIfNeededAndWasQuickRejected();
12152 notifySubtreeAccessibilityStateChangedIfNeeded();
12157 * The amount that the view is scaled in y around the pivot point, as a proportion of
12158 * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
12160 * <p>By default, this is 1.0f.
12162 * @see #getPivotX()
12163 * @see #getPivotY()
12164 * @return The scaling factor.
12166 @ViewDebug.ExportedProperty(category = "drawing")
12167 public float getScaleY() {
12168 return mRenderNode.getScaleY();
12172 * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
12173 * the view's unscaled width. A value of 1 means that no scaling is applied.
12175 * @param scaleY The scaling factor.
12176 * @see #getPivotX()
12177 * @see #getPivotY()
12179 * @attr ref android.R.styleable#View_scaleY
12181 public void setScaleY(float scaleY) {
12182 if (scaleY != getScaleY()) {
12183 invalidateViewProperty(true, false);
12184 mRenderNode.setScaleY(scaleY);
12185 invalidateViewProperty(false, true);
12187 invalidateParentIfNeededAndWasQuickRejected();
12188 notifySubtreeAccessibilityStateChangedIfNeeded();
12193 * The x location of the point around which the view is {@link #setRotation(float) rotated}
12194 * and {@link #setScaleX(float) scaled}.
12196 * @see #getRotation()
12197 * @see #getScaleX()
12198 * @see #getScaleY()
12199 * @see #getPivotY()
12200 * @return The x location of the pivot point.
12202 * @attr ref android.R.styleable#View_transformPivotX
12204 @ViewDebug.ExportedProperty(category = "drawing")
12205 public float getPivotX() {
12206 return mRenderNode.getPivotX();
12210 * Sets the x location of the point around which the view is
12211 * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
12212 * By default, the pivot point is centered on the object.
12213 * Setting this property disables this behavior and causes the view to use only the
12214 * explicitly set pivotX and pivotY values.
12216 * @param pivotX The x location of the pivot point.
12217 * @see #getRotation()
12218 * @see #getScaleX()
12219 * @see #getScaleY()
12220 * @see #getPivotY()
12222 * @attr ref android.R.styleable#View_transformPivotX
12224 public void setPivotX(float pivotX) {
12225 if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
12226 invalidateViewProperty(true, false);
12227 mRenderNode.setPivotX(pivotX);
12228 invalidateViewProperty(false, true);
12230 invalidateParentIfNeededAndWasQuickRejected();
12235 * The y location of the point around which the view is {@link #setRotation(float) rotated}
12236 * and {@link #setScaleY(float) scaled}.
12238 * @see #getRotation()
12239 * @see #getScaleX()
12240 * @see #getScaleY()
12241 * @see #getPivotY()
12242 * @return The y location of the pivot point.
12244 * @attr ref android.R.styleable#View_transformPivotY
12246 @ViewDebug.ExportedProperty(category = "drawing")
12247 public float getPivotY() {
12248 return mRenderNode.getPivotY();
12252 * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
12253 * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
12254 * Setting this property disables this behavior and causes the view to use only the
12255 * explicitly set pivotX and pivotY values.
12257 * @param pivotY The y location of the pivot point.
12258 * @see #getRotation()
12259 * @see #getScaleX()
12260 * @see #getScaleY()
12261 * @see #getPivotY()
12263 * @attr ref android.R.styleable#View_transformPivotY
12265 public void setPivotY(float pivotY) {
12266 if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
12267 invalidateViewProperty(true, false);
12268 mRenderNode.setPivotY(pivotY);
12269 invalidateViewProperty(false, true);
12271 invalidateParentIfNeededAndWasQuickRejected();
12276 * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
12277 * completely transparent and 1 means the view is completely opaque.
12279 * <p>By default this is 1.0f.
12280 * @return The opacity of the view.
12282 @ViewDebug.ExportedProperty(category = "drawing")
12283 public float getAlpha() {
12284 return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
12288 * Sets the behavior for overlapping rendering for this view (see {@link
12289 * #hasOverlappingRendering()} for more details on this behavior). Calling this method
12290 * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
12291 * providing the value which is then used internally. That is, when {@link
12292 * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
12293 * #hasOverlappingRendering()} is ignored and the value passed into this method is used
12296 * @param hasOverlappingRendering The value for overlapping rendering to be used internally
12297 * instead of that returned by {@link #hasOverlappingRendering()}.
12299 * @attr ref android.R.styleable#View_forceHasOverlappingRendering
12301 public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
12302 mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
12303 if (hasOverlappingRendering) {
12304 mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
12306 mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
12311 * Returns the value for overlapping rendering that is used internally. This is either
12312 * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
12313 * the return value of {@link #hasOverlappingRendering()}, otherwise.
12315 * @return The value for overlapping rendering being used internally.
12317 public final boolean getHasOverlappingRendering() {
12318 return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
12319 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
12320 hasOverlappingRendering();
12324 * Returns whether this View has content which overlaps.
12326 * <p>This function, intended to be overridden by specific View types, is an optimization when
12327 * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
12328 * an offscreen buffer and then composited into place, which can be expensive. If the view has
12329 * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
12330 * directly. An example of overlapping rendering is a TextView with a background image, such as
12331 * a Button. An example of non-overlapping rendering is a TextView with no background, or an
12332 * ImageView with only the foreground image. The default implementation returns true; subclasses
12333 * should override if they have cases which can be optimized.</p>
12335 * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
12336 * necessitates that a View return true if it uses the methods internally without passing the
12337 * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
12339 * <p><strong>Note:</strong> The return value of this method is ignored if {@link
12340 * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
12342 * @return true if the content in this view might overlap, false otherwise.
12344 @ViewDebug.ExportedProperty(category = "drawing")
12345 public boolean hasOverlappingRendering() {
12350 * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
12351 * completely transparent and 1 means the view is completely opaque.
12353 * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
12354 * can have significant performance implications, especially for large views. It is best to use
12355 * the alpha property sparingly and transiently, as in the case of fading animations.</p>
12357 * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
12358 * strongly recommended for performance reasons to either override
12359 * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
12360 * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
12361 * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
12362 * the default path for rendering an unlayered View with alpha could add multiple milliseconds
12363 * of rendering cost, even for simple or small views. Starting with
12364 * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
12365 * applied to the view at the rendering level.</p>
12367 * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
12368 * responsible for applying the opacity itself.</p>
12370 * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
12371 * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
12372 * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
12373 * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
12375 * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
12376 * value will clip a View to its bounds, unless the View returns <code>false</code> from
12377 * {@link #hasOverlappingRendering}.</p>
12379 * @param alpha The opacity of the view.
12381 * @see #hasOverlappingRendering()
12382 * @see #setLayerType(int, android.graphics.Paint)
12384 * @attr ref android.R.styleable#View_alpha
12386 public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
12387 ensureTransformationInfo();
12388 if (mTransformationInfo.mAlpha != alpha) {
12389 // Report visibility changes, which can affect children, to accessibility
12390 if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
12391 notifySubtreeAccessibilityStateChangedIfNeeded();
12393 mTransformationInfo.mAlpha = alpha;
12394 if (onSetAlpha((int) (alpha * 255))) {
12395 mPrivateFlags |= PFLAG_ALPHA_SET;
12396 // subclass is handling alpha - don't optimize rendering cache invalidation
12397 invalidateParentCaches();
12400 mPrivateFlags &= ~PFLAG_ALPHA_SET;
12401 invalidateViewProperty(true, false);
12402 mRenderNode.setAlpha(getFinalAlpha());
12408 * Faster version of setAlpha() which performs the same steps except there are
12409 * no calls to invalidate(). The caller of this function should perform proper invalidation
12410 * on the parent and this object. The return value indicates whether the subclass handles
12411 * alpha (the return value for onSetAlpha()).
12413 * @param alpha The new value for the alpha property
12414 * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
12415 * the new value for the alpha property is different from the old value
12417 boolean setAlphaNoInvalidation(float alpha) {
12418 ensureTransformationInfo();
12419 if (mTransformationInfo.mAlpha != alpha) {
12420 mTransformationInfo.mAlpha = alpha;
12421 boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
12422 if (subclassHandlesAlpha) {
12423 mPrivateFlags |= PFLAG_ALPHA_SET;
12426 mPrivateFlags &= ~PFLAG_ALPHA_SET;
12427 mRenderNode.setAlpha(getFinalAlpha());
12434 * This property is hidden and intended only for use by the Fade transition, which
12435 * animates it to produce a visual translucency that does not side-effect (or get
12436 * affected by) the real alpha property. This value is composited with the other
12437 * alpha value (and the AlphaAnimation value, when that is present) to produce
12438 * a final visual translucency result, which is what is passed into the DisplayList.
12442 public void setTransitionAlpha(float alpha) {
12443 ensureTransformationInfo();
12444 if (mTransformationInfo.mTransitionAlpha != alpha) {
12445 mTransformationInfo.mTransitionAlpha = alpha;
12446 mPrivateFlags &= ~PFLAG_ALPHA_SET;
12447 invalidateViewProperty(true, false);
12448 mRenderNode.setAlpha(getFinalAlpha());
12453 * Calculates the visual alpha of this view, which is a combination of the actual
12454 * alpha value and the transitionAlpha value (if set).
12456 private float getFinalAlpha() {
12457 if (mTransformationInfo != null) {
12458 return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
12464 * This property is hidden and intended only for use by the Fade transition, which
12465 * animates it to produce a visual translucency that does not side-effect (or get
12466 * affected by) the real alpha property. This value is composited with the other
12467 * alpha value (and the AlphaAnimation value, when that is present) to produce
12468 * a final visual translucency result, which is what is passed into the DisplayList.
12472 @ViewDebug.ExportedProperty(category = "drawing")
12473 public float getTransitionAlpha() {
12474 return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
12478 * Top position of this view relative to its parent.
12480 * @return The top of this view, in pixels.
12482 @ViewDebug.CapturedViewProperty
12483 public final int getTop() {
12488 * Sets the top position of this view relative to its parent. This method is meant to be called
12489 * by the layout system and should not generally be called otherwise, because the property
12490 * may be changed at any time by the layout.
12492 * @param top The top of this view, in pixels.
12494 public final void setTop(int top) {
12496 final boolean matrixIsIdentity = hasIdentityMatrix();
12497 if (matrixIsIdentity) {
12498 if (mAttachInfo != null) {
12508 invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
12511 // Double-invalidation is necessary to capture view's old and new areas
12515 int width = mRight - mLeft;
12516 int oldHeight = mBottom - mTop;
12519 mRenderNode.setTop(mTop);
12521 sizeChange(width, mBottom - mTop, width, oldHeight);
12523 if (!matrixIsIdentity) {
12524 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12527 mBackgroundSizeChanged = true;
12528 if (mForegroundInfo != null) {
12529 mForegroundInfo.mBoundsChanged = true;
12531 invalidateParentIfNeeded();
12532 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12533 // View was rejected last time it was drawn by its parent; this may have changed
12534 invalidateParentIfNeeded();
12540 * Bottom position of this view relative to its parent.
12542 * @return The bottom of this view, in pixels.
12544 @ViewDebug.CapturedViewProperty
12545 public final int getBottom() {
12550 * True if this view has changed since the last time being drawn.
12552 * @return The dirty state of this view.
12554 public boolean isDirty() {
12555 return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
12559 * Sets the bottom position of this view relative to its parent. This method is meant to be
12560 * called by the layout system and should not generally be called otherwise, because the
12561 * property may be changed at any time by the layout.
12563 * @param bottom The bottom of this view, in pixels.
12565 public final void setBottom(int bottom) {
12566 if (bottom != mBottom) {
12567 final boolean matrixIsIdentity = hasIdentityMatrix();
12568 if (matrixIsIdentity) {
12569 if (mAttachInfo != null) {
12571 if (bottom < mBottom) {
12572 maxBottom = mBottom;
12574 maxBottom = bottom;
12576 invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
12579 // Double-invalidation is necessary to capture view's old and new areas
12583 int width = mRight - mLeft;
12584 int oldHeight = mBottom - mTop;
12587 mRenderNode.setBottom(mBottom);
12589 sizeChange(width, mBottom - mTop, width, oldHeight);
12591 if (!matrixIsIdentity) {
12592 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12595 mBackgroundSizeChanged = true;
12596 if (mForegroundInfo != null) {
12597 mForegroundInfo.mBoundsChanged = true;
12599 invalidateParentIfNeeded();
12600 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12601 // View was rejected last time it was drawn by its parent; this may have changed
12602 invalidateParentIfNeeded();
12608 * Left position of this view relative to its parent.
12610 * @return The left edge of this view, in pixels.
12612 @ViewDebug.CapturedViewProperty
12613 public final int getLeft() {
12618 * Sets the left position of this view relative to its parent. This method is meant to be called
12619 * by the layout system and should not generally be called otherwise, because the property
12620 * may be changed at any time by the layout.
12622 * @param left The left of this view, in pixels.
12624 public final void setLeft(int left) {
12625 if (left != mLeft) {
12626 final boolean matrixIsIdentity = hasIdentityMatrix();
12627 if (matrixIsIdentity) {
12628 if (mAttachInfo != null) {
12631 if (left < mLeft) {
12633 xLoc = left - mLeft;
12638 invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
12641 // Double-invalidation is necessary to capture view's old and new areas
12645 int oldWidth = mRight - mLeft;
12646 int height = mBottom - mTop;
12649 mRenderNode.setLeft(left);
12651 sizeChange(mRight - mLeft, height, oldWidth, height);
12653 if (!matrixIsIdentity) {
12654 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12657 mBackgroundSizeChanged = true;
12658 if (mForegroundInfo != null) {
12659 mForegroundInfo.mBoundsChanged = true;
12661 invalidateParentIfNeeded();
12662 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12663 // View was rejected last time it was drawn by its parent; this may have changed
12664 invalidateParentIfNeeded();
12670 * Right position of this view relative to its parent.
12672 * @return The right edge of this view, in pixels.
12674 @ViewDebug.CapturedViewProperty
12675 public final int getRight() {
12680 * Sets the right position of this view relative to its parent. This method is meant to be called
12681 * by the layout system and should not generally be called otherwise, because the property
12682 * may be changed at any time by the layout.
12684 * @param right The right of this view, in pixels.
12686 public final void setRight(int right) {
12687 if (right != mRight) {
12688 final boolean matrixIsIdentity = hasIdentityMatrix();
12689 if (matrixIsIdentity) {
12690 if (mAttachInfo != null) {
12692 if (right < mRight) {
12697 invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
12700 // Double-invalidation is necessary to capture view's old and new areas
12704 int oldWidth = mRight - mLeft;
12705 int height = mBottom - mTop;
12708 mRenderNode.setRight(mRight);
12710 sizeChange(mRight - mLeft, height, oldWidth, height);
12712 if (!matrixIsIdentity) {
12713 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12716 mBackgroundSizeChanged = true;
12717 if (mForegroundInfo != null) {
12718 mForegroundInfo.mBoundsChanged = true;
12720 invalidateParentIfNeeded();
12721 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12722 // View was rejected last time it was drawn by its parent; this may have changed
12723 invalidateParentIfNeeded();
12729 * The visual x position of this view, in pixels. This is equivalent to the
12730 * {@link #setTranslationX(float) translationX} property plus the current
12731 * {@link #getLeft() left} property.
12733 * @return The visual x position of this view, in pixels.
12735 @ViewDebug.ExportedProperty(category = "drawing")
12736 public float getX() {
12737 return mLeft + getTranslationX();
12741 * Sets the visual x position of this view, in pixels. This is equivalent to setting the
12742 * {@link #setTranslationX(float) translationX} property to be the difference between
12743 * the x value passed in and the current {@link #getLeft() left} property.
12745 * @param x The visual x position of this view, in pixels.
12747 public void setX(float x) {
12748 setTranslationX(x - mLeft);
12752 * The visual y position of this view, in pixels. This is equivalent to the
12753 * {@link #setTranslationY(float) translationY} property plus the current
12754 * {@link #getTop() top} property.
12756 * @return The visual y position of this view, in pixels.
12758 @ViewDebug.ExportedProperty(category = "drawing")
12759 public float getY() {
12760 return mTop + getTranslationY();
12764 * Sets the visual y position of this view, in pixels. This is equivalent to setting the
12765 * {@link #setTranslationY(float) translationY} property to be the difference between
12766 * the y value passed in and the current {@link #getTop() top} property.
12768 * @param y The visual y position of this view, in pixels.
12770 public void setY(float y) {
12771 setTranslationY(y - mTop);
12775 * The visual z position of this view, in pixels. This is equivalent to the
12776 * {@link #setTranslationZ(float) translationZ} property plus the current
12777 * {@link #getElevation() elevation} property.
12779 * @return The visual z position of this view, in pixels.
12781 @ViewDebug.ExportedProperty(category = "drawing")
12782 public float getZ() {
12783 return getElevation() + getTranslationZ();
12787 * Sets the visual z position of this view, in pixels. This is equivalent to setting the
12788 * {@link #setTranslationZ(float) translationZ} property to be the difference between
12789 * the x value passed in and the current {@link #getElevation() elevation} property.
12791 * @param z The visual z position of this view, in pixels.
12793 public void setZ(float z) {
12794 setTranslationZ(z - getElevation());
12798 * The base elevation of this view relative to its parent, in pixels.
12800 * @return The base depth position of the view, in pixels.
12802 @ViewDebug.ExportedProperty(category = "drawing")
12803 public float getElevation() {
12804 return mRenderNode.getElevation();
12808 * Sets the base elevation of this view, in pixels.
12810 * @attr ref android.R.styleable#View_elevation
12812 public void setElevation(float elevation) {
12813 if (elevation != getElevation()) {
12814 invalidateViewProperty(true, false);
12815 mRenderNode.setElevation(elevation);
12816 invalidateViewProperty(false, true);
12818 invalidateParentIfNeededAndWasQuickRejected();
12823 * The horizontal location of this view relative to its {@link #getLeft() left} position.
12824 * This position is post-layout, in addition to wherever the object's
12825 * layout placed it.
12827 * @return The horizontal position of this view relative to its left position, in pixels.
12829 @ViewDebug.ExportedProperty(category = "drawing")
12830 public float getTranslationX() {
12831 return mRenderNode.getTranslationX();
12835 * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
12836 * This effectively positions the object post-layout, in addition to wherever the object's
12837 * layout placed it.
12839 * @param translationX The horizontal position of this view relative to its left position,
12842 * @attr ref android.R.styleable#View_translationX
12844 public void setTranslationX(float translationX) {
12845 if (translationX != getTranslationX()) {
12846 invalidateViewProperty(true, false);
12847 mRenderNode.setTranslationX(translationX);
12848 invalidateViewProperty(false, true);
12850 invalidateParentIfNeededAndWasQuickRejected();
12851 notifySubtreeAccessibilityStateChangedIfNeeded();
12856 * The vertical location of this view relative to its {@link #getTop() top} position.
12857 * This position is post-layout, in addition to wherever the object's
12858 * layout placed it.
12860 * @return The vertical position of this view relative to its top position,
12863 @ViewDebug.ExportedProperty(category = "drawing")
12864 public float getTranslationY() {
12865 return mRenderNode.getTranslationY();
12869 * Sets the vertical location of this view relative to its {@link #getTop() top} position.
12870 * This effectively positions the object post-layout, in addition to wherever the object's
12871 * layout placed it.
12873 * @param translationY The vertical position of this view relative to its top position,
12876 * @attr ref android.R.styleable#View_translationY
12878 public void setTranslationY(float translationY) {
12879 if (translationY != getTranslationY()) {
12880 invalidateViewProperty(true, false);
12881 mRenderNode.setTranslationY(translationY);
12882 invalidateViewProperty(false, true);
12884 invalidateParentIfNeededAndWasQuickRejected();
12885 notifySubtreeAccessibilityStateChangedIfNeeded();
12890 * The depth location of this view relative to its {@link #getElevation() elevation}.
12892 * @return The depth of this view relative to its elevation.
12894 @ViewDebug.ExportedProperty(category = "drawing")
12895 public float getTranslationZ() {
12896 return mRenderNode.getTranslationZ();
12900 * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
12902 * @attr ref android.R.styleable#View_translationZ
12904 public void setTranslationZ(float translationZ) {
12905 if (translationZ != getTranslationZ()) {
12906 invalidateViewProperty(true, false);
12907 mRenderNode.setTranslationZ(translationZ);
12908 invalidateViewProperty(false, true);
12910 invalidateParentIfNeededAndWasQuickRejected();
12915 public void setAnimationMatrix(Matrix matrix) {
12916 invalidateViewProperty(true, false);
12917 mRenderNode.setAnimationMatrix(matrix);
12918 invalidateViewProperty(false, true);
12920 invalidateParentIfNeededAndWasQuickRejected();
12924 * Returns the current StateListAnimator if exists.
12926 * @return StateListAnimator or null if it does not exists
12927 * @see #setStateListAnimator(android.animation.StateListAnimator)
12929 public StateListAnimator getStateListAnimator() {
12930 return mStateListAnimator;
12934 * Attaches the provided StateListAnimator to this View.
12936 * Any previously attached StateListAnimator will be detached.
12938 * @param stateListAnimator The StateListAnimator to update the view
12939 * @see android.animation.StateListAnimator
12941 public void setStateListAnimator(StateListAnimator stateListAnimator) {
12942 if (mStateListAnimator == stateListAnimator) {
12945 if (mStateListAnimator != null) {
12946 mStateListAnimator.setTarget(null);
12948 mStateListAnimator = stateListAnimator;
12949 if (stateListAnimator != null) {
12950 stateListAnimator.setTarget(this);
12951 if (isAttachedToWindow()) {
12952 stateListAnimator.setState(getDrawableState());
12958 * Returns whether the Outline should be used to clip the contents of the View.
12960 * Note that this flag will only be respected if the View's Outline returns true from
12961 * {@link Outline#canClip()}.
12963 * @see #setOutlineProvider(ViewOutlineProvider)
12964 * @see #setClipToOutline(boolean)
12966 public final boolean getClipToOutline() {
12967 return mRenderNode.getClipToOutline();
12971 * Sets whether the View's Outline should be used to clip the contents of the View.
12973 * Only a single non-rectangular clip can be applied on a View at any time.
12974 * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
12975 * circular reveal} animation take priority over Outline clipping, and
12976 * child Outline clipping takes priority over Outline clipping done by a
12979 * Note that this flag will only be respected if the View's Outline returns true from
12980 * {@link Outline#canClip()}.
12982 * @see #setOutlineProvider(ViewOutlineProvider)
12983 * @see #getClipToOutline()
12985 public void setClipToOutline(boolean clipToOutline) {
12987 if (getClipToOutline() != clipToOutline) {
12988 mRenderNode.setClipToOutline(clipToOutline);
12992 // correspond to the enum values of View_outlineProvider
12993 private static final int PROVIDER_BACKGROUND = 0;
12994 private static final int PROVIDER_NONE = 1;
12995 private static final int PROVIDER_BOUNDS = 2;
12996 private static final int PROVIDER_PADDED_BOUNDS = 3;
12997 private void setOutlineProviderFromAttribute(int providerInt) {
12998 switch (providerInt) {
12999 case PROVIDER_BACKGROUND:
13000 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
13002 case PROVIDER_NONE:
13003 setOutlineProvider(null);
13005 case PROVIDER_BOUNDS:
13006 setOutlineProvider(ViewOutlineProvider.BOUNDS);
13008 case PROVIDER_PADDED_BOUNDS:
13009 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
13015 * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
13016 * the shape of the shadow it casts, and enables outline clipping.
13018 * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
13019 * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
13020 * outline provider with this method allows this behavior to be overridden.
13022 * If the ViewOutlineProvider is null, if querying it for an outline returns false,
13023 * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
13025 * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
13027 * @see #setClipToOutline(boolean)
13028 * @see #getClipToOutline()
13029 * @see #getOutlineProvider()
13031 public void setOutlineProvider(ViewOutlineProvider provider) {
13032 mOutlineProvider = provider;
13033 invalidateOutline();
13037 * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
13038 * that defines the shape of the shadow it casts, and enables outline clipping.
13040 * @see #setOutlineProvider(ViewOutlineProvider)
13042 public ViewOutlineProvider getOutlineProvider() {
13043 return mOutlineProvider;
13047 * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
13049 * @see #setOutlineProvider(ViewOutlineProvider)
13051 public void invalidateOutline() {
13054 notifySubtreeAccessibilityStateChangedIfNeeded();
13055 invalidateViewProperty(false, false);
13059 * Internal version of {@link #invalidateOutline()} which invalidates the
13060 * outline without invalidating the view itself. This is intended to be called from
13061 * within methods in the View class itself which are the result of the view being
13062 * invalidated already. For example, when we are drawing the background of a View,
13063 * we invalidate the outline in case it changed in the meantime, but we do not
13064 * need to invalidate the view because we're already drawing the background as part
13065 * of drawing the view in response to an earlier invalidation of the view.
13067 private void rebuildOutline() {
13068 // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
13069 if (mAttachInfo == null) return;
13071 if (mOutlineProvider == null) {
13072 // no provider, remove outline
13073 mRenderNode.setOutline(null);
13075 final Outline outline = mAttachInfo.mTmpOutline;
13076 outline.setEmpty();
13077 outline.setAlpha(1.0f);
13079 mOutlineProvider.getOutline(this, outline);
13080 mRenderNode.setOutline(outline);
13085 * HierarchyViewer only
13089 @ViewDebug.ExportedProperty(category = "drawing")
13090 public boolean hasShadow() {
13091 return mRenderNode.hasShadow();
13096 public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
13097 mRenderNode.setRevealClip(shouldClip, x, y, radius);
13098 invalidateViewProperty(false, false);
13102 * Hit rectangle in parent's coordinates
13104 * @param outRect The hit rectangle of the view.
13106 public void getHitRect(Rect outRect) {
13107 if (hasIdentityMatrix() || mAttachInfo == null) {
13108 outRect.set(mLeft, mTop, mRight, mBottom);
13110 final RectF tmpRect = mAttachInfo.mTmpTransformRect;
13111 tmpRect.set(0, 0, getWidth(), getHeight());
13112 getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
13113 outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
13114 (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
13119 * Determines whether the given point, in local coordinates is inside the view.
13121 /*package*/ final boolean pointInView(float localX, float localY) {
13122 return pointInView(localX, localY, 0);
13126 * Utility method to determine whether the given point, in local coordinates,
13127 * is inside the view, where the area of the view is expanded by the slop factor.
13128 * This method is called while processing touch-move events to determine if the event
13129 * is still within the view.
13133 public boolean pointInView(float localX, float localY, float slop) {
13134 return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
13135 localY < ((mBottom - mTop) + slop);
13139 * When a view has focus and the user navigates away from it, the next view is searched for
13140 * starting from the rectangle filled in by this method.
13142 * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
13143 * of the view. However, if your view maintains some idea of internal selection,
13144 * such as a cursor, or a selected row or column, you should override this method and
13145 * fill in a more specific rectangle.
13147 * @param r The rectangle to fill in, in this view's coordinates.
13149 public void getFocusedRect(Rect r) {
13154 * If some part of this view is not clipped by any of its parents, then
13155 * return that area in r in global (root) coordinates. To convert r to local
13156 * coordinates (without taking possible View rotations into account), offset
13157 * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
13158 * If the view is completely clipped or translated out, return false.
13160 * @param r If true is returned, r holds the global coordinates of the
13161 * visible portion of this view.
13162 * @param globalOffset If true is returned, globalOffset holds the dx,dy
13163 * between this view and its root. globalOffet may be null.
13164 * @return true if r is non-empty (i.e. part of the view is visible at the
13167 public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
13168 int width = mRight - mLeft;
13169 int height = mBottom - mTop;
13170 if (width > 0 && height > 0) {
13171 r.set(0, 0, width, height);
13172 if (globalOffset != null) {
13173 globalOffset.set(-mScrollX, -mScrollY);
13175 return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
13180 public final boolean getGlobalVisibleRect(Rect r) {
13181 return getGlobalVisibleRect(r, null);
13184 public final boolean getLocalVisibleRect(Rect r) {
13185 final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
13186 if (getGlobalVisibleRect(r, offset)) {
13187 r.offset(-offset.x, -offset.y); // make r local
13194 * Offset this view's vertical location by the specified number of pixels.
13196 * @param offset the number of pixels to offset the view by
13198 public void offsetTopAndBottom(int offset) {
13200 final boolean matrixIsIdentity = hasIdentityMatrix();
13201 if (matrixIsIdentity) {
13202 if (isHardwareAccelerated()) {
13203 invalidateViewProperty(false, false);
13205 final ViewParent p = mParent;
13206 if (p != null && mAttachInfo != null) {
13207 final Rect r = mAttachInfo.mTmpInvalRect;
13212 minTop = mTop + offset;
13213 maxBottom = mBottom;
13217 maxBottom = mBottom + offset;
13220 r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
13221 p.invalidateChild(this, r);
13225 invalidateViewProperty(false, false);
13230 mRenderNode.offsetTopAndBottom(offset);
13231 if (isHardwareAccelerated()) {
13232 invalidateViewProperty(false, false);
13233 invalidateParentIfNeededAndWasQuickRejected();
13235 if (!matrixIsIdentity) {
13236 invalidateViewProperty(false, true);
13238 invalidateParentIfNeeded();
13240 notifySubtreeAccessibilityStateChangedIfNeeded();
13245 * Offset this view's horizontal location by the specified amount of pixels.
13247 * @param offset the number of pixels to offset the view by
13249 public void offsetLeftAndRight(int offset) {
13251 final boolean matrixIsIdentity = hasIdentityMatrix();
13252 if (matrixIsIdentity) {
13253 if (isHardwareAccelerated()) {
13254 invalidateViewProperty(false, false);
13256 final ViewParent p = mParent;
13257 if (p != null && mAttachInfo != null) {
13258 final Rect r = mAttachInfo.mTmpInvalRect;
13262 minLeft = mLeft + offset;
13266 maxRight = mRight + offset;
13268 r.set(0, 0, maxRight - minLeft, mBottom - mTop);
13269 p.invalidateChild(this, r);
13273 invalidateViewProperty(false, false);
13278 mRenderNode.offsetLeftAndRight(offset);
13279 if (isHardwareAccelerated()) {
13280 invalidateViewProperty(false, false);
13281 invalidateParentIfNeededAndWasQuickRejected();
13283 if (!matrixIsIdentity) {
13284 invalidateViewProperty(false, true);
13286 invalidateParentIfNeeded();
13288 notifySubtreeAccessibilityStateChangedIfNeeded();
13293 * Get the LayoutParams associated with this view. All views should have
13294 * layout parameters. These supply parameters to the <i>parent</i> of this
13295 * view specifying how it should be arranged. There are many subclasses of
13296 * ViewGroup.LayoutParams, and these correspond to the different subclasses
13297 * of ViewGroup that are responsible for arranging their children.
13299 * This method may return null if this View is not attached to a parent
13300 * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
13301 * was not invoked successfully. When a View is attached to a parent
13302 * ViewGroup, this method must not return null.
13304 * @return The LayoutParams associated with this view, or null if no
13305 * parameters have been set yet
13307 @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
13308 public ViewGroup.LayoutParams getLayoutParams() {
13309 return mLayoutParams;
13313 * Set the layout parameters associated with this view. These supply
13314 * parameters to the <i>parent</i> of this view specifying how it should be
13315 * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
13316 * correspond to the different subclasses of ViewGroup that are responsible
13317 * for arranging their children.
13319 * @param params The layout parameters for this view, cannot be null
13321 public void setLayoutParams(ViewGroup.LayoutParams params) {
13322 if (params == null) {
13323 throw new NullPointerException("Layout parameters cannot be null");
13325 mLayoutParams = params;
13326 resolveLayoutParams();
13327 if (mParent instanceof ViewGroup) {
13328 ((ViewGroup) mParent).onSetLayoutParams(this, params);
13334 * Resolve the layout parameters depending on the resolved layout direction
13338 public void resolveLayoutParams() {
13339 if (mLayoutParams != null) {
13340 mLayoutParams.resolveLayoutDirection(getLayoutDirection());
13345 * Set the scrolled position of your view. This will cause a call to
13346 * {@link #onScrollChanged(int, int, int, int)} and the view will be
13348 * @param x the x position to scroll to
13349 * @param y the y position to scroll to
13351 public void scrollTo(int x, int y) {
13352 if (mScrollX != x || mScrollY != y) {
13353 int oldX = mScrollX;
13354 int oldY = mScrollY;
13357 invalidateParentCaches();
13358 onScrollChanged(mScrollX, mScrollY, oldX, oldY);
13359 if (!awakenScrollBars()) {
13360 postInvalidateOnAnimation();
13366 * Move the scrolled position of your view. This will cause a call to
13367 * {@link #onScrollChanged(int, int, int, int)} and the view will be
13369 * @param x the amount of pixels to scroll by horizontally
13370 * @param y the amount of pixels to scroll by vertically
13372 public void scrollBy(int x, int y) {
13373 scrollTo(mScrollX + x, mScrollY + y);
13377 * <p>Trigger the scrollbars to draw. When invoked this method starts an
13378 * animation to fade the scrollbars out after a default delay. If a subclass
13379 * provides animated scrolling, the start delay should equal the duration
13380 * of the scrolling animation.</p>
13382 * <p>The animation starts only if at least one of the scrollbars is
13383 * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
13384 * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13385 * this method returns true, and false otherwise. If the animation is
13386 * started, this method calls {@link #invalidate()}; in that case the
13387 * caller should not call {@link #invalidate()}.</p>
13389 * <p>This method should be invoked every time a subclass directly updates
13390 * the scroll parameters.</p>
13392 * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
13393 * and {@link #scrollTo(int, int)}.</p>
13395 * @return true if the animation is played, false otherwise
13397 * @see #awakenScrollBars(int)
13398 * @see #scrollBy(int, int)
13399 * @see #scrollTo(int, int)
13400 * @see #isHorizontalScrollBarEnabled()
13401 * @see #isVerticalScrollBarEnabled()
13402 * @see #setHorizontalScrollBarEnabled(boolean)
13403 * @see #setVerticalScrollBarEnabled(boolean)
13405 protected boolean awakenScrollBars() {
13406 return mScrollCache != null &&
13407 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
13411 * Trigger the scrollbars to draw.
13412 * This method differs from awakenScrollBars() only in its default duration.
13413 * initialAwakenScrollBars() will show the scroll bars for longer than
13414 * usual to give the user more of a chance to notice them.
13416 * @return true if the animation is played, false otherwise.
13418 private boolean initialAwakenScrollBars() {
13419 return mScrollCache != null &&
13420 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
13425 * Trigger the scrollbars to draw. When invoked this method starts an
13426 * animation to fade the scrollbars out after a fixed delay. If a subclass
13427 * provides animated scrolling, the start delay should equal the duration of
13428 * the scrolling animation.
13432 * The animation starts only if at least one of the scrollbars is enabled,
13433 * as specified by {@link #isHorizontalScrollBarEnabled()} and
13434 * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13435 * this method returns true, and false otherwise. If the animation is
13436 * started, this method calls {@link #invalidate()}; in that case the caller
13437 * should not call {@link #invalidate()}.
13441 * This method should be invoked every time a subclass directly updates the
13442 * scroll parameters.
13445 * @param startDelay the delay, in milliseconds, after which the animation
13446 * should start; when the delay is 0, the animation starts
13448 * @return true if the animation is played, false otherwise
13450 * @see #scrollBy(int, int)
13451 * @see #scrollTo(int, int)
13452 * @see #isHorizontalScrollBarEnabled()
13453 * @see #isVerticalScrollBarEnabled()
13454 * @see #setHorizontalScrollBarEnabled(boolean)
13455 * @see #setVerticalScrollBarEnabled(boolean)
13457 protected boolean awakenScrollBars(int startDelay) {
13458 return awakenScrollBars(startDelay, true);
13463 * Trigger the scrollbars to draw. When invoked this method starts an
13464 * animation to fade the scrollbars out after a fixed delay. If a subclass
13465 * provides animated scrolling, the start delay should equal the duration of
13466 * the scrolling animation.
13470 * The animation starts only if at least one of the scrollbars is enabled,
13471 * as specified by {@link #isHorizontalScrollBarEnabled()} and
13472 * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13473 * this method returns true, and false otherwise. If the animation is
13474 * started, this method calls {@link #invalidate()} if the invalidate parameter
13475 * is set to true; in that case the caller
13476 * should not call {@link #invalidate()}.
13480 * This method should be invoked every time a subclass directly updates the
13481 * scroll parameters.
13484 * @param startDelay the delay, in milliseconds, after which the animation
13485 * should start; when the delay is 0, the animation starts
13488 * @param invalidate Whether this method should call invalidate
13490 * @return true if the animation is played, false otherwise
13492 * @see #scrollBy(int, int)
13493 * @see #scrollTo(int, int)
13494 * @see #isHorizontalScrollBarEnabled()
13495 * @see #isVerticalScrollBarEnabled()
13496 * @see #setHorizontalScrollBarEnabled(boolean)
13497 * @see #setVerticalScrollBarEnabled(boolean)
13499 protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
13500 final ScrollabilityCache scrollCache = mScrollCache;
13502 if (scrollCache == null || !scrollCache.fadeScrollBars) {
13506 if (scrollCache.scrollBar == null) {
13507 scrollCache.scrollBar = new ScrollBarDrawable();
13508 scrollCache.scrollBar.setState(getDrawableState());
13509 scrollCache.scrollBar.setCallback(this);
13512 if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
13515 // Invalidate to show the scrollbars
13516 postInvalidateOnAnimation();
13519 if (scrollCache.state == ScrollabilityCache.OFF) {
13520 // FIXME: this is copied from WindowManagerService.
13521 // We should get this value from the system when it
13522 // is possible to do so.
13523 final int KEY_REPEAT_FIRST_DELAY = 750;
13524 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
13527 // Tell mScrollCache when we should start fading. This may
13528 // extend the fade start time if one was already scheduled
13529 long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
13530 scrollCache.fadeStartTime = fadeStartTime;
13531 scrollCache.state = ScrollabilityCache.ON;
13533 // Schedule our fader to run, unscheduling any old ones first
13534 if (mAttachInfo != null) {
13535 mAttachInfo.mHandler.removeCallbacks(scrollCache);
13536 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
13546 * Do not invalidate views which are not visible and which are not running an animation. They
13547 * will not get drawn and they should not set dirty flags as if they will be drawn
13549 private boolean skipInvalidate() {
13550 return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
13551 (!(mParent instanceof ViewGroup) ||
13552 !((ViewGroup) mParent).isViewTransitioning(this));
13556 * Mark the area defined by dirty as needing to be drawn. If the view is
13557 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
13558 * point in the future.
13560 * This must be called from a UI thread. To call from a non-UI thread, call
13561 * {@link #postInvalidate()}.
13563 * <b>WARNING:</b> In API 19 and below, this method may be destructive to
13566 * @param dirty the rectangle representing the bounds of the dirty region
13568 public void invalidate(Rect dirty) {
13569 final int scrollX = mScrollX;
13570 final int scrollY = mScrollY;
13571 invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
13572 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
13576 * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
13577 * coordinates of the dirty rect are relative to the view. If the view is
13578 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
13579 * point in the future.
13581 * This must be called from a UI thread. To call from a non-UI thread, call
13582 * {@link #postInvalidate()}.
13584 * @param l the left position of the dirty region
13585 * @param t the top position of the dirty region
13586 * @param r the right position of the dirty region
13587 * @param b the bottom position of the dirty region
13589 public void invalidate(int l, int t, int r, int b) {
13590 final int scrollX = mScrollX;
13591 final int scrollY = mScrollY;
13592 invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
13596 * Invalidate the whole view. If the view is visible,
13597 * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
13600 * This must be called from a UI thread. To call from a non-UI thread, call
13601 * {@link #postInvalidate()}.
13603 public void invalidate() {
13608 * This is where the invalidate() work actually happens. A full invalidate()
13609 * causes the drawing cache to be invalidated, but this function can be
13610 * called with invalidateCache set to false to skip that invalidation step
13611 * for cases that do not need it (for example, a component that remains at
13612 * the same dimensions with the same content).
13614 * @param invalidateCache Whether the drawing cache for this view should be
13615 * invalidated as well. This is usually true for a full
13616 * invalidate, but may be set to false if the View's contents or
13617 * dimensions have not changed.
13619 void invalidate(boolean invalidateCache) {
13620 invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
13623 void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
13624 boolean fullInvalidate) {
13625 if (mGhostView != null) {
13626 mGhostView.invalidate(true);
13630 if (skipInvalidate()) {
13634 if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
13635 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
13636 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
13637 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
13638 if (fullInvalidate) {
13639 mLastIsOpaque = isOpaque();
13640 mPrivateFlags &= ~PFLAG_DRAWN;
13643 mPrivateFlags |= PFLAG_DIRTY;
13645 if (invalidateCache) {
13646 mPrivateFlags |= PFLAG_INVALIDATED;
13647 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13650 // Propagate the damage rectangle to the parent view.
13651 final AttachInfo ai = mAttachInfo;
13652 final ViewParent p = mParent;
13653 if (p != null && ai != null && l < r && t < b) {
13654 final Rect damage = ai.mTmpInvalRect;
13655 damage.set(l, t, r, b);
13656 p.invalidateChild(this, damage);
13659 // Damage the entire projection receiver, if necessary.
13660 if (mBackground != null && mBackground.isProjected()) {
13661 final View receiver = getProjectionReceiver();
13662 if (receiver != null) {
13663 receiver.damageInParent();
13667 // Damage the entire IsolatedZVolume receiving this view's shadow.
13668 if (isHardwareAccelerated() && getZ() != 0) {
13669 damageShadowReceiver();
13675 * @return this view's projection receiver, or {@code null} if none exists
13677 private View getProjectionReceiver() {
13678 ViewParent p = getParent();
13679 while (p != null && p instanceof View) {
13680 final View v = (View) p;
13681 if (v.isProjectionReceiver()) {
13691 * @return whether the view is a projection receiver
13693 private boolean isProjectionReceiver() {
13694 return mBackground != null;
13698 * Damage area of the screen that can be covered by this View's shadow.
13700 * This method will guarantee that any changes to shadows cast by a View
13701 * are damaged on the screen for future redraw.
13703 private void damageShadowReceiver() {
13704 final AttachInfo ai = mAttachInfo;
13706 ViewParent p = getParent();
13707 if (p != null && p instanceof ViewGroup) {
13708 final ViewGroup vg = (ViewGroup) p;
13709 vg.damageInParent();
13715 * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
13716 * set any flags or handle all of the cases handled by the default invalidation methods.
13717 * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
13718 * dirty rect. This method calls into fast invalidation methods in ViewGroup that
13719 * walk up the hierarchy, transforming the dirty rect as necessary.
13721 * The method also handles normal invalidation logic if display list properties are not
13722 * being used in this view. The invalidateParent and forceRedraw flags are used by that
13723 * backup approach, to handle these cases used in the various property-setting methods.
13725 * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
13726 * are not being used in this view
13727 * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
13728 * list properties are not being used in this view
13730 void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
13731 if (!isHardwareAccelerated()
13732 || !mRenderNode.isValid()
13733 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
13734 if (invalidateParent) {
13735 invalidateParentCaches();
13738 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13744 if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
13745 damageShadowReceiver();
13750 * Tells the parent view to damage this view's bounds.
13754 protected void damageInParent() {
13755 final AttachInfo ai = mAttachInfo;
13756 final ViewParent p = mParent;
13757 if (p != null && ai != null) {
13758 final Rect r = ai.mTmpInvalRect;
13759 r.set(0, 0, mRight - mLeft, mBottom - mTop);
13760 if (mParent instanceof ViewGroup) {
13761 ((ViewGroup) mParent).damageChild(this, r);
13763 mParent.invalidateChild(this, r);
13769 * Utility method to transform a given Rect by the current matrix of this view.
13771 void transformRect(final Rect rect) {
13772 if (!getMatrix().isIdentity()) {
13773 RectF boundingRect = mAttachInfo.mTmpTransformRect;
13774 boundingRect.set(rect);
13775 getMatrix().mapRect(boundingRect);
13776 rect.set((int) Math.floor(boundingRect.left),
13777 (int) Math.floor(boundingRect.top),
13778 (int) Math.ceil(boundingRect.right),
13779 (int) Math.ceil(boundingRect.bottom));
13784 * Used to indicate that the parent of this view should clear its caches. This functionality
13785 * is used to force the parent to rebuild its display list (when hardware-accelerated),
13786 * which is necessary when various parent-managed properties of the view change, such as
13787 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
13788 * clears the parent caches and does not causes an invalidate event.
13792 protected void invalidateParentCaches() {
13793 if (mParent instanceof View) {
13794 ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
13799 * Used to indicate that the parent of this view should be invalidated. This functionality
13800 * is used to force the parent to rebuild its display list (when hardware-accelerated),
13801 * which is necessary when various parent-managed properties of the view change, such as
13802 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
13803 * an invalidation event to the parent.
13807 protected void invalidateParentIfNeeded() {
13808 if (isHardwareAccelerated() && mParent instanceof View) {
13809 ((View) mParent).invalidate(true);
13816 protected void invalidateParentIfNeededAndWasQuickRejected() {
13817 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
13818 // View was rejected last time it was drawn by its parent; this may have changed
13819 invalidateParentIfNeeded();
13824 * Indicates whether this View is opaque. An opaque View guarantees that it will
13825 * draw all the pixels overlapping its bounds using a fully opaque color.
13827 * Subclasses of View should override this method whenever possible to indicate
13828 * whether an instance is opaque. Opaque Views are treated in a special way by
13829 * the View hierarchy, possibly allowing it to perform optimizations during
13830 * invalidate/draw passes.
13832 * @return True if this View is guaranteed to be fully opaque, false otherwise.
13834 @ViewDebug.ExportedProperty(category = "drawing")
13835 public boolean isOpaque() {
13836 return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
13837 getFinalAlpha() >= 1.0f;
13843 protected void computeOpaqueFlags() {
13845 // - Has a background
13846 // - Background is opaque
13847 // - Doesn't have scrollbars or scrollbars overlay
13849 if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
13850 mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
13852 mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
13855 final int flags = mViewFlags;
13856 if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
13857 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
13858 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
13859 mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
13861 mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
13868 protected boolean hasOpaqueScrollbars() {
13869 return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
13873 * @return A handler associated with the thread running the View. This
13874 * handler can be used to pump events in the UI events queue.
13876 public Handler getHandler() {
13877 final AttachInfo attachInfo = mAttachInfo;
13878 if (attachInfo != null) {
13879 return attachInfo.mHandler;
13885 * Returns the queue of runnable for this view.
13887 * @return the queue of runnables for this view
13889 private HandlerActionQueue getRunQueue() {
13890 if (mRunQueue == null) {
13891 mRunQueue = new HandlerActionQueue();
13897 * Gets the view root associated with the View.
13898 * @return The view root, or null if none.
13901 public ViewRootImpl getViewRootImpl() {
13902 if (mAttachInfo != null) {
13903 return mAttachInfo.mViewRootImpl;
13911 public ThreadedRenderer getHardwareRenderer() {
13912 return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
13916 * <p>Causes the Runnable to be added to the message queue.
13917 * The runnable will be run on the user interface thread.</p>
13919 * @param action The Runnable that will be executed.
13921 * @return Returns true if the Runnable was successfully placed in to the
13922 * message queue. Returns false on failure, usually because the
13923 * looper processing the message queue is exiting.
13925 * @see #postDelayed
13926 * @see #removeCallbacks
13928 public boolean post(Runnable action) {
13929 final AttachInfo attachInfo = mAttachInfo;
13930 if (attachInfo != null) {
13931 return attachInfo.mHandler.post(action);
13934 // Postpone the runnable until we know on which thread it needs to run.
13935 // Assume that the runnable will be successfully placed after attach.
13936 getRunQueue().post(action);
13941 * <p>Causes the Runnable to be added to the message queue, to be run
13942 * after the specified amount of time elapses.
13943 * The runnable will be run on the user interface thread.</p>
13945 * @param action The Runnable that will be executed.
13946 * @param delayMillis The delay (in milliseconds) until the Runnable
13947 * will be executed.
13949 * @return true if the Runnable was successfully placed in to the
13950 * message queue. Returns false on failure, usually because the
13951 * looper processing the message queue is exiting. Note that a
13952 * result of true does not mean the Runnable will be processed --
13953 * if the looper is quit before the delivery time of the message
13954 * occurs then the message will be dropped.
13957 * @see #removeCallbacks
13959 public boolean postDelayed(Runnable action, long delayMillis) {
13960 final AttachInfo attachInfo = mAttachInfo;
13961 if (attachInfo != null) {
13962 return attachInfo.mHandler.postDelayed(action, delayMillis);
13965 // Postpone the runnable until we know on which thread it needs to run.
13966 // Assume that the runnable will be successfully placed after attach.
13967 getRunQueue().postDelayed(action, delayMillis);
13972 * <p>Causes the Runnable to execute on the next animation time step.
13973 * The runnable will be run on the user interface thread.</p>
13975 * @param action The Runnable that will be executed.
13977 * @see #postOnAnimationDelayed
13978 * @see #removeCallbacks
13980 public void postOnAnimation(Runnable action) {
13981 final AttachInfo attachInfo = mAttachInfo;
13982 if (attachInfo != null) {
13983 attachInfo.mViewRootImpl.mChoreographer.postCallback(
13984 Choreographer.CALLBACK_ANIMATION, action, null);
13986 // Postpone the runnable until we know
13987 // on which thread it needs to run.
13988 getRunQueue().post(action);
13993 * <p>Causes the Runnable to execute on the next animation time step,
13994 * after the specified amount of time elapses.
13995 * The runnable will be run on the user interface thread.</p>
13997 * @param action The Runnable that will be executed.
13998 * @param delayMillis The delay (in milliseconds) until the Runnable
13999 * will be executed.
14001 * @see #postOnAnimation
14002 * @see #removeCallbacks
14004 public void postOnAnimationDelayed(Runnable action, long delayMillis) {
14005 final AttachInfo attachInfo = mAttachInfo;
14006 if (attachInfo != null) {
14007 attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
14008 Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
14010 // Postpone the runnable until we know
14011 // on which thread it needs to run.
14012 getRunQueue().postDelayed(action, delayMillis);
14017 * <p>Removes the specified Runnable from the message queue.</p>
14019 * @param action The Runnable to remove from the message handling queue
14021 * @return true if this view could ask the Handler to remove the Runnable,
14022 * false otherwise. When the returned value is true, the Runnable
14023 * may or may not have been actually removed from the message queue
14024 * (for instance, if the Runnable was not in the queue already.)
14027 * @see #postDelayed
14028 * @see #postOnAnimation
14029 * @see #postOnAnimationDelayed
14031 public boolean removeCallbacks(Runnable action) {
14032 if (action != null) {
14033 final AttachInfo attachInfo = mAttachInfo;
14034 if (attachInfo != null) {
14035 attachInfo.mHandler.removeCallbacks(action);
14036 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
14037 Choreographer.CALLBACK_ANIMATION, action, null);
14039 getRunQueue().removeCallbacks(action);
14045 * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
14046 * Use this to invalidate the View from a non-UI thread.</p>
14048 * <p>This method can be invoked from outside of the UI thread
14049 * only when this View is attached to a window.</p>
14051 * @see #invalidate()
14052 * @see #postInvalidateDelayed(long)
14054 public void postInvalidate() {
14055 postInvalidateDelayed(0);
14059 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14060 * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
14062 * <p>This method can be invoked from outside of the UI thread
14063 * only when this View is attached to a window.</p>
14065 * @param left The left coordinate of the rectangle to invalidate.
14066 * @param top The top coordinate of the rectangle to invalidate.
14067 * @param right The right coordinate of the rectangle to invalidate.
14068 * @param bottom The bottom coordinate of the rectangle to invalidate.
14070 * @see #invalidate(int, int, int, int)
14071 * @see #invalidate(Rect)
14072 * @see #postInvalidateDelayed(long, int, int, int, int)
14074 public void postInvalidate(int left, int top, int right, int bottom) {
14075 postInvalidateDelayed(0, left, top, right, bottom);
14079 * <p>Cause an invalidate to happen on a subsequent cycle through the event
14080 * loop. Waits for the specified amount of time.</p>
14082 * <p>This method can be invoked from outside of the UI thread
14083 * only when this View is attached to a window.</p>
14085 * @param delayMilliseconds the duration in milliseconds to delay the
14088 * @see #invalidate()
14089 * @see #postInvalidate()
14091 public void postInvalidateDelayed(long delayMilliseconds) {
14092 // We try only with the AttachInfo because there's no point in invalidating
14093 // if we are not attached to our window
14094 final AttachInfo attachInfo = mAttachInfo;
14095 if (attachInfo != null) {
14096 attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
14101 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14102 * through the event loop. Waits for the specified amount of time.</p>
14104 * <p>This method can be invoked from outside of the UI thread
14105 * only when this View is attached to a window.</p>
14107 * @param delayMilliseconds the duration in milliseconds to delay the
14109 * @param left The left coordinate of the rectangle to invalidate.
14110 * @param top The top coordinate of the rectangle to invalidate.
14111 * @param right The right coordinate of the rectangle to invalidate.
14112 * @param bottom The bottom coordinate of the rectangle to invalidate.
14114 * @see #invalidate(int, int, int, int)
14115 * @see #invalidate(Rect)
14116 * @see #postInvalidate(int, int, int, int)
14118 public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
14119 int right, int bottom) {
14121 // We try only with the AttachInfo because there's no point in invalidating
14122 // if we are not attached to our window
14123 final AttachInfo attachInfo = mAttachInfo;
14124 if (attachInfo != null) {
14125 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14126 info.target = this;
14129 info.right = right;
14130 info.bottom = bottom;
14132 attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
14137 * <p>Cause an invalidate to happen on the next animation time step, typically the
14138 * next display frame.</p>
14140 * <p>This method can be invoked from outside of the UI thread
14141 * only when this View is attached to a window.</p>
14143 * @see #invalidate()
14145 public void postInvalidateOnAnimation() {
14146 // We try only with the AttachInfo because there's no point in invalidating
14147 // if we are not attached to our window
14148 final AttachInfo attachInfo = mAttachInfo;
14149 if (attachInfo != null) {
14150 attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
14155 * <p>Cause an invalidate of the specified area to happen on the next animation
14156 * time step, typically the next display frame.</p>
14158 * <p>This method can be invoked from outside of the UI thread
14159 * only when this View is attached to a window.</p>
14161 * @param left The left coordinate of the rectangle to invalidate.
14162 * @param top The top coordinate of the rectangle to invalidate.
14163 * @param right The right coordinate of the rectangle to invalidate.
14164 * @param bottom The bottom coordinate of the rectangle to invalidate.
14166 * @see #invalidate(int, int, int, int)
14167 * @see #invalidate(Rect)
14169 public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
14170 // We try only with the AttachInfo because there's no point in invalidating
14171 // if we are not attached to our window
14172 final AttachInfo attachInfo = mAttachInfo;
14173 if (attachInfo != null) {
14174 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14175 info.target = this;
14178 info.right = right;
14179 info.bottom = bottom;
14181 attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
14186 * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
14187 * This event is sent at most once every
14188 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
14190 private void postSendViewScrolledAccessibilityEventCallback() {
14191 if (mSendViewScrolledAccessibilityEvent == null) {
14192 mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
14194 if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
14195 mSendViewScrolledAccessibilityEvent.mIsPending = true;
14196 postDelayed(mSendViewScrolledAccessibilityEvent,
14197 ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
14202 * Called by a parent to request that a child update its values for mScrollX
14203 * and mScrollY if necessary. This will typically be done if the child is
14204 * animating a scroll using a {@link android.widget.Scroller Scroller}
14207 public void computeScroll() {
14211 * <p>Indicate whether the horizontal edges are faded when the view is
14212 * scrolled horizontally.</p>
14214 * @return true if the horizontal edges should are faded on scroll, false
14217 * @see #setHorizontalFadingEdgeEnabled(boolean)
14219 * @attr ref android.R.styleable#View_requiresFadingEdge
14221 public boolean isHorizontalFadingEdgeEnabled() {
14222 return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
14226 * <p>Define whether the horizontal edges should be faded when this view
14227 * is scrolled horizontally.</p>
14229 * @param horizontalFadingEdgeEnabled true if the horizontal edges should
14230 * be faded when the view is scrolled
14233 * @see #isHorizontalFadingEdgeEnabled()
14235 * @attr ref android.R.styleable#View_requiresFadingEdge
14237 public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
14238 if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
14239 if (horizontalFadingEdgeEnabled) {
14243 mViewFlags ^= FADING_EDGE_HORIZONTAL;
14248 * <p>Indicate whether the vertical edges are faded when the view is
14249 * scrolled horizontally.</p>
14251 * @return true if the vertical edges should are faded on scroll, false
14254 * @see #setVerticalFadingEdgeEnabled(boolean)
14256 * @attr ref android.R.styleable#View_requiresFadingEdge
14258 public boolean isVerticalFadingEdgeEnabled() {
14259 return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
14263 * <p>Define whether the vertical edges should be faded when this view
14264 * is scrolled vertically.</p>
14266 * @param verticalFadingEdgeEnabled true if the vertical edges should
14267 * be faded when the view is scrolled
14270 * @see #isVerticalFadingEdgeEnabled()
14272 * @attr ref android.R.styleable#View_requiresFadingEdge
14274 public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
14275 if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
14276 if (verticalFadingEdgeEnabled) {
14280 mViewFlags ^= FADING_EDGE_VERTICAL;
14285 * Returns the strength, or intensity, of the top faded edge. The strength is
14286 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14287 * returns 0.0 or 1.0 but no value in between.
14289 * Subclasses should override this method to provide a smoother fade transition
14290 * when scrolling occurs.
14292 * @return the intensity of the top fade as a float between 0.0f and 1.0f
14294 protected float getTopFadingEdgeStrength() {
14295 return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
14299 * Returns the strength, or intensity, of the bottom faded edge. The strength is
14300 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14301 * returns 0.0 or 1.0 but no value in between.
14303 * Subclasses should override this method to provide a smoother fade transition
14304 * when scrolling occurs.
14306 * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
14308 protected float getBottomFadingEdgeStrength() {
14309 return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
14310 computeVerticalScrollRange() ? 1.0f : 0.0f;
14314 * Returns the strength, or intensity, of the left faded edge. The strength is
14315 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14316 * returns 0.0 or 1.0 but no value in between.
14318 * Subclasses should override this method to provide a smoother fade transition
14319 * when scrolling occurs.
14321 * @return the intensity of the left fade as a float between 0.0f and 1.0f
14323 protected float getLeftFadingEdgeStrength() {
14324 return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
14328 * Returns the strength, or intensity, of the right faded edge. The strength is
14329 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14330 * returns 0.0 or 1.0 but no value in between.
14332 * Subclasses should override this method to provide a smoother fade transition
14333 * when scrolling occurs.
14335 * @return the intensity of the right fade as a float between 0.0f and 1.0f
14337 protected float getRightFadingEdgeStrength() {
14338 return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
14339 computeHorizontalScrollRange() ? 1.0f : 0.0f;
14343 * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
14344 * scrollbar is not drawn by default.</p>
14346 * @return true if the horizontal scrollbar should be painted, false
14349 * @see #setHorizontalScrollBarEnabled(boolean)
14351 public boolean isHorizontalScrollBarEnabled() {
14352 return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
14356 * <p>Define whether the horizontal scrollbar should be drawn or not. The
14357 * scrollbar is not drawn by default.</p>
14359 * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
14362 * @see #isHorizontalScrollBarEnabled()
14364 public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
14365 if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
14366 mViewFlags ^= SCROLLBARS_HORIZONTAL;
14367 computeOpaqueFlags();
14373 * <p>Indicate whether the vertical scrollbar should be drawn or not. The
14374 * scrollbar is not drawn by default.</p>
14376 * @return true if the vertical scrollbar should be painted, false
14379 * @see #setVerticalScrollBarEnabled(boolean)
14381 public boolean isVerticalScrollBarEnabled() {
14382 return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
14386 * <p>Define whether the vertical scrollbar should be drawn or not. The
14387 * scrollbar is not drawn by default.</p>
14389 * @param verticalScrollBarEnabled true if the vertical scrollbar should
14392 * @see #isVerticalScrollBarEnabled()
14394 public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
14395 if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
14396 mViewFlags ^= SCROLLBARS_VERTICAL;
14397 computeOpaqueFlags();
14405 protected void recomputePadding() {
14406 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
14410 * Define whether scrollbars will fade when the view is not scrolling.
14412 * @param fadeScrollbars whether to enable fading
14414 * @attr ref android.R.styleable#View_fadeScrollbars
14416 public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
14418 final ScrollabilityCache scrollabilityCache = mScrollCache;
14419 scrollabilityCache.fadeScrollBars = fadeScrollbars;
14420 if (fadeScrollbars) {
14421 scrollabilityCache.state = ScrollabilityCache.OFF;
14423 scrollabilityCache.state = ScrollabilityCache.ON;
14429 * Returns true if scrollbars will fade when this view is not scrolling
14431 * @return true if scrollbar fading is enabled
14433 * @attr ref android.R.styleable#View_fadeScrollbars
14435 public boolean isScrollbarFadingEnabled() {
14436 return mScrollCache != null && mScrollCache.fadeScrollBars;
14441 * Returns the delay before scrollbars fade.
14443 * @return the delay before scrollbars fade
14445 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
14447 public int getScrollBarDefaultDelayBeforeFade() {
14448 return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
14449 mScrollCache.scrollBarDefaultDelayBeforeFade;
14453 * Define the delay before scrollbars fade.
14455 * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
14457 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
14459 public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
14460 getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
14465 * Returns the scrollbar fade duration.
14467 * @return the scrollbar fade duration
14469 * @attr ref android.R.styleable#View_scrollbarFadeDuration
14471 public int getScrollBarFadeDuration() {
14472 return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
14473 mScrollCache.scrollBarFadeDuration;
14477 * Define the scrollbar fade duration.
14479 * @param scrollBarFadeDuration - the scrollbar fade duration
14481 * @attr ref android.R.styleable#View_scrollbarFadeDuration
14483 public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
14484 getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
14489 * Returns the scrollbar size.
14491 * @return the scrollbar size
14493 * @attr ref android.R.styleable#View_scrollbarSize
14495 public int getScrollBarSize() {
14496 return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
14497 mScrollCache.scrollBarSize;
14501 * Define the scrollbar size.
14503 * @param scrollBarSize - the scrollbar size
14505 * @attr ref android.R.styleable#View_scrollbarSize
14507 public void setScrollBarSize(int scrollBarSize) {
14508 getScrollCache().scrollBarSize = scrollBarSize;
14512 * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
14513 * inset. When inset, they add to the padding of the view. And the scrollbars
14514 * can be drawn inside the padding area or on the edge of the view. For example,
14515 * if a view has a background drawable and you want to draw the scrollbars
14516 * inside the padding specified by the drawable, you can use
14517 * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
14518 * appear at the edge of the view, ignoring the padding, then you can use
14519 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
14520 * @param style the style of the scrollbars. Should be one of
14521 * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
14522 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
14523 * @see #SCROLLBARS_INSIDE_OVERLAY
14524 * @see #SCROLLBARS_INSIDE_INSET
14525 * @see #SCROLLBARS_OUTSIDE_OVERLAY
14526 * @see #SCROLLBARS_OUTSIDE_INSET
14528 * @attr ref android.R.styleable#View_scrollbarStyle
14530 public void setScrollBarStyle(@ScrollBarStyle int style) {
14531 if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
14532 mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
14533 computeOpaqueFlags();
14539 * <p>Returns the current scrollbar style.</p>
14540 * @return the current scrollbar style
14541 * @see #SCROLLBARS_INSIDE_OVERLAY
14542 * @see #SCROLLBARS_INSIDE_INSET
14543 * @see #SCROLLBARS_OUTSIDE_OVERLAY
14544 * @see #SCROLLBARS_OUTSIDE_INSET
14546 * @attr ref android.R.styleable#View_scrollbarStyle
14548 @ViewDebug.ExportedProperty(mapping = {
14549 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
14550 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
14551 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
14552 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
14555 public int getScrollBarStyle() {
14556 return mViewFlags & SCROLLBARS_STYLE_MASK;
14560 * <p>Compute the horizontal range that the horizontal scrollbar
14563 * <p>The range is expressed in arbitrary units that must be the same as the
14564 * units used by {@link #computeHorizontalScrollExtent()} and
14565 * {@link #computeHorizontalScrollOffset()}.</p>
14567 * <p>The default range is the drawing width of this view.</p>
14569 * @return the total horizontal range represented by the horizontal
14572 * @see #computeHorizontalScrollExtent()
14573 * @see #computeHorizontalScrollOffset()
14574 * @see android.widget.ScrollBarDrawable
14576 protected int computeHorizontalScrollRange() {
14581 * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
14582 * within the horizontal range. This value is used to compute the position
14583 * of the thumb within the scrollbar's track.</p>
14585 * <p>The range is expressed in arbitrary units that must be the same as the
14586 * units used by {@link #computeHorizontalScrollRange()} and
14587 * {@link #computeHorizontalScrollExtent()}.</p>
14589 * <p>The default offset is the scroll offset of this view.</p>
14591 * @return the horizontal offset of the scrollbar's thumb
14593 * @see #computeHorizontalScrollRange()
14594 * @see #computeHorizontalScrollExtent()
14595 * @see android.widget.ScrollBarDrawable
14597 protected int computeHorizontalScrollOffset() {
14602 * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
14603 * within the horizontal range. This value is used to compute the length
14604 * of the thumb within the scrollbar's track.</p>
14606 * <p>The range is expressed in arbitrary units that must be the same as the
14607 * units used by {@link #computeHorizontalScrollRange()} and
14608 * {@link #computeHorizontalScrollOffset()}.</p>
14610 * <p>The default extent is the drawing width of this view.</p>
14612 * @return the horizontal extent of the scrollbar's thumb
14614 * @see #computeHorizontalScrollRange()
14615 * @see #computeHorizontalScrollOffset()
14616 * @see android.widget.ScrollBarDrawable
14618 protected int computeHorizontalScrollExtent() {
14623 * <p>Compute the vertical range that the vertical scrollbar represents.</p>
14625 * <p>The range is expressed in arbitrary units that must be the same as the
14626 * units used by {@link #computeVerticalScrollExtent()} and
14627 * {@link #computeVerticalScrollOffset()}.</p>
14629 * @return the total vertical range represented by the vertical scrollbar
14631 * <p>The default range is the drawing height of this view.</p>
14633 * @see #computeVerticalScrollExtent()
14634 * @see #computeVerticalScrollOffset()
14635 * @see android.widget.ScrollBarDrawable
14637 protected int computeVerticalScrollRange() {
14638 return getHeight();
14642 * <p>Compute the vertical offset of the vertical scrollbar's thumb
14643 * within the horizontal range. This value is used to compute the position
14644 * of the thumb within the scrollbar's track.</p>
14646 * <p>The range is expressed in arbitrary units that must be the same as the
14647 * units used by {@link #computeVerticalScrollRange()} and
14648 * {@link #computeVerticalScrollExtent()}.</p>
14650 * <p>The default offset is the scroll offset of this view.</p>
14652 * @return the vertical offset of the scrollbar's thumb
14654 * @see #computeVerticalScrollRange()
14655 * @see #computeVerticalScrollExtent()
14656 * @see android.widget.ScrollBarDrawable
14658 protected int computeVerticalScrollOffset() {
14663 * <p>Compute the vertical extent of the vertical scrollbar's thumb
14664 * within the vertical range. This value is used to compute the length
14665 * of the thumb within the scrollbar's track.</p>
14667 * <p>The range is expressed in arbitrary units that must be the same as the
14668 * units used by {@link #computeVerticalScrollRange()} and
14669 * {@link #computeVerticalScrollOffset()}.</p>
14671 * <p>The default extent is the drawing height of this view.</p>
14673 * @return the vertical extent of the scrollbar's thumb
14675 * @see #computeVerticalScrollRange()
14676 * @see #computeVerticalScrollOffset()
14677 * @see android.widget.ScrollBarDrawable
14679 protected int computeVerticalScrollExtent() {
14680 return getHeight();
14684 * Check if this view can be scrolled horizontally in a certain direction.
14686 * @param direction Negative to check scrolling left, positive to check scrolling right.
14687 * @return true if this view can be scrolled in the specified direction, false otherwise.
14689 public boolean canScrollHorizontally(int direction) {
14690 final int offset = computeHorizontalScrollOffset();
14691 final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
14692 if (range == 0) return false;
14693 if (direction < 0) {
14696 return offset < range - 1;
14701 * Check if this view can be scrolled vertically in a certain direction.
14703 * @param direction Negative to check scrolling up, positive to check scrolling down.
14704 * @return true if this view can be scrolled in the specified direction, false otherwise.
14706 public boolean canScrollVertically(int direction) {
14707 final int offset = computeVerticalScrollOffset();
14708 final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
14709 if (range == 0) return false;
14710 if (direction < 0) {
14713 return offset < range - 1;
14717 void getScrollIndicatorBounds(@NonNull Rect out) {
14718 out.left = mScrollX;
14719 out.right = mScrollX + mRight - mLeft;
14720 out.top = mScrollY;
14721 out.bottom = mScrollY + mBottom - mTop;
14724 private void onDrawScrollIndicators(Canvas c) {
14725 if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
14726 // No scroll indicators enabled.
14730 final Drawable dr = mScrollIndicatorDrawable;
14732 // Scroll indicators aren't supported here.
14736 final int h = dr.getIntrinsicHeight();
14737 final int w = dr.getIntrinsicWidth();
14738 final Rect rect = mAttachInfo.mTmpInvalRect;
14739 getScrollIndicatorBounds(rect);
14741 if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
14742 final boolean canScrollUp = canScrollVertically(-1);
14744 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
14749 if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
14750 final boolean canScrollDown = canScrollVertically(1);
14751 if (canScrollDown) {
14752 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
14758 final int rightRtl;
14759 if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14760 leftRtl = PFLAG3_SCROLL_INDICATOR_END;
14761 rightRtl = PFLAG3_SCROLL_INDICATOR_START;
14763 leftRtl = PFLAG3_SCROLL_INDICATOR_START;
14764 rightRtl = PFLAG3_SCROLL_INDICATOR_END;
14767 final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
14768 if ((mPrivateFlags3 & leftMask) != 0) {
14769 final boolean canScrollLeft = canScrollHorizontally(-1);
14770 if (canScrollLeft) {
14771 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
14776 final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
14777 if ((mPrivateFlags3 & rightMask) != 0) {
14778 final boolean canScrollRight = canScrollHorizontally(1);
14779 if (canScrollRight) {
14780 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
14786 private void getHorizontalScrollBarBounds(Rect bounds) {
14787 final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
14788 final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
14789 && !isVerticalScrollBarHidden();
14790 final int size = getHorizontalScrollbarHeight();
14791 final int verticalScrollBarGap = drawVerticalScrollBar ?
14792 getVerticalScrollbarWidth() : 0;
14793 final int width = mRight - mLeft;
14794 final int height = mBottom - mTop;
14795 bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
14796 bounds.left = mScrollX + (mPaddingLeft & inside);
14797 bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
14798 bounds.bottom = bounds.top + size;
14801 private void getVerticalScrollBarBounds(Rect bounds) {
14802 if (mRoundScrollbarRenderer == null) {
14803 getStraightVerticalScrollBarBounds(bounds);
14805 getRoundVerticalScrollBarBounds(bounds);
14809 private void getRoundVerticalScrollBarBounds(Rect bounds) {
14810 final int width = mRight - mLeft;
14811 final int height = mBottom - mTop;
14812 // Do not take padding into account as we always want the scrollbars
14813 // to hug the screen for round wearable devices.
14814 bounds.left = mScrollX;
14815 bounds.top = mScrollY;
14816 bounds.right = bounds.left + width;
14817 bounds.bottom = mScrollY + height;
14820 private void getStraightVerticalScrollBarBounds(Rect bounds) {
14821 final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
14822 final int size = getVerticalScrollbarWidth();
14823 int verticalScrollbarPosition = mVerticalScrollbarPosition;
14824 if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
14825 verticalScrollbarPosition = isLayoutRtl() ?
14826 SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
14828 final int width = mRight - mLeft;
14829 final int height = mBottom - mTop;
14830 switch (verticalScrollbarPosition) {
14832 case SCROLLBAR_POSITION_RIGHT:
14833 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
14835 case SCROLLBAR_POSITION_LEFT:
14836 bounds.left = mScrollX + (mUserPaddingLeft & inside);
14839 bounds.top = mScrollY + (mPaddingTop & inside);
14840 bounds.right = bounds.left + size;
14841 bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
14845 * <p>Request the drawing of the horizontal and the vertical scrollbar. The
14846 * scrollbars are painted only if they have been awakened first.</p>
14848 * @param canvas the canvas on which to draw the scrollbars
14850 * @see #awakenScrollBars(int)
14852 protected final void onDrawScrollBars(Canvas canvas) {
14853 // scrollbars are drawn only when the animation is running
14854 final ScrollabilityCache cache = mScrollCache;
14856 if (cache != null) {
14858 int state = cache.state;
14860 if (state == ScrollabilityCache.OFF) {
14864 boolean invalidate = false;
14866 if (state == ScrollabilityCache.FADING) {
14867 // We're fading -- get our fade interpolation
14868 if (cache.interpolatorValues == null) {
14869 cache.interpolatorValues = new float[1];
14872 float[] values = cache.interpolatorValues;
14874 // Stops the animation if we're done
14875 if (cache.scrollBarInterpolator.timeToValues(values) ==
14876 Interpolator.Result.FREEZE_END) {
14877 cache.state = ScrollabilityCache.OFF;
14879 cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
14882 // This will make the scroll bars inval themselves after
14883 // drawing. We only want this when we're fading so that
14884 // we prevent excessive redraws
14887 // We're just on -- but we may have been fading before so
14889 cache.scrollBar.mutate().setAlpha(255);
14892 final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
14893 final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
14894 && !isVerticalScrollBarHidden();
14896 // Fork out the scroll bar drawing for round wearable devices.
14897 if (mRoundScrollbarRenderer != null) {
14898 if (drawVerticalScrollBar) {
14899 final Rect bounds = cache.mScrollBarBounds;
14900 getVerticalScrollBarBounds(bounds);
14901 mRoundScrollbarRenderer.drawRoundScrollbars(
14902 canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
14907 // Do not draw horizontal scroll bars for round wearable devices.
14908 } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
14909 final ScrollBarDrawable scrollBar = cache.scrollBar;
14911 if (drawHorizontalScrollBar) {
14912 scrollBar.setParameters(computeHorizontalScrollRange(),
14913 computeHorizontalScrollOffset(),
14914 computeHorizontalScrollExtent(), false);
14915 final Rect bounds = cache.mScrollBarBounds;
14916 getHorizontalScrollBarBounds(bounds);
14917 onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
14918 bounds.right, bounds.bottom);
14920 invalidate(bounds);
14924 if (drawVerticalScrollBar) {
14925 scrollBar.setParameters(computeVerticalScrollRange(),
14926 computeVerticalScrollOffset(),
14927 computeVerticalScrollExtent(), true);
14928 final Rect bounds = cache.mScrollBarBounds;
14929 getVerticalScrollBarBounds(bounds);
14930 onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
14931 bounds.right, bounds.bottom);
14933 invalidate(bounds);
14941 * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
14942 * FastScroller is visible.
14943 * @return whether to temporarily hide the vertical scrollbar
14946 protected boolean isVerticalScrollBarHidden() {
14951 * <p>Draw the horizontal scrollbar if
14952 * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
14954 * @param canvas the canvas on which to draw the scrollbar
14955 * @param scrollBar the scrollbar's drawable
14957 * @see #isHorizontalScrollBarEnabled()
14958 * @see #computeHorizontalScrollRange()
14959 * @see #computeHorizontalScrollExtent()
14960 * @see #computeHorizontalScrollOffset()
14961 * @see android.widget.ScrollBarDrawable
14964 protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
14965 int l, int t, int r, int b) {
14966 scrollBar.setBounds(l, t, r, b);
14967 scrollBar.draw(canvas);
14971 * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
14972 * returns true.</p>
14974 * @param canvas the canvas on which to draw the scrollbar
14975 * @param scrollBar the scrollbar's drawable
14977 * @see #isVerticalScrollBarEnabled()
14978 * @see #computeVerticalScrollRange()
14979 * @see #computeVerticalScrollExtent()
14980 * @see #computeVerticalScrollOffset()
14981 * @see android.widget.ScrollBarDrawable
14984 protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
14985 int l, int t, int r, int b) {
14986 scrollBar.setBounds(l, t, r, b);
14987 scrollBar.draw(canvas);
14991 * Implement this to do your drawing.
14993 * @param canvas the canvas on which the background will be drawn
14995 protected void onDraw(Canvas canvas) {
14999 * Caller is responsible for calling requestLayout if necessary.
15000 * (This allows addViewInLayout to not request a new layout.)
15002 void assignParent(ViewParent parent) {
15003 if (mParent == null) {
15005 } else if (parent == null) {
15008 throw new RuntimeException("view " + this + " being added, but"
15009 + " it already has a parent");
15014 * This is called when the view is attached to a window. At this point it
15015 * has a Surface and will start drawing. Note that this function is
15016 * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
15017 * however it may be called any time before the first onDraw -- including
15018 * before or after {@link #onMeasure(int, int)}.
15020 * @see #onDetachedFromWindow()
15023 protected void onAttachedToWindow() {
15024 if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
15025 mParent.requestTransparentRegion(this);
15028 mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
15030 jumpDrawablesToCurrentState();
15032 resetSubtreeAccessibilityStateChanged();
15034 // rebuild, since Outline not maintained while View is detached
15038 InputMethodManager imm = InputMethodManager.peekInstance();
15046 * Resolve all RTL related properties.
15048 * @return true if resolution of RTL properties has been done
15052 public boolean resolveRtlPropertiesIfNeeded() {
15053 if (!needRtlPropertiesResolution()) return false;
15055 // Order is important here: LayoutDirection MUST be resolved first
15056 if (!isLayoutDirectionResolved()) {
15057 resolveLayoutDirection();
15058 resolveLayoutParams();
15060 // ... then we can resolve the others properties depending on the resolved LayoutDirection.
15061 if (!isTextDirectionResolved()) {
15062 resolveTextDirection();
15064 if (!isTextAlignmentResolved()) {
15065 resolveTextAlignment();
15067 // Should resolve Drawables before Padding because we need the layout direction of the
15068 // Drawable to correctly resolve Padding.
15069 if (!areDrawablesResolved()) {
15070 resolveDrawables();
15072 if (!isPaddingResolved()) {
15075 onRtlPropertiesChanged(getLayoutDirection());
15080 * Reset resolution of all RTL related properties.
15084 public void resetRtlProperties() {
15085 resetResolvedLayoutDirection();
15086 resetResolvedTextDirection();
15087 resetResolvedTextAlignment();
15088 resetResolvedPadding();
15089 resetResolvedDrawables();
15093 * @see #onScreenStateChanged(int)
15095 void dispatchScreenStateChanged(int screenState) {
15096 onScreenStateChanged(screenState);
15100 * This method is called whenever the state of the screen this view is
15101 * attached to changes. A state change will usually occurs when the screen
15102 * turns on or off (whether it happens automatically or the user does it
15105 * @param screenState The new state of the screen. Can be either
15106 * {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
15108 public void onScreenStateChanged(int screenState) {
15112 * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
15114 private boolean hasRtlSupport() {
15115 return mContext.getApplicationInfo().hasRtlSupport();
15119 * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
15120 * RTL not supported)
15122 private boolean isRtlCompatibilityMode() {
15123 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
15124 return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
15128 * @return true if RTL properties need resolution.
15131 private boolean needRtlPropertiesResolution() {
15132 return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
15136 * Called when any RTL property (layout direction or text direction or text alignment) has
15139 * Subclasses need to override this method to take care of cached information that depends on the
15140 * resolved layout direction, or to inform child views that inherit their layout direction.
15142 * The default implementation does nothing.
15144 * @param layoutDirection the direction of the layout
15146 * @see #LAYOUT_DIRECTION_LTR
15147 * @see #LAYOUT_DIRECTION_RTL
15149 public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
15153 * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
15154 * that the parent directionality can and will be resolved before its children.
15156 * @return true if resolution has been done, false otherwise.
15160 public boolean resolveLayoutDirection() {
15161 // Clear any previous layout direction resolution
15162 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15164 if (hasRtlSupport()) {
15165 // Set resolved depending on layout direction
15166 switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
15167 PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
15168 case LAYOUT_DIRECTION_INHERIT:
15169 // We cannot resolve yet. LTR is by default and let the resolution happen again
15170 // later to get the correct resolved value
15171 if (!canResolveLayoutDirection()) return false;
15173 // Parent has not yet resolved, LTR is still the default
15175 if (!mParent.isLayoutDirectionResolved()) return false;
15177 if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
15178 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15180 } catch (AbstractMethodError e) {
15181 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15182 " does not fully implement ViewParent", e);
15185 case LAYOUT_DIRECTION_RTL:
15186 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15188 case LAYOUT_DIRECTION_LOCALE:
15189 if((LAYOUT_DIRECTION_RTL ==
15190 TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
15191 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15195 // Nothing to do, LTR by default
15200 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
15205 * Check if layout direction resolution can be done.
15207 * @return true if layout direction resolution can be done otherwise return false.
15209 public boolean canResolveLayoutDirection() {
15210 switch (getRawLayoutDirection()) {
15211 case LAYOUT_DIRECTION_INHERIT:
15212 if (mParent != null) {
15214 return mParent.canResolveLayoutDirection();
15215 } catch (AbstractMethodError e) {
15216 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15217 " does not fully implement ViewParent", e);
15228 * Reset the resolved layout direction. Layout direction will be resolved during a call to
15229 * {@link #onMeasure(int, int)}.
15233 public void resetResolvedLayoutDirection() {
15234 // Reset the current resolved bits
15235 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15239 * @return true if the layout direction is inherited.
15243 public boolean isLayoutDirectionInherited() {
15244 return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
15248 * @return true if layout direction has been resolved.
15250 public boolean isLayoutDirectionResolved() {
15251 return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
15255 * Return if padding has been resolved
15259 boolean isPaddingResolved() {
15260 return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
15264 * Resolves padding depending on layout direction, if applicable, and
15265 * recomputes internal padding values to adjust for scroll bars.
15269 public void resolvePadding() {
15270 final int resolvedLayoutDirection = getLayoutDirection();
15272 if (!isRtlCompatibilityMode()) {
15273 // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
15274 // If start / end padding are defined, they will be resolved (hence overriding) to
15275 // left / right or right / left depending on the resolved layout direction.
15276 // If start / end padding are not defined, use the left / right ones.
15277 if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
15278 Rect padding = sThreadLocal.get();
15279 if (padding == null) {
15280 padding = new Rect();
15281 sThreadLocal.set(padding);
15283 mBackground.getPadding(padding);
15284 if (!mLeftPaddingDefined) {
15285 mUserPaddingLeftInitial = padding.left;
15287 if (!mRightPaddingDefined) {
15288 mUserPaddingRightInitial = padding.right;
15291 switch (resolvedLayoutDirection) {
15292 case LAYOUT_DIRECTION_RTL:
15293 if (mUserPaddingStart != UNDEFINED_PADDING) {
15294 mUserPaddingRight = mUserPaddingStart;
15296 mUserPaddingRight = mUserPaddingRightInitial;
15298 if (mUserPaddingEnd != UNDEFINED_PADDING) {
15299 mUserPaddingLeft = mUserPaddingEnd;
15301 mUserPaddingLeft = mUserPaddingLeftInitial;
15304 case LAYOUT_DIRECTION_LTR:
15306 if (mUserPaddingStart != UNDEFINED_PADDING) {
15307 mUserPaddingLeft = mUserPaddingStart;
15309 mUserPaddingLeft = mUserPaddingLeftInitial;
15311 if (mUserPaddingEnd != UNDEFINED_PADDING) {
15312 mUserPaddingRight = mUserPaddingEnd;
15314 mUserPaddingRight = mUserPaddingRightInitial;
15318 mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
15321 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
15322 onRtlPropertiesChanged(resolvedLayoutDirection);
15324 mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
15328 * Reset the resolved layout direction.
15332 public void resetResolvedPadding() {
15333 resetResolvedPaddingInternal();
15337 * Used when we only want to reset *this* view's padding and not trigger overrides
15338 * in ViewGroup that reset children too.
15340 void resetResolvedPaddingInternal() {
15341 mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
15345 * This is called when the view is detached from a window. At this point it
15346 * no longer has a surface for drawing.
15348 * @see #onAttachedToWindow()
15351 protected void onDetachedFromWindow() {
15355 * This is a framework-internal mirror of onDetachedFromWindow() that's called
15356 * after onDetachedFromWindow().
15358 * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
15359 * The super method should be called at the end of the overridden method to ensure
15360 * subclasses are destroyed first
15365 protected void onDetachedFromWindowInternal() {
15366 mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
15367 mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
15368 mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
15370 removeUnsetPressCallback();
15371 removeLongPressCallback();
15372 removePerformClickCallback();
15373 removeSendViewScrolledAccessibilityEventCallback();
15374 stopNestedScroll();
15376 // Anything that started animating right before detach should already
15377 // be in its final state when re-attached.
15378 jumpDrawablesToCurrentState();
15380 destroyDrawingCache();
15383 mCurrentAnimation = null;
15386 private void cleanupDraw() {
15387 resetDisplayList();
15388 if (mAttachInfo != null) {
15389 mAttachInfo.mViewRootImpl.cancelInvalidate(this);
15393 void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
15397 * @return The number of times this view has been attached to a window
15399 protected int getWindowAttachCount() {
15400 return mWindowAttachCount;
15404 * Retrieve a unique token identifying the window this view is attached to.
15405 * @return Return the window's token for use in
15406 * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
15408 public IBinder getWindowToken() {
15409 return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
15413 * Retrieve the {@link WindowId} for the window this view is
15414 * currently attached to.
15416 public WindowId getWindowId() {
15417 if (mAttachInfo == null) {
15420 if (mAttachInfo.mWindowId == null) {
15422 mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
15423 mAttachInfo.mWindowToken);
15424 mAttachInfo.mWindowId = new WindowId(
15425 mAttachInfo.mIWindowId);
15426 } catch (RemoteException e) {
15429 return mAttachInfo.mWindowId;
15433 * Retrieve a unique token identifying the top-level "real" window of
15434 * the window that this view is attached to. That is, this is like
15435 * {@link #getWindowToken}, except if the window this view in is a panel
15436 * window (attached to another containing window), then the token of
15437 * the containing window is returned instead.
15439 * @return Returns the associated window token, either
15440 * {@link #getWindowToken()} or the containing window's token.
15442 public IBinder getApplicationWindowToken() {
15443 AttachInfo ai = mAttachInfo;
15445 IBinder appWindowToken = ai.mPanelParentWindowToken;
15446 if (appWindowToken == null) {
15447 appWindowToken = ai.mWindowToken;
15449 return appWindowToken;
15455 * Gets the logical display to which the view's window has been attached.
15457 * @return The logical display, or null if the view is not currently attached to a window.
15459 public Display getDisplay() {
15460 return mAttachInfo != null ? mAttachInfo.mDisplay : null;
15464 * Retrieve private session object this view hierarchy is using to
15465 * communicate with the window manager.
15466 * @return the session object to communicate with the window manager
15468 /*package*/ IWindowSession getWindowSession() {
15469 return mAttachInfo != null ? mAttachInfo.mSession : null;
15473 * Return the visibility value of the least visible component passed.
15475 int combineVisibility(int vis1, int vis2) {
15476 // This works because VISIBLE < INVISIBLE < GONE.
15477 return Math.max(vis1, vis2);
15481 * @param info the {@link android.view.View.AttachInfo} to associated with
15484 void dispatchAttachedToWindow(AttachInfo info, int visibility) {
15485 mAttachInfo = info;
15486 if (mOverlay != null) {
15487 mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
15489 mWindowAttachCount++;
15490 // We will need to evaluate the drawable state at least once.
15491 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
15492 if (mFloatingTreeObserver != null) {
15493 info.mTreeObserver.merge(mFloatingTreeObserver);
15494 mFloatingTreeObserver = null;
15497 registerPendingFrameMetricsObservers();
15499 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
15500 mAttachInfo.mScrollContainers.add(this);
15501 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
15503 // Transfer all pending runnables.
15504 if (mRunQueue != null) {
15505 mRunQueue.executeActions(info.mHandler);
15508 performCollectViewAttributes(mAttachInfo, visibility);
15509 onAttachedToWindow();
15511 ListenerInfo li = mListenerInfo;
15512 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
15513 li != null ? li.mOnAttachStateChangeListeners : null;
15514 if (listeners != null && listeners.size() > 0) {
15515 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
15516 // perform the dispatching. The iterator is a safe guard against listeners that
15517 // could mutate the list by calling the various add/remove methods. This prevents
15518 // the array from being modified while we iterate it.
15519 for (OnAttachStateChangeListener listener : listeners) {
15520 listener.onViewAttachedToWindow(this);
15524 int vis = info.mWindowVisibility;
15526 onWindowVisibilityChanged(vis);
15528 // Calling onVisibilityAggregated directly here since the subtree will also
15529 // receive dispatchAttachedToWindow and this same call
15530 onVisibilityAggregated(vis == VISIBLE);
15534 // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
15535 // As all views in the subtree will already receive dispatchAttachedToWindow
15536 // traversing the subtree again here is not desired.
15537 onVisibilityChanged(this, visibility);
15539 if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
15540 // If nobody has evaluated the drawable state yet, then do it now.
15541 refreshDrawableState();
15543 needGlobalAttributesUpdate(false);
15546 void dispatchDetachedFromWindow() {
15547 AttachInfo info = mAttachInfo;
15548 if (info != null) {
15549 int vis = info.mWindowVisibility;
15551 onWindowVisibilityChanged(GONE);
15553 // Invoking onVisibilityAggregated directly here since the subtree
15554 // will also receive detached from window
15555 onVisibilityAggregated(false);
15560 onDetachedFromWindow();
15561 onDetachedFromWindowInternal();
15563 InputMethodManager imm = InputMethodManager.peekInstance();
15565 imm.onViewDetachedFromWindow(this);
15568 ListenerInfo li = mListenerInfo;
15569 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
15570 li != null ? li.mOnAttachStateChangeListeners : null;
15571 if (listeners != null && listeners.size() > 0) {
15572 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
15573 // perform the dispatching. The iterator is a safe guard against listeners that
15574 // could mutate the list by calling the various add/remove methods. This prevents
15575 // the array from being modified while we iterate it.
15576 for (OnAttachStateChangeListener listener : listeners) {
15577 listener.onViewDetachedFromWindow(this);
15581 if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
15582 mAttachInfo.mScrollContainers.remove(this);
15583 mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
15586 mAttachInfo = null;
15587 if (mOverlay != null) {
15588 mOverlay.getOverlayView().dispatchDetachedFromWindow();
15593 * Cancel any deferred high-level input events that were previously posted to the event queue.
15595 * <p>Many views post high-level events such as click handlers to the event queue
15596 * to run deferred in order to preserve a desired user experience - clearing visible
15597 * pressed states before executing, etc. This method will abort any events of this nature
15598 * that are currently in flight.</p>
15600 * <p>Custom views that generate their own high-level deferred input events should override
15601 * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
15603 * <p>This will also cancel pending input events for any child views.</p>
15605 * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
15606 * This will not impact newer events posted after this call that may occur as a result of
15607 * lower-level input events still waiting in the queue. If you are trying to prevent
15608 * double-submitted events for the duration of some sort of asynchronous transaction
15609 * you should also take other steps to protect against unexpected double inputs e.g. calling
15610 * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
15611 * the transaction completes, tracking already submitted transaction IDs, etc.</p>
15613 public final void cancelPendingInputEvents() {
15614 dispatchCancelPendingInputEvents();
15618 * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
15619 * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
15621 void dispatchCancelPendingInputEvents() {
15622 mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
15623 onCancelPendingInputEvents();
15624 if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
15625 throw new SuperNotCalledException("View " + getClass().getSimpleName() +
15626 " did not call through to super.onCancelPendingInputEvents()");
15631 * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
15634 * <p>This method is responsible for removing any pending high-level input events that were
15635 * posted to the event queue to run later. Custom view classes that post their own deferred
15636 * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
15637 * {@link android.os.Handler} should override this method, call
15638 * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
15641 public void onCancelPendingInputEvents() {
15642 removePerformClickCallback();
15644 mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
15648 * Store this view hierarchy's frozen state into the given container.
15650 * @param container The SparseArray in which to save the view's state.
15652 * @see #restoreHierarchyState(android.util.SparseArray)
15653 * @see #dispatchSaveInstanceState(android.util.SparseArray)
15654 * @see #onSaveInstanceState()
15656 public void saveHierarchyState(SparseArray<Parcelable> container) {
15657 dispatchSaveInstanceState(container);
15661 * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
15662 * this view and its children. May be overridden to modify how freezing happens to a
15663 * view's children; for example, some views may want to not store state for their children.
15665 * @param container The SparseArray in which to save the view's state.
15667 * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15668 * @see #saveHierarchyState(android.util.SparseArray)
15669 * @see #onSaveInstanceState()
15671 protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
15672 if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
15673 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
15674 Parcelable state = onSaveInstanceState();
15675 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
15676 throw new IllegalStateException(
15677 "Derived class did not call super.onSaveInstanceState()");
15679 if (state != null) {
15680 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
15681 // + ": " + state);
15682 container.put(mID, state);
15688 * Hook allowing a view to generate a representation of its internal state
15689 * that can later be used to create a new instance with that same state.
15690 * This state should only contain information that is not persistent or can
15691 * not be reconstructed later. For example, you will never store your
15692 * current position on screen because that will be computed again when a
15693 * new instance of the view is placed in its view hierarchy.
15695 * Some examples of things you may store here: the current cursor position
15696 * in a text view (but usually not the text itself since that is stored in a
15697 * content provider or other persistent storage), the currently selected
15698 * item in a list view.
15700 * @return Returns a Parcelable object containing the view's current dynamic
15701 * state, or null if there is nothing interesting to save. The
15702 * default implementation returns null.
15703 * @see #onRestoreInstanceState(android.os.Parcelable)
15704 * @see #saveHierarchyState(android.util.SparseArray)
15705 * @see #dispatchSaveInstanceState(android.util.SparseArray)
15706 * @see #setSaveEnabled(boolean)
15709 protected Parcelable onSaveInstanceState() {
15710 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
15711 if (mStartActivityRequestWho != null) {
15712 BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
15713 state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
15716 return BaseSavedState.EMPTY_STATE;
15720 * Restore this view hierarchy's frozen state from the given container.
15722 * @param container The SparseArray which holds previously frozen states.
15724 * @see #saveHierarchyState(android.util.SparseArray)
15725 * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15726 * @see #onRestoreInstanceState(android.os.Parcelable)
15728 public void restoreHierarchyState(SparseArray<Parcelable> container) {
15729 dispatchRestoreInstanceState(container);
15733 * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
15734 * state for this view and its children. May be overridden to modify how restoring
15735 * happens to a view's children; for example, some views may want to not store state
15736 * for their children.
15738 * @param container The SparseArray which holds previously saved state.
15740 * @see #dispatchSaveInstanceState(android.util.SparseArray)
15741 * @see #restoreHierarchyState(android.util.SparseArray)
15742 * @see #onRestoreInstanceState(android.os.Parcelable)
15744 protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
15745 if (mID != NO_ID) {
15746 Parcelable state = container.get(mID);
15747 if (state != null) {
15748 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
15749 // + ": " + state);
15750 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
15751 onRestoreInstanceState(state);
15752 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
15753 throw new IllegalStateException(
15754 "Derived class did not call super.onRestoreInstanceState()");
15761 * Hook allowing a view to re-apply a representation of its internal state that had previously
15762 * been generated by {@link #onSaveInstanceState}. This function will never be called with a
15765 * @param state The frozen state that had previously been returned by
15766 * {@link #onSaveInstanceState}.
15768 * @see #onSaveInstanceState()
15769 * @see #restoreHierarchyState(android.util.SparseArray)
15770 * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15773 protected void onRestoreInstanceState(Parcelable state) {
15774 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
15775 if (state != null && !(state instanceof AbsSavedState)) {
15776 throw new IllegalArgumentException("Wrong state class, expecting View State but "
15777 + "received " + state.getClass().toString() + " instead. This usually happens "
15778 + "when two views of different type have the same id in the same hierarchy. "
15779 + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
15780 + "other views do not use the same id.");
15782 if (state != null && state instanceof BaseSavedState) {
15783 mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
15788 * <p>Return the time at which the drawing of the view hierarchy started.</p>
15790 * @return the drawing start time in milliseconds
15792 public long getDrawingTime() {
15793 return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
15797 * <p>Enables or disables the duplication of the parent's state into this view. When
15798 * duplication is enabled, this view gets its drawable state from its parent rather
15799 * than from its own internal properties.</p>
15801 * <p>Note: in the current implementation, setting this property to true after the
15802 * view was added to a ViewGroup might have no effect at all. This property should
15803 * always be used from XML or set to true before adding this view to a ViewGroup.</p>
15805 * <p>Note: if this view's parent addStateFromChildren property is enabled and this
15806 * property is enabled, an exception will be thrown.</p>
15808 * <p>Note: if the child view uses and updates additional states which are unknown to the
15809 * parent, these states should not be affected by this method.</p>
15811 * @param enabled True to enable duplication of the parent's drawable state, false
15814 * @see #getDrawableState()
15815 * @see #isDuplicateParentStateEnabled()
15817 public void setDuplicateParentStateEnabled(boolean enabled) {
15818 setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
15822 * <p>Indicates whether this duplicates its drawable state from its parent.</p>
15824 * @return True if this view's drawable state is duplicated from the parent,
15827 * @see #getDrawableState()
15828 * @see #setDuplicateParentStateEnabled(boolean)
15830 public boolean isDuplicateParentStateEnabled() {
15831 return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
15835 * <p>Specifies the type of layer backing this view. The layer can be
15836 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15837 * {@link #LAYER_TYPE_HARDWARE}.</p>
15839 * <p>A layer is associated with an optional {@link android.graphics.Paint}
15840 * instance that controls how the layer is composed on screen. The following
15841 * properties of the paint are taken into account when composing the layer:</p>
15843 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15844 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15845 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15848 * <p>If this view has an alpha value set to < 1.0 by calling
15849 * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
15850 * by this view's alpha value.</p>
15852 * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
15853 * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
15854 * for more information on when and how to use layers.</p>
15856 * @param layerType The type of layer to use with this view, must be one of
15857 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15858 * {@link #LAYER_TYPE_HARDWARE}
15859 * @param paint The paint used to compose the layer. This argument is optional
15860 * and can be null. It is ignored when the layer type is
15861 * {@link #LAYER_TYPE_NONE}
15863 * @see #getLayerType()
15864 * @see #LAYER_TYPE_NONE
15865 * @see #LAYER_TYPE_SOFTWARE
15866 * @see #LAYER_TYPE_HARDWARE
15867 * @see #setAlpha(float)
15869 * @attr ref android.R.styleable#View_layerType
15871 public void setLayerType(int layerType, @Nullable Paint paint) {
15872 if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
15873 throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
15874 + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
15877 boolean typeChanged = mRenderNode.setLayerType(layerType);
15879 if (!typeChanged) {
15880 setLayerPaint(paint);
15884 if (layerType != LAYER_TYPE_SOFTWARE) {
15885 // Destroy any previous software drawing cache if present
15886 // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
15887 // drawing cache created in View#draw when drawing to a SW canvas.
15888 destroyDrawingCache();
15891 mLayerType = layerType;
15892 mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
15893 mRenderNode.setLayerPaint(mLayerPaint);
15895 // draw() behaves differently if we are on a layer, so we need to
15896 // invalidate() here
15897 invalidateParentCaches();
15902 * Updates the {@link Paint} object used with the current layer (used only if the current
15903 * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
15904 * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
15905 * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
15906 * ensure that the view gets redrawn immediately.
15908 * <p>A layer is associated with an optional {@link android.graphics.Paint}
15909 * instance that controls how the layer is composed on screen. The following
15910 * properties of the paint are taken into account when composing the layer:</p>
15912 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15913 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15914 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15917 * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
15918 * alpha value of the layer's paint is superseded by this view's alpha value.</p>
15920 * @param paint The paint used to compose the layer. This argument is optional
15921 * and can be null. It is ignored when the layer type is
15922 * {@link #LAYER_TYPE_NONE}
15924 * @see #setLayerType(int, android.graphics.Paint)
15926 public void setLayerPaint(@Nullable Paint paint) {
15927 int layerType = getLayerType();
15928 if (layerType != LAYER_TYPE_NONE) {
15929 mLayerPaint = paint;
15930 if (layerType == LAYER_TYPE_HARDWARE) {
15931 if (mRenderNode.setLayerPaint(paint)) {
15932 invalidateViewProperty(false, false);
15941 * Indicates what type of layer is currently associated with this view. By default
15942 * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
15943 * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
15944 * for more information on the different types of layers.
15946 * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15947 * {@link #LAYER_TYPE_HARDWARE}
15949 * @see #setLayerType(int, android.graphics.Paint)
15950 * @see #buildLayer()
15951 * @see #LAYER_TYPE_NONE
15952 * @see #LAYER_TYPE_SOFTWARE
15953 * @see #LAYER_TYPE_HARDWARE
15955 public int getLayerType() {
15960 * Forces this view's layer to be created and this view to be rendered
15961 * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
15962 * invoking this method will have no effect.
15964 * This method can for instance be used to render a view into its layer before
15965 * starting an animation. If this view is complex, rendering into the layer
15966 * before starting the animation will avoid skipping frames.
15968 * @throws IllegalStateException If this view is not attached to a window
15970 * @see #setLayerType(int, android.graphics.Paint)
15972 public void buildLayer() {
15973 if (mLayerType == LAYER_TYPE_NONE) return;
15975 final AttachInfo attachInfo = mAttachInfo;
15976 if (attachInfo == null) {
15977 throw new IllegalStateException("This view must be attached to a window first");
15980 if (getWidth() == 0 || getHeight() == 0) {
15984 switch (mLayerType) {
15985 case LAYER_TYPE_HARDWARE:
15986 updateDisplayListIfDirty();
15987 if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
15988 attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
15991 case LAYER_TYPE_SOFTWARE:
15992 buildDrawingCache(true);
15998 * Destroys all hardware rendering resources. This method is invoked
15999 * when the system needs to reclaim resources. Upon execution of this
16000 * method, you should free any OpenGL resources created by the view.
16002 * Note: you <strong>must</strong> call
16003 * <code>super.destroyHardwareResources()</code> when overriding
16009 protected void destroyHardwareResources() {
16010 // Although the Layer will be destroyed by RenderNode, we want to release
16011 // the staging display list, which is also a signal to RenderNode that it's
16012 // safe to free its copy of the display list as it knows that we will
16013 // push an updated DisplayList if we try to draw again
16014 resetDisplayList();
16018 * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
16019 * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
16020 * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
16021 * the cache is enabled. To benefit from the cache, you must request the drawing cache by
16022 * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
16025 * <p>Enabling the drawing cache is similar to
16026 * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
16027 * acceleration is turned off. When hardware acceleration is turned on, enabling the
16028 * drawing cache has no effect on rendering because the system uses a different mechanism
16029 * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
16030 * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
16031 * for information on how to enable software and hardware layers.</p>
16033 * <p>This API can be used to manually generate
16034 * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
16035 * {@link #getDrawingCache()}.</p>
16037 * @param enabled true to enable the drawing cache, false otherwise
16039 * @see #isDrawingCacheEnabled()
16040 * @see #getDrawingCache()
16041 * @see #buildDrawingCache()
16042 * @see #setLayerType(int, android.graphics.Paint)
16044 public void setDrawingCacheEnabled(boolean enabled) {
16045 mCachingFailed = false;
16046 setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
16050 * <p>Indicates whether the drawing cache is enabled for this view.</p>
16052 * @return true if the drawing cache is enabled
16054 * @see #setDrawingCacheEnabled(boolean)
16055 * @see #getDrawingCache()
16057 @ViewDebug.ExportedProperty(category = "drawing")
16058 public boolean isDrawingCacheEnabled() {
16059 return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
16063 * Debugging utility which recursively outputs the dirty state of a view and its
16068 @SuppressWarnings({"UnusedDeclaration"})
16069 public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
16070 Log.d("View", indent + this + " DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
16071 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
16072 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
16073 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
16075 mPrivateFlags &= clearMask;
16077 if (this instanceof ViewGroup) {
16078 ViewGroup parent = (ViewGroup) this;
16079 final int count = parent.getChildCount();
16080 for (int i = 0; i < count; i++) {
16081 final View child = parent.getChildAt(i);
16082 child.outputDirtyFlags(indent + " ", clear, clearMask);
16088 * This method is used by ViewGroup to cause its children to restore or recreate their
16089 * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
16090 * to recreate its own display list, which would happen if it went through the normal
16091 * draw/dispatchDraw mechanisms.
16095 protected void dispatchGetDisplayList() {}
16098 * A view that is not attached or hardware accelerated cannot create a display list.
16099 * This method checks these conditions and returns the appropriate result.
16101 * @return true if view has the ability to create a display list, false otherwise.
16105 public boolean canHaveDisplayList() {
16106 return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
16110 * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
16114 public RenderNode updateDisplayListIfDirty() {
16115 final RenderNode renderNode = mRenderNode;
16116 if (!canHaveDisplayList()) {
16117 // can't populate RenderNode, don't try
16121 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
16122 || !renderNode.isValid()
16123 || (mRecreateDisplayList)) {
16124 // Don't need to recreate the display list, just need to tell our
16125 // children to restore/recreate theirs
16126 if (renderNode.isValid()
16127 && !mRecreateDisplayList) {
16128 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16129 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16130 dispatchGetDisplayList();
16132 return renderNode; // no work needed
16135 // If we got here, we're recreating it. Mark it as such to ensure that
16136 // we copy in child display lists into ours in drawChild()
16137 mRecreateDisplayList = true;
16139 int width = mRight - mLeft;
16140 int height = mBottom - mTop;
16141 int layerType = getLayerType();
16143 final DisplayListCanvas canvas = renderNode.start(width, height);
16144 canvas.setHighContrastText(mAttachInfo.mHighContrastText);
16147 if (layerType == LAYER_TYPE_SOFTWARE) {
16148 buildDrawingCache(true);
16149 Bitmap cache = getDrawingCache(true);
16150 if (cache != null) {
16151 canvas.drawBitmap(cache, 0, 0, mLayerPaint);
16156 canvas.translate(-mScrollX, -mScrollY);
16157 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16158 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16160 // Fast path for layouts with no backgrounds
16161 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16162 dispatchDraw(canvas);
16163 if (mOverlay != null && !mOverlay.isEmpty()) {
16164 mOverlay.getOverlayView().draw(canvas);
16171 renderNode.end(canvas);
16172 setDisplayListProperties(renderNode);
16175 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16176 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16181 private void resetDisplayList() {
16182 if (mRenderNode.isValid()) {
16183 mRenderNode.discardDisplayList();
16186 if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
16187 mBackgroundRenderNode.discardDisplayList();
16192 * Called when the passed RenderNode is removed from the draw tree
16195 public void onRenderNodeDetached(RenderNode renderNode) {
16199 * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
16201 * @return A non-scaled bitmap representing this view or null if cache is disabled.
16203 * @see #getDrawingCache(boolean)
16205 public Bitmap getDrawingCache() {
16206 return getDrawingCache(false);
16210 * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
16211 * is null when caching is disabled. If caching is enabled and the cache is not ready,
16212 * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
16213 * draw from the cache when the cache is enabled. To benefit from the cache, you must
16214 * request the drawing cache by calling this method and draw it on screen if the
16215 * returned bitmap is not null.</p>
16217 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
16218 * this method will create a bitmap of the same size as this view. Because this bitmap
16219 * will be drawn scaled by the parent ViewGroup, the result on screen might show
16220 * scaling artifacts. To avoid such artifacts, you should call this method by setting
16221 * the auto scaling to true. Doing so, however, will generate a bitmap of a different
16222 * size than the view. This implies that your application must be able to handle this
16225 * @param autoScale Indicates whether the generated bitmap should be scaled based on
16226 * the current density of the screen when the application is in compatibility
16229 * @return A bitmap representing this view or null if cache is disabled.
16231 * @see #setDrawingCacheEnabled(boolean)
16232 * @see #isDrawingCacheEnabled()
16233 * @see #buildDrawingCache(boolean)
16234 * @see #destroyDrawingCache()
16236 public Bitmap getDrawingCache(boolean autoScale) {
16237 if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
16240 if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
16241 buildDrawingCache(autoScale);
16243 return autoScale ? mDrawingCache : mUnscaledDrawingCache;
16247 * <p>Frees the resources used by the drawing cache. If you call
16248 * {@link #buildDrawingCache()} manually without calling
16249 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
16250 * should cleanup the cache with this method afterwards.</p>
16252 * @see #setDrawingCacheEnabled(boolean)
16253 * @see #buildDrawingCache()
16254 * @see #getDrawingCache()
16256 public void destroyDrawingCache() {
16257 if (mDrawingCache != null) {
16258 mDrawingCache.recycle();
16259 mDrawingCache = null;
16261 if (mUnscaledDrawingCache != null) {
16262 mUnscaledDrawingCache.recycle();
16263 mUnscaledDrawingCache = null;
16268 * Setting a solid background color for the drawing cache's bitmaps will improve
16269 * performance and memory usage. Note, though that this should only be used if this
16270 * view will always be drawn on top of a solid color.
16272 * @param color The background color to use for the drawing cache's bitmap
16274 * @see #setDrawingCacheEnabled(boolean)
16275 * @see #buildDrawingCache()
16276 * @see #getDrawingCache()
16278 public void setDrawingCacheBackgroundColor(@ColorInt int color) {
16279 if (color != mDrawingCacheBackgroundColor) {
16280 mDrawingCacheBackgroundColor = color;
16281 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
16286 * @see #setDrawingCacheBackgroundColor(int)
16288 * @return The background color to used for the drawing cache's bitmap
16291 public int getDrawingCacheBackgroundColor() {
16292 return mDrawingCacheBackgroundColor;
16296 * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
16298 * @see #buildDrawingCache(boolean)
16300 public void buildDrawingCache() {
16301 buildDrawingCache(false);
16305 * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
16307 * <p>If you call {@link #buildDrawingCache()} manually without calling
16308 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
16309 * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
16311 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
16312 * this method will create a bitmap of the same size as this view. Because this bitmap
16313 * will be drawn scaled by the parent ViewGroup, the result on screen might show
16314 * scaling artifacts. To avoid such artifacts, you should call this method by setting
16315 * the auto scaling to true. Doing so, however, will generate a bitmap of a different
16316 * size than the view. This implies that your application must be able to handle this
16319 * <p>You should avoid calling this method when hardware acceleration is enabled. If
16320 * you do not need the drawing cache bitmap, calling this method will increase memory
16321 * usage and cause the view to be rendered in software once, thus negatively impacting
16324 * @see #getDrawingCache()
16325 * @see #destroyDrawingCache()
16327 public void buildDrawingCache(boolean autoScale) {
16328 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
16329 mDrawingCache == null : mUnscaledDrawingCache == null)) {
16330 if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
16331 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
16332 "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
16335 buildDrawingCacheImpl(autoScale);
16337 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
16343 * private, internal implementation of buildDrawingCache, used to enable tracing
16345 private void buildDrawingCacheImpl(boolean autoScale) {
16346 mCachingFailed = false;
16348 int width = mRight - mLeft;
16349 int height = mBottom - mTop;
16351 final AttachInfo attachInfo = mAttachInfo;
16352 final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
16354 if (autoScale && scalingRequired) {
16355 width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
16356 height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
16359 final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
16360 final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
16361 final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
16363 final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
16364 final long drawingCacheSize =
16365 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
16366 if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
16367 if (width > 0 && height > 0) {
16368 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
16369 + " too large to fit into a software layer (or drawing cache), needs "
16370 + projectedBitmapSize + " bytes, only "
16371 + drawingCacheSize + " available");
16373 destroyDrawingCache();
16374 mCachingFailed = true;
16378 boolean clear = true;
16379 Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
16381 if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
16382 Bitmap.Config quality;
16384 // Never pick ARGB_4444 because it looks awful
16385 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
16386 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
16387 case DRAWING_CACHE_QUALITY_AUTO:
16388 case DRAWING_CACHE_QUALITY_LOW:
16389 case DRAWING_CACHE_QUALITY_HIGH:
16391 quality = Bitmap.Config.ARGB_8888;
16395 // Optimization for translucent windows
16396 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
16397 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
16400 // Try to cleanup memory
16401 if (bitmap != null) bitmap.recycle();
16404 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
16405 width, height, quality);
16406 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
16408 mDrawingCache = bitmap;
16410 mUnscaledDrawingCache = bitmap;
16412 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
16413 } catch (OutOfMemoryError e) {
16414 // If there is not enough memory to create the bitmap cache, just
16415 // ignore the issue as bitmap caches are not required to draw the
16418 mDrawingCache = null;
16420 mUnscaledDrawingCache = null;
16422 mCachingFailed = true;
16426 clear = drawingCacheBackgroundColor != 0;
16430 if (attachInfo != null) {
16431 canvas = attachInfo.mCanvas;
16432 if (canvas == null) {
16433 canvas = new Canvas();
16435 canvas.setBitmap(bitmap);
16436 // Temporarily clobber the cached Canvas in case one of our children
16437 // is also using a drawing cache. Without this, the children would
16438 // steal the canvas by attaching their own bitmap to it and bad, bad
16439 // thing would happen (invisible views, corrupted drawings, etc.)
16440 attachInfo.mCanvas = null;
16442 // This case should hopefully never or seldom happen
16443 canvas = new Canvas(bitmap);
16447 bitmap.eraseColor(drawingCacheBackgroundColor);
16451 final int restoreCount = canvas.save();
16453 if (autoScale && scalingRequired) {
16454 final float scale = attachInfo.mApplicationScale;
16455 canvas.scale(scale, scale);
16458 canvas.translate(-mScrollX, -mScrollY);
16460 mPrivateFlags |= PFLAG_DRAWN;
16461 if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
16462 mLayerType != LAYER_TYPE_NONE) {
16463 mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
16466 // Fast path for layouts with no backgrounds
16467 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16468 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16469 dispatchDraw(canvas);
16470 if (mOverlay != null && !mOverlay.isEmpty()) {
16471 mOverlay.getOverlayView().draw(canvas);
16477 canvas.restoreToCount(restoreCount);
16478 canvas.setBitmap(null);
16480 if (attachInfo != null) {
16481 // Restore the cached Canvas for our siblings
16482 attachInfo.mCanvas = canvas;
16487 * Create a snapshot of the view into a bitmap. We should probably make
16488 * some form of this public, but should think about the API.
16492 public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
16493 int width = mRight - mLeft;
16494 int height = mBottom - mTop;
16496 final AttachInfo attachInfo = mAttachInfo;
16497 final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
16498 width = (int) ((width * scale) + 0.5f);
16499 height = (int) ((height * scale) + 0.5f);
16501 Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
16502 width > 0 ? width : 1, height > 0 ? height : 1, quality);
16503 if (bitmap == null) {
16504 throw new OutOfMemoryError();
16507 Resources resources = getResources();
16508 if (resources != null) {
16509 bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
16513 if (attachInfo != null) {
16514 canvas = attachInfo.mCanvas;
16515 if (canvas == null) {
16516 canvas = new Canvas();
16518 canvas.setBitmap(bitmap);
16519 // Temporarily clobber the cached Canvas in case one of our children
16520 // is also using a drawing cache. Without this, the children would
16521 // steal the canvas by attaching their own bitmap to it and bad, bad
16522 // things would happen (invisible views, corrupted drawings, etc.)
16523 attachInfo.mCanvas = null;
16525 // This case should hopefully never or seldom happen
16526 canvas = new Canvas(bitmap);
16529 if ((backgroundColor & 0xff000000) != 0) {
16530 bitmap.eraseColor(backgroundColor);
16534 final int restoreCount = canvas.save();
16535 canvas.scale(scale, scale);
16536 canvas.translate(-mScrollX, -mScrollY);
16538 // Temporarily remove the dirty mask
16539 int flags = mPrivateFlags;
16540 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16542 // Fast path for layouts with no backgrounds
16543 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16544 dispatchDraw(canvas);
16545 if (mOverlay != null && !mOverlay.isEmpty()) {
16546 mOverlay.getOverlayView().draw(canvas);
16552 mPrivateFlags = flags;
16554 canvas.restoreToCount(restoreCount);
16555 canvas.setBitmap(null);
16557 if (attachInfo != null) {
16558 // Restore the cached Canvas for our siblings
16559 attachInfo.mCanvas = canvas;
16566 * Indicates whether this View is currently in edit mode. A View is usually
16567 * in edit mode when displayed within a developer tool. For instance, if
16568 * this View is being drawn by a visual user interface builder, this method
16569 * should return true.
16571 * Subclasses should check the return value of this method to provide
16572 * different behaviors if their normal behavior might interfere with the
16573 * host environment. For instance: the class spawns a thread in its
16574 * constructor, the drawing code relies on device-specific features, etc.
16576 * This method is usually checked in the drawing code of custom widgets.
16578 * @return True if this View is in edit mode, false otherwise.
16580 public boolean isInEditMode() {
16585 * If the View draws content inside its padding and enables fading edges,
16586 * it needs to support padding offsets. Padding offsets are added to the
16587 * fading edges to extend the length of the fade so that it covers pixels
16588 * drawn inside the padding.
16590 * Subclasses of this class should override this method if they need
16591 * to draw content inside the padding.
16593 * @return True if padding offset must be applied, false otherwise.
16595 * @see #getLeftPaddingOffset()
16596 * @see #getRightPaddingOffset()
16597 * @see #getTopPaddingOffset()
16598 * @see #getBottomPaddingOffset()
16602 protected boolean isPaddingOffsetRequired() {
16607 * Amount by which to extend the left fading region. Called only when
16608 * {@link #isPaddingOffsetRequired()} returns true.
16610 * @return The left padding offset in pixels.
16612 * @see #isPaddingOffsetRequired()
16616 protected int getLeftPaddingOffset() {
16621 * Amount by which to extend the right fading region. Called only when
16622 * {@link #isPaddingOffsetRequired()} returns true.
16624 * @return The right padding offset in pixels.
16626 * @see #isPaddingOffsetRequired()
16630 protected int getRightPaddingOffset() {
16635 * Amount by which to extend the top fading region. Called only when
16636 * {@link #isPaddingOffsetRequired()} returns true.
16638 * @return The top padding offset in pixels.
16640 * @see #isPaddingOffsetRequired()
16644 protected int getTopPaddingOffset() {
16649 * Amount by which to extend the bottom fading region. Called only when
16650 * {@link #isPaddingOffsetRequired()} returns true.
16652 * @return The bottom padding offset in pixels.
16654 * @see #isPaddingOffsetRequired()
16658 protected int getBottomPaddingOffset() {
16664 * @param offsetRequired
16666 protected int getFadeTop(boolean offsetRequired) {
16667 int top = mPaddingTop;
16668 if (offsetRequired) top += getTopPaddingOffset();
16674 * @param offsetRequired
16676 protected int getFadeHeight(boolean offsetRequired) {
16677 int padding = mPaddingTop;
16678 if (offsetRequired) padding += getTopPaddingOffset();
16679 return mBottom - mTop - mPaddingBottom - padding;
16683 * <p>Indicates whether this view is attached to a hardware accelerated
16684 * window or not.</p>
16686 * <p>Even if this method returns true, it does not mean that every call
16687 * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
16688 * accelerated {@link android.graphics.Canvas}. For instance, if this view
16689 * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
16690 * window is hardware accelerated,
16691 * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
16692 * return false, and this method will return true.</p>
16694 * @return True if the view is attached to a window and the window is
16695 * hardware accelerated; false in any other case.
16697 @ViewDebug.ExportedProperty(category = "drawing")
16698 public boolean isHardwareAccelerated() {
16699 return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
16703 * Sets a rectangular area on this view to which the view will be clipped
16704 * when it is drawn. Setting the value to null will remove the clip bounds
16705 * and the view will draw normally, using its full bounds.
16707 * @param clipBounds The rectangular area, in the local coordinates of
16708 * this view, to which future drawing operations will be clipped.
16710 public void setClipBounds(Rect clipBounds) {
16711 if (clipBounds == mClipBounds
16712 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
16715 if (clipBounds != null) {
16716 if (mClipBounds == null) {
16717 mClipBounds = new Rect(clipBounds);
16719 mClipBounds.set(clipBounds);
16722 mClipBounds = null;
16724 mRenderNode.setClipBounds(mClipBounds);
16725 invalidateViewProperty(false, false);
16729 * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
16731 * @return A copy of the current clip bounds if clip bounds are set,
16734 public Rect getClipBounds() {
16735 return (mClipBounds != null) ? new Rect(mClipBounds) : null;
16740 * Populates an output rectangle with the clip bounds of the view,
16741 * returning {@code true} if successful or {@code false} if the view's
16742 * clip bounds are {@code null}.
16744 * @param outRect rectangle in which to place the clip bounds of the view
16745 * @return {@code true} if successful or {@code false} if the view's
16746 * clip bounds are {@code null}
16748 public boolean getClipBounds(Rect outRect) {
16749 if (mClipBounds != null) {
16750 outRect.set(mClipBounds);
16757 * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
16758 * case of an active Animation being run on the view.
16760 private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
16761 Animation a, boolean scalingRequired) {
16762 Transformation invalidationTransform;
16763 final int flags = parent.mGroupFlags;
16764 final boolean initialized = a.isInitialized();
16765 if (!initialized) {
16766 a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
16767 a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
16768 if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
16769 onAnimationStart();
16772 final Transformation t = parent.getChildTransformation();
16773 boolean more = a.getTransformation(drawingTime, t, 1f);
16774 if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
16775 if (parent.mInvalidationTransformation == null) {
16776 parent.mInvalidationTransformation = new Transformation();
16778 invalidationTransform = parent.mInvalidationTransformation;
16779 a.getTransformation(drawingTime, invalidationTransform, 1f);
16781 invalidationTransform = t;
16785 if (!a.willChangeBounds()) {
16786 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
16787 ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
16788 parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
16789 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
16790 // The child need to draw an animation, potentially offscreen, so
16791 // make sure we do not cancel invalidate requests
16792 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16793 parent.invalidate(mLeft, mTop, mRight, mBottom);
16796 if (parent.mInvalidateRegion == null) {
16797 parent.mInvalidateRegion = new RectF();
16799 final RectF region = parent.mInvalidateRegion;
16800 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
16801 invalidationTransform);
16803 // The child need to draw an animation, potentially offscreen, so
16804 // make sure we do not cancel invalidate requests
16805 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16807 final int left = mLeft + (int) region.left;
16808 final int top = mTop + (int) region.top;
16809 parent.invalidate(left, top, left + (int) (region.width() + .5f),
16810 top + (int) (region.height() + .5f));
16817 * This method is called by getDisplayList() when a display list is recorded for a View.
16818 * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
16820 void setDisplayListProperties(RenderNode renderNode) {
16821 if (renderNode != null) {
16822 renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
16823 renderNode.setClipToBounds(mParent instanceof ViewGroup
16824 && ((ViewGroup) mParent).getClipChildren());
16827 if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
16828 ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16829 ViewGroup parentVG = (ViewGroup) mParent;
16830 final Transformation t = parentVG.getChildTransformation();
16831 if (parentVG.getChildStaticTransformation(this, t)) {
16832 final int transformType = t.getTransformationType();
16833 if (transformType != Transformation.TYPE_IDENTITY) {
16834 if ((transformType & Transformation.TYPE_ALPHA) != 0) {
16835 alpha = t.getAlpha();
16837 if ((transformType & Transformation.TYPE_MATRIX) != 0) {
16838 renderNode.setStaticMatrix(t.getMatrix());
16843 if (mTransformationInfo != null) {
16844 alpha *= getFinalAlpha();
16846 final int multipliedAlpha = (int) (255 * alpha);
16847 if (onSetAlpha(multipliedAlpha)) {
16851 renderNode.setAlpha(alpha);
16852 } else if (alpha < 1) {
16853 renderNode.setAlpha(alpha);
16859 * This method is called by ViewGroup.drawChild() to have each child view draw itself.
16861 * This is where the View specializes rendering behavior based on layer type,
16862 * and hardware acceleration.
16864 boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
16865 final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
16866 /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
16868 * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
16869 * HW accelerated, it can't handle drawing RenderNodes.
16871 boolean drawingWithRenderNode = mAttachInfo != null
16872 && mAttachInfo.mHardwareAccelerated
16873 && hardwareAcceleratedCanvas;
16875 boolean more = false;
16876 final boolean childHasIdentityMatrix = hasIdentityMatrix();
16877 final int parentFlags = parent.mGroupFlags;
16879 if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
16880 parent.getChildTransformation().clear();
16881 parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16884 Transformation transformToApply = null;
16885 boolean concatMatrix = false;
16886 final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
16887 final Animation a = getAnimation();
16889 more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
16890 concatMatrix = a.willChangeTransformationMatrix();
16891 if (concatMatrix) {
16892 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16894 transformToApply = parent.getChildTransformation();
16896 if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
16897 // No longer animating: clear out old animation matrix
16898 mRenderNode.setAnimationMatrix(null);
16899 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16901 if (!drawingWithRenderNode
16902 && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16903 final Transformation t = parent.getChildTransformation();
16904 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
16905 if (hasTransform) {
16906 final int transformType = t.getTransformationType();
16907 transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
16908 concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
16913 concatMatrix |= !childHasIdentityMatrix;
16915 // Sets the flag as early as possible to allow draw() implementations
16916 // to call invalidate() successfully when doing animations
16917 mPrivateFlags |= PFLAG_DRAWN;
16919 if (!concatMatrix &&
16920 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
16921 ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
16922 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
16923 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
16924 mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
16927 mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
16929 if (hardwareAcceleratedCanvas) {
16930 // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
16931 // retain the flag's value temporarily in the mRecreateDisplayList flag
16932 mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
16933 mPrivateFlags &= ~PFLAG_INVALIDATED;
16936 RenderNode renderNode = null;
16937 Bitmap cache = null;
16938 int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
16939 if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
16940 if (layerType != LAYER_TYPE_NONE) {
16941 // If not drawing with RenderNode, treat HW layers as SW
16942 layerType = LAYER_TYPE_SOFTWARE;
16943 buildDrawingCache(true);
16945 cache = getDrawingCache(true);
16948 if (drawingWithRenderNode) {
16949 // Delay getting the display list until animation-driven alpha values are
16950 // set up and possibly passed on to the view
16951 renderNode = updateDisplayListIfDirty();
16952 if (!renderNode.isValid()) {
16953 // Uncommon, but possible. If a view is removed from the hierarchy during the call
16954 // to getDisplayList(), the display list will be marked invalid and we should not
16955 // try to use it again.
16957 drawingWithRenderNode = false;
16963 if (!drawingWithRenderNode) {
16969 final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
16970 final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
16972 int restoreTo = -1;
16973 if (!drawingWithRenderNode || transformToApply != null) {
16974 restoreTo = canvas.save();
16976 if (offsetForScroll) {
16977 canvas.translate(mLeft - sx, mTop - sy);
16979 if (!drawingWithRenderNode) {
16980 canvas.translate(mLeft, mTop);
16982 if (scalingRequired) {
16983 if (drawingWithRenderNode) {
16984 // TODO: Might not need this if we put everything inside the DL
16985 restoreTo = canvas.save();
16987 // mAttachInfo cannot be null, otherwise scalingRequired == false
16988 final float scale = 1.0f / mAttachInfo.mApplicationScale;
16989 canvas.scale(scale, scale);
16993 float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
16994 if (transformToApply != null
16996 || !hasIdentityMatrix()
16997 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16998 if (transformToApply != null || !childHasIdentityMatrix) {
17002 if (offsetForScroll) {
17007 if (transformToApply != null) {
17008 if (concatMatrix) {
17009 if (drawingWithRenderNode) {
17010 renderNode.setAnimationMatrix(transformToApply.getMatrix());
17012 // Undo the scroll translation, apply the transformation matrix,
17013 // then redo the scroll translate to get the correct result.
17014 canvas.translate(-transX, -transY);
17015 canvas.concat(transformToApply.getMatrix());
17016 canvas.translate(transX, transY);
17018 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17021 float transformAlpha = transformToApply.getAlpha();
17022 if (transformAlpha < 1) {
17023 alpha *= transformAlpha;
17024 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17028 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
17029 canvas.translate(-transX, -transY);
17030 canvas.concat(getMatrix());
17031 canvas.translate(transX, transY);
17035 // Deal with alpha if it is or used to be <1
17036 if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
17038 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
17040 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
17042 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17043 if (!drawingWithDrawingCache) {
17044 final int multipliedAlpha = (int) (255 * alpha);
17045 if (!onSetAlpha(multipliedAlpha)) {
17046 if (drawingWithRenderNode) {
17047 renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
17048 } else if (layerType == LAYER_TYPE_NONE) {
17049 canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
17053 // Alpha is handled by the child directly, clobber the layer's alpha
17054 mPrivateFlags |= PFLAG_ALPHA_SET;
17058 } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17060 mPrivateFlags &= ~PFLAG_ALPHA_SET;
17063 if (!drawingWithRenderNode) {
17064 // apply clips directly, since RenderNode won't do it for this draw
17065 if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
17066 if (offsetForScroll) {
17067 canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
17069 if (!scalingRequired || cache == null) {
17070 canvas.clipRect(0, 0, getWidth(), getHeight());
17072 canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
17077 if (mClipBounds != null) {
17078 // clip bounds ignore scroll
17079 canvas.clipRect(mClipBounds);
17083 if (!drawingWithDrawingCache) {
17084 if (drawingWithRenderNode) {
17085 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17086 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
17088 // Fast path for layouts with no backgrounds
17089 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17090 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17091 dispatchDraw(canvas);
17096 } else if (cache != null) {
17097 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17098 if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
17099 // no layer paint, use temporary paint to draw bitmap
17100 Paint cachePaint = parent.mCachePaint;
17101 if (cachePaint == null) {
17102 cachePaint = new Paint();
17103 cachePaint.setDither(false);
17104 parent.mCachePaint = cachePaint;
17106 cachePaint.setAlpha((int) (alpha * 255));
17107 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
17109 // use layer paint to draw the bitmap, merging the two alphas, but also restore
17110 int layerPaintAlpha = mLayerPaint.getAlpha();
17112 mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
17114 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
17116 mLayerPaint.setAlpha(layerPaintAlpha);
17121 if (restoreTo >= 0) {
17122 canvas.restoreToCount(restoreTo);
17125 if (a != null && !more) {
17126 if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
17129 parent.finishAnimatingView(this, a);
17132 if (more && hardwareAcceleratedCanvas) {
17133 if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17134 // alpha animations should cause the child to recreate its display list
17139 mRecreateDisplayList = false;
17145 * Manually render this view (and all of its children) to the given Canvas.
17146 * The view must have already done a full layout before this function is
17147 * called. When implementing a view, implement
17148 * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
17149 * If you do need to override this method, call the superclass version.
17151 * @param canvas The Canvas to which the View is rendered.
17154 public void draw(Canvas canvas) {
17155 final int privateFlags = mPrivateFlags;
17156 final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
17157 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
17158 mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
17161 * Draw traversal performs several drawing steps which must be executed
17162 * in the appropriate order:
17164 * 1. Draw the background
17165 * 2. If necessary, save the canvas' layers to prepare for fading
17166 * 3. Draw view's content
17168 * 5. If necessary, draw the fading edges and restore layers
17169 * 6. Draw decorations (scrollbars for instance)
17172 // Step 1, draw the background, if needed
17175 if (!dirtyOpaque) {
17176 drawBackground(canvas);
17179 // skip step 2 & 5 if possible (common case)
17180 final int viewFlags = mViewFlags;
17181 boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
17182 boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
17183 if (!verticalEdges && !horizontalEdges) {
17184 // Step 3, draw the content
17185 if (!dirtyOpaque) onDraw(canvas);
17187 // Step 4, draw the children
17188 dispatchDraw(canvas);
17190 // Overlay is part of the content and draws beneath Foreground
17191 if (mOverlay != null && !mOverlay.isEmpty()) {
17192 mOverlay.getOverlayView().dispatchDraw(canvas);
17195 // Step 6, draw decorations (foreground, scrollbars)
17196 onDrawForeground(canvas);
17203 * Here we do the full fledged routine...
17204 * (this is an uncommon case where speed matters less,
17205 * this is why we repeat some of the tests that have been
17209 boolean drawTop = false;
17210 boolean drawBottom = false;
17211 boolean drawLeft = false;
17212 boolean drawRight = false;
17214 float topFadeStrength = 0.0f;
17215 float bottomFadeStrength = 0.0f;
17216 float leftFadeStrength = 0.0f;
17217 float rightFadeStrength = 0.0f;
17219 // Step 2, save the canvas' layers
17220 int paddingLeft = mPaddingLeft;
17222 final boolean offsetRequired = isPaddingOffsetRequired();
17223 if (offsetRequired) {
17224 paddingLeft += getLeftPaddingOffset();
17227 int left = mScrollX + paddingLeft;
17228 int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
17229 int top = mScrollY + getFadeTop(offsetRequired);
17230 int bottom = top + getFadeHeight(offsetRequired);
17232 if (offsetRequired) {
17233 right += getRightPaddingOffset();
17234 bottom += getBottomPaddingOffset();
17237 final ScrollabilityCache scrollabilityCache = mScrollCache;
17238 final float fadeHeight = scrollabilityCache.fadingEdgeLength;
17239 int length = (int) fadeHeight;
17241 // clip the fade length if top and bottom fades overlap
17242 // overlapping fades produce odd-looking artifacts
17243 if (verticalEdges && (top + length > bottom - length)) {
17244 length = (bottom - top) / 2;
17247 // also clip horizontal fades if necessary
17248 if (horizontalEdges && (left + length > right - length)) {
17249 length = (right - left) / 2;
17252 if (verticalEdges) {
17253 topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
17254 drawTop = topFadeStrength * fadeHeight > 1.0f;
17255 bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
17256 drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
17259 if (horizontalEdges) {
17260 leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
17261 drawLeft = leftFadeStrength * fadeHeight > 1.0f;
17262 rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
17263 drawRight = rightFadeStrength * fadeHeight > 1.0f;
17266 saveCount = canvas.getSaveCount();
17268 int solidColor = getSolidColor();
17269 if (solidColor == 0) {
17270 final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
17273 canvas.saveLayer(left, top, right, top + length, null, flags);
17277 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
17281 canvas.saveLayer(left, top, left + length, bottom, null, flags);
17285 canvas.saveLayer(right - length, top, right, bottom, null, flags);
17288 scrollabilityCache.setFadeColor(solidColor);
17291 // Step 3, draw the content
17292 if (!dirtyOpaque) onDraw(canvas);
17294 // Step 4, draw the children
17295 dispatchDraw(canvas);
17297 // Step 5, draw the fade effect and restore layers
17298 final Paint p = scrollabilityCache.paint;
17299 final Matrix matrix = scrollabilityCache.matrix;
17300 final Shader fade = scrollabilityCache.shader;
17303 matrix.setScale(1, fadeHeight * topFadeStrength);
17304 matrix.postTranslate(left, top);
17305 fade.setLocalMatrix(matrix);
17307 canvas.drawRect(left, top, right, top + length, p);
17311 matrix.setScale(1, fadeHeight * bottomFadeStrength);
17312 matrix.postRotate(180);
17313 matrix.postTranslate(left, bottom);
17314 fade.setLocalMatrix(matrix);
17316 canvas.drawRect(left, bottom - length, right, bottom, p);
17320 matrix.setScale(1, fadeHeight * leftFadeStrength);
17321 matrix.postRotate(-90);
17322 matrix.postTranslate(left, top);
17323 fade.setLocalMatrix(matrix);
17325 canvas.drawRect(left, top, left + length, bottom, p);
17329 matrix.setScale(1, fadeHeight * rightFadeStrength);
17330 matrix.postRotate(90);
17331 matrix.postTranslate(right, top);
17332 fade.setLocalMatrix(matrix);
17334 canvas.drawRect(right - length, top, right, bottom, p);
17337 canvas.restoreToCount(saveCount);
17339 // Overlay is part of the content and draws beneath Foreground
17340 if (mOverlay != null && !mOverlay.isEmpty()) {
17341 mOverlay.getOverlayView().dispatchDraw(canvas);
17344 // Step 6, draw decorations (foreground, scrollbars)
17345 onDrawForeground(canvas);
17349 * Draws the background onto the specified canvas.
17351 * @param canvas Canvas on which to draw the background
17353 private void drawBackground(Canvas canvas) {
17354 final Drawable background = mBackground;
17355 if (background == null) {
17359 setBackgroundBounds();
17361 // Attempt to use a display list if requested.
17362 if (canvas.isHardwareAccelerated() && mAttachInfo != null
17363 && mAttachInfo.mHardwareRenderer != null) {
17364 mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
17366 final RenderNode renderNode = mBackgroundRenderNode;
17367 if (renderNode != null && renderNode.isValid()) {
17368 setBackgroundRenderNodeProperties(renderNode);
17369 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
17374 final int scrollX = mScrollX;
17375 final int scrollY = mScrollY;
17376 if ((scrollX | scrollY) == 0) {
17377 background.draw(canvas);
17379 canvas.translate(scrollX, scrollY);
17380 background.draw(canvas);
17381 canvas.translate(-scrollX, -scrollY);
17386 * Sets the correct background bounds and rebuilds the outline, if needed.
17388 * This is called by LayoutLib.
17390 void setBackgroundBounds() {
17391 if (mBackgroundSizeChanged && mBackground != null) {
17392 mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
17393 mBackgroundSizeChanged = false;
17398 private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
17399 renderNode.setTranslationX(mScrollX);
17400 renderNode.setTranslationY(mScrollY);
17404 * Creates a new display list or updates the existing display list for the
17405 * specified Drawable.
17407 * @param drawable Drawable for which to create a display list
17408 * @param renderNode Existing RenderNode, or {@code null}
17409 * @return A valid display list for the specified drawable
17411 private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
17412 if (renderNode == null) {
17413 renderNode = RenderNode.create(drawable.getClass().getName(), this);
17416 final Rect bounds = drawable.getBounds();
17417 final int width = bounds.width();
17418 final int height = bounds.height();
17419 final DisplayListCanvas canvas = renderNode.start(width, height);
17421 // Reverse left/top translation done by drawable canvas, which will
17422 // instead be applied by rendernode's LTRB bounds below. This way, the
17423 // drawable's bounds match with its rendernode bounds and its content
17424 // will lie within those bounds in the rendernode tree.
17425 canvas.translate(-bounds.left, -bounds.top);
17428 drawable.draw(canvas);
17430 renderNode.end(canvas);
17433 // Set up drawable properties that are view-independent.
17434 renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
17435 renderNode.setProjectBackwards(drawable.isProjected());
17436 renderNode.setProjectionReceiver(true);
17437 renderNode.setClipToBounds(false);
17442 * Returns the overlay for this view, creating it if it does not yet exist.
17443 * Adding drawables to the overlay will cause them to be displayed whenever
17444 * the view itself is redrawn. Objects in the overlay should be actively
17445 * managed: remove them when they should not be displayed anymore. The
17446 * overlay will always have the same size as its host view.
17448 * <p>Note: Overlays do not currently work correctly with {@link
17449 * SurfaceView} or {@link TextureView}; contents in overlays for these
17450 * types of views may not display correctly.</p>
17452 * @return The ViewOverlay object for this view.
17455 public ViewOverlay getOverlay() {
17456 if (mOverlay == null) {
17457 mOverlay = new ViewOverlay(mContext, this);
17463 * Override this if your view is known to always be drawn on top of a solid color background,
17464 * and needs to draw fading edges. Returning a non-zero color enables the view system to
17465 * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
17466 * should be set to 0xFF.
17468 * @see #setVerticalFadingEdgeEnabled(boolean)
17469 * @see #setHorizontalFadingEdgeEnabled(boolean)
17471 * @return The known solid color background for this view, or 0 if the color may vary
17473 @ViewDebug.ExportedProperty(category = "drawing")
17475 public int getSolidColor() {
17480 * Build a human readable string representation of the specified view flags.
17482 * @param flags the view flags to convert to a string
17483 * @return a String representing the supplied flags
17485 private static String printFlags(int flags) {
17486 String output = "";
17488 if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
17489 output += "TAKES_FOCUS";
17493 switch (flags & VISIBILITY_MASK) {
17495 if (numFlags > 0) {
17498 output += "INVISIBLE";
17499 // USELESS HERE numFlags++;
17502 if (numFlags > 0) {
17506 // USELESS HERE numFlags++;
17515 * Build a human readable string representation of the specified private
17518 * @param privateFlags the private view flags to convert to a string
17519 * @return a String representing the supplied flags
17521 private static String printPrivateFlags(int privateFlags) {
17522 String output = "";
17525 if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
17526 output += "WANTS_FOCUS";
17530 if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
17531 if (numFlags > 0) {
17534 output += "FOCUSED";
17538 if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
17539 if (numFlags > 0) {
17542 output += "SELECTED";
17546 if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
17547 if (numFlags > 0) {
17550 output += "IS_ROOT_NAMESPACE";
17554 if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
17555 if (numFlags > 0) {
17558 output += "HAS_BOUNDS";
17562 if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
17563 if (numFlags > 0) {
17567 // USELESS HERE numFlags++;
17573 * <p>Indicates whether or not this view's layout will be requested during
17574 * the next hierarchy layout pass.</p>
17576 * @return true if the layout will be forced during next layout pass
17578 public boolean isLayoutRequested() {
17579 return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
17583 * Return true if o is a ViewGroup that is laying out using optical bounds.
17586 public static boolean isLayoutModeOptical(Object o) {
17587 return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
17590 private boolean setOpticalFrame(int left, int top, int right, int bottom) {
17591 Insets parentInsets = mParent instanceof View ?
17592 ((View) mParent).getOpticalInsets() : Insets.NONE;
17593 Insets childInsets = getOpticalInsets();
17595 left + parentInsets.left - childInsets.left,
17596 top + parentInsets.top - childInsets.top,
17597 right + parentInsets.left + childInsets.right,
17598 bottom + parentInsets.top + childInsets.bottom);
17602 * Assign a size and position to a view and all of its
17605 * <p>This is the second phase of the layout mechanism.
17606 * (The first is measuring). In this phase, each parent calls
17607 * layout on all of its children to position them.
17608 * This is typically done using the child measurements
17609 * that were stored in the measure pass().</p>
17611 * <p>Derived classes should not override this method.
17612 * Derived classes with children should override
17613 * onLayout. In that method, they should
17614 * call layout on each of their children.</p>
17616 * @param l Left position, relative to parent
17617 * @param t Top position, relative to parent
17618 * @param r Right position, relative to parent
17619 * @param b Bottom position, relative to parent
17621 @SuppressWarnings({"unchecked"})
17622 public void layout(int l, int t, int r, int b) {
17623 if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
17624 onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
17625 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
17630 int oldB = mBottom;
17633 boolean changed = isLayoutModeOptical(mParent) ?
17634 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
17636 if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
17637 onLayout(changed, l, t, r, b);
17639 if (shouldDrawRoundScrollbar()) {
17640 if(mRoundScrollbarRenderer == null) {
17641 mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
17644 mRoundScrollbarRenderer = null;
17647 mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
17649 ListenerInfo li = mListenerInfo;
17650 if (li != null && li.mOnLayoutChangeListeners != null) {
17651 ArrayList<OnLayoutChangeListener> listenersCopy =
17652 (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
17653 int numListeners = listenersCopy.size();
17654 for (int i = 0; i < numListeners; ++i) {
17655 listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
17660 mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
17661 mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
17665 * Called from layout when this view should
17666 * assign a size and position to each of its children.
17668 * Derived classes with children should override
17669 * this method and call layout on each of
17671 * @param changed This is a new size or position for this view
17672 * @param left Left position, relative to parent
17673 * @param top Top position, relative to parent
17674 * @param right Right position, relative to parent
17675 * @param bottom Bottom position, relative to parent
17677 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
17681 * Assign a size and position to this view.
17683 * This is called from layout.
17685 * @param left Left position, relative to parent
17686 * @param top Top position, relative to parent
17687 * @param right Right position, relative to parent
17688 * @param bottom Bottom position, relative to parent
17689 * @return true if the new size and position are different than the
17693 protected boolean setFrame(int left, int top, int right, int bottom) {
17694 boolean changed = false;
17697 Log.d("View", this + " View.setFrame(" + left + "," + top + ","
17698 + right + "," + bottom + ")");
17701 if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
17704 // Remember our drawn bit
17705 int drawn = mPrivateFlags & PFLAG_DRAWN;
17707 int oldWidth = mRight - mLeft;
17708 int oldHeight = mBottom - mTop;
17709 int newWidth = right - left;
17710 int newHeight = bottom - top;
17711 boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
17713 // Invalidate our old position
17714 invalidate(sizeChanged);
17720 mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
17722 mPrivateFlags |= PFLAG_HAS_BOUNDS;
17726 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
17729 if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
17730 // If we are visible, force the DRAWN bit to on so that
17731 // this invalidate will go through (at least to our parent).
17732 // This is because someone may have invalidated this view
17733 // before this call to setFrame came in, thereby clearing
17735 mPrivateFlags |= PFLAG_DRAWN;
17736 invalidate(sizeChanged);
17737 // parent display list may need to be recreated based on a change in the bounds
17739 invalidateParentCaches();
17742 // Reset drawn bit to original value (invalidate turns it off)
17743 mPrivateFlags |= drawn;
17745 mBackgroundSizeChanged = true;
17746 if (mForegroundInfo != null) {
17747 mForegroundInfo.mBoundsChanged = true;
17750 notifySubtreeAccessibilityStateChangedIfNeeded();
17756 * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
17759 public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
17760 setFrame(left, top, right, bottom);
17763 private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
17764 onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
17765 if (mOverlay != null) {
17766 mOverlay.getOverlayView().setRight(newWidth);
17767 mOverlay.getOverlayView().setBottom(newHeight);
17773 * Finalize inflating a view from XML. This is called as the last phase
17774 * of inflation, after all child views have been added.
17776 * <p>Even if the subclass overrides onFinishInflate, they should always be
17777 * sure to call the super method, so that we get called.
17780 protected void onFinishInflate() {
17784 * Returns the resources associated with this view.
17786 * @return Resources object.
17788 public Resources getResources() {
17793 * Invalidates the specified Drawable.
17795 * @param drawable the drawable to invalidate
17798 public void invalidateDrawable(@NonNull Drawable drawable) {
17799 if (verifyDrawable(drawable)) {
17800 final Rect dirty = drawable.getDirtyBounds();
17801 final int scrollX = mScrollX;
17802 final int scrollY = mScrollY;
17804 invalidate(dirty.left + scrollX, dirty.top + scrollY,
17805 dirty.right + scrollX, dirty.bottom + scrollY);
17811 * Schedules an action on a drawable to occur at a specified time.
17813 * @param who the recipient of the action
17814 * @param what the action to run on the drawable
17815 * @param when the time at which the action must occur. Uses the
17816 * {@link SystemClock#uptimeMillis} timebase.
17819 public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
17820 if (verifyDrawable(who) && what != null) {
17821 final long delay = when - SystemClock.uptimeMillis();
17822 if (mAttachInfo != null) {
17823 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
17824 Choreographer.CALLBACK_ANIMATION, what, who,
17825 Choreographer.subtractFrameDelay(delay));
17827 // Postpone the runnable until we know
17828 // on which thread it needs to run.
17829 getRunQueue().postDelayed(what, delay);
17835 * Cancels a scheduled action on a drawable.
17837 * @param who the recipient of the action
17838 * @param what the action to cancel
17841 public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
17842 if (verifyDrawable(who) && what != null) {
17843 if (mAttachInfo != null) {
17844 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17845 Choreographer.CALLBACK_ANIMATION, what, who);
17847 getRunQueue().removeCallbacks(what);
17852 * Unschedule any events associated with the given Drawable. This can be
17853 * used when selecting a new Drawable into a view, so that the previous
17854 * one is completely unscheduled.
17856 * @param who The Drawable to unschedule.
17858 * @see #drawableStateChanged
17860 public void unscheduleDrawable(Drawable who) {
17861 if (mAttachInfo != null && who != null) {
17862 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17863 Choreographer.CALLBACK_ANIMATION, null, who);
17868 * Resolve the Drawables depending on the layout direction. This is implicitly supposing
17869 * that the View directionality can and will be resolved before its Drawables.
17871 * Will call {@link View#onResolveDrawables} when resolution is done.
17875 protected void resolveDrawables() {
17876 // Drawables resolution may need to happen before resolving the layout direction (which is
17877 // done only during the measure() call).
17878 // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
17879 // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
17880 // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
17881 // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
17882 // direction to be resolved as its resolved value will be the same as its raw value.
17883 if (!isLayoutDirectionResolved() &&
17884 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
17888 final int layoutDirection = isLayoutDirectionResolved() ?
17889 getLayoutDirection() : getRawLayoutDirection();
17891 if (mBackground != null) {
17892 mBackground.setLayoutDirection(layoutDirection);
17894 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17895 mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
17897 mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
17898 onResolveDrawables(layoutDirection);
17901 boolean areDrawablesResolved() {
17902 return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
17906 * Called when layout direction has been resolved.
17908 * The default implementation does nothing.
17910 * @param layoutDirection The resolved layout direction.
17912 * @see #LAYOUT_DIRECTION_LTR
17913 * @see #LAYOUT_DIRECTION_RTL
17917 public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
17923 protected void resetResolvedDrawables() {
17924 resetResolvedDrawablesInternal();
17927 void resetResolvedDrawablesInternal() {
17928 mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
17932 * If your view subclass is displaying its own Drawable objects, it should
17933 * override this function and return true for any Drawable it is
17934 * displaying. This allows animations for those drawables to be
17937 * <p>Be sure to call through to the super class when overriding this
17940 * @param who The Drawable to verify. Return true if it is one you are
17941 * displaying, else return the result of calling through to the
17944 * @return boolean If true than the Drawable is being displayed in the
17945 * view; else false and it is not allowed to animate.
17947 * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
17948 * @see #drawableStateChanged()
17951 protected boolean verifyDrawable(@NonNull Drawable who) {
17952 // Avoid verifying the scroll bar drawable so that we don't end up in
17953 // an invalidation loop. This effectively prevents the scroll bar
17954 // drawable from triggering invalidations and scheduling runnables.
17955 return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
17959 * This function is called whenever the state of the view changes in such
17960 * a way that it impacts the state of drawables being shown.
17962 * If the View has a StateListAnimator, it will also be called to run necessary state
17963 * change animations.
17965 * Be sure to call through to the superclass when overriding this function.
17967 * @see Drawable#setState(int[])
17970 protected void drawableStateChanged() {
17971 final int[] state = getDrawableState();
17972 boolean changed = false;
17974 final Drawable bg = mBackground;
17975 if (bg != null && bg.isStateful()) {
17976 changed |= bg.setState(state);
17979 final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17980 if (fg != null && fg.isStateful()) {
17981 changed |= fg.setState(state);
17984 if (mScrollCache != null) {
17985 final Drawable scrollBar = mScrollCache.scrollBar;
17986 if (scrollBar != null && scrollBar.isStateful()) {
17987 changed |= scrollBar.setState(state)
17988 && mScrollCache.state != ScrollabilityCache.OFF;
17992 if (mStateListAnimator != null) {
17993 mStateListAnimator.setState(state);
18002 * This function is called whenever the view hotspot changes and needs to
18003 * be propagated to drawables or child views managed by the view.
18005 * Dispatching to child views is handled by
18006 * {@link #dispatchDrawableHotspotChanged(float, float)}.
18008 * Be sure to call through to the superclass when overriding this function.
18010 * @param x hotspot x coordinate
18011 * @param y hotspot y coordinate
18014 public void drawableHotspotChanged(float x, float y) {
18015 if (mBackground != null) {
18016 mBackground.setHotspot(x, y);
18018 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18019 mForegroundInfo.mDrawable.setHotspot(x, y);
18022 dispatchDrawableHotspotChanged(x, y);
18026 * Dispatches drawableHotspotChanged to all of this View's children.
18028 * @param x hotspot x coordinate
18029 * @param y hotspot y coordinate
18030 * @see #drawableHotspotChanged(float, float)
18032 public void dispatchDrawableHotspotChanged(float x, float y) {
18036 * Call this to force a view to update its drawable state. This will cause
18037 * drawableStateChanged to be called on this view. Views that are interested
18038 * in the new state should call getDrawableState.
18040 * @see #drawableStateChanged
18041 * @see #getDrawableState
18043 public void refreshDrawableState() {
18044 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
18045 drawableStateChanged();
18047 ViewParent parent = mParent;
18048 if (parent != null) {
18049 parent.childDrawableStateChanged(this);
18054 * Return an array of resource IDs of the drawable states representing the
18055 * current state of the view.
18057 * @return The current drawable state
18059 * @see Drawable#setState(int[])
18060 * @see #drawableStateChanged()
18061 * @see #onCreateDrawableState(int)
18063 public final int[] getDrawableState() {
18064 if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
18065 return mDrawableState;
18067 mDrawableState = onCreateDrawableState(0);
18068 mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
18069 return mDrawableState;
18074 * Generate the new {@link android.graphics.drawable.Drawable} state for
18075 * this view. This is called by the view
18076 * system when the cached Drawable state is determined to be invalid. To
18077 * retrieve the current state, you should use {@link #getDrawableState}.
18079 * @param extraSpace if non-zero, this is the number of extra entries you
18080 * would like in the returned array in which you can place your own
18083 * @return Returns an array holding the current {@link Drawable} state of
18086 * @see #mergeDrawableStates(int[], int[])
18088 protected int[] onCreateDrawableState(int extraSpace) {
18089 if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
18090 mParent instanceof View) {
18091 return ((View) mParent).onCreateDrawableState(extraSpace);
18094 int[] drawableState;
18096 int privateFlags = mPrivateFlags;
18098 int viewStateIndex = 0;
18099 if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
18100 if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
18101 if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
18102 if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
18103 if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
18104 if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
18105 if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
18106 ThreadedRenderer.isAvailable()) {
18107 // This is set if HW acceleration is requested, even if the current
18108 // process doesn't allow it. This is just to allow app preview
18109 // windows to better match their app.
18110 viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
18112 if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
18114 final int privateFlags2 = mPrivateFlags2;
18115 if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
18116 viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
18118 if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
18119 viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
18122 drawableState = StateSet.get(viewStateIndex);
18124 //noinspection ConstantIfStatement
18126 Log.i("View", "drawableStateIndex=" + viewStateIndex);
18127 Log.i("View", toString()
18128 + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
18129 + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
18130 + " fo=" + hasFocus()
18131 + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
18132 + " wf=" + hasWindowFocus()
18133 + ": " + Arrays.toString(drawableState));
18136 if (extraSpace == 0) {
18137 return drawableState;
18140 final int[] fullState;
18141 if (drawableState != null) {
18142 fullState = new int[drawableState.length + extraSpace];
18143 System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
18145 fullState = new int[extraSpace];
18152 * Merge your own state values in <var>additionalState</var> into the base
18153 * state values <var>baseState</var> that were returned by
18154 * {@link #onCreateDrawableState(int)}.
18156 * @param baseState The base state values returned by
18157 * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
18158 * own additional state values.
18160 * @param additionalState The additional state values you would like
18161 * added to <var>baseState</var>; this array is not modified.
18163 * @return As a convenience, the <var>baseState</var> array you originally
18164 * passed into the function is returned.
18166 * @see #onCreateDrawableState(int)
18168 protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
18169 final int N = baseState.length;
18171 while (i >= 0 && baseState[i] == 0) {
18174 System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
18179 * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
18180 * on all Drawable objects associated with this view.
18182 * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
18183 * attached to this view.
18186 public void jumpDrawablesToCurrentState() {
18187 if (mBackground != null) {
18188 mBackground.jumpToCurrentState();
18190 if (mStateListAnimator != null) {
18191 mStateListAnimator.jumpToCurrentState();
18193 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18194 mForegroundInfo.mDrawable.jumpToCurrentState();
18199 * Sets the background color for this view.
18200 * @param color the color of the background
18202 @RemotableViewMethod
18203 public void setBackgroundColor(@ColorInt int color) {
18204 if (mBackground instanceof ColorDrawable) {
18205 ((ColorDrawable) mBackground.mutate()).setColor(color);
18206 computeOpaqueFlags();
18207 mBackgroundResource = 0;
18209 setBackground(new ColorDrawable(color));
18214 * Set the background to a given resource. The resource should refer to
18215 * a Drawable object or 0 to remove the background.
18216 * @param resid The identifier of the resource.
18218 * @attr ref android.R.styleable#View_background
18220 @RemotableViewMethod
18221 public void setBackgroundResource(@DrawableRes int resid) {
18222 if (resid != 0 && resid == mBackgroundResource) {
18228 d = mContext.getDrawable(resid);
18232 mBackgroundResource = resid;
18236 * Set the background to a given Drawable, or remove the background. If the
18237 * background has padding, this View's padding is set to the background's
18238 * padding. However, when a background is removed, this View's padding isn't
18239 * touched. If setting the padding is desired, please use
18240 * {@link #setPadding(int, int, int, int)}.
18242 * @param background The Drawable to use as the background, or null to remove the
18245 public void setBackground(Drawable background) {
18246 //noinspection deprecation
18247 setBackgroundDrawable(background);
18251 * @deprecated use {@link #setBackground(Drawable)} instead
18254 public void setBackgroundDrawable(Drawable background) {
18255 computeOpaqueFlags();
18257 if (background == mBackground) {
18261 boolean requestLayout = false;
18263 mBackgroundResource = 0;
18266 * Regardless of whether we're setting a new background or not, we want
18267 * to clear the previous drawable. setVisible first while we still have the callback set.
18269 if (mBackground != null) {
18270 if (isAttachedToWindow()) {
18271 mBackground.setVisible(false, false);
18273 mBackground.setCallback(null);
18274 unscheduleDrawable(mBackground);
18277 if (background != null) {
18278 Rect padding = sThreadLocal.get();
18279 if (padding == null) {
18280 padding = new Rect();
18281 sThreadLocal.set(padding);
18283 resetResolvedDrawablesInternal();
18284 background.setLayoutDirection(getLayoutDirection());
18285 if (background.getPadding(padding)) {
18286 resetResolvedPaddingInternal();
18287 switch (background.getLayoutDirection()) {
18288 case LAYOUT_DIRECTION_RTL:
18289 mUserPaddingLeftInitial = padding.right;
18290 mUserPaddingRightInitial = padding.left;
18291 internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
18293 case LAYOUT_DIRECTION_LTR:
18295 mUserPaddingLeftInitial = padding.left;
18296 mUserPaddingRightInitial = padding.right;
18297 internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
18299 mLeftPaddingDefined = false;
18300 mRightPaddingDefined = false;
18303 // Compare the minimum sizes of the old Drawable and the new. If there isn't an old or
18304 // if it has a different minimum size, we should layout again
18305 if (mBackground == null
18306 || mBackground.getMinimumHeight() != background.getMinimumHeight()
18307 || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
18308 requestLayout = true;
18311 // Set mBackground before we set this as the callback and start making other
18312 // background drawable state change calls. In particular, the setVisible call below
18313 // can result in drawables attempting to start animations or otherwise invalidate,
18314 // which requires the view set as the callback (us) to recognize the drawable as
18315 // belonging to it as per verifyDrawable.
18316 mBackground = background;
18317 if (background.isStateful()) {
18318 background.setState(getDrawableState());
18320 if (isAttachedToWindow()) {
18321 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
18324 applyBackgroundTint();
18326 // Set callback last, since the view may still be initializing.
18327 background.setCallback(this);
18329 if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
18330 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18331 requestLayout = true;
18334 /* Remove the background */
18335 mBackground = null;
18336 if ((mViewFlags & WILL_NOT_DRAW) != 0
18337 && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
18338 mPrivateFlags |= PFLAG_SKIP_DRAW;
18342 * When the background is set, we try to apply its padding to this
18343 * View. When the background is removed, we don't touch this View's
18344 * padding. This is noted in the Javadocs. Hence, we don't need to
18345 * requestLayout(), the invalidate() below is sufficient.
18348 // The old background's minimum size could have affected this
18349 // View's layout, so let's requestLayout
18350 requestLayout = true;
18353 computeOpaqueFlags();
18355 if (requestLayout) {
18359 mBackgroundSizeChanged = true;
18361 invalidateOutline();
18365 * Gets the background drawable
18367 * @return The drawable used as the background for this view, if any.
18369 * @see #setBackground(Drawable)
18371 * @attr ref android.R.styleable#View_background
18373 public Drawable getBackground() {
18374 return mBackground;
18378 * Applies a tint to the background drawable. Does not modify the current tint
18379 * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
18381 * Subsequent calls to {@link #setBackground(Drawable)} will automatically
18382 * mutate the drawable and apply the specified tint and tint mode using
18383 * {@link Drawable#setTintList(ColorStateList)}.
18385 * @param tint the tint to apply, may be {@code null} to clear tint
18387 * @attr ref android.R.styleable#View_backgroundTint
18388 * @see #getBackgroundTintList()
18389 * @see Drawable#setTintList(ColorStateList)
18391 public void setBackgroundTintList(@Nullable ColorStateList tint) {
18392 if (mBackgroundTint == null) {
18393 mBackgroundTint = new TintInfo();
18395 mBackgroundTint.mTintList = tint;
18396 mBackgroundTint.mHasTintList = true;
18398 applyBackgroundTint();
18402 * Return the tint applied to the background drawable, if specified.
18404 * @return the tint applied to the background drawable
18405 * @attr ref android.R.styleable#View_backgroundTint
18406 * @see #setBackgroundTintList(ColorStateList)
18409 public ColorStateList getBackgroundTintList() {
18410 return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
18414 * Specifies the blending mode used to apply the tint specified by
18415 * {@link #setBackgroundTintList(ColorStateList)}} to the background
18416 * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
18418 * @param tintMode the blending mode used to apply the tint, may be
18419 * {@code null} to clear tint
18420 * @attr ref android.R.styleable#View_backgroundTintMode
18421 * @see #getBackgroundTintMode()
18422 * @see Drawable#setTintMode(PorterDuff.Mode)
18424 public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
18425 if (mBackgroundTint == null) {
18426 mBackgroundTint = new TintInfo();
18428 mBackgroundTint.mTintMode = tintMode;
18429 mBackgroundTint.mHasTintMode = true;
18431 applyBackgroundTint();
18435 * Return the blending mode used to apply the tint to the background
18436 * drawable, if specified.
18438 * @return the blending mode used to apply the tint to the background
18440 * @attr ref android.R.styleable#View_backgroundTintMode
18441 * @see #setBackgroundTintMode(PorterDuff.Mode)
18444 public PorterDuff.Mode getBackgroundTintMode() {
18445 return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
18448 private void applyBackgroundTint() {
18449 if (mBackground != null && mBackgroundTint != null) {
18450 final TintInfo tintInfo = mBackgroundTint;
18451 if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
18452 mBackground = mBackground.mutate();
18454 if (tintInfo.mHasTintList) {
18455 mBackground.setTintList(tintInfo.mTintList);
18458 if (tintInfo.mHasTintMode) {
18459 mBackground.setTintMode(tintInfo.mTintMode);
18462 // The drawable (or one of its children) may not have been
18463 // stateful before applying the tint, so let's try again.
18464 if (mBackground.isStateful()) {
18465 mBackground.setState(getDrawableState());
18472 * Returns the drawable used as the foreground of this View. The
18473 * foreground drawable, if non-null, is always drawn on top of the view's content.
18475 * @return a Drawable or null if no foreground was set
18477 * @see #onDrawForeground(Canvas)
18479 public Drawable getForeground() {
18480 return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18484 * Supply a Drawable that is to be rendered on top of all of the content in the view.
18486 * @param foreground the Drawable to be drawn on top of the children
18488 * @attr ref android.R.styleable#View_foreground
18490 public void setForeground(Drawable foreground) {
18491 if (mForegroundInfo == null) {
18492 if (foreground == null) {
18496 mForegroundInfo = new ForegroundInfo();
18499 if (foreground == mForegroundInfo.mDrawable) {
18504 if (mForegroundInfo.mDrawable != null) {
18505 if (isAttachedToWindow()) {
18506 mForegroundInfo.mDrawable.setVisible(false, false);
18508 mForegroundInfo.mDrawable.setCallback(null);
18509 unscheduleDrawable(mForegroundInfo.mDrawable);
18512 mForegroundInfo.mDrawable = foreground;
18513 mForegroundInfo.mBoundsChanged = true;
18514 if (foreground != null) {
18515 if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
18516 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18518 foreground.setLayoutDirection(getLayoutDirection());
18519 if (foreground.isStateful()) {
18520 foreground.setState(getDrawableState());
18522 applyForegroundTint();
18523 if (isAttachedToWindow()) {
18524 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
18526 // Set callback last, since the view may still be initializing.
18527 foreground.setCallback(this);
18528 } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
18529 mPrivateFlags |= PFLAG_SKIP_DRAW;
18536 * Magic bit used to support features of framework-internal window decor implementation details.
18537 * This used to live exclusively in FrameLayout.
18539 * @return true if the foreground should draw inside the padding region or false
18540 * if it should draw inset by the view's padding
18541 * @hide internal use only; only used by FrameLayout and internal screen layouts.
18543 public boolean isForegroundInsidePadding() {
18544 return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
18548 * Describes how the foreground is positioned.
18550 * @return foreground gravity.
18552 * @see #setForegroundGravity(int)
18554 * @attr ref android.R.styleable#View_foregroundGravity
18556 public int getForegroundGravity() {
18557 return mForegroundInfo != null ? mForegroundInfo.mGravity
18558 : Gravity.START | Gravity.TOP;
18562 * Describes how the foreground is positioned. Defaults to START and TOP.
18564 * @param gravity see {@link android.view.Gravity}
18566 * @see #getForegroundGravity()
18568 * @attr ref android.R.styleable#View_foregroundGravity
18570 public void setForegroundGravity(int gravity) {
18571 if (mForegroundInfo == null) {
18572 mForegroundInfo = new ForegroundInfo();
18575 if (mForegroundInfo.mGravity != gravity) {
18576 if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
18577 gravity |= Gravity.START;
18580 if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
18581 gravity |= Gravity.TOP;
18584 mForegroundInfo.mGravity = gravity;
18590 * Applies a tint to the foreground drawable. Does not modify the current tint
18591 * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
18593 * Subsequent calls to {@link #setForeground(Drawable)} will automatically
18594 * mutate the drawable and apply the specified tint and tint mode using
18595 * {@link Drawable#setTintList(ColorStateList)}.
18597 * @param tint the tint to apply, may be {@code null} to clear tint
18599 * @attr ref android.R.styleable#View_foregroundTint
18600 * @see #getForegroundTintList()
18601 * @see Drawable#setTintList(ColorStateList)
18603 public void setForegroundTintList(@Nullable ColorStateList tint) {
18604 if (mForegroundInfo == null) {
18605 mForegroundInfo = new ForegroundInfo();
18607 if (mForegroundInfo.mTintInfo == null) {
18608 mForegroundInfo.mTintInfo = new TintInfo();
18610 mForegroundInfo.mTintInfo.mTintList = tint;
18611 mForegroundInfo.mTintInfo.mHasTintList = true;
18613 applyForegroundTint();
18617 * Return the tint applied to the foreground drawable, if specified.
18619 * @return the tint applied to the foreground drawable
18620 * @attr ref android.R.styleable#View_foregroundTint
18621 * @see #setForegroundTintList(ColorStateList)
18624 public ColorStateList getForegroundTintList() {
18625 return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
18626 ? mForegroundInfo.mTintInfo.mTintList : null;
18630 * Specifies the blending mode used to apply the tint specified by
18631 * {@link #setForegroundTintList(ColorStateList)}} to the background
18632 * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
18634 * @param tintMode the blending mode used to apply the tint, may be
18635 * {@code null} to clear tint
18636 * @attr ref android.R.styleable#View_foregroundTintMode
18637 * @see #getForegroundTintMode()
18638 * @see Drawable#setTintMode(PorterDuff.Mode)
18640 public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
18641 if (mForegroundInfo == null) {
18642 mForegroundInfo = new ForegroundInfo();
18644 if (mForegroundInfo.mTintInfo == null) {
18645 mForegroundInfo.mTintInfo = new TintInfo();
18647 mForegroundInfo.mTintInfo.mTintMode = tintMode;
18648 mForegroundInfo.mTintInfo.mHasTintMode = true;
18650 applyForegroundTint();
18654 * Return the blending mode used to apply the tint to the foreground
18655 * drawable, if specified.
18657 * @return the blending mode used to apply the tint to the foreground
18659 * @attr ref android.R.styleable#View_foregroundTintMode
18660 * @see #setForegroundTintMode(PorterDuff.Mode)
18663 public PorterDuff.Mode getForegroundTintMode() {
18664 return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
18665 ? mForegroundInfo.mTintInfo.mTintMode : null;
18668 private void applyForegroundTint() {
18669 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
18670 && mForegroundInfo.mTintInfo != null) {
18671 final TintInfo tintInfo = mForegroundInfo.mTintInfo;
18672 if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
18673 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
18675 if (tintInfo.mHasTintList) {
18676 mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
18679 if (tintInfo.mHasTintMode) {
18680 mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
18683 // The drawable (or one of its children) may not have been
18684 // stateful before applying the tint, so let's try again.
18685 if (mForegroundInfo.mDrawable.isStateful()) {
18686 mForegroundInfo.mDrawable.setState(getDrawableState());
18693 * Draw any foreground content for this view.
18695 * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
18696 * drawable or other view-specific decorations. The foreground is drawn on top of the
18697 * primary view content.</p>
18699 * @param canvas canvas to draw into
18701 public void onDrawForeground(Canvas canvas) {
18702 onDrawScrollIndicators(canvas);
18703 onDrawScrollBars(canvas);
18705 final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18706 if (foreground != null) {
18707 if (mForegroundInfo.mBoundsChanged) {
18708 mForegroundInfo.mBoundsChanged = false;
18709 final Rect selfBounds = mForegroundInfo.mSelfBounds;
18710 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
18712 if (mForegroundInfo.mInsidePadding) {
18713 selfBounds.set(0, 0, getWidth(), getHeight());
18715 selfBounds.set(getPaddingLeft(), getPaddingTop(),
18716 getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
18719 final int ld = getLayoutDirection();
18720 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
18721 foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
18722 foreground.setBounds(overlayBounds);
18725 foreground.draw(canvas);
18730 * Sets the padding. The view may add on the space required to display
18731 * the scrollbars, depending on the style and visibility of the scrollbars.
18732 * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
18733 * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
18734 * from the values set in this call.
18736 * @attr ref android.R.styleable#View_padding
18737 * @attr ref android.R.styleable#View_paddingBottom
18738 * @attr ref android.R.styleable#View_paddingLeft
18739 * @attr ref android.R.styleable#View_paddingRight
18740 * @attr ref android.R.styleable#View_paddingTop
18741 * @param left the left padding in pixels
18742 * @param top the top padding in pixels
18743 * @param right the right padding in pixels
18744 * @param bottom the bottom padding in pixels
18746 public void setPadding(int left, int top, int right, int bottom) {
18747 resetResolvedPaddingInternal();
18749 mUserPaddingStart = UNDEFINED_PADDING;
18750 mUserPaddingEnd = UNDEFINED_PADDING;
18752 mUserPaddingLeftInitial = left;
18753 mUserPaddingRightInitial = right;
18755 mLeftPaddingDefined = true;
18756 mRightPaddingDefined = true;
18758 internalSetPadding(left, top, right, bottom);
18764 protected void internalSetPadding(int left, int top, int right, int bottom) {
18765 mUserPaddingLeft = left;
18766 mUserPaddingRight = right;
18767 mUserPaddingBottom = bottom;
18769 final int viewFlags = mViewFlags;
18770 boolean changed = false;
18772 // Common case is there are no scroll bars.
18773 if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
18774 if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
18775 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
18776 ? 0 : getVerticalScrollbarWidth();
18777 switch (mVerticalScrollbarPosition) {
18778 case SCROLLBAR_POSITION_DEFAULT:
18779 if (isLayoutRtl()) {
18785 case SCROLLBAR_POSITION_RIGHT:
18788 case SCROLLBAR_POSITION_LEFT:
18793 if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
18794 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
18795 ? 0 : getHorizontalScrollbarHeight();
18799 if (mPaddingLeft != left) {
18801 mPaddingLeft = left;
18803 if (mPaddingTop != top) {
18807 if (mPaddingRight != right) {
18809 mPaddingRight = right;
18811 if (mPaddingBottom != bottom) {
18813 mPaddingBottom = bottom;
18818 invalidateOutline();
18823 * Sets the relative padding. The view may add on the space required to display
18824 * the scrollbars, depending on the style and visibility of the scrollbars.
18825 * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
18826 * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
18827 * from the values set in this call.
18829 * @attr ref android.R.styleable#View_padding
18830 * @attr ref android.R.styleable#View_paddingBottom
18831 * @attr ref android.R.styleable#View_paddingStart
18832 * @attr ref android.R.styleable#View_paddingEnd
18833 * @attr ref android.R.styleable#View_paddingTop
18834 * @param start the start padding in pixels
18835 * @param top the top padding in pixels
18836 * @param end the end padding in pixels
18837 * @param bottom the bottom padding in pixels
18839 public void setPaddingRelative(int start, int top, int end, int bottom) {
18840 resetResolvedPaddingInternal();
18842 mUserPaddingStart = start;
18843 mUserPaddingEnd = end;
18844 mLeftPaddingDefined = true;
18845 mRightPaddingDefined = true;
18847 switch(getLayoutDirection()) {
18848 case LAYOUT_DIRECTION_RTL:
18849 mUserPaddingLeftInitial = end;
18850 mUserPaddingRightInitial = start;
18851 internalSetPadding(end, top, start, bottom);
18853 case LAYOUT_DIRECTION_LTR:
18855 mUserPaddingLeftInitial = start;
18856 mUserPaddingRightInitial = end;
18857 internalSetPadding(start, top, end, bottom);
18862 * Returns the top padding of this view.
18864 * @return the top padding in pixels
18866 public int getPaddingTop() {
18867 return mPaddingTop;
18871 * Returns the bottom padding of this view. If there are inset and enabled
18872 * scrollbars, this value may include the space required to display the
18873 * scrollbars as well.
18875 * @return the bottom padding in pixels
18877 public int getPaddingBottom() {
18878 return mPaddingBottom;
18882 * Returns the left padding of this view. If there are inset and enabled
18883 * scrollbars, this value may include the space required to display the
18884 * scrollbars as well.
18886 * @return the left padding in pixels
18888 public int getPaddingLeft() {
18889 if (!isPaddingResolved()) {
18892 return mPaddingLeft;
18896 * Returns the start padding of this view depending on its resolved layout direction.
18897 * If there are inset and enabled scrollbars, this value may include the space
18898 * required to display the scrollbars as well.
18900 * @return the start padding in pixels
18902 public int getPaddingStart() {
18903 if (!isPaddingResolved()) {
18906 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18907 mPaddingRight : mPaddingLeft;
18911 * Returns the right padding of this view. If there are inset and enabled
18912 * scrollbars, this value may include the space required to display the
18913 * scrollbars as well.
18915 * @return the right padding in pixels
18917 public int getPaddingRight() {
18918 if (!isPaddingResolved()) {
18921 return mPaddingRight;
18925 * Returns the end padding of this view depending on its resolved layout direction.
18926 * If there are inset and enabled scrollbars, this value may include the space
18927 * required to display the scrollbars as well.
18929 * @return the end padding in pixels
18931 public int getPaddingEnd() {
18932 if (!isPaddingResolved()) {
18935 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18936 mPaddingLeft : mPaddingRight;
18940 * Return if the padding has been set through relative values
18941 * {@link #setPaddingRelative(int, int, int, int)} or through
18942 * @attr ref android.R.styleable#View_paddingStart or
18943 * @attr ref android.R.styleable#View_paddingEnd
18945 * @return true if the padding is relative or false if it is not.
18947 public boolean isPaddingRelative() {
18948 return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
18951 Insets computeOpticalInsets() {
18952 return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
18958 public void resetPaddingToInitialValues() {
18959 if (isRtlCompatibilityMode()) {
18960 mPaddingLeft = mUserPaddingLeftInitial;
18961 mPaddingRight = mUserPaddingRightInitial;
18964 if (isLayoutRtl()) {
18965 mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
18966 mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
18968 mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
18969 mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
18976 public Insets getOpticalInsets() {
18977 if (mLayoutInsets == null) {
18978 mLayoutInsets = computeOpticalInsets();
18980 return mLayoutInsets;
18984 * Set this view's optical insets.
18986 * <p>This method should be treated similarly to setMeasuredDimension and not as a general
18987 * property. Views that compute their own optical insets should call it as part of measurement.
18988 * This method does not request layout. If you are setting optical insets outside of
18989 * measure/layout itself you will want to call requestLayout() yourself.
18993 public void setOpticalInsets(Insets insets) {
18994 mLayoutInsets = insets;
18998 * Changes the selection state of this view. A view can be selected or not.
18999 * Note that selection is not the same as focus. Views are typically
19000 * selected in the context of an AdapterView like ListView or GridView;
19001 * the selected view is the view that is highlighted.
19003 * @param selected true if the view must be selected, false otherwise
19005 public void setSelected(boolean selected) {
19006 //noinspection DoubleNegation
19007 if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
19008 mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
19009 if (!selected) resetPressedState();
19011 refreshDrawableState();
19012 dispatchSetSelected(selected);
19014 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
19016 notifyViewAccessibilityStateChangedIfNeeded(
19017 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
19023 * Dispatch setSelected to all of this View's children.
19025 * @see #setSelected(boolean)
19027 * @param selected The new selected state
19029 protected void dispatchSetSelected(boolean selected) {
19033 * Indicates the selection state of this view.
19035 * @return true if the view is selected, false otherwise
19037 @ViewDebug.ExportedProperty
19038 public boolean isSelected() {
19039 return (mPrivateFlags & PFLAG_SELECTED) != 0;
19043 * Changes the activated state of this view. A view can be activated or not.
19044 * Note that activation is not the same as selection. Selection is
19045 * a transient property, representing the view (hierarchy) the user is
19046 * currently interacting with. Activation is a longer-term state that the
19047 * user can move views in and out of. For example, in a list view with
19048 * single or multiple selection enabled, the views in the current selection
19049 * set are activated. (Um, yeah, we are deeply sorry about the terminology
19050 * here.) The activated state is propagated down to children of the view it
19053 * @param activated true if the view must be activated, false otherwise
19055 public void setActivated(boolean activated) {
19056 //noinspection DoubleNegation
19057 if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
19058 mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
19060 refreshDrawableState();
19061 dispatchSetActivated(activated);
19066 * Dispatch setActivated to all of this View's children.
19068 * @see #setActivated(boolean)
19070 * @param activated The new activated state
19072 protected void dispatchSetActivated(boolean activated) {
19076 * Indicates the activation state of this view.
19078 * @return true if the view is activated, false otherwise
19080 @ViewDebug.ExportedProperty
19081 public boolean isActivated() {
19082 return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
19086 * Returns the ViewTreeObserver for this view's hierarchy. The view tree
19087 * observer can be used to get notifications when global events, like
19090 * The returned ViewTreeObserver observer is not guaranteed to remain
19091 * valid for the lifetime of this View. If the caller of this method keeps
19092 * a long-lived reference to ViewTreeObserver, it should always check for
19093 * the return value of {@link ViewTreeObserver#isAlive()}.
19095 * @return The ViewTreeObserver for this view's hierarchy.
19097 public ViewTreeObserver getViewTreeObserver() {
19098 if (mAttachInfo != null) {
19099 return mAttachInfo.mTreeObserver;
19101 if (mFloatingTreeObserver == null) {
19102 mFloatingTreeObserver = new ViewTreeObserver();
19104 return mFloatingTreeObserver;
19108 * <p>Finds the topmost view in the current view hierarchy.</p>
19110 * @return the topmost view containing this view
19112 public View getRootView() {
19113 if (mAttachInfo != null) {
19114 final View v = mAttachInfo.mRootView;
19120 View parent = this;
19122 while (parent.mParent != null && parent.mParent instanceof View) {
19123 parent = (View) parent.mParent;
19130 * Transforms a motion event from view-local coordinates to on-screen
19133 * @param ev the view-local motion event
19134 * @return false if the transformation could not be applied
19137 public boolean toGlobalMotionEvent(MotionEvent ev) {
19138 final AttachInfo info = mAttachInfo;
19139 if (info == null) {
19143 final Matrix m = info.mTmpMatrix;
19144 m.set(Matrix.IDENTITY_MATRIX);
19145 transformMatrixToGlobal(m);
19151 * Transforms a motion event from on-screen coordinates to view-local
19154 * @param ev the on-screen motion event
19155 * @return false if the transformation could not be applied
19158 public boolean toLocalMotionEvent(MotionEvent ev) {
19159 final AttachInfo info = mAttachInfo;
19160 if (info == null) {
19164 final Matrix m = info.mTmpMatrix;
19165 m.set(Matrix.IDENTITY_MATRIX);
19166 transformMatrixToLocal(m);
19172 * Modifies the input matrix such that it maps view-local coordinates to
19173 * on-screen coordinates.
19175 * @param m input matrix to modify
19178 public void transformMatrixToGlobal(Matrix m) {
19179 final ViewParent parent = mParent;
19180 if (parent instanceof View) {
19181 final View vp = (View) parent;
19182 vp.transformMatrixToGlobal(m);
19183 m.preTranslate(-vp.mScrollX, -vp.mScrollY);
19184 } else if (parent instanceof ViewRootImpl) {
19185 final ViewRootImpl vr = (ViewRootImpl) parent;
19186 vr.transformMatrixToGlobal(m);
19187 m.preTranslate(0, -vr.mCurScrollY);
19190 m.preTranslate(mLeft, mTop);
19192 if (!hasIdentityMatrix()) {
19193 m.preConcat(getMatrix());
19198 * Modifies the input matrix such that it maps on-screen coordinates to
19199 * view-local coordinates.
19201 * @param m input matrix to modify
19204 public void transformMatrixToLocal(Matrix m) {
19205 final ViewParent parent = mParent;
19206 if (parent instanceof View) {
19207 final View vp = (View) parent;
19208 vp.transformMatrixToLocal(m);
19209 m.postTranslate(vp.mScrollX, vp.mScrollY);
19210 } else if (parent instanceof ViewRootImpl) {
19211 final ViewRootImpl vr = (ViewRootImpl) parent;
19212 vr.transformMatrixToLocal(m);
19213 m.postTranslate(0, vr.mCurScrollY);
19216 m.postTranslate(-mLeft, -mTop);
19218 if (!hasIdentityMatrix()) {
19219 m.postConcat(getInverseMatrix());
19226 @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
19227 @ViewDebug.IntToString(from = 0, to = "x"),
19228 @ViewDebug.IntToString(from = 1, to = "y")
19230 public int[] getLocationOnScreen() {
19231 int[] location = new int[2];
19232 getLocationOnScreen(location);
19237 * <p>Computes the coordinates of this view on the screen. The argument
19238 * must be an array of two integers. After the method returns, the array
19239 * contains the x and y location in that order.</p>
19241 * @param outLocation an array of two integers in which to hold the coordinates
19243 public void getLocationOnScreen(@Size(2) int[] outLocation) {
19244 getLocationInWindow(outLocation);
19246 final AttachInfo info = mAttachInfo;
19247 if (info != null) {
19248 outLocation[0] += info.mWindowLeft;
19249 outLocation[1] += info.mWindowTop;
19254 * <p>Computes the coordinates of this view in its window. The argument
19255 * must be an array of two integers. After the method returns, the array
19256 * contains the x and y location in that order.</p>
19258 * @param outLocation an array of two integers in which to hold the coordinates
19260 public void getLocationInWindow(@Size(2) int[] outLocation) {
19261 if (outLocation == null || outLocation.length < 2) {
19262 throw new IllegalArgumentException("outLocation must be an array of two integers");
19265 outLocation[0] = 0;
19266 outLocation[1] = 0;
19268 transformFromViewToWindowSpace(outLocation);
19272 public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
19273 if (inOutLocation == null || inOutLocation.length < 2) {
19274 throw new IllegalArgumentException("inOutLocation must be an array of two integers");
19277 if (mAttachInfo == null) {
19278 // When the view is not attached to a window, this method does not make sense
19279 inOutLocation[0] = inOutLocation[1] = 0;
19283 float position[] = mAttachInfo.mTmpTransformLocation;
19284 position[0] = inOutLocation[0];
19285 position[1] = inOutLocation[1];
19287 if (!hasIdentityMatrix()) {
19288 getMatrix().mapPoints(position);
19291 position[0] += mLeft;
19292 position[1] += mTop;
19294 ViewParent viewParent = mParent;
19295 while (viewParent instanceof View) {
19296 final View view = (View) viewParent;
19298 position[0] -= view.mScrollX;
19299 position[1] -= view.mScrollY;
19301 if (!view.hasIdentityMatrix()) {
19302 view.getMatrix().mapPoints(position);
19305 position[0] += view.mLeft;
19306 position[1] += view.mTop;
19308 viewParent = view.mParent;
19311 if (viewParent instanceof ViewRootImpl) {
19313 final ViewRootImpl vr = (ViewRootImpl) viewParent;
19314 position[1] -= vr.mCurScrollY;
19317 inOutLocation[0] = Math.round(position[0]);
19318 inOutLocation[1] = Math.round(position[1]);
19323 * @param id the id of the view to be found
19324 * @return the view of the specified id, null if cannot be found
19326 protected View findViewTraversal(@IdRes int id) {
19335 * @param tag the tag of the view to be found
19336 * @return the view of specified tag, null if cannot be found
19338 protected View findViewWithTagTraversal(Object tag) {
19339 if (tag != null && tag.equals(mTag)) {
19347 * @param predicate The predicate to evaluate.
19348 * @param childToSkip If not null, ignores this child during the recursive traversal.
19349 * @return The first view that matches the predicate or null.
19351 protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
19352 if (predicate.apply(this)) {
19359 * Look for a child view with the given id. If this view has the given
19360 * id, return this view.
19362 * @param id The id to search for.
19363 * @return The view that has the given id in the hierarchy or null
19366 public final View findViewById(@IdRes int id) {
19370 return findViewTraversal(id);
19374 * Finds a view by its unuque and stable accessibility id.
19376 * @param accessibilityId The searched accessibility id.
19377 * @return The found view.
19379 final View findViewByAccessibilityId(int accessibilityId) {
19380 if (accessibilityId < 0) {
19383 View view = findViewByAccessibilityIdTraversal(accessibilityId);
19384 if (view != null) {
19385 return view.includeForAccessibility() ? view : null;
19391 * Performs the traversal to find a view by its unuque and stable accessibility id.
19393 * <strong>Note:</strong>This method does not stop at the root namespace
19394 * boundary since the user can touch the screen at an arbitrary location
19395 * potentially crossing the root namespace bounday which will send an
19396 * accessibility event to accessibility services and they should be able
19397 * to obtain the event source. Also accessibility ids are guaranteed to be
19398 * unique in the window.
19400 * @param accessibilityId The accessibility id.
19401 * @return The found view.
19405 public View findViewByAccessibilityIdTraversal(int accessibilityId) {
19406 if (getAccessibilityViewId() == accessibilityId) {
19413 * Look for a child view with the given tag. If this view has the given
19414 * tag, return this view.
19416 * @param tag The tag to search for, using "tag.equals(getTag())".
19417 * @return The View that has the given tag in the hierarchy or null
19419 public final View findViewWithTag(Object tag) {
19423 return findViewWithTagTraversal(tag);
19428 * Look for a child view that matches the specified predicate.
19429 * If this view matches the predicate, return this view.
19431 * @param predicate The predicate to evaluate.
19432 * @return The first view that matches the predicate or null.
19434 public final View findViewByPredicate(Predicate<View> predicate) {
19435 return findViewByPredicateTraversal(predicate, null);
19440 * Look for a child view that matches the specified predicate,
19441 * starting with the specified view and its descendents and then
19442 * recusively searching the ancestors and siblings of that view
19443 * until this view is reached.
19445 * This method is useful in cases where the predicate does not match
19446 * a single unique view (perhaps multiple views use the same id)
19447 * and we are trying to find the view that is "closest" in scope to the
19450 * @param start The view to start from.
19451 * @param predicate The predicate to evaluate.
19452 * @return The first view that matches the predicate or null.
19454 public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
19455 View childToSkip = null;
19457 View view = start.findViewByPredicateTraversal(predicate, childToSkip);
19458 if (view != null || start == this) {
19462 ViewParent parent = start.getParent();
19463 if (parent == null || !(parent instanceof View)) {
19467 childToSkip = start;
19468 start = (View) parent;
19473 * Sets the identifier for this view. The identifier does not have to be
19474 * unique in this view's hierarchy. The identifier should be a positive
19479 * @see #findViewById(int)
19481 * @param id a number used to identify the view
19483 * @attr ref android.R.styleable#View_id
19485 public void setId(@IdRes int id) {
19487 if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
19488 mID = generateViewId();
19495 * @param isRoot true if the view belongs to the root namespace, false
19498 public void setIsRootNamespace(boolean isRoot) {
19500 mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
19502 mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
19509 * @return true if the view belongs to the root namespace, false otherwise
19511 public boolean isRootNamespace() {
19512 return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
19516 * Returns this view's identifier.
19518 * @return a positive integer used to identify the view or {@link #NO_ID}
19519 * if the view has no ID
19522 * @see #findViewById(int)
19523 * @attr ref android.R.styleable#View_id
19526 @ViewDebug.CapturedViewProperty
19527 public int getId() {
19532 * Returns this view's tag.
19534 * @return the Object stored in this view as a tag, or {@code null} if not
19537 * @see #setTag(Object)
19538 * @see #getTag(int)
19540 @ViewDebug.ExportedProperty
19541 public Object getTag() {
19546 * Sets the tag associated with this view. A tag can be used to mark
19547 * a view in its hierarchy and does not have to be unique within the
19548 * hierarchy. Tags can also be used to store data within a view without
19549 * resorting to another data structure.
19551 * @param tag an Object to tag the view with
19554 * @see #setTag(int, Object)
19556 public void setTag(final Object tag) {
19561 * Returns the tag associated with this view and the specified key.
19563 * @param key The key identifying the tag
19565 * @return the Object stored in this view as a tag, or {@code null} if not
19568 * @see #setTag(int, Object)
19571 public Object getTag(int key) {
19572 if (mKeyedTags != null) return mKeyedTags.get(key);
19577 * Sets a tag associated with this view and a key. A tag can be used
19578 * to mark a view in its hierarchy and does not have to be unique within
19579 * the hierarchy. Tags can also be used to store data within a view
19580 * without resorting to another data structure.
19582 * The specified key should be an id declared in the resources of the
19583 * application to ensure it is unique (see the <a
19584 * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
19585 * Keys identified as belonging to
19586 * the Android framework or not associated with any package will cause
19587 * an {@link IllegalArgumentException} to be thrown.
19589 * @param key The key identifying the tag
19590 * @param tag An Object to tag the view with
19592 * @throws IllegalArgumentException If they specified key is not valid
19594 * @see #setTag(Object)
19595 * @see #getTag(int)
19597 public void setTag(int key, final Object tag) {
19598 // If the package id is 0x00 or 0x01, it's either an undefined package
19599 // or a framework id
19600 if ((key >>> 24) < 2) {
19601 throw new IllegalArgumentException("The key must be an application-specific "
19605 setKeyedTag(key, tag);
19609 * Variation of {@link #setTag(int, Object)} that enforces the key to be a
19614 public void setTagInternal(int key, Object tag) {
19615 if ((key >>> 24) != 0x1) {
19616 throw new IllegalArgumentException("The key must be a framework-specific "
19620 setKeyedTag(key, tag);
19623 private void setKeyedTag(int key, Object tag) {
19624 if (mKeyedTags == null) {
19625 mKeyedTags = new SparseArray<Object>(2);
19628 mKeyedTags.put(key, tag);
19632 * Prints information about this view in the log output, with the tag
19633 * {@link #VIEW_LOG_TAG}.
19637 public void debug() {
19642 * Prints information about this view in the log output, with the tag
19643 * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
19644 * indentation defined by the <code>depth</code>.
19646 * @param depth the indentation level
19650 protected void debug(int depth) {
19651 String output = debugIndent(depth - 1);
19653 output += "+ " + this;
19656 output += " (id=" + id + ")";
19658 Object tag = getTag();
19660 output += " (tag=" + tag + ")";
19662 Log.d(VIEW_LOG_TAG, output);
19664 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
19665 output = debugIndent(depth) + " FOCUSED";
19666 Log.d(VIEW_LOG_TAG, output);
19669 output = debugIndent(depth);
19670 output += "frame={" + mLeft + ", " + mTop + ", " + mRight
19671 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
19673 Log.d(VIEW_LOG_TAG, output);
19675 if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
19676 || mPaddingBottom != 0) {
19677 output = debugIndent(depth);
19678 output += "padding={" + mPaddingLeft + ", " + mPaddingTop
19679 + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
19680 Log.d(VIEW_LOG_TAG, output);
19683 output = debugIndent(depth);
19684 output += "mMeasureWidth=" + mMeasuredWidth +
19685 " mMeasureHeight=" + mMeasuredHeight;
19686 Log.d(VIEW_LOG_TAG, output);
19688 output = debugIndent(depth);
19689 if (mLayoutParams == null) {
19690 output += "BAD! no layout params";
19692 output = mLayoutParams.debug(output);
19694 Log.d(VIEW_LOG_TAG, output);
19696 output = debugIndent(depth);
19697 output += "flags={";
19698 output += View.printFlags(mViewFlags);
19700 Log.d(VIEW_LOG_TAG, output);
19702 output = debugIndent(depth);
19703 output += "privateFlags={";
19704 output += View.printPrivateFlags(mPrivateFlags);
19706 Log.d(VIEW_LOG_TAG, output);
19710 * Creates a string of whitespaces used for indentation.
19712 * @param depth the indentation level
19713 * @return a String containing (depth * 2 + 3) * 2 white spaces
19717 protected static String debugIndent(int depth) {
19718 StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
19719 for (int i = 0; i < (depth * 2) + 3; i++) {
19720 spaces.append(' ').append(' ');
19722 return spaces.toString();
19726 * <p>Return the offset of the widget's text baseline from the widget's top
19727 * boundary. If this widget does not support baseline alignment, this
19728 * method returns -1. </p>
19730 * @return the offset of the baseline within the widget's bounds or -1
19731 * if baseline alignment is not supported
19733 @ViewDebug.ExportedProperty(category = "layout")
19734 public int getBaseline() {
19739 * Returns whether the view hierarchy is currently undergoing a layout pass. This
19740 * information is useful to avoid situations such as calling {@link #requestLayout()} during
19743 * @return whether the view hierarchy is currently undergoing a layout pass
19745 public boolean isInLayout() {
19746 ViewRootImpl viewRoot = getViewRootImpl();
19747 return (viewRoot != null && viewRoot.isInLayout());
19751 * Call this when something has changed which has invalidated the
19752 * layout of this view. This will schedule a layout pass of the view
19753 * tree. This should not be called while the view hierarchy is currently in a layout
19754 * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
19755 * end of the current layout pass (and then layout will run again) or after the current
19756 * frame is drawn and the next layout occurs.
19758 * <p>Subclasses which override this method should call the superclass method to
19759 * handle possible request-during-layout errors correctly.</p>
19762 public void requestLayout() {
19763 if (mMeasureCache != null) mMeasureCache.clear();
19765 if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
19766 // Only trigger request-during-layout logic if this is the view requesting it,
19767 // not the views in its parent hierarchy
19768 ViewRootImpl viewRoot = getViewRootImpl();
19769 if (viewRoot != null && viewRoot.isInLayout()) {
19770 if (!viewRoot.requestLayoutDuringLayout(this)) {
19774 mAttachInfo.mViewRequestingLayout = this;
19777 mPrivateFlags |= PFLAG_FORCE_LAYOUT;
19778 mPrivateFlags |= PFLAG_INVALIDATED;
19780 if (mParent != null && !mParent.isLayoutRequested()) {
19781 mParent.requestLayout();
19783 if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
19784 mAttachInfo.mViewRequestingLayout = null;
19789 * Forces this view to be laid out during the next layout pass.
19790 * This method does not call requestLayout() or forceLayout()
19793 public void forceLayout() {
19794 if (mMeasureCache != null) mMeasureCache.clear();
19796 mPrivateFlags |= PFLAG_FORCE_LAYOUT;
19797 mPrivateFlags |= PFLAG_INVALIDATED;
19802 * This is called to find out how big a view should be. The parent
19803 * supplies constraint information in the width and height parameters.
19807 * The actual measurement work of a view is performed in
19808 * {@link #onMeasure(int, int)}, called by this method. Therefore, only
19809 * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
19813 * @param widthMeasureSpec Horizontal space requirements as imposed by the
19815 * @param heightMeasureSpec Vertical space requirements as imposed by the
19818 * @see #onMeasure(int, int)
19820 public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
19821 boolean optical = isLayoutModeOptical(this);
19822 if (optical != isLayoutModeOptical(mParent)) {
19823 Insets insets = getOpticalInsets();
19824 int oWidth = insets.left + insets.right;
19825 int oHeight = insets.top + insets.bottom;
19826 widthMeasureSpec = MeasureSpec.adjust(widthMeasureSpec, optical ? -oWidth : oWidth);
19827 heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
19830 // Suppress sign extension for the low bytes
19831 long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
19832 if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
19834 final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19836 // Optimize layout by avoiding an extra EXACTLY pass when the view is
19837 // already measured as the correct size. In API 23 and below, this
19838 // extra pass is required to make LinearLayout re-distribute weight.
19839 final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
19840 || heightMeasureSpec != mOldHeightMeasureSpec;
19841 final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
19842 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
19843 final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
19844 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
19845 final boolean needsLayout = specChanged
19846 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
19848 if (forceLayout || needsLayout) {
19849 // first clears the measured dimension flag
19850 mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
19852 resolveRtlPropertiesIfNeeded();
19854 int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
19855 if (cacheIndex < 0 || sIgnoreMeasureCache) {
19856 // measure ourselves, this should set the measured dimension flag back
19857 onMeasure(widthMeasureSpec, heightMeasureSpec);
19858 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19860 long value = mMeasureCache.valueAt(cacheIndex);
19861 // Casting a long to int drops the high 32 bits, no mask needed
19862 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
19863 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19866 // flag not set, setMeasuredDimension() was not invoked, we raise
19867 // an exception to warn the developer
19868 if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
19869 throw new IllegalStateException("View with id " + getId() + ": "
19870 + getClass().getName() + "#onMeasure() did not set the"
19871 + " measured dimension by calling"
19872 + " setMeasuredDimension()");
19875 mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
19878 mOldWidthMeasureSpec = widthMeasureSpec;
19879 mOldHeightMeasureSpec = heightMeasureSpec;
19881 mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
19882 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
19887 * Measure the view and its content to determine the measured width and the
19888 * measured height. This method is invoked by {@link #measure(int, int)} and
19889 * should be overridden by subclasses to provide accurate and efficient
19890 * measurement of their contents.
19894 * <strong>CONTRACT:</strong> When overriding this method, you
19895 * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
19896 * measured width and height of this view. Failure to do so will trigger an
19897 * <code>IllegalStateException</code>, thrown by
19898 * {@link #measure(int, int)}. Calling the superclass'
19899 * {@link #onMeasure(int, int)} is a valid use.
19903 * The base class implementation of measure defaults to the background size,
19904 * unless a larger size is allowed by the MeasureSpec. Subclasses should
19905 * override {@link #onMeasure(int, int)} to provide better measurements of
19910 * If this method is overridden, it is the subclass's responsibility to make
19911 * sure the measured height and width are at least the view's minimum height
19912 * and width ({@link #getSuggestedMinimumHeight()} and
19913 * {@link #getSuggestedMinimumWidth()}).
19916 * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
19917 * The requirements are encoded with
19918 * {@link android.view.View.MeasureSpec}.
19919 * @param heightMeasureSpec vertical space requirements as imposed by the parent.
19920 * The requirements are encoded with
19921 * {@link android.view.View.MeasureSpec}.
19923 * @see #getMeasuredWidth()
19924 * @see #getMeasuredHeight()
19925 * @see #setMeasuredDimension(int, int)
19926 * @see #getSuggestedMinimumHeight()
19927 * @see #getSuggestedMinimumWidth()
19928 * @see android.view.View.MeasureSpec#getMode(int)
19929 * @see android.view.View.MeasureSpec#getSize(int)
19931 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
19932 setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
19933 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
19937 * <p>This method must be called by {@link #onMeasure(int, int)} to store the
19938 * measured width and measured height. Failing to do so will trigger an
19939 * exception at measurement time.</p>
19941 * @param measuredWidth The measured width of this view. May be a complex
19942 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19943 * {@link #MEASURED_STATE_TOO_SMALL}.
19944 * @param measuredHeight The measured height of this view. May be a complex
19945 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19946 * {@link #MEASURED_STATE_TOO_SMALL}.
19948 protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
19949 boolean optical = isLayoutModeOptical(this);
19950 if (optical != isLayoutModeOptical(mParent)) {
19951 Insets insets = getOpticalInsets();
19952 int opticalWidth = insets.left + insets.right;
19953 int opticalHeight = insets.top + insets.bottom;
19955 measuredWidth += optical ? opticalWidth : -opticalWidth;
19956 measuredHeight += optical ? opticalHeight : -opticalHeight;
19958 setMeasuredDimensionRaw(measuredWidth, measuredHeight);
19962 * Sets the measured dimension without extra processing for things like optical bounds.
19963 * Useful for reapplying consistent values that have already been cooked with adjustments
19964 * for optical bounds, etc. such as those from the measurement cache.
19966 * @param measuredWidth The measured width of this view. May be a complex
19967 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19968 * {@link #MEASURED_STATE_TOO_SMALL}.
19969 * @param measuredHeight The measured height of this view. May be a complex
19970 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19971 * {@link #MEASURED_STATE_TOO_SMALL}.
19973 private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
19974 mMeasuredWidth = measuredWidth;
19975 mMeasuredHeight = measuredHeight;
19977 mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
19981 * Merge two states as returned by {@link #getMeasuredState()}.
19982 * @param curState The current state as returned from a view or the result
19983 * of combining multiple views.
19984 * @param newState The new view state to combine.
19985 * @return Returns a new integer reflecting the combination of the two
19988 public static int combineMeasuredStates(int curState, int newState) {
19989 return curState | newState;
19993 * Version of {@link #resolveSizeAndState(int, int, int)}
19994 * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
19996 public static int resolveSize(int size, int measureSpec) {
19997 return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
20001 * Utility to reconcile a desired size and state, with constraints imposed
20002 * by a MeasureSpec. Will take the desired size, unless a different size
20003 * is imposed by the constraints. The returned value is a compound integer,
20004 * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
20005 * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
20006 * resulting size is smaller than the size the view wants to be.
20008 * @param size How big the view wants to be.
20009 * @param measureSpec Constraints imposed by the parent.
20010 * @param childMeasuredState Size information bit mask for the view's
20012 * @return Size information bit mask as defined by
20013 * {@link #MEASURED_SIZE_MASK} and
20014 * {@link #MEASURED_STATE_TOO_SMALL}.
20016 public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
20017 final int specMode = MeasureSpec.getMode(measureSpec);
20018 final int specSize = MeasureSpec.getSize(measureSpec);
20020 switch (specMode) {
20021 case MeasureSpec.AT_MOST:
20022 if (specSize < size) {
20023 result = specSize | MEASURED_STATE_TOO_SMALL;
20028 case MeasureSpec.EXACTLY:
20031 case MeasureSpec.UNSPECIFIED:
20035 return result | (childMeasuredState & MEASURED_STATE_MASK);
20039 * Utility to return a default size. Uses the supplied size if the
20040 * MeasureSpec imposed no constraints. Will get larger if allowed
20041 * by the MeasureSpec.
20043 * @param size Default size for this view
20044 * @param measureSpec Constraints imposed by the parent
20045 * @return The size this view should be.
20047 public static int getDefaultSize(int size, int measureSpec) {
20049 int specMode = MeasureSpec.getMode(measureSpec);
20050 int specSize = MeasureSpec.getSize(measureSpec);
20052 switch (specMode) {
20053 case MeasureSpec.UNSPECIFIED:
20056 case MeasureSpec.AT_MOST:
20057 case MeasureSpec.EXACTLY:
20065 * Returns the suggested minimum height that the view should use. This
20066 * returns the maximum of the view's minimum height
20067 * and the background's minimum height
20068 * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
20070 * When being used in {@link #onMeasure(int, int)}, the caller should still
20071 * ensure the returned height is within the requirements of the parent.
20073 * @return The suggested minimum height of the view.
20075 protected int getSuggestedMinimumHeight() {
20076 return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
20081 * Returns the suggested minimum width that the view should use. This
20082 * returns the maximum of the view's minimum width
20083 * and the background's minimum width
20084 * ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
20086 * When being used in {@link #onMeasure(int, int)}, the caller should still
20087 * ensure the returned width is within the requirements of the parent.
20089 * @return The suggested minimum width of the view.
20091 protected int getSuggestedMinimumWidth() {
20092 return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
20096 * Returns the minimum height of the view.
20098 * @return the minimum height the view will try to be.
20100 * @see #setMinimumHeight(int)
20102 * @attr ref android.R.styleable#View_minHeight
20104 public int getMinimumHeight() {
20109 * Sets the minimum height of the view. It is not guaranteed the view will
20110 * be able to achieve this minimum height (for example, if its parent layout
20111 * constrains it with less available height).
20113 * @param minHeight The minimum height the view will try to be.
20115 * @see #getMinimumHeight()
20117 * @attr ref android.R.styleable#View_minHeight
20119 @RemotableViewMethod
20120 public void setMinimumHeight(int minHeight) {
20121 mMinHeight = minHeight;
20126 * Returns the minimum width of the view.
20128 * @return the minimum width the view will try to be.
20130 * @see #setMinimumWidth(int)
20132 * @attr ref android.R.styleable#View_minWidth
20134 public int getMinimumWidth() {
20139 * Sets the minimum width of the view. It is not guaranteed the view will
20140 * be able to achieve this minimum width (for example, if its parent layout
20141 * constrains it with less available width).
20143 * @param minWidth The minimum width the view will try to be.
20145 * @see #getMinimumWidth()
20147 * @attr ref android.R.styleable#View_minWidth
20149 public void setMinimumWidth(int minWidth) {
20150 mMinWidth = minWidth;
20156 * Get the animation currently associated with this view.
20158 * @return The animation that is currently playing or
20159 * scheduled to play for this view.
20161 public Animation getAnimation() {
20162 return mCurrentAnimation;
20166 * Start the specified animation now.
20168 * @param animation the animation to start now
20170 public void startAnimation(Animation animation) {
20171 animation.setStartTime(Animation.START_ON_FIRST_FRAME);
20172 setAnimation(animation);
20173 invalidateParentCaches();
20178 * Cancels any animations for this view.
20180 public void clearAnimation() {
20181 if (mCurrentAnimation != null) {
20182 mCurrentAnimation.detach();
20184 mCurrentAnimation = null;
20185 invalidateParentIfNeeded();
20189 * Sets the next animation to play for this view.
20190 * If you want the animation to play immediately, use
20191 * {@link #startAnimation(android.view.animation.Animation)} instead.
20192 * This method provides allows fine-grained
20193 * control over the start time and invalidation, but you
20194 * must make sure that 1) the animation has a start time set, and
20195 * 2) the view's parent (which controls animations on its children)
20196 * will be invalidated when the animation is supposed to
20199 * @param animation The next animation, or null.
20201 public void setAnimation(Animation animation) {
20202 mCurrentAnimation = animation;
20204 if (animation != null) {
20205 // If the screen is off assume the animation start time is now instead of
20206 // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
20207 // would cause the animation to start when the screen turns back on
20208 if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
20209 && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
20210 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
20217 * Invoked by a parent ViewGroup to notify the start of the animation
20218 * currently associated with this view. If you override this method,
20219 * always call super.onAnimationStart();
20221 * @see #setAnimation(android.view.animation.Animation)
20222 * @see #getAnimation()
20225 protected void onAnimationStart() {
20226 mPrivateFlags |= PFLAG_ANIMATION_STARTED;
20230 * Invoked by a parent ViewGroup to notify the end of the animation
20231 * currently associated with this view. If you override this method,
20232 * always call super.onAnimationEnd();
20234 * @see #setAnimation(android.view.animation.Animation)
20235 * @see #getAnimation()
20238 protected void onAnimationEnd() {
20239 mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
20243 * Invoked if there is a Transform that involves alpha. Subclass that can
20244 * draw themselves with the specified alpha should return true, and then
20245 * respect that alpha when their onDraw() is called. If this returns false
20246 * then the view may be redirected to draw into an offscreen buffer to
20247 * fulfill the request, which will look fine, but may be slower than if the
20248 * subclass handles it internally. The default implementation returns false.
20250 * @param alpha The alpha (0..255) to apply to the view's drawing
20251 * @return true if the view can draw with the specified alpha.
20253 protected boolean onSetAlpha(int alpha) {
20258 * This is used by the RootView to perform an optimization when
20259 * the view hierarchy contains one or several SurfaceView.
20260 * SurfaceView is always considered transparent, but its children are not,
20261 * therefore all View objects remove themselves from the global transparent
20262 * region (passed as a parameter to this function).
20264 * @param region The transparent region for this ViewAncestor (window).
20266 * @return Returns true if the effective visibility of the view at this
20267 * point is opaque, regardless of the transparent region; returns false
20268 * if it is possible for underlying windows to be seen behind the view.
20272 public boolean gatherTransparentRegion(Region region) {
20273 final AttachInfo attachInfo = mAttachInfo;
20274 if (region != null && attachInfo != null) {
20275 final int pflags = mPrivateFlags;
20276 if ((pflags & PFLAG_SKIP_DRAW) == 0) {
20277 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
20278 // remove it from the transparent region.
20279 final int[] location = attachInfo.mTransparentLocation;
20280 getLocationInWindow(location);
20281 // When a view has Z value, then it will be better to leave some area below the view
20282 // for drawing shadow. The shadow outset is proportional to the Z value. Note that
20283 // the bottom part needs more offset than the left, top and right parts due to the
20284 // spot light effects.
20285 int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
20286 region.op(location[0] - shadowOffset, location[1] - shadowOffset,
20287 location[0] + mRight - mLeft + shadowOffset,
20288 location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
20290 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
20291 // The SKIP_DRAW flag IS set and the background drawable exists, we remove
20292 // the background drawable's non-transparent parts from this transparent region.
20293 applyDrawableToTransparentRegion(mBackground, region);
20295 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20296 && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
20297 // Similarly, we remove the foreground drawable's non-transparent parts.
20298 applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
20306 * Play a sound effect for this view.
20308 * <p>The framework will play sound effects for some built in actions, such as
20309 * clicking, but you may wish to play these effects in your widget,
20310 * for instance, for internal navigation.
20312 * <p>The sound effect will only be played if sound effects are enabled by the user, and
20313 * {@link #isSoundEffectsEnabled()} is true.
20315 * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
20317 public void playSoundEffect(int soundConstant) {
20318 if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
20321 mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
20327 * <p>Provide haptic feedback to the user for this view.
20329 * <p>The framework will provide haptic feedback for some built in actions,
20330 * such as long presses, but you may wish to provide feedback for your
20333 * <p>The feedback will only be performed if
20334 * {@link #isHapticFeedbackEnabled()} is true.
20336 * @param feedbackConstant One of the constants defined in
20337 * {@link HapticFeedbackConstants}
20339 public boolean performHapticFeedback(int feedbackConstant) {
20340 return performHapticFeedback(feedbackConstant, 0);
20346 * <p>Like {@link #performHapticFeedback(int)}, with additional options.
20348 * @param feedbackConstant One of the constants defined in
20349 * {@link HapticFeedbackConstants}
20350 * @param flags Additional flags as per {@link HapticFeedbackConstants}.
20352 public boolean performHapticFeedback(int feedbackConstant, int flags) {
20353 if (mAttachInfo == null) {
20356 //noinspection SimplifiableIfStatement
20357 if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
20358 && !isHapticFeedbackEnabled()) {
20361 return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
20362 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
20366 * Request that the visibility of the status bar or other screen/window
20367 * decorations be changed.
20369 * <p>This method is used to put the over device UI into temporary modes
20370 * where the user's attention is focused more on the application content,
20371 * by dimming or hiding surrounding system affordances. This is typically
20372 * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
20373 * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
20374 * to be placed behind the action bar (and with these flags other system
20375 * affordances) so that smooth transitions between hiding and showing them
20378 * <p>Two representative examples of the use of system UI visibility is
20379 * implementing a content browsing application (like a magazine reader)
20380 * and a video playing application.
20382 * <p>The first code shows a typical implementation of a View in a content
20383 * browsing application. In this implementation, the application goes
20384 * into a content-oriented mode by hiding the status bar and action bar,
20385 * and putting the navigation elements into lights out mode. The user can
20386 * then interact with content while in this mode. Such an application should
20387 * provide an easy way for the user to toggle out of the mode (such as to
20388 * check information in the status bar or access notifications). In the
20389 * implementation here, this is done simply by tapping on the content.
20391 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
20394 * <p>This second code sample shows a typical implementation of a View
20395 * in a video playing application. In this situation, while the video is
20396 * playing the application would like to go into a complete full-screen mode,
20397 * to use as much of the display as possible for the video. When in this state
20398 * the user can not interact with the application; the system intercepts
20399 * touching on the screen to pop the UI out of full screen mode. See
20400 * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
20402 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
20405 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20406 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
20407 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
20408 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
20409 * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
20411 public void setSystemUiVisibility(int visibility) {
20412 if (visibility != mSystemUiVisibility) {
20413 mSystemUiVisibility = visibility;
20414 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
20415 mParent.recomputeViewAttributes(this);
20421 * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
20422 * @return Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20423 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
20424 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
20425 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
20426 * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
20428 public int getSystemUiVisibility() {
20429 return mSystemUiVisibility;
20433 * Returns the current system UI visibility that is currently set for
20434 * the entire window. This is the combination of the
20435 * {@link #setSystemUiVisibility(int)} values supplied by all of the
20436 * views in the window.
20438 public int getWindowSystemUiVisibility() {
20439 return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
20443 * Override to find out when the window's requested system UI visibility
20444 * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
20445 * This is different from the callbacks received through
20446 * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
20447 * in that this is only telling you about the local request of the window,
20448 * not the actual values applied by the system.
20450 public void onWindowSystemUiVisibilityChanged(int visible) {
20454 * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
20455 * the view hierarchy.
20457 public void dispatchWindowSystemUiVisiblityChanged(int visible) {
20458 onWindowSystemUiVisibilityChanged(visible);
20462 * Set a listener to receive callbacks when the visibility of the system bar changes.
20463 * @param l The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
20465 public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
20466 getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
20467 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
20468 mParent.recomputeViewAttributes(this);
20473 * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
20474 * the view hierarchy.
20476 public void dispatchSystemUiVisibilityChanged(int visibility) {
20477 ListenerInfo li = mListenerInfo;
20478 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
20479 li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
20480 visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
20484 boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
20485 int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
20486 if (val != mSystemUiVisibility) {
20487 setSystemUiVisibility(val);
20494 public void setDisabledSystemUiVisibility(int flags) {
20495 if (mAttachInfo != null) {
20496 if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
20497 mAttachInfo.mDisabledSystemUiVisibility = flags;
20498 if (mParent != null) {
20499 mParent.recomputeViewAttributes(this);
20506 * Creates an image that the system displays during the drag and drop
20507 * operation. This is called a "drag shadow". The default implementation
20508 * for a DragShadowBuilder based on a View returns an image that has exactly the same
20509 * appearance as the given View. The default also positions the center of the drag shadow
20510 * directly under the touch point. If no View is provided (the constructor with no parameters
20511 * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
20512 * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
20513 * default is an invisible drag shadow.
20515 * You are not required to use the View you provide to the constructor as the basis of the
20516 * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
20517 * anything you want as the drag shadow.
20520 * You pass a DragShadowBuilder object to the system when you start the drag. The system
20521 * calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
20522 * size and position of the drag shadow. It uses this data to construct a
20523 * {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
20524 * so that your application can draw the shadow image in the Canvas.
20527 * <div class="special reference">
20528 * <h3>Developer Guides</h3>
20529 * <p>For a guide to implementing drag and drop features, read the
20530 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
20533 public static class DragShadowBuilder {
20534 private final WeakReference<View> mView;
20537 * Constructs a shadow image builder based on a View. By default, the resulting drag
20538 * shadow will have the same appearance and dimensions as the View, with the touch point
20539 * over the center of the View.
20540 * @param view A View. Any View in scope can be used.
20542 public DragShadowBuilder(View view) {
20543 mView = new WeakReference<View>(view);
20547 * Construct a shadow builder object with no associated View. This
20548 * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
20549 * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
20550 * to supply the drag shadow's dimensions and appearance without
20551 * reference to any View object. If they are not overridden, then the result is an
20552 * invisible drag shadow.
20554 public DragShadowBuilder() {
20555 mView = new WeakReference<View>(null);
20559 * Returns the View object that had been passed to the
20560 * {@link #View.DragShadowBuilder(View)}
20561 * constructor. If that View parameter was {@code null} or if the
20562 * {@link #View.DragShadowBuilder()}
20563 * constructor was used to instantiate the builder object, this method will return
20566 * @return The View object associate with this builder object.
20568 @SuppressWarnings({"JavadocReference"})
20569 final public View getView() {
20570 return mView.get();
20574 * Provides the metrics for the shadow image. These include the dimensions of
20575 * the shadow image, and the point within that shadow that should
20576 * be centered under the touch location while dragging.
20578 * The default implementation sets the dimensions of the shadow to be the
20579 * same as the dimensions of the View itself and centers the shadow under
20583 * @param outShadowSize A {@link android.graphics.Point} containing the width and height
20584 * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
20585 * desired width and must set {@link android.graphics.Point#y} to the desired height of the
20588 * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
20589 * shadow image that should be underneath the touch point during the drag and drop
20590 * operation. Your application must set {@link android.graphics.Point#x} to the
20591 * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
20593 public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
20594 final View view = mView.get();
20595 if (view != null) {
20596 outShadowSize.set(view.getWidth(), view.getHeight());
20597 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
20599 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
20604 * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
20605 * based on the dimensions it received from the
20606 * {@link #onProvideShadowMetrics(Point, Point)} callback.
20608 * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
20610 public void onDrawShadow(Canvas canvas) {
20611 final View view = mView.get();
20612 if (view != null) {
20615 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
20621 * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
20622 * startDragAndDrop()} for newer platform versions.
20624 public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
20625 Object myLocalState, int flags) {
20626 return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
20630 * Starts a drag and drop operation. When your application calls this method, it passes a
20631 * {@link android.view.View.DragShadowBuilder} object to the system. The
20632 * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
20633 * to get metrics for the drag shadow, and then calls the object's
20634 * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
20636 * Once the system has the drag shadow, it begins the drag and drop operation by sending
20637 * drag events to all the View objects in your application that are currently visible. It does
20638 * this either by calling the View object's drag listener (an implementation of
20639 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
20640 * View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
20641 * Both are passed a {@link android.view.DragEvent} object that has a
20642 * {@link android.view.DragEvent#getAction()} value of
20643 * {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
20646 * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
20647 * int) startDragAndDrop()} on any attached View object. The View object does not need to be
20648 * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
20649 * to the View the user selected for dragging.
20651 * @param data A {@link android.content.ClipData} object pointing to the data to be
20652 * transferred by the drag and drop operation.
20653 * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
20655 * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
20656 * drop operation. When dispatching drag events to views in the same activity this object
20657 * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
20658 * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
20659 * will return null).
20661 * myLocalState is a lightweight mechanism for the sending information from the dragged View
20662 * to the target Views. For example, it can contain flags that differentiate between a
20663 * a copy operation and a move operation.
20665 * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
20666 * flags, or any combination of the following:
20668 * <li>{@link #DRAG_FLAG_GLOBAL}</li>
20669 * <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
20670 * <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
20671 * <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
20672 * <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
20673 * <li>{@link #DRAG_FLAG_OPAQUE}</li>
20675 * @return {@code true} if the method completes successfully, or
20676 * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
20677 * do a drag, and so no drag operation is in progress.
20679 public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
20680 Object myLocalState, int flags) {
20681 if (ViewDebug.DEBUG_DRAG) {
20682 Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
20684 if (mAttachInfo == null) {
20685 Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
20688 boolean okay = false;
20690 Point shadowSize = new Point();
20691 Point shadowTouchPoint = new Point();
20692 shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
20694 if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
20695 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
20696 throw new IllegalStateException("Drag shadow dimensions must not be negative");
20699 if (ViewDebug.DEBUG_DRAG) {
20700 Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
20701 + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
20703 if (mAttachInfo.mDragSurface != null) {
20704 mAttachInfo.mDragSurface.release();
20706 mAttachInfo.mDragSurface = new Surface();
20708 mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
20709 flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
20710 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
20711 + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
20712 if (mAttachInfo.mDragToken != null) {
20713 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
20715 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
20716 shadowBuilder.onDrawShadow(canvas);
20718 mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
20721 final ViewRootImpl root = getViewRootImpl();
20723 // Cache the local state object for delivery with DragEvents
20724 root.setLocalDragState(myLocalState);
20726 // repurpose 'shadowSize' for the last touch point
20727 root.getLastTouchPoint(shadowSize);
20729 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
20730 root.getLastTouchSource(), shadowSize.x, shadowSize.y,
20731 shadowTouchPoint.x, shadowTouchPoint.y, data);
20732 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
20734 } catch (Exception e) {
20735 Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
20736 mAttachInfo.mDragSurface.destroy();
20737 mAttachInfo.mDragSurface = null;
20744 * Cancels an ongoing drag and drop operation.
20746 * A {@link android.view.DragEvent} object with
20747 * {@link android.view.DragEvent#getAction()} value of
20748 * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
20749 * {@link android.view.DragEvent#getResult()} value of {@code false}
20750 * will be sent to every
20751 * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
20752 * even if they are not currently visible.
20755 * This method can be called on any View in the same window as the View on which
20756 * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
20760 public final void cancelDragAndDrop() {
20761 if (ViewDebug.DEBUG_DRAG) {
20762 Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
20764 if (mAttachInfo == null) {
20765 Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
20768 if (mAttachInfo.mDragToken != null) {
20770 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
20771 } catch (Exception e) {
20772 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
20774 mAttachInfo.mDragToken = null;
20776 Log.e(VIEW_LOG_TAG, "No active drag to cancel");
20781 * Updates the drag shadow for the ongoing drag and drop operation.
20783 * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
20786 public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
20787 if (ViewDebug.DEBUG_DRAG) {
20788 Log.d(VIEW_LOG_TAG, "updateDragShadow");
20790 if (mAttachInfo == null) {
20791 Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
20794 if (mAttachInfo.mDragToken != null) {
20796 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
20798 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
20799 shadowBuilder.onDrawShadow(canvas);
20801 mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
20803 } catch (Exception e) {
20804 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
20807 Log.e(VIEW_LOG_TAG, "No active drag");
20812 * Starts a move from {startX, startY}, the amount of the movement will be the offset
20813 * between {startX, startY} and the new cursor positon.
20814 * @param startX horizontal coordinate where the move started.
20815 * @param startY vertical coordinate where the move started.
20816 * @return whether moving was started successfully.
20819 public final boolean startMovingTask(float startX, float startY) {
20820 if (ViewDebug.DEBUG_POSITIONING) {
20821 Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
20824 return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
20825 } catch (RemoteException e) {
20826 Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
20832 * Handles drag events sent by the system following a call to
20833 * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
20834 * startDragAndDrop()}.
20836 * When the system calls this method, it passes a
20837 * {@link android.view.DragEvent} object. A call to
20838 * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
20839 * in DragEvent. The method uses these to determine what is happening in the drag and drop
20841 * @param event The {@link android.view.DragEvent} sent by the system.
20842 * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
20843 * in DragEvent, indicating the type of drag event represented by this object.
20844 * @return {@code true} if the method was successful, otherwise {@code false}.
20846 * The method should return {@code true} in response to an action type of
20847 * {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
20851 * The method should also return {@code true} in response to an action type of
20852 * {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
20853 * {@code false} if it didn't.
20856 public boolean onDragEvent(DragEvent event) {
20860 // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
20861 boolean dispatchDragEnterExitInPreN(DragEvent event) {
20862 return callDragEventHandler(event);
20866 * Detects if this View is enabled and has a drag event listener.
20867 * If both are true, then it calls the drag event listener with the
20868 * {@link android.view.DragEvent} it received. If the drag event listener returns
20869 * {@code true}, then dispatchDragEvent() returns {@code true}.
20871 * For all other cases, the method calls the
20872 * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
20873 * method and returns its result.
20876 * This ensures that a drag event is always consumed, even if the View does not have a drag
20877 * event listener. However, if the View has a listener and the listener returns true, then
20878 * onDragEvent() is not called.
20881 public boolean dispatchDragEvent(DragEvent event) {
20882 event.mEventHandlerWasCalled = true;
20883 if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
20884 event.mAction == DragEvent.ACTION_DROP) {
20885 // About to deliver an event with coordinates to this view. Notify that now this view
20886 // has drag focus. This will send exit/enter events as needed.
20887 getViewRootImpl().setDragFocus(this, event);
20889 return callDragEventHandler(event);
20892 final boolean callDragEventHandler(DragEvent event) {
20893 final boolean result;
20895 ListenerInfo li = mListenerInfo;
20896 //noinspection SimplifiableIfStatement
20897 if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
20898 && li.mOnDragListener.onDrag(this, event)) {
20901 result = onDragEvent(event);
20904 switch (event.mAction) {
20905 case DragEvent.ACTION_DRAG_ENTERED: {
20906 mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
20907 refreshDrawableState();
20909 case DragEvent.ACTION_DRAG_EXITED: {
20910 mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
20911 refreshDrawableState();
20913 case DragEvent.ACTION_DRAG_ENDED: {
20914 mPrivateFlags2 &= ~View.DRAG_MASK;
20915 refreshDrawableState();
20922 boolean canAcceptDrag() {
20923 return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
20927 * This needs to be a better API (NOT ON VIEW) before it is exposed. If
20928 * it is ever exposed at all.
20931 public void onCloseSystemDialogs(String reason) {
20935 * Given a Drawable whose bounds have been set to draw into this view,
20936 * update a Region being computed for
20937 * {@link #gatherTransparentRegion(android.graphics.Region)} so
20938 * that any non-transparent parts of the Drawable are removed from the
20939 * given transparent region.
20941 * @param dr The Drawable whose transparency is to be applied to the region.
20942 * @param region A Region holding the current transparency information,
20943 * where any parts of the region that are set are considered to be
20944 * transparent. On return, this region will be modified to have the
20945 * transparency information reduced by the corresponding parts of the
20946 * Drawable that are not transparent.
20949 public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
20951 Log.i("View", "Getting transparent region for: " + this);
20953 final Region r = dr.getTransparentRegion();
20954 final Rect db = dr.getBounds();
20955 final AttachInfo attachInfo = mAttachInfo;
20956 if (r != null && attachInfo != null) {
20957 final int w = getRight()-getLeft();
20958 final int h = getBottom()-getTop();
20960 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
20961 r.op(0, 0, db.left, h, Region.Op.UNION);
20963 if (db.right < w) {
20964 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
20965 r.op(db.right, 0, w, h, Region.Op.UNION);
20968 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
20969 r.op(0, 0, w, db.top, Region.Op.UNION);
20971 if (db.bottom < h) {
20972 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
20973 r.op(0, db.bottom, w, h, Region.Op.UNION);
20975 final int[] location = attachInfo.mTransparentLocation;
20976 getLocationInWindow(location);
20977 r.translate(location[0], location[1]);
20978 region.op(r, Region.Op.INTERSECT);
20980 region.op(db, Region.Op.DIFFERENCE);
20984 private void checkForLongClick(int delayOffset, float x, float y) {
20985 if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
20986 mHasPerformedLongPress = false;
20988 if (mPendingCheckForLongPress == null) {
20989 mPendingCheckForLongPress = new CheckForLongPress();
20991 mPendingCheckForLongPress.setAnchor(x, y);
20992 mPendingCheckForLongPress.rememberWindowAttachCount();
20993 postDelayed(mPendingCheckForLongPress,
20994 ViewConfiguration.getLongPressTimeout() - delayOffset);
20999 * Inflate a view from an XML resource. This convenience method wraps the {@link
21000 * LayoutInflater} class, which provides a full range of options for view inflation.
21002 * @param context The Context object for your activity or application.
21003 * @param resource The resource ID to inflate
21004 * @param root A view group that will be the parent. Used to properly inflate the
21005 * layout_* parameters.
21006 * @see LayoutInflater
21008 public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
21009 LayoutInflater factory = LayoutInflater.from(context);
21010 return factory.inflate(resource, root);
21014 * Scroll the view with standard behavior for scrolling beyond the normal
21015 * content boundaries. Views that call this method should override
21016 * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
21017 * results of an over-scroll operation.
21019 * Views can use this method to handle any touch or fling-based scrolling.
21021 * @param deltaX Change in X in pixels
21022 * @param deltaY Change in Y in pixels
21023 * @param scrollX Current X scroll value in pixels before applying deltaX
21024 * @param scrollY Current Y scroll value in pixels before applying deltaY
21025 * @param scrollRangeX Maximum content scroll range along the X axis
21026 * @param scrollRangeY Maximum content scroll range along the Y axis
21027 * @param maxOverScrollX Number of pixels to overscroll by in either direction
21028 * along the X axis.
21029 * @param maxOverScrollY Number of pixels to overscroll by in either direction
21030 * along the Y axis.
21031 * @param isTouchEvent true if this scroll operation is the result of a touch event.
21032 * @return true if scrolling was clamped to an over-scroll boundary along either
21033 * axis, false otherwise.
21035 @SuppressWarnings({"UnusedParameters"})
21036 protected boolean overScrollBy(int deltaX, int deltaY,
21037 int scrollX, int scrollY,
21038 int scrollRangeX, int scrollRangeY,
21039 int maxOverScrollX, int maxOverScrollY,
21040 boolean isTouchEvent) {
21041 final int overScrollMode = mOverScrollMode;
21042 final boolean canScrollHorizontal =
21043 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
21044 final boolean canScrollVertical =
21045 computeVerticalScrollRange() > computeVerticalScrollExtent();
21046 final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
21047 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
21048 final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
21049 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
21051 int newScrollX = scrollX + deltaX;
21052 if (!overScrollHorizontal) {
21053 maxOverScrollX = 0;
21056 int newScrollY = scrollY + deltaY;
21057 if (!overScrollVertical) {
21058 maxOverScrollY = 0;
21061 // Clamp values if at the limits and record
21062 final int left = -maxOverScrollX;
21063 final int right = maxOverScrollX + scrollRangeX;
21064 final int top = -maxOverScrollY;
21065 final int bottom = maxOverScrollY + scrollRangeY;
21067 boolean clampedX = false;
21068 if (newScrollX > right) {
21069 newScrollX = right;
21071 } else if (newScrollX < left) {
21076 boolean clampedY = false;
21077 if (newScrollY > bottom) {
21078 newScrollY = bottom;
21080 } else if (newScrollY < top) {
21085 onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
21087 return clampedX || clampedY;
21091 * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
21092 * respond to the results of an over-scroll operation.
21094 * @param scrollX New X scroll value in pixels
21095 * @param scrollY New Y scroll value in pixels
21096 * @param clampedX True if scrollX was clamped to an over-scroll boundary
21097 * @param clampedY True if scrollY was clamped to an over-scroll boundary
21099 protected void onOverScrolled(int scrollX, int scrollY,
21100 boolean clampedX, boolean clampedY) {
21101 // Intentionally empty.
21105 * Returns the over-scroll mode for this view. The result will be
21106 * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
21107 * (allow over-scrolling only if the view content is larger than the container),
21108 * or {@link #OVER_SCROLL_NEVER}.
21110 * @return This view's over-scroll mode.
21112 public int getOverScrollMode() {
21113 return mOverScrollMode;
21117 * Set the over-scroll mode for this view. Valid over-scroll modes are
21118 * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
21119 * (allow over-scrolling only if the view content is larger than the container),
21120 * or {@link #OVER_SCROLL_NEVER}.
21122 * Setting the over-scroll mode of a view will have an effect only if the
21123 * view is capable of scrolling.
21125 * @param overScrollMode The new over-scroll mode for this view.
21127 public void setOverScrollMode(int overScrollMode) {
21128 if (overScrollMode != OVER_SCROLL_ALWAYS &&
21129 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
21130 overScrollMode != OVER_SCROLL_NEVER) {
21131 throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
21133 mOverScrollMode = overScrollMode;
21137 * Enable or disable nested scrolling for this view.
21139 * <p>If this property is set to true the view will be permitted to initiate nested
21140 * scrolling operations with a compatible parent view in the current hierarchy. If this
21141 * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
21142 * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
21143 * the nested scroll.</p>
21145 * @param enabled true to enable nested scrolling, false to disable
21147 * @see #isNestedScrollingEnabled()
21149 public void setNestedScrollingEnabled(boolean enabled) {
21151 mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
21153 stopNestedScroll();
21154 mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
21159 * Returns true if nested scrolling is enabled for this view.
21161 * <p>If nested scrolling is enabled and this View class implementation supports it,
21162 * this view will act as a nested scrolling child view when applicable, forwarding data
21163 * about the scroll operation in progress to a compatible and cooperating nested scrolling
21166 * @return true if nested scrolling is enabled
21168 * @see #setNestedScrollingEnabled(boolean)
21170 public boolean isNestedScrollingEnabled() {
21171 return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
21172 PFLAG3_NESTED_SCROLLING_ENABLED;
21176 * Begin a nestable scroll operation along the given axes.
21178 * <p>A view starting a nested scroll promises to abide by the following contract:</p>
21180 * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
21181 * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
21182 * In the case of touch scrolling the nested scroll will be terminated automatically in
21183 * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
21184 * In the event of programmatic scrolling the caller must explicitly call
21185 * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
21187 * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
21188 * If it returns false the caller may ignore the rest of this contract until the next scroll.
21189 * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
21191 * <p>At each incremental step of the scroll the caller should invoke
21192 * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
21193 * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
21194 * parent at least partially consumed the scroll and the caller should adjust the amount it
21197 * <p>After applying the remainder of the scroll delta the caller should invoke
21198 * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
21199 * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
21200 * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
21203 * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
21204 * {@link #SCROLL_AXIS_VERTICAL}.
21205 * @return true if a cooperative parent was found and nested scrolling has been enabled for
21206 * the current gesture.
21208 * @see #stopNestedScroll()
21209 * @see #dispatchNestedPreScroll(int, int, int[], int[])
21210 * @see #dispatchNestedScroll(int, int, int, int, int[])
21212 public boolean startNestedScroll(int axes) {
21213 if (hasNestedScrollingParent()) {
21214 // Already in progress
21217 if (isNestedScrollingEnabled()) {
21218 ViewParent p = getParent();
21220 while (p != null) {
21222 if (p.onStartNestedScroll(child, this, axes)) {
21223 mNestedScrollingParent = p;
21224 p.onNestedScrollAccepted(child, this, axes);
21227 } catch (AbstractMethodError e) {
21228 Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
21229 "method onStartNestedScroll", e);
21230 // Allow the search upward to continue
21232 if (p instanceof View) {
21242 * Stop a nested scroll in progress.
21244 * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
21246 * @see #startNestedScroll(int)
21248 public void stopNestedScroll() {
21249 if (mNestedScrollingParent != null) {
21250 mNestedScrollingParent.onStopNestedScroll(this);
21251 mNestedScrollingParent = null;
21256 * Returns true if this view has a nested scrolling parent.
21258 * <p>The presence of a nested scrolling parent indicates that this view has initiated
21259 * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
21261 * @return whether this view has a nested scrolling parent
21263 public boolean hasNestedScrollingParent() {
21264 return mNestedScrollingParent != null;
21268 * Dispatch one step of a nested scroll in progress.
21270 * <p>Implementations of views that support nested scrolling should call this to report
21271 * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
21272 * is not currently in progress or nested scrolling is not
21273 * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
21275 * <p>Compatible View implementations should also call
21276 * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
21277 * consuming a component of the scroll event themselves.</p>
21279 * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
21280 * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
21281 * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
21282 * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
21283 * @param offsetInWindow Optional. If not null, on return this will contain the offset
21284 * in local view coordinates of this view from before this operation
21285 * to after it completes. View implementations may use this to adjust
21286 * expected input coordinate tracking.
21287 * @return true if the event was dispatched, false if it could not be dispatched.
21288 * @see #dispatchNestedPreScroll(int, int, int[], int[])
21290 public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
21291 int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
21292 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21293 if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
21296 if (offsetInWindow != null) {
21297 getLocationInWindow(offsetInWindow);
21298 startX = offsetInWindow[0];
21299 startY = offsetInWindow[1];
21302 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
21303 dxUnconsumed, dyUnconsumed);
21305 if (offsetInWindow != null) {
21306 getLocationInWindow(offsetInWindow);
21307 offsetInWindow[0] -= startX;
21308 offsetInWindow[1] -= startY;
21311 } else if (offsetInWindow != null) {
21312 // No motion, no dispatch. Keep offsetInWindow up to date.
21313 offsetInWindow[0] = 0;
21314 offsetInWindow[1] = 0;
21321 * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
21323 * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
21324 * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
21325 * scrolling operation to consume some or all of the scroll operation before the child view
21328 * @param dx Horizontal scroll distance in pixels
21329 * @param dy Vertical scroll distance in pixels
21330 * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
21331 * and consumed[1] the consumed dy.
21332 * @param offsetInWindow Optional. If not null, on return this will contain the offset
21333 * in local view coordinates of this view from before this operation
21334 * to after it completes. View implementations may use this to adjust
21335 * expected input coordinate tracking.
21336 * @return true if the parent consumed some or all of the scroll delta
21337 * @see #dispatchNestedScroll(int, int, int, int, int[])
21339 public boolean dispatchNestedPreScroll(int dx, int dy,
21340 @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
21341 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21342 if (dx != 0 || dy != 0) {
21345 if (offsetInWindow != null) {
21346 getLocationInWindow(offsetInWindow);
21347 startX = offsetInWindow[0];
21348 startY = offsetInWindow[1];
21351 if (consumed == null) {
21352 if (mTempNestedScrollConsumed == null) {
21353 mTempNestedScrollConsumed = new int[2];
21355 consumed = mTempNestedScrollConsumed;
21359 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
21361 if (offsetInWindow != null) {
21362 getLocationInWindow(offsetInWindow);
21363 offsetInWindow[0] -= startX;
21364 offsetInWindow[1] -= startY;
21366 return consumed[0] != 0 || consumed[1] != 0;
21367 } else if (offsetInWindow != null) {
21368 offsetInWindow[0] = 0;
21369 offsetInWindow[1] = 0;
21376 * Dispatch a fling to a nested scrolling parent.
21378 * <p>This method should be used to indicate that a nested scrolling child has detected
21379 * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
21380 * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
21381 * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
21382 * along a scrollable axis.</p>
21384 * <p>If a nested scrolling child view would normally fling but it is at the edge of
21385 * its own content, it can use this method to delegate the fling to its nested scrolling
21386 * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
21388 * @param velocityX Horizontal fling velocity in pixels per second
21389 * @param velocityY Vertical fling velocity in pixels per second
21390 * @param consumed true if the child consumed the fling, false otherwise
21391 * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
21393 public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
21394 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21395 return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
21401 * Dispatch a fling to a nested scrolling parent before it is processed by this view.
21403 * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
21404 * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
21405 * offsets an opportunity for the parent view in a nested fling to fully consume the fling
21406 * before the child view consumes it. If this method returns <code>true</code>, a nested
21407 * parent view consumed the fling and this view should not scroll as a result.</p>
21409 * <p>For a better user experience, only one view in a nested scrolling chain should consume
21410 * the fling at a time. If a parent view consumed the fling this method will return false.
21411 * Custom view implementations should account for this in two ways:</p>
21414 * <li>If a custom view is paged and needs to settle to a fixed page-point, do not
21415 * call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
21416 * position regardless.</li>
21417 * <li>If a nested parent does consume the fling, this view should not scroll at all,
21418 * even to settle back to a valid idle position.</li>
21421 * <p>Views should also not offer fling velocities to nested parent views along an axis
21422 * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
21423 * should not offer a horizontal fling velocity to its parents since scrolling along that
21424 * axis is not permitted and carrying velocity along that motion does not make sense.</p>
21426 * @param velocityX Horizontal fling velocity in pixels per second
21427 * @param velocityY Vertical fling velocity in pixels per second
21428 * @return true if a nested scrolling parent consumed the fling
21430 public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
21431 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21432 return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
21438 * Gets a scale factor that determines the distance the view should scroll
21439 * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
21440 * @return The vertical scroll scale factor.
21443 protected float getVerticalScrollFactor() {
21444 if (mVerticalScrollFactor == 0) {
21445 TypedValue outValue = new TypedValue();
21446 if (!mContext.getTheme().resolveAttribute(
21447 com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
21448 throw new IllegalStateException(
21449 "Expected theme to define listPreferredItemHeight.");
21451 mVerticalScrollFactor = outValue.getDimension(
21452 mContext.getResources().getDisplayMetrics());
21454 return mVerticalScrollFactor;
21458 * Gets a scale factor that determines the distance the view should scroll
21459 * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
21460 * @return The horizontal scroll scale factor.
21463 protected float getHorizontalScrollFactor() {
21464 // TODO: Should use something else.
21465 return getVerticalScrollFactor();
21469 * Return the value specifying the text direction or policy that was set with
21470 * {@link #setTextDirection(int)}.
21472 * @return the defined text direction. It can be one of:
21474 * {@link #TEXT_DIRECTION_INHERIT},
21475 * {@link #TEXT_DIRECTION_FIRST_STRONG},
21476 * {@link #TEXT_DIRECTION_ANY_RTL},
21477 * {@link #TEXT_DIRECTION_LTR},
21478 * {@link #TEXT_DIRECTION_RTL},
21479 * {@link #TEXT_DIRECTION_LOCALE},
21480 * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21481 * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
21483 * @attr ref android.R.styleable#View_textDirection
21487 @ViewDebug.ExportedProperty(category = "text", mapping = {
21488 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
21489 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
21490 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
21491 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
21492 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
21493 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
21494 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
21495 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
21497 public int getRawTextDirection() {
21498 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
21502 * Set the text direction.
21504 * @param textDirection the direction to set. Should be one of:
21506 * {@link #TEXT_DIRECTION_INHERIT},
21507 * {@link #TEXT_DIRECTION_FIRST_STRONG},
21508 * {@link #TEXT_DIRECTION_ANY_RTL},
21509 * {@link #TEXT_DIRECTION_LTR},
21510 * {@link #TEXT_DIRECTION_RTL},
21511 * {@link #TEXT_DIRECTION_LOCALE}
21512 * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21513 * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
21515 * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
21516 * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
21517 * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
21519 * @attr ref android.R.styleable#View_textDirection
21521 public void setTextDirection(int textDirection) {
21522 if (getRawTextDirection() != textDirection) {
21523 // Reset the current text direction and the resolved one
21524 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
21525 resetResolvedTextDirection();
21526 // Set the new text direction
21527 mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
21529 resolveTextDirection();
21531 onRtlPropertiesChanged(getLayoutDirection());
21539 * Return the resolved text direction.
21541 * @return the resolved text direction. Returns one of:
21543 * {@link #TEXT_DIRECTION_FIRST_STRONG},
21544 * {@link #TEXT_DIRECTION_ANY_RTL},
21545 * {@link #TEXT_DIRECTION_LTR},
21546 * {@link #TEXT_DIRECTION_RTL},
21547 * {@link #TEXT_DIRECTION_LOCALE},
21548 * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21549 * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
21551 * @attr ref android.R.styleable#View_textDirection
21553 @ViewDebug.ExportedProperty(category = "text", mapping = {
21554 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
21555 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
21556 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
21557 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
21558 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
21559 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
21560 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
21561 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
21563 public int getTextDirection() {
21564 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
21568 * Resolve the text direction.
21570 * @return true if resolution has been done, false otherwise.
21574 public boolean resolveTextDirection() {
21575 // Reset any previous text direction resolution
21576 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
21578 if (hasRtlSupport()) {
21579 // Set resolved text direction flag depending on text direction flag
21580 final int textDirection = getRawTextDirection();
21581 switch(textDirection) {
21582 case TEXT_DIRECTION_INHERIT:
21583 if (!canResolveTextDirection()) {
21584 // We cannot do the resolution if there is no parent, so use the default one
21585 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21586 // Resolution will need to happen again later
21590 // Parent has not yet resolved, so we still return the default
21592 if (!mParent.isTextDirectionResolved()) {
21593 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21594 // Resolution will need to happen again later
21597 } catch (AbstractMethodError e) {
21598 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21599 " does not fully implement ViewParent", e);
21600 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
21601 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21605 // Set current resolved direction to the same value as the parent's one
21606 int parentResolvedDirection;
21608 parentResolvedDirection = mParent.getTextDirection();
21609 } catch (AbstractMethodError e) {
21610 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21611 " does not fully implement ViewParent", e);
21612 parentResolvedDirection = TEXT_DIRECTION_LTR;
21614 switch (parentResolvedDirection) {
21615 case TEXT_DIRECTION_FIRST_STRONG:
21616 case TEXT_DIRECTION_ANY_RTL:
21617 case TEXT_DIRECTION_LTR:
21618 case TEXT_DIRECTION_RTL:
21619 case TEXT_DIRECTION_LOCALE:
21620 case TEXT_DIRECTION_FIRST_STRONG_LTR:
21621 case TEXT_DIRECTION_FIRST_STRONG_RTL:
21623 (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
21626 // Default resolved direction is "first strong" heuristic
21627 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21630 case TEXT_DIRECTION_FIRST_STRONG:
21631 case TEXT_DIRECTION_ANY_RTL:
21632 case TEXT_DIRECTION_LTR:
21633 case TEXT_DIRECTION_RTL:
21634 case TEXT_DIRECTION_LOCALE:
21635 case TEXT_DIRECTION_FIRST_STRONG_LTR:
21636 case TEXT_DIRECTION_FIRST_STRONG_RTL:
21637 // Resolved direction is the same as text direction
21638 mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
21641 // Default resolved direction is "first strong" heuristic
21642 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21645 // Default resolved direction is "first strong" heuristic
21646 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21650 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
21655 * Check if text direction resolution can be done.
21657 * @return true if text direction resolution can be done otherwise return false.
21659 public boolean canResolveTextDirection() {
21660 switch (getRawTextDirection()) {
21661 case TEXT_DIRECTION_INHERIT:
21662 if (mParent != null) {
21664 return mParent.canResolveTextDirection();
21665 } catch (AbstractMethodError e) {
21666 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21667 " does not fully implement ViewParent", e);
21678 * Reset resolved text direction. Text direction will be resolved during a call to
21679 * {@link #onMeasure(int, int)}.
21683 public void resetResolvedTextDirection() {
21684 // Reset any previous text direction resolution
21685 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
21686 // Set to default value
21687 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21691 * @return true if text direction is inherited.
21695 public boolean isTextDirectionInherited() {
21696 return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
21700 * @return true if text direction is resolved.
21702 public boolean isTextDirectionResolved() {
21703 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
21707 * Return the value specifying the text alignment or policy that was set with
21708 * {@link #setTextAlignment(int)}.
21710 * @return the defined text alignment. It can be one of:
21712 * {@link #TEXT_ALIGNMENT_INHERIT},
21713 * {@link #TEXT_ALIGNMENT_GRAVITY},
21714 * {@link #TEXT_ALIGNMENT_CENTER},
21715 * {@link #TEXT_ALIGNMENT_TEXT_START},
21716 * {@link #TEXT_ALIGNMENT_TEXT_END},
21717 * {@link #TEXT_ALIGNMENT_VIEW_START},
21718 * {@link #TEXT_ALIGNMENT_VIEW_END}
21720 * @attr ref android.R.styleable#View_textAlignment
21724 @ViewDebug.ExportedProperty(category = "text", mapping = {
21725 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
21726 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
21727 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
21728 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
21729 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
21730 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
21731 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
21734 public int getRawTextAlignment() {
21735 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
21739 * Set the text alignment.
21741 * @param textAlignment The text alignment to set. Should be one of
21743 * {@link #TEXT_ALIGNMENT_INHERIT},
21744 * {@link #TEXT_ALIGNMENT_GRAVITY},
21745 * {@link #TEXT_ALIGNMENT_CENTER},
21746 * {@link #TEXT_ALIGNMENT_TEXT_START},
21747 * {@link #TEXT_ALIGNMENT_TEXT_END},
21748 * {@link #TEXT_ALIGNMENT_VIEW_START},
21749 * {@link #TEXT_ALIGNMENT_VIEW_END}
21751 * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
21752 * proceeds up the parent chain of the view to get the value. If there is no parent, then it
21753 * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
21755 * @attr ref android.R.styleable#View_textAlignment
21757 public void setTextAlignment(@TextAlignment int textAlignment) {
21758 if (textAlignment != getRawTextAlignment()) {
21759 // Reset the current and resolved text alignment
21760 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
21761 resetResolvedTextAlignment();
21762 // Set the new text alignment
21764 ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
21766 resolveTextAlignment();
21768 onRtlPropertiesChanged(getLayoutDirection());
21776 * Return the resolved text alignment.
21778 * @return the resolved text alignment. Returns one of:
21780 * {@link #TEXT_ALIGNMENT_GRAVITY},
21781 * {@link #TEXT_ALIGNMENT_CENTER},
21782 * {@link #TEXT_ALIGNMENT_TEXT_START},
21783 * {@link #TEXT_ALIGNMENT_TEXT_END},
21784 * {@link #TEXT_ALIGNMENT_VIEW_START},
21785 * {@link #TEXT_ALIGNMENT_VIEW_END}
21787 * @attr ref android.R.styleable#View_textAlignment
21789 @ViewDebug.ExportedProperty(category = "text", mapping = {
21790 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
21791 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
21792 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
21793 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
21794 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
21795 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
21796 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
21799 public int getTextAlignment() {
21800 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
21801 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
21805 * Resolve the text alignment.
21807 * @return true if resolution has been done, false otherwise.
21811 public boolean resolveTextAlignment() {
21812 // Reset any previous text alignment resolution
21813 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
21815 if (hasRtlSupport()) {
21816 // Set resolved text alignment flag depending on text alignment flag
21817 final int textAlignment = getRawTextAlignment();
21818 switch (textAlignment) {
21819 case TEXT_ALIGNMENT_INHERIT:
21820 // Check if we can resolve the text alignment
21821 if (!canResolveTextAlignment()) {
21822 // We cannot do the resolution if there is no parent so use the default
21823 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21824 // Resolution will need to happen again later
21828 // Parent has not yet resolved, so we still return the default
21830 if (!mParent.isTextAlignmentResolved()) {
21831 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21832 // Resolution will need to happen again later
21835 } catch (AbstractMethodError e) {
21836 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21837 " does not fully implement ViewParent", e);
21838 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
21839 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21843 int parentResolvedTextAlignment;
21845 parentResolvedTextAlignment = mParent.getTextAlignment();
21846 } catch (AbstractMethodError e) {
21847 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21848 " does not fully implement ViewParent", e);
21849 parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
21851 switch (parentResolvedTextAlignment) {
21852 case TEXT_ALIGNMENT_GRAVITY:
21853 case TEXT_ALIGNMENT_TEXT_START:
21854 case TEXT_ALIGNMENT_TEXT_END:
21855 case TEXT_ALIGNMENT_CENTER:
21856 case TEXT_ALIGNMENT_VIEW_START:
21857 case TEXT_ALIGNMENT_VIEW_END:
21858 // Resolved text alignment is the same as the parent resolved
21861 (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
21864 // Use default resolved text alignment
21865 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21868 case TEXT_ALIGNMENT_GRAVITY:
21869 case TEXT_ALIGNMENT_TEXT_START:
21870 case TEXT_ALIGNMENT_TEXT_END:
21871 case TEXT_ALIGNMENT_CENTER:
21872 case TEXT_ALIGNMENT_VIEW_START:
21873 case TEXT_ALIGNMENT_VIEW_END:
21874 // Resolved text alignment is the same as text alignment
21875 mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
21878 // Use default resolved text alignment
21879 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21882 // Use default resolved text alignment
21883 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21886 // Set the resolved
21887 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
21892 * Check if text alignment resolution can be done.
21894 * @return true if text alignment resolution can be done otherwise return false.
21896 public boolean canResolveTextAlignment() {
21897 switch (getRawTextAlignment()) {
21898 case TEXT_DIRECTION_INHERIT:
21899 if (mParent != null) {
21901 return mParent.canResolveTextAlignment();
21902 } catch (AbstractMethodError e) {
21903 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21904 " does not fully implement ViewParent", e);
21915 * Reset resolved text alignment. Text alignment will be resolved during a call to
21916 * {@link #onMeasure(int, int)}.
21920 public void resetResolvedTextAlignment() {
21921 // Reset any previous text alignment resolution
21922 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
21924 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21928 * @return true if text alignment is inherited.
21932 public boolean isTextAlignmentInherited() {
21933 return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
21937 * @return true if text alignment is resolved.
21939 public boolean isTextAlignmentResolved() {
21940 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
21944 * Generate a value suitable for use in {@link #setId(int)}.
21945 * This value will not collide with ID values generated at build time by aapt for R.id.
21947 * @return a generated ID value
21949 public static int generateViewId() {
21951 final int result = sNextGeneratedId.get();
21952 // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
21953 int newValue = result + 1;
21954 if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
21955 if (sNextGeneratedId.compareAndSet(result, newValue)) {
21962 * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
21963 * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
21964 * a normal View or a ViewGroup with
21965 * {@link android.view.ViewGroup#isTransitionGroup()} true.
21968 public void captureTransitioningViews(List<View> transitioningViews) {
21969 if (getVisibility() == View.VISIBLE) {
21970 transitioningViews.add(this);
21975 * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
21976 * @param namedElements Will contain all Views in the hierarchy having a transitionName.
21979 public void findNamedViews(Map<String, View> namedElements) {
21980 if (getVisibility() == VISIBLE || mGhostView != null) {
21981 String transitionName = getTransitionName();
21982 if (transitionName != null) {
21983 namedElements.put(transitionName, this);
21989 * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
21990 * The default implementation does not care the location or event types, but some subclasses
21991 * may use it (such as WebViews).
21992 * @param event The MotionEvent from a mouse
21993 * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
21994 * This will be between 0 and {@link MotionEvent#getPointerCount()}.
21997 public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
21998 final float x = event.getX(pointerIndex);
21999 final float y = event.getY(pointerIndex);
22000 if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
22001 return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
22003 return mPointerIcon;
22007 * Set the pointer icon for the current view.
22008 * Passing {@code null} will restore the pointer icon to its default value.
22009 * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
22011 public void setPointerIcon(PointerIcon pointerIcon) {
22012 mPointerIcon = pointerIcon;
22013 if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
22017 mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
22018 } catch (RemoteException e) {
22023 * Gets the pointer icon for the current view.
22025 public PointerIcon getPointerIcon() {
22026 return mPointerIcon;
22033 * A Property wrapper around the <code>alpha</code> functionality handled by the
22034 * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
22036 public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
22038 public void setValue(View object, float value) {
22039 object.setAlpha(value);
22043 public Float get(View object) {
22044 return object.getAlpha();
22049 * A Property wrapper around the <code>translationX</code> functionality handled by the
22050 * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
22052 public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
22054 public void setValue(View object, float value) {
22055 object.setTranslationX(value);
22059 public Float get(View object) {
22060 return object.getTranslationX();
22065 * A Property wrapper around the <code>translationY</code> functionality handled by the
22066 * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
22068 public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
22070 public void setValue(View object, float value) {
22071 object.setTranslationY(value);
22075 public Float get(View object) {
22076 return object.getTranslationY();
22081 * A Property wrapper around the <code>translationZ</code> functionality handled by the
22082 * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
22084 public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
22086 public void setValue(View object, float value) {
22087 object.setTranslationZ(value);
22091 public Float get(View object) {
22092 return object.getTranslationZ();
22097 * A Property wrapper around the <code>x</code> functionality handled by the
22098 * {@link View#setX(float)} and {@link View#getX()} methods.
22100 public static final Property<View, Float> X = new FloatProperty<View>("x") {
22102 public void setValue(View object, float value) {
22103 object.setX(value);
22107 public Float get(View object) {
22108 return object.getX();
22113 * A Property wrapper around the <code>y</code> functionality handled by the
22114 * {@link View#setY(float)} and {@link View#getY()} methods.
22116 public static final Property<View, Float> Y = new FloatProperty<View>("y") {
22118 public void setValue(View object, float value) {
22119 object.setY(value);
22123 public Float get(View object) {
22124 return object.getY();
22129 * A Property wrapper around the <code>z</code> functionality handled by the
22130 * {@link View#setZ(float)} and {@link View#getZ()} methods.
22132 public static final Property<View, Float> Z = new FloatProperty<View>("z") {
22134 public void setValue(View object, float value) {
22135 object.setZ(value);
22139 public Float get(View object) {
22140 return object.getZ();
22145 * A Property wrapper around the <code>rotation</code> functionality handled by the
22146 * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
22148 public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
22150 public void setValue(View object, float value) {
22151 object.setRotation(value);
22155 public Float get(View object) {
22156 return object.getRotation();
22161 * A Property wrapper around the <code>rotationX</code> functionality handled by the
22162 * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
22164 public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
22166 public void setValue(View object, float value) {
22167 object.setRotationX(value);
22171 public Float get(View object) {
22172 return object.getRotationX();
22177 * A Property wrapper around the <code>rotationY</code> functionality handled by the
22178 * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
22180 public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
22182 public void setValue(View object, float value) {
22183 object.setRotationY(value);
22187 public Float get(View object) {
22188 return object.getRotationY();
22193 * A Property wrapper around the <code>scaleX</code> functionality handled by the
22194 * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
22196 public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
22198 public void setValue(View object, float value) {
22199 object.setScaleX(value);
22203 public Float get(View object) {
22204 return object.getScaleX();
22209 * A Property wrapper around the <code>scaleY</code> functionality handled by the
22210 * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
22212 public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
22214 public void setValue(View object, float value) {
22215 object.setScaleY(value);
22219 public Float get(View object) {
22220 return object.getScaleY();
22225 * A MeasureSpec encapsulates the layout requirements passed from parent to child.
22226 * Each MeasureSpec represents a requirement for either the width or the height.
22227 * A MeasureSpec is comprised of a size and a mode. There are three possible
22230 * <dt>UNSPECIFIED</dt>
22232 * The parent has not imposed any constraint on the child. It can be whatever size
22238 * The parent has determined an exact size for the child. The child is going to be
22239 * given those bounds regardless of how big it wants to be.
22244 * The child can be as large as it wants up to the specified size.
22248 * MeasureSpecs are implemented as ints to reduce object allocation. This class
22249 * is provided to pack and unpack the <size, mode> tuple into the int.
22251 public static class MeasureSpec {
22252 private static final int MODE_SHIFT = 30;
22253 private static final int MODE_MASK = 0x3 << MODE_SHIFT;
22256 @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
22257 @Retention(RetentionPolicy.SOURCE)
22258 public @interface MeasureSpecMode {}
22261 * Measure specification mode: The parent has not imposed any constraint
22262 * on the child. It can be whatever size it wants.
22264 public static final int UNSPECIFIED = 0 << MODE_SHIFT;
22267 * Measure specification mode: The parent has determined an exact size
22268 * for the child. The child is going to be given those bounds regardless
22269 * of how big it wants to be.
22271 public static final int EXACTLY = 1 << MODE_SHIFT;
22274 * Measure specification mode: The child can be as large as it wants up
22275 * to the specified size.
22277 public static final int AT_MOST = 2 << MODE_SHIFT;
22280 * Creates a measure specification based on the supplied size and mode.
22282 * The mode must always be one of the following:
22284 * <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
22285 * <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
22286 * <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
22289 * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
22290 * implementation was such that the order of arguments did not matter
22291 * and overflow in either value could impact the resulting MeasureSpec.
22292 * {@link android.widget.RelativeLayout} was affected by this bug.
22293 * Apps targeting API levels greater than 17 will get the fixed, more strict
22296 * @param size the size of the measure specification
22297 * @param mode the mode of the measure specification
22298 * @return the measure specification based on size and mode
22300 public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
22301 @MeasureSpecMode int mode) {
22302 if (sUseBrokenMakeMeasureSpec) {
22303 return size + mode;
22305 return (size & ~MODE_MASK) | (mode & MODE_MASK);
22310 * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
22311 * will automatically get a size of 0. Older apps expect this.
22313 * @hide internal use only for compatibility with system widgets and older apps
22315 public static int makeSafeMeasureSpec(int size, int mode) {
22316 if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
22319 return makeMeasureSpec(size, mode);
22323 * Extracts the mode from the supplied measure specification.
22325 * @param measureSpec the measure specification to extract the mode from
22326 * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
22327 * {@link android.view.View.MeasureSpec#AT_MOST} or
22328 * {@link android.view.View.MeasureSpec#EXACTLY}
22331 public static int getMode(int measureSpec) {
22332 //noinspection ResourceType
22333 return (measureSpec & MODE_MASK);
22337 * Extracts the size from the supplied measure specification.
22339 * @param measureSpec the measure specification to extract the size from
22340 * @return the size in pixels defined in the supplied measure specification
22342 public static int getSize(int measureSpec) {
22343 return (measureSpec & ~MODE_MASK);
22346 static int adjust(int measureSpec, int delta) {
22347 final int mode = getMode(measureSpec);
22348 int size = getSize(measureSpec);
22349 if (mode == UNSPECIFIED) {
22350 // No need to adjust size for UNSPECIFIED mode.
22351 return makeMeasureSpec(size, UNSPECIFIED);
22355 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
22356 ") spec: " + toString(measureSpec) + " delta: " + delta);
22359 return makeMeasureSpec(size, mode);
22363 * Returns a String representation of the specified measure
22366 * @param measureSpec the measure specification to convert to a String
22367 * @return a String with the following format: "MeasureSpec: MODE SIZE"
22369 public static String toString(int measureSpec) {
22370 int mode = getMode(measureSpec);
22371 int size = getSize(measureSpec);
22373 StringBuilder sb = new StringBuilder("MeasureSpec: ");
22375 if (mode == UNSPECIFIED)
22376 sb.append("UNSPECIFIED ");
22377 else if (mode == EXACTLY)
22378 sb.append("EXACTLY ");
22379 else if (mode == AT_MOST)
22380 sb.append("AT_MOST ");
22382 sb.append(mode).append(" ");
22385 return sb.toString();
22389 private final class CheckForLongPress implements Runnable {
22390 private int mOriginalWindowAttachCount;
22395 public void run() {
22396 if (isPressed() && (mParent != null)
22397 && mOriginalWindowAttachCount == mWindowAttachCount) {
22398 if (performLongClick(mX, mY)) {
22399 mHasPerformedLongPress = true;
22404 public void setAnchor(float x, float y) {
22409 public void rememberWindowAttachCount() {
22410 mOriginalWindowAttachCount = mWindowAttachCount;
22414 private final class CheckForTap implements Runnable {
22419 public void run() {
22420 mPrivateFlags &= ~PFLAG_PREPRESSED;
22421 setPressed(true, x, y);
22422 checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
22426 private final class PerformClick implements Runnable {
22428 public void run() {
22434 * This method returns a ViewPropertyAnimator object, which can be used to animate
22435 * specific properties on this View.
22437 * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
22439 public ViewPropertyAnimator animate() {
22440 if (mAnimator == null) {
22441 mAnimator = new ViewPropertyAnimator(this);
22447 * Sets the name of the View to be used to identify Views in Transitions.
22448 * Names should be unique in the View hierarchy.
22450 * @param transitionName The name of the View to uniquely identify it for Transitions.
22452 public final void setTransitionName(String transitionName) {
22453 mTransitionName = transitionName;
22457 * Returns the name of the View to be used to identify Views in Transitions.
22458 * Names should be unique in the View hierarchy.
22460 * <p>This returns null if the View has not been given a name.</p>
22462 * @return The name used of the View to be used to identify Views in Transitions or null
22463 * if no name has been given.
22465 @ViewDebug.ExportedProperty
22466 public String getTransitionName() {
22467 return mTransitionName;
22473 public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
22478 * Interface definition for a callback to be invoked when a hardware key event is
22479 * dispatched to this view. The callback will be invoked before the key event is
22480 * given to the view. This is only useful for hardware keyboards; a software input
22481 * method has no obligation to trigger this listener.
22483 public interface OnKeyListener {
22485 * Called when a hardware key is dispatched to a view. This allows listeners to
22486 * get a chance to respond before the target view.
22487 * <p>Key presses in software keyboards will generally NOT trigger this method,
22488 * although some may elect to do so in some situations. Do not assume a
22489 * software input method has to be key-based; even if it is, it may use key presses
22490 * in a different way than you expect, so there is no way to reliably catch soft
22491 * input key presses.
22493 * @param v The view the key has been dispatched to.
22494 * @param keyCode The code for the physical key that was pressed
22495 * @param event The KeyEvent object containing full information about
22497 * @return True if the listener has consumed the event, false otherwise.
22499 boolean onKey(View v, int keyCode, KeyEvent event);
22503 * Interface definition for a callback to be invoked when a touch event is
22504 * dispatched to this view. The callback will be invoked before the touch
22505 * event is given to the view.
22507 public interface OnTouchListener {
22509 * Called when a touch event is dispatched to a view. This allows listeners to
22510 * get a chance to respond before the target view.
22512 * @param v The view the touch event has been dispatched to.
22513 * @param event The MotionEvent object containing full information about
22515 * @return True if the listener has consumed the event, false otherwise.
22517 boolean onTouch(View v, MotionEvent event);
22521 * Interface definition for a callback to be invoked when a hover event is
22522 * dispatched to this view. The callback will be invoked before the hover
22523 * event is given to the view.
22525 public interface OnHoverListener {
22527 * Called when a hover event is dispatched to a view. This allows listeners to
22528 * get a chance to respond before the target view.
22530 * @param v The view the hover event has been dispatched to.
22531 * @param event The MotionEvent object containing full information about
22533 * @return True if the listener has consumed the event, false otherwise.
22535 boolean onHover(View v, MotionEvent event);
22539 * Interface definition for a callback to be invoked when a generic motion event is
22540 * dispatched to this view. The callback will be invoked before the generic motion
22541 * event is given to the view.
22543 public interface OnGenericMotionListener {
22545 * Called when a generic motion event is dispatched to a view. This allows listeners to
22546 * get a chance to respond before the target view.
22548 * @param v The view the generic motion event has been dispatched to.
22549 * @param event The MotionEvent object containing full information about
22551 * @return True if the listener has consumed the event, false otherwise.
22553 boolean onGenericMotion(View v, MotionEvent event);
22557 * Interface definition for a callback to be invoked when a view has been clicked and held.
22559 public interface OnLongClickListener {
22561 * Called when a view has been clicked and held.
22563 * @param v The view that was clicked and held.
22565 * @return true if the callback consumed the long click, false otherwise.
22567 boolean onLongClick(View v);
22571 * Interface definition for a callback to be invoked when a drag is being dispatched
22572 * to this view. The callback will be invoked before the hosting view's own
22573 * onDrag(event) method. If the listener wants to fall back to the hosting view's
22574 * onDrag(event) behavior, it should return 'false' from this callback.
22576 * <div class="special reference">
22577 * <h3>Developer Guides</h3>
22578 * <p>For a guide to implementing drag and drop features, read the
22579 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
22582 public interface OnDragListener {
22584 * Called when a drag event is dispatched to a view. This allows listeners
22585 * to get a chance to override base View behavior.
22587 * @param v The View that received the drag event.
22588 * @param event The {@link android.view.DragEvent} object for the drag event.
22589 * @return {@code true} if the drag event was handled successfully, or {@code false}
22590 * if the drag event was not handled. Note that {@code false} will trigger the View
22591 * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
22593 boolean onDrag(View v, DragEvent event);
22597 * Interface definition for a callback to be invoked when the focus state of
22600 public interface OnFocusChangeListener {
22602 * Called when the focus state of a view has changed.
22604 * @param v The view whose state has changed.
22605 * @param hasFocus The new focus state of v.
22607 void onFocusChange(View v, boolean hasFocus);
22611 * Interface definition for a callback to be invoked when a view is clicked.
22613 public interface OnClickListener {
22615 * Called when a view has been clicked.
22617 * @param v The view that was clicked.
22619 void onClick(View v);
22623 * Interface definition for a callback to be invoked when a view is context clicked.
22625 public interface OnContextClickListener {
22627 * Called when a view is context clicked.
22629 * @param v The view that has been context clicked.
22630 * @return true if the callback consumed the context click, false otherwise.
22632 boolean onContextClick(View v);
22636 * Interface definition for a callback to be invoked when the context menu
22637 * for this view is being built.
22639 public interface OnCreateContextMenuListener {
22641 * Called when the context menu for this view is being built. It is not
22642 * safe to hold onto the menu after this method returns.
22644 * @param menu The context menu that is being built
22645 * @param v The view for which the context menu is being built
22646 * @param menuInfo Extra information about the item for which the
22647 * context menu should be shown. This information will vary
22648 * depending on the class of v.
22650 void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
22654 * Interface definition for a callback to be invoked when the status bar changes
22655 * visibility. This reports <strong>global</strong> changes to the system UI
22656 * state, not what the application is requesting.
22658 * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
22660 public interface OnSystemUiVisibilityChangeListener {
22662 * Called when the status bar changes visibility because of a call to
22663 * {@link View#setSystemUiVisibility(int)}.
22665 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22666 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
22667 * This tells you the <strong>global</strong> state of these UI visibility
22668 * flags, not what your app is currently applying.
22670 public void onSystemUiVisibilityChange(int visibility);
22674 * Interface definition for a callback to be invoked when this view is attached
22675 * or detached from its window.
22677 public interface OnAttachStateChangeListener {
22679 * Called when the view is attached to a window.
22680 * @param v The view that was attached
22682 public void onViewAttachedToWindow(View v);
22684 * Called when the view is detached from a window.
22685 * @param v The view that was detached
22687 public void onViewDetachedFromWindow(View v);
22691 * Listener for applying window insets on a view in a custom way.
22693 * <p>Apps may choose to implement this interface if they want to apply custom policy
22694 * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
22696 * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
22697 * method will be called instead of the View's own
22698 * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
22699 * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
22700 * the View's normal behavior as part of its own.</p>
22702 public interface OnApplyWindowInsetsListener {
22704 * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
22705 * on a View, this listener method will be called instead of the view's own
22706 * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
22708 * @param v The view applying window insets
22709 * @param insets The insets to apply
22710 * @return The insets supplied, minus any insets that were consumed
22712 public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
22715 private final class UnsetPressedState implements Runnable {
22717 public void run() {
22723 * Base class for derived classes that want to save and restore their own
22724 * state in {@link android.view.View#onSaveInstanceState()}.
22726 public static class BaseSavedState extends AbsSavedState {
22727 String mStartActivityRequestWhoSaved;
22730 * Constructor used when reading from a parcel. Reads the state of the superclass.
22732 * @param source parcel to read from
22734 public BaseSavedState(Parcel source) {
22735 this(source, null);
22739 * Constructor used when reading from a parcel using a given class loader.
22740 * Reads the state of the superclass.
22742 * @param source parcel to read from
22743 * @param loader ClassLoader to use for reading
22745 public BaseSavedState(Parcel source, ClassLoader loader) {
22746 super(source, loader);
22747 mStartActivityRequestWhoSaved = source.readString();
22751 * Constructor called by derived classes when creating their SavedState objects
22753 * @param superState The state of the superclass of this view
22755 public BaseSavedState(Parcelable superState) {
22760 public void writeToParcel(Parcel out, int flags) {
22761 super.writeToParcel(out, flags);
22762 out.writeString(mStartActivityRequestWhoSaved);
22765 public static final Parcelable.Creator<BaseSavedState> CREATOR
22766 = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
22768 public BaseSavedState createFromParcel(Parcel in) {
22769 return new BaseSavedState(in);
22773 public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
22774 return new BaseSavedState(in, loader);
22778 public BaseSavedState[] newArray(int size) {
22779 return new BaseSavedState[size];
22785 * A set of information given to a view when it is attached to its parent
22788 final static class AttachInfo {
22789 interface Callbacks {
22790 void playSoundEffect(int effectId);
22791 boolean performHapticFeedback(int effectId, boolean always);
22795 * InvalidateInfo is used to post invalidate(int, int, int, int) messages
22796 * to a Handler. This class contains the target (View) to invalidate and
22797 * the coordinates of the dirty rectangle.
22799 * For performance purposes, this class also implements a pool of up to
22800 * POOL_LIMIT objects that get reused. This reduces memory allocations
22801 * whenever possible.
22803 static class InvalidateInfo {
22804 private static final int POOL_LIMIT = 10;
22806 private static final SynchronizedPool<InvalidateInfo> sPool =
22807 new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
22816 public static InvalidateInfo obtain() {
22817 InvalidateInfo instance = sPool.acquire();
22818 return (instance != null) ? instance : new InvalidateInfo();
22821 public void recycle() {
22823 sPool.release(this);
22827 final IWindowSession mSession;
22829 final IWindow mWindow;
22831 final IBinder mWindowToken;
22833 final Display mDisplay;
22835 final Callbacks mRootCallbacks;
22837 IWindowId mIWindowId;
22838 WindowId mWindowId;
22841 * The top view of the hierarchy.
22845 IBinder mPanelParentWindowToken;
22847 boolean mHardwareAccelerated;
22848 boolean mHardwareAccelerationRequested;
22849 ThreadedRenderer mHardwareRenderer;
22850 List<RenderNode> mPendingAnimatingRenderNodes;
22853 * The state of the display to which the window is attached, as reported
22854 * by {@link Display#getState()}. Note that the display state constants
22855 * declared by {@link Display} do not exactly line up with the screen state
22856 * constants declared by {@link View} (there are more display states than
22859 int mDisplayState = Display.STATE_UNKNOWN;
22862 * Scale factor used by the compatibility mode
22864 float mApplicationScale;
22867 * Indicates whether the application is in compatibility mode
22869 boolean mScalingRequired;
22872 * Left position of this view's window
22877 * Top position of this view's window
22882 * Indicates whether views need to use 32-bit drawing caches
22884 boolean mUse32BitDrawingCache;
22887 * For windows that are full-screen but using insets to layout inside
22888 * of the screen areas, these are the current insets to appear inside
22889 * the overscan area of the display.
22891 final Rect mOverscanInsets = new Rect();
22894 * For windows that are full-screen but using insets to layout inside
22895 * of the screen decorations, these are the current insets for the
22896 * content of the window.
22898 final Rect mContentInsets = new Rect();
22901 * For windows that are full-screen but using insets to layout inside
22902 * of the screen decorations, these are the current insets for the
22903 * actual visible parts of the window.
22905 final Rect mVisibleInsets = new Rect();
22908 * For windows that are full-screen but using insets to layout inside
22909 * of the screen decorations, these are the current insets for the
22910 * stable system windows.
22912 final Rect mStableInsets = new Rect();
22915 * For windows that include areas that are not covered by real surface these are the outsets
22916 * for real surface.
22918 final Rect mOutsets = new Rect();
22921 * In multi-window we force show the navigation bar. Because we don't want that the surface
22922 * size changes in this mode, we instead have a flag whether the navigation bar size should
22923 * always be consumed, so the app is treated like there is no virtual navigation bar at all.
22925 boolean mAlwaysConsumeNavBar;
22928 * The internal insets given by this window. This value is
22929 * supplied by the client (through
22930 * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
22931 * be given to the window manager when changed to be used in laying
22932 * out windows behind it.
22934 final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
22935 = new ViewTreeObserver.InternalInsetsInfo();
22938 * Set to true when mGivenInternalInsets is non-empty.
22940 boolean mHasNonEmptyGivenInternalInsets;
22943 * All views in the window's hierarchy that serve as scroll containers,
22944 * used to determine if the window can be resized or must be panned
22945 * to adjust for a soft input area.
22947 final ArrayList<View> mScrollContainers = new ArrayList<View>();
22949 final KeyEvent.DispatcherState mKeyDispatchState
22950 = new KeyEvent.DispatcherState();
22953 * Indicates whether the view's window currently has the focus.
22955 boolean mHasWindowFocus;
22958 * The current visibility of the window.
22960 int mWindowVisibility;
22963 * Indicates the time at which drawing started to occur.
22968 * Indicates whether or not ignoring the DIRTY_MASK flags.
22970 boolean mIgnoreDirtyState;
22973 * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
22974 * to avoid clearing that flag prematurely.
22976 boolean mSetIgnoreDirtyState = false;
22979 * Indicates whether the view's window is currently in touch mode.
22981 boolean mInTouchMode;
22984 * Indicates whether the view has requested unbuffered input dispatching for the current
22987 boolean mUnbufferedDispatchRequested;
22990 * Indicates that ViewAncestor should trigger a global layout change
22991 * the next time it performs a traversal
22993 boolean mRecomputeGlobalAttributes;
22996 * Always report new attributes at next traversal.
22998 boolean mForceReportNewAttributes;
23001 * Set during a traveral if any views want to keep the screen on.
23003 boolean mKeepScreenOn;
23006 * Set during a traveral if the light center needs to be updated.
23008 boolean mNeedsUpdateLightCenter;
23011 * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
23013 int mSystemUiVisibility;
23016 * Hack to force certain system UI visibility flags to be cleared.
23018 int mDisabledSystemUiVisibility;
23021 * Last global system UI visibility reported by the window manager.
23023 int mGlobalSystemUiVisibility = -1;
23026 * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
23029 boolean mHasSystemUiListeners;
23032 * Set if the window has requested to extend into the overscan region
23033 * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
23035 boolean mOverscanRequested;
23038 * Set if the visibility of any views has changed.
23040 boolean mViewVisibilityChanged;
23043 * Set to true if a view has been scrolled.
23045 boolean mViewScrollChanged;
23048 * Set to true if high contrast mode enabled
23050 boolean mHighContrastText;
23053 * Set to true if a pointer event is currently being handled.
23055 boolean mHandlingPointerEvent;
23058 * Global to the view hierarchy used as a temporary for dealing with
23059 * x/y points in the transparent region computations.
23061 final int[] mTransparentLocation = new int[2];
23064 * Global to the view hierarchy used as a temporary for dealing with
23065 * x/y points in the ViewGroup.invalidateChild implementation.
23067 final int[] mInvalidateChildLocation = new int[2];
23070 * Global to the view hierarchy used as a temporary for dealing with
23071 * computing absolute on-screen location.
23073 final int[] mTmpLocation = new int[2];
23076 * Global to the view hierarchy used as a temporary for dealing with
23077 * x/y location when view is transformed.
23079 final float[] mTmpTransformLocation = new float[2];
23082 * The view tree observer used to dispatch global events like
23083 * layout, pre-draw, touch mode change, etc.
23085 final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
23088 * A Canvas used by the view hierarchy to perform bitmap caching.
23093 * The view root impl.
23095 final ViewRootImpl mViewRootImpl;
23098 * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
23099 * handler can be used to pump events in the UI events queue.
23101 final Handler mHandler;
23104 * Temporary for use in computing invalidate rectangles while
23105 * calling up the hierarchy.
23107 final Rect mTmpInvalRect = new Rect();
23110 * Temporary for use in computing hit areas with transformed views
23112 final RectF mTmpTransformRect = new RectF();
23115 * Temporary for use in computing hit areas with transformed views
23117 final RectF mTmpTransformRect1 = new RectF();
23120 * Temporary list of rectanges.
23122 final List<RectF> mTmpRectList = new ArrayList<>();
23125 * Temporary for use in transforming invalidation rect
23127 final Matrix mTmpMatrix = new Matrix();
23130 * Temporary for use in transforming invalidation rect
23132 final Transformation mTmpTransformation = new Transformation();
23135 * Temporary for use in querying outlines from OutlineProviders
23137 final Outline mTmpOutline = new Outline();
23140 * Temporary list for use in collecting focusable descendents of a view.
23142 final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
23145 * The id of the window for accessibility purposes.
23147 int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
23150 * Flags related to accessibility processing.
23152 * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
23153 * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
23155 int mAccessibilityFetchFlags;
23158 * The drawable for highlighting accessibility focus.
23160 Drawable mAccessibilityFocusDrawable;
23163 * Show where the margins, bounds and layout bounds are for each view.
23165 boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
23168 * Point used to compute visible regions.
23170 final Point mPoint = new Point();
23173 * Used to track which View originated a requestLayout() call, used when
23174 * requestLayout() is called during layout.
23176 View mViewRequestingLayout;
23179 * Used to track views that need (at least) a partial relayout at their current size
23180 * during the next traversal.
23182 List<View> mPartialLayoutViews = new ArrayList<>();
23185 * Swapped with mPartialLayoutViews during layout to avoid concurrent
23186 * modification. Lazily assigned during ViewRootImpl layout.
23188 List<View> mEmptyPartialLayoutViews;
23191 * Used to track the identity of the current drag operation.
23193 IBinder mDragToken;
23196 * The drag shadow surface for the current drag operation.
23198 public Surface mDragSurface;
23201 * Creates a new set of attachment information with the specified
23202 * events handler and thread.
23204 * @param handler the events handler the view must use
23206 AttachInfo(IWindowSession session, IWindow window, Display display,
23207 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
23208 mSession = session;
23210 mWindowToken = window.asBinder();
23211 mDisplay = display;
23212 mViewRootImpl = viewRootImpl;
23213 mHandler = handler;
23214 mRootCallbacks = effectPlayer;
23219 * <p>ScrollabilityCache holds various fields used by a View when scrolling
23220 * is supported. This avoids keeping too many unused fields in most
23221 * instances of View.</p>
23223 private static class ScrollabilityCache implements Runnable {
23226 * Scrollbars are not visible
23228 public static final int OFF = 0;
23231 * Scrollbars are visible
23233 public static final int ON = 1;
23236 * Scrollbars are fading away
23238 public static final int FADING = 2;
23240 public boolean fadeScrollBars;
23242 public int fadingEdgeLength;
23243 public int scrollBarDefaultDelayBeforeFade;
23244 public int scrollBarFadeDuration;
23246 public int scrollBarSize;
23247 public ScrollBarDrawable scrollBar;
23248 public float[] interpolatorValues;
23251 public final Paint paint;
23252 public final Matrix matrix;
23253 public Shader shader;
23255 public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
23257 private static final float[] OPAQUE = { 255 };
23258 private static final float[] TRANSPARENT = { 0.0f };
23261 * When fading should start. This time moves into the future every time
23262 * a new scroll happens. Measured based on SystemClock.uptimeMillis()
23264 public long fadeStartTime;
23268 * The current state of the scrollbars: ON, OFF, or FADING
23270 public int state = OFF;
23272 private int mLastColor;
23274 public final Rect mScrollBarBounds = new Rect();
23276 public static final int NOT_DRAGGING = 0;
23277 public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
23278 public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
23279 public int mScrollBarDraggingState = NOT_DRAGGING;
23281 public float mScrollBarDraggingPos = 0;
23283 public ScrollabilityCache(ViewConfiguration configuration, View host) {
23284 fadingEdgeLength = configuration.getScaledFadingEdgeLength();
23285 scrollBarSize = configuration.getScaledScrollBarSize();
23286 scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
23287 scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
23289 paint = new Paint();
23290 matrix = new Matrix();
23291 // use use a height of 1, and then wack the matrix each time we
23292 // actually use it.
23293 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
23294 paint.setShader(shader);
23295 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
23300 public void setFadeColor(int color) {
23301 if (color != mLastColor) {
23302 mLastColor = color;
23305 shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
23306 color & 0x00FFFFFF, Shader.TileMode.CLAMP);
23307 paint.setShader(shader);
23308 // Restore the default transfer mode (src_over)
23309 paint.setXfermode(null);
23311 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
23312 paint.setShader(shader);
23313 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
23318 public void run() {
23319 long now = AnimationUtils.currentAnimationTimeMillis();
23320 if (now >= fadeStartTime) {
23322 // the animation fades the scrollbars out by changing
23323 // the opacity (alpha) from fully opaque to fully
23325 int nextFrame = (int) now;
23326 int framesCount = 0;
23328 Interpolator interpolator = scrollBarInterpolator;
23331 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
23334 nextFrame += scrollBarFadeDuration;
23335 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
23339 // Kick off the fade animation
23340 host.invalidate(true);
23346 * Resuable callback for sending
23347 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
23349 private class SendViewScrolledAccessibilityEvent implements Runnable {
23350 public volatile boolean mIsPending;
23352 public void run() {
23353 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
23354 mIsPending = false;
23360 * This class represents a delegate that can be registered in a {@link View}
23361 * to enhance accessibility support via composition rather via inheritance.
23362 * It is specifically targeted to widget developers that extend basic View
23363 * classes i.e. classes in package android.view, that would like their
23364 * applications to be backwards compatible.
23366 * <div class="special reference">
23367 * <h3>Developer Guides</h3>
23368 * <p>For more information about making applications accessible, read the
23369 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
23370 * developer guide.</p>
23373 * A scenario in which a developer would like to use an accessibility delegate
23374 * is overriding a method introduced in a later API version then the minimal API
23375 * version supported by the application. For example, the method
23376 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
23377 * in API version 4 when the accessibility APIs were first introduced. If a
23378 * developer would like his application to run on API version 4 devices (assuming
23379 * all other APIs used by the application are version 4 or lower) and take advantage
23380 * of this method, instead of overriding the method which would break the application's
23381 * backwards compatibility, he can override the corresponding method in this
23382 * delegate and register the delegate in the target View if the API version of
23383 * the system is high enough i.e. the API version is same or higher to the API
23384 * version that introduced
23385 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
23388 * Here is an example implementation:
23391 * if (Build.VERSION.SDK_INT >= 14) {
23392 * // If the API version is equal of higher than the version in
23393 * // which onInitializeAccessibilityNodeInfo was introduced we
23394 * // register a delegate with a customized implementation.
23395 * View view = findViewById(R.id.view_id);
23396 * view.setAccessibilityDelegate(new AccessibilityDelegate() {
23397 * public void onInitializeAccessibilityNodeInfo(View host,
23398 * AccessibilityNodeInfo info) {
23399 * // Let the default implementation populate the info.
23400 * super.onInitializeAccessibilityNodeInfo(host, info);
23401 * // Set some other information.
23402 * info.setEnabled(host.isEnabled());
23406 * </code></pre></p>
23408 * This delegate contains methods that correspond to the accessibility methods
23409 * in View. If a delegate has been specified the implementation in View hands
23410 * off handling to the corresponding method in this delegate. The default
23411 * implementation the delegate methods behaves exactly as the corresponding
23412 * method in View for the case of no accessibility delegate been set. Hence,
23413 * to customize the behavior of a View method, clients can override only the
23414 * corresponding delegate method without altering the behavior of the rest
23415 * accessibility related methods of the host view.
23418 * <strong>Note:</strong> On platform versions prior to
23419 * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
23420 * views in the {@code android.widget.*} package are called <i>before</i>
23421 * host methods. This prevents certain properties such as class name from
23422 * being modified by overriding
23423 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
23424 * as any changes will be overwritten by the host class.
23426 * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
23427 * methods are called <i>after</i> host methods, which all properties to be
23428 * modified without being overwritten by the host class.
23430 public static class AccessibilityDelegate {
23433 * Sends an accessibility event of the given type. If accessibility is not
23434 * enabled this method has no effect.
23436 * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
23437 * View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
23441 * @param host The View hosting the delegate.
23442 * @param eventType The type of the event to send.
23444 * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
23446 public void sendAccessibilityEvent(View host, int eventType) {
23447 host.sendAccessibilityEventInternal(eventType);
23451 * Performs the specified accessibility action on the view. For
23452 * possible accessibility actions look at {@link AccessibilityNodeInfo}.
23454 * The default implementation behaves as
23455 * {@link View#performAccessibilityAction(int, Bundle)
23456 * View#performAccessibilityAction(int, Bundle)} for the case of
23457 * no accessibility delegate been set.
23460 * @param action The action to perform.
23461 * @return Whether the action was performed.
23463 * @see View#performAccessibilityAction(int, Bundle)
23464 * View#performAccessibilityAction(int, Bundle)
23466 public boolean performAccessibilityAction(View host, int action, Bundle args) {
23467 return host.performAccessibilityActionInternal(action, args);
23471 * Sends an accessibility event. This method behaves exactly as
23472 * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
23473 * empty {@link AccessibilityEvent} and does not perform a check whether
23474 * accessibility is enabled.
23476 * The default implementation behaves as
23477 * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23478 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
23479 * the case of no accessibility delegate been set.
23482 * @param host The View hosting the delegate.
23483 * @param event The event to send.
23485 * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23486 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23488 public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
23489 host.sendAccessibilityEventUncheckedInternal(event);
23493 * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
23494 * to its children for adding their text content to the event.
23496 * The default implementation behaves as
23497 * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23498 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
23499 * the case of no accessibility delegate been set.
23502 * @param host The View hosting the delegate.
23503 * @param event The event.
23504 * @return True if the event population was completed.
23506 * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23507 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23509 public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
23510 return host.dispatchPopulateAccessibilityEventInternal(event);
23514 * Gives a chance to the host View to populate the accessibility event with its
23517 * The default implementation behaves as
23518 * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
23519 * View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
23520 * the case of no accessibility delegate been set.
23523 * @param host The View hosting the delegate.
23524 * @param event The accessibility event which to populate.
23526 * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
23527 * View#onPopulateAccessibilityEvent(AccessibilityEvent)
23529 public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
23530 host.onPopulateAccessibilityEventInternal(event);
23534 * Initializes an {@link AccessibilityEvent} with information about the
23535 * the host View which is the event source.
23537 * The default implementation behaves as
23538 * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
23539 * View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
23540 * the case of no accessibility delegate been set.
23543 * @param host The View hosting the delegate.
23544 * @param event The event to initialize.
23546 * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
23547 * View#onInitializeAccessibilityEvent(AccessibilityEvent)
23549 public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
23550 host.onInitializeAccessibilityEventInternal(event);
23554 * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
23556 * The default implementation behaves as
23557 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23558 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
23559 * the case of no accessibility delegate been set.
23562 * @param host The View hosting the delegate.
23563 * @param info The instance to initialize.
23565 * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23566 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23568 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
23569 host.onInitializeAccessibilityNodeInfoInternal(info);
23573 * Called when a child of the host View has requested sending an
23574 * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
23575 * to augment the event.
23577 * The default implementation behaves as
23578 * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23579 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
23580 * the case of no accessibility delegate been set.
23583 * @param host The View hosting the delegate.
23584 * @param child The child which requests sending the event.
23585 * @param event The event to be sent.
23586 * @return True if the event should be sent
23588 * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23589 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23591 public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
23592 AccessibilityEvent event) {
23593 return host.onRequestSendAccessibilityEventInternal(child, event);
23597 * Gets the provider for managing a virtual view hierarchy rooted at this View
23598 * and reported to {@link android.accessibilityservice.AccessibilityService}s
23599 * that explore the window content.
23601 * The default implementation behaves as
23602 * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
23603 * the case of no accessibility delegate been set.
23606 * @return The provider.
23608 * @see AccessibilityNodeProvider
23610 public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
23615 * Returns an {@link AccessibilityNodeInfo} representing the host view from the
23616 * point of view of an {@link android.accessibilityservice.AccessibilityService}.
23617 * This method is responsible for obtaining an accessibility node info from a
23618 * pool of reusable instances and calling
23619 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
23620 * view to initialize the former.
23622 * <strong>Note:</strong> The client is responsible for recycling the obtained
23623 * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
23627 * The default implementation behaves as
23628 * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
23629 * the case of no accessibility delegate been set.
23631 * @return A populated {@link AccessibilityNodeInfo}.
23633 * @see AccessibilityNodeInfo
23637 public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
23638 return host.createAccessibilityNodeInfoInternal();
23642 private class MatchIdPredicate implements Predicate<View> {
23646 public boolean apply(View view) {
23647 return (view.mID == mId);
23651 private class MatchLabelForPredicate implements Predicate<View> {
23652 private int mLabeledId;
23655 public boolean apply(View view) {
23656 return (view.mLabelForId == mLabeledId);
23660 private class SendViewStateChangedAccessibilityEvent implements Runnable {
23661 private int mChangeTypes = 0;
23662 private boolean mPosted;
23663 private boolean mPostedWithDelay;
23664 private long mLastEventTimeMillis;
23667 public void run() {
23669 mPostedWithDelay = false;
23670 mLastEventTimeMillis = SystemClock.uptimeMillis();
23671 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
23672 final AccessibilityEvent event = AccessibilityEvent.obtain();
23673 event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
23674 event.setContentChangeTypes(mChangeTypes);
23675 sendAccessibilityEventUnchecked(event);
23680 public void runOrPost(int changeType) {
23681 mChangeTypes |= changeType;
23683 // If this is a live region or the child of a live region, collect
23684 // all events from this frame and send them on the next frame.
23685 if (inLiveRegion()) {
23686 // If we're already posted with a delay, remove that.
23687 if (mPostedWithDelay) {
23688 removeCallbacks(this);
23689 mPostedWithDelay = false;
23691 // Only post if we're not already posted.
23703 final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
23704 final long minEventIntevalMillis =
23705 ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
23706 if (timeSinceLastMillis >= minEventIntevalMillis) {
23707 removeCallbacks(this);
23710 postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
23711 mPostedWithDelay = true;
23716 private boolean inLiveRegion() {
23717 if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
23721 ViewParent parent = getParent();
23722 while (parent instanceof View) {
23723 if (((View) parent).getAccessibilityLiveRegion()
23724 != View.ACCESSIBILITY_LIVE_REGION_NONE) {
23727 parent = parent.getParent();
23734 * Dump all private flags in readable format, useful for documentation and
23737 private static void dumpFlags() {
23738 final HashMap<String, String> found = Maps.newHashMap();
23740 for (Field field : View.class.getDeclaredFields()) {
23741 final int modifiers = field.getModifiers();
23742 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
23743 if (field.getType().equals(int.class)) {
23744 final int value = field.getInt(null);
23745 dumpFlag(found, field.getName(), value);
23746 } else if (field.getType().equals(int[].class)) {
23747 final int[] values = (int[]) field.get(null);
23748 for (int i = 0; i < values.length; i++) {
23749 dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
23754 } catch (IllegalAccessException e) {
23755 throw new RuntimeException(e);
23758 final ArrayList<String> keys = Lists.newArrayList();
23759 keys.addAll(found.keySet());
23760 Collections.sort(keys);
23761 for (String key : keys) {
23762 Log.d(VIEW_LOG_TAG, found.get(key));
23766 private static void dumpFlag(HashMap<String, String> found, String name, int value) {
23767 // Sort flags by prefix, then by bits, always keeping unique keys
23768 final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
23769 final int prefix = name.indexOf('_');
23770 final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
23771 final String output = bits + " " + name;
23772 found.put(key, output);
23776 public void encode(@NonNull ViewHierarchyEncoder stream) {
23777 stream.beginObject(this);
23778 encodeProperties(stream);
23779 stream.endObject();
23784 protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
23785 Object resolveId = ViewDebug.resolveId(getContext(), mID);
23786 if (resolveId instanceof String) {
23787 stream.addProperty("id", (String) resolveId);
23789 stream.addProperty("id", mID);
23792 stream.addProperty("misc:transformation.alpha",
23793 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
23794 stream.addProperty("misc:transitionName", getTransitionName());
23797 stream.addProperty("layout:left", mLeft);
23798 stream.addProperty("layout:right", mRight);
23799 stream.addProperty("layout:top", mTop);
23800 stream.addProperty("layout:bottom", mBottom);
23801 stream.addProperty("layout:width", getWidth());
23802 stream.addProperty("layout:height", getHeight());
23803 stream.addProperty("layout:layoutDirection", getLayoutDirection());
23804 stream.addProperty("layout:layoutRtl", isLayoutRtl());
23805 stream.addProperty("layout:hasTransientState", hasTransientState());
23806 stream.addProperty("layout:baseline", getBaseline());
23809 ViewGroup.LayoutParams layoutParams = getLayoutParams();
23810 if (layoutParams != null) {
23811 stream.addPropertyKey("layoutParams");
23812 layoutParams.encode(stream);
23816 stream.addProperty("scrolling:scrollX", mScrollX);
23817 stream.addProperty("scrolling:scrollY", mScrollY);
23820 stream.addProperty("padding:paddingLeft", mPaddingLeft);
23821 stream.addProperty("padding:paddingRight", mPaddingRight);
23822 stream.addProperty("padding:paddingTop", mPaddingTop);
23823 stream.addProperty("padding:paddingBottom", mPaddingBottom);
23824 stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
23825 stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
23826 stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
23827 stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
23828 stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
23831 stream.addProperty("measurement:minHeight", mMinHeight);
23832 stream.addProperty("measurement:minWidth", mMinWidth);
23833 stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
23834 stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
23837 stream.addProperty("drawing:elevation", getElevation());
23838 stream.addProperty("drawing:translationX", getTranslationX());
23839 stream.addProperty("drawing:translationY", getTranslationY());
23840 stream.addProperty("drawing:translationZ", getTranslationZ());
23841 stream.addProperty("drawing:rotation", getRotation());
23842 stream.addProperty("drawing:rotationX", getRotationX());
23843 stream.addProperty("drawing:rotationY", getRotationY());
23844 stream.addProperty("drawing:scaleX", getScaleX());
23845 stream.addProperty("drawing:scaleY", getScaleY());
23846 stream.addProperty("drawing:pivotX", getPivotX());
23847 stream.addProperty("drawing:pivotY", getPivotY());
23848 stream.addProperty("drawing:opaque", isOpaque());
23849 stream.addProperty("drawing:alpha", getAlpha());
23850 stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
23851 stream.addProperty("drawing:shadow", hasShadow());
23852 stream.addProperty("drawing:solidColor", getSolidColor());
23853 stream.addProperty("drawing:layerType", mLayerType);
23854 stream.addProperty("drawing:willNotDraw", willNotDraw());
23855 stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
23856 stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
23857 stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
23858 stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
23861 stream.addProperty("focus:hasFocus", hasFocus());
23862 stream.addProperty("focus:isFocused", isFocused());
23863 stream.addProperty("focus:isFocusable", isFocusable());
23864 stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
23866 stream.addProperty("misc:clickable", isClickable());
23867 stream.addProperty("misc:pressed", isPressed());
23868 stream.addProperty("misc:selected", isSelected());
23869 stream.addProperty("misc:touchMode", isInTouchMode());
23870 stream.addProperty("misc:hovered", isHovered());
23871 stream.addProperty("misc:activated", isActivated());
23873 stream.addProperty("misc:visibility", getVisibility());
23874 stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
23875 stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
23877 stream.addProperty("misc:enabled", isEnabled());
23878 stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
23879 stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
23881 // theme attributes
23882 Resources.Theme theme = getContext().getTheme();
23883 if (theme != null) {
23884 stream.addPropertyKey("theme");
23885 theme.encode(stream);
23888 // view attribute information
23889 int n = mAttributes != null ? mAttributes.length : 0;
23890 stream.addProperty("meta:__attrCount__", n/2);
23891 for (int i = 0; i < n; i += 2) {
23892 stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
23895 stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
23898 stream.addProperty("text:textDirection", getTextDirection());
23899 stream.addProperty("text:textAlignment", getTextAlignment());
23902 CharSequence contentDescription = getContentDescription();
23903 stream.addProperty("accessibility:contentDescription",
23904 contentDescription == null ? "" : contentDescription.toString());
23905 stream.addProperty("accessibility:labelFor", getLabelFor());
23906 stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
23910 * Determine if this view is rendered on a round wearable device and is the main view
23913 private boolean shouldDrawRoundScrollbar() {
23914 if (!mResources.getConfiguration().isScreenRound()) {
23918 final View rootView = getRootView();
23919 final WindowInsets insets = getRootWindowInsets();
23921 int height = getHeight();
23922 int width = getWidth();
23923 int displayHeight = rootView.getHeight();
23924 int displayWidth = rootView.getWidth();
23926 if (height != displayHeight || width != displayWidth) {
23930 getLocationOnScreen(mAttachInfo.mTmpLocation);
23931 return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
23932 && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();