2 * Copyright (C) 2006 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 import android.animation.AnimatorInflater;
20 import android.animation.StateListAnimator;
21 import android.annotation.IntDef;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.content.ClipData;
25 import android.content.Context;
26 import android.content.res.ColorStateList;
27 import android.content.res.Configuration;
28 import android.content.res.Resources;
29 import android.content.res.TypedArray;
30 import android.graphics.Bitmap;
31 import android.graphics.Canvas;
32 import android.graphics.Insets;
33 import android.graphics.Interpolator;
34 import android.graphics.LinearGradient;
35 import android.graphics.Matrix;
36 import android.graphics.Outline;
37 import android.graphics.Paint;
38 import android.graphics.Path;
39 import android.graphics.PathMeasure;
40 import android.graphics.PixelFormat;
41 import android.graphics.Point;
42 import android.graphics.PorterDuff;
43 import android.graphics.PorterDuffXfermode;
44 import android.graphics.Rect;
45 import android.graphics.RectF;
46 import android.graphics.Region;
47 import android.graphics.Shader;
48 import android.graphics.drawable.ColorDrawable;
49 import android.graphics.drawable.Drawable;
50 import android.hardware.display.DisplayManagerGlobal;
51 import android.os.Bundle;
52 import android.os.Handler;
53 import android.os.IBinder;
54 import android.os.Parcel;
55 import android.os.Parcelable;
56 import android.os.RemoteException;
57 import android.os.SystemClock;
58 import android.os.SystemProperties;
59 import android.text.TextUtils;
60 import android.util.AttributeSet;
61 import android.util.FloatProperty;
62 import android.util.LayoutDirection;
63 import android.util.Log;
64 import android.util.LongSparseLongArray;
65 import android.util.Pools.SynchronizedPool;
66 import android.util.Property;
67 import android.util.SparseArray;
68 import android.util.SuperNotCalledException;
69 import android.util.TypedValue;
70 import android.view.ContextMenu.ContextMenuInfo;
71 import android.view.AccessibilityIterators.TextSegmentIterator;
72 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
73 import android.view.AccessibilityIterators.WordTextSegmentIterator;
74 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
75 import android.view.accessibility.AccessibilityEvent;
76 import android.view.accessibility.AccessibilityEventSource;
77 import android.view.accessibility.AccessibilityManager;
78 import android.view.accessibility.AccessibilityNodeInfo;
79 import android.view.accessibility.AccessibilityNodeProvider;
80 import android.view.animation.Animation;
81 import android.view.animation.AnimationUtils;
82 import android.view.animation.Transformation;
83 import android.view.inputmethod.EditorInfo;
84 import android.view.inputmethod.InputConnection;
85 import android.view.inputmethod.InputMethodManager;
86 import android.widget.ScrollBarDrawable;
88 import static android.os.Build.VERSION_CODES.*;
89 import static java.lang.Math.max;
91 import com.android.internal.R;
92 import com.android.internal.util.Predicate;
93 import com.android.internal.view.menu.MenuBuilder;
94 import com.google.android.collect.Lists;
95 import com.google.android.collect.Maps;
97 import java.lang.annotation.Retention;
98 import java.lang.annotation.RetentionPolicy;
99 import java.lang.ref.WeakReference;
100 import java.lang.reflect.Field;
101 import java.lang.reflect.InvocationTargetException;
102 import java.lang.reflect.Method;
103 import java.lang.reflect.Modifier;
104 import java.util.ArrayList;
105 import java.util.Arrays;
106 import java.util.Collections;
107 import java.util.HashMap;
108 import java.util.List;
109 import java.util.Locale;
110 import java.util.Map;
111 import java.util.concurrent.CopyOnWriteArrayList;
112 import java.util.concurrent.atomic.AtomicInteger;
116 * This class represents the basic building block for user interface components. A View
117 * occupies a rectangular area on the screen and is responsible for drawing and
118 * event handling. View is the base class for <em>widgets</em>, which are
119 * used to create interactive UI components (buttons, text fields, etc.). The
120 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
121 * are invisible containers that hold other Views (or other ViewGroups) and define
122 * their layout properties.
125 * <div class="special reference">
126 * <h3>Developer Guides</h3>
127 * <p>For information about using this class to develop your application's user interface,
128 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
131 * <a name="Using"></a>
132 * <h3>Using Views</h3>
134 * All of the views in a window are arranged in a single tree. You can add views
135 * either from code or by specifying a tree of views in one or more XML layout
136 * files. There are many specialized subclasses of views that act as controls or
137 * are capable of displaying text, images, or other content.
140 * Once you have created a tree of views, there are typically a few types of
141 * common operations you may wish to perform:
143 * <li><strong>Set properties:</strong> for example setting the text of a
144 * {@link android.widget.TextView}. The available properties and the methods
145 * that set them will vary among the different subclasses of views. Note that
146 * properties that are known at build time can be set in the XML layout
148 * <li><strong>Set focus:</strong> The framework will handled moving focus in
149 * response to user input. To force focus to a specific view, call
150 * {@link #requestFocus}.</li>
151 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
152 * that will be notified when something interesting happens to the view. For
153 * example, all views will let you set a listener to be notified when the view
154 * gains or loses focus. You can register such a listener using
155 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
156 * Other view subclasses offer more specialized listeners. For example, a Button
157 * exposes a listener to notify clients when the button is clicked.</li>
158 * <li><strong>Set visibility:</strong> You can hide or show views using
159 * {@link #setVisibility(int)}.</li>
163 * Note: The Android framework is responsible for measuring, laying out and
164 * drawing views. You should not call methods that perform these actions on
165 * views yourself unless you are actually implementing a
166 * {@link android.view.ViewGroup}.
169 * <a name="Lifecycle"></a>
170 * <h3>Implementing a Custom View</h3>
173 * To implement a custom view, you will usually begin by providing overrides for
174 * some of the standard methods that the framework calls on all views. You do
175 * not need to override all of these methods. In fact, you can start by just
176 * overriding {@link #onDraw(android.graphics.Canvas)}.
177 * <table border="2" width="85%" align="center" cellpadding="5">
179 * <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
184 * <td rowspan="2">Creation</td>
185 * <td>Constructors</td>
186 * <td>There is a form of the constructor that are called when the view
187 * is created from code and a form that is called when the view is
188 * inflated from a layout file. The second form should parse and apply
189 * any attributes defined in the layout file.
193 * <td><code>{@link #onFinishInflate()}</code></td>
194 * <td>Called after a view and all of its children has been inflated
199 * <td rowspan="3">Layout</td>
200 * <td><code>{@link #onMeasure(int, int)}</code></td>
201 * <td>Called to determine the size requirements for this view and all
206 * <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
207 * <td>Called when this view should assign a size and position to all
212 * <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
213 * <td>Called when the size of this view has changed.
219 * <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
220 * <td>Called when the view should render its content.
225 * <td rowspan="4">Event processing</td>
226 * <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
227 * <td>Called when a new hardware key event occurs.
231 * <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
232 * <td>Called when a hardware key up event occurs.
236 * <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
237 * <td>Called when a trackball motion event occurs.
241 * <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
242 * <td>Called when a touch screen motion event occurs.
247 * <td rowspan="2">Focus</td>
248 * <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
249 * <td>Called when the view gains or loses focus.
254 * <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
255 * <td>Called when the window containing the view gains or loses focus.
260 * <td rowspan="3">Attaching</td>
261 * <td><code>{@link #onAttachedToWindow()}</code></td>
262 * <td>Called when the view is attached to a window.
267 * <td><code>{@link #onDetachedFromWindow}</code></td>
268 * <td>Called when the view is detached from its window.
273 * <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
274 * <td>Called when the visibility of the window containing the view
285 * Views may have an integer id associated with them. These ids are typically
286 * assigned in the layout XML files, and are used to find specific views within
287 * the view tree. A common pattern is to:
289 * <li>Define a Button in the layout file and assign it a unique ID.
292 * android:id="@+id/my_button"
293 * android:layout_width="wrap_content"
294 * android:layout_height="wrap_content"
295 * android:text="@string/my_button_text"/>
297 * <li>From the onCreate method of an Activity, find the Button
298 * <pre class="prettyprint">
299 * Button myButton = (Button) findViewById(R.id.my_button);
303 * View IDs need not be unique throughout the tree, but it is good practice to
304 * ensure that they are at least unique within the part of the tree you are
308 * <a name="Position"></a>
311 * The geometry of a view is that of a rectangle. A view has a location,
312 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
313 * two dimensions, expressed as a width and a height. The unit for location
314 * and dimensions is the pixel.
318 * It is possible to retrieve the location of a view by invoking the methods
319 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
320 * coordinate of the rectangle representing the view. The latter returns the
321 * top, or Y, coordinate of the rectangle representing the view. These methods
322 * both return the location of the view relative to its parent. For instance,
323 * when getLeft() returns 20, that means the view is located 20 pixels to the
324 * right of the left edge of its direct parent.
328 * In addition, several convenience methods are offered to avoid unnecessary
329 * computations, namely {@link #getRight()} and {@link #getBottom()}.
330 * These methods return the coordinates of the right and bottom edges of the
331 * rectangle representing the view. For instance, calling {@link #getRight()}
332 * is similar to the following computation: <code>getLeft() + getWidth()</code>
333 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
336 * <a name="SizePaddingMargins"></a>
337 * <h3>Size, padding and margins</h3>
339 * The size of a view is expressed with a width and a height. A view actually
340 * possess two pairs of width and height values.
344 * The first pair is known as <em>measured width</em> and
345 * <em>measured height</em>. These dimensions define how big a view wants to be
346 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
347 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
348 * and {@link #getMeasuredHeight()}.
352 * The second pair is simply known as <em>width</em> and <em>height</em>, or
353 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
354 * dimensions define the actual size of the view on screen, at drawing time and
355 * after layout. These values may, but do not have to, be different from the
356 * measured width and height. The width and height can be obtained by calling
357 * {@link #getWidth()} and {@link #getHeight()}.
361 * To measure its dimensions, a view takes into account its padding. The padding
362 * is expressed in pixels for the left, top, right and bottom parts of the view.
363 * Padding can be used to offset the content of the view by a specific amount of
364 * pixels. For instance, a left padding of 2 will push the view's content by
365 * 2 pixels to the right of the left edge. Padding can be set using the
366 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
367 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
368 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
369 * {@link #getPaddingEnd()}.
373 * Even though a view can define a padding, it does not provide any support for
374 * margins. However, view groups provide such a support. Refer to
375 * {@link android.view.ViewGroup} and
376 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
379 * <a name="Layout"></a>
382 * Layout is a two pass process: a measure pass and a layout pass. The measuring
383 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
384 * of the view tree. Each view pushes dimension specifications down the tree
385 * during the recursion. At the end of the measure pass, every view has stored
386 * its measurements. The second pass happens in
387 * {@link #layout(int,int,int,int)} and is also top-down. During
388 * this pass each parent is responsible for positioning all of its children
389 * using the sizes computed in the measure pass.
393 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
394 * {@link #getMeasuredHeight()} values must be set, along with those for all of
395 * that view's descendants. A view's measured width and measured height values
396 * must respect the constraints imposed by the view's parents. This guarantees
397 * that at the end of the measure pass, all parents accept all of their
398 * children's measurements. A parent view may call measure() more than once on
399 * its children. For example, the parent may measure each child once with
400 * unspecified dimensions to find out how big they want to be, then call
401 * measure() on them again with actual numbers if the sum of all the children's
402 * unconstrained sizes is too big or too small.
406 * The measure pass uses two classes to communicate dimensions. The
407 * {@link MeasureSpec} class is used by views to tell their parents how they
408 * want to be measured and positioned. The base LayoutParams class just
409 * describes how big the view wants to be for both width and height. For each
410 * dimension, it can specify one of:
412 * <li> an exact number
413 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
415 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
416 * enclose its content (plus padding).
418 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
419 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
424 * MeasureSpecs are used to push requirements down the tree from parent to
425 * child. A MeasureSpec can be in one of three modes:
427 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
428 * of a child view. For example, a LinearLayout may call measure() on its child
429 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
430 * tall the child view wants to be given a width of 240 pixels.
431 * <li>EXACTLY: This is used by the parent to impose an exact size on the
432 * child. The child must use this size, and guarantee that all of its
433 * descendants will fit within this size.
434 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
435 * child. The child must guarantee that it and all of its descendants will fit
441 * To intiate a layout, call {@link #requestLayout}. This method is typically
442 * called by a view on itself when it believes that is can no longer fit within
443 * its current bounds.
446 * <a name="Drawing"></a>
449 * Drawing is handled by walking the tree and recording the drawing commands of
450 * any View that needs to update. After this, the drawing commands of the
451 * entire tree are issued to screen, clipped to the newly damaged area.
455 * The tree is largely recorded and drawn in order, with parents drawn before
456 * (i.e., behind) their children, with siblings drawn in the order they appear
457 * in the tree. If you set a background drawable for a View, then the View will
458 * draw it before calling back to its <code>onDraw()</code> method. The child
459 * drawing order can be overridden with
460 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
461 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
465 * To force a view to draw, call {@link #invalidate()}.
468 * <a name="EventHandlingThreading"></a>
469 * <h3>Event Handling and Threading</h3>
471 * The basic cycle of a view is as follows:
473 * <li>An event comes in and is dispatched to the appropriate view. The view
474 * handles the event and notifies any listeners.</li>
475 * <li>If in the course of processing the event, the view's bounds may need
476 * to be changed, the view will call {@link #requestLayout()}.</li>
477 * <li>Similarly, if in the course of processing the event the view's appearance
478 * may need to be changed, the view will call {@link #invalidate()}.</li>
479 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
480 * the framework will take care of measuring, laying out, and drawing the tree
481 * as appropriate.</li>
485 * <p><em>Note: The entire view tree is single threaded. You must always be on
486 * the UI thread when calling any method on any view.</em>
487 * If you are doing work on other threads and want to update the state of a view
488 * from that thread, you should use a {@link Handler}.
491 * <a name="FocusHandling"></a>
492 * <h3>Focus Handling</h3>
494 * The framework will handle routine focus movement in response to user input.
495 * This includes changing the focus as views are removed or hidden, or as new
496 * views become available. Views indicate their willingness to take focus
497 * through the {@link #isFocusable} method. To change whether a view can take
498 * focus, call {@link #setFocusable(boolean)}. When in touch mode (see notes below)
499 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
500 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
503 * Focus movement is based on an algorithm which finds the nearest neighbor in a
504 * given direction. In rare cases, the default algorithm may not match the
505 * intended behavior of the developer. In these situations, you can provide
506 * explicit overrides by using these XML attributes in the layout file:
517 * To get a particular view to take focus, call {@link #requestFocus()}.
520 * <a name="TouchMode"></a>
521 * <h3>Touch Mode</h3>
523 * When a user is navigating a user interface via directional keys such as a D-pad, it is
524 * necessary to give focus to actionable items such as buttons so the user can see
525 * what will take input. If the device has touch capabilities, however, and the user
526 * begins interacting with the interface by touching it, it is no longer necessary to
527 * always highlight, or give focus to, a particular view. This motivates a mode
528 * for interaction named 'touch mode'.
531 * For a touch capable device, once the user touches the screen, the device
532 * will enter touch mode. From this point onward, only views for which
533 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
534 * Other views that are touchable, like buttons, will not take focus when touched; they will
535 * only fire the on click listeners.
538 * Any time a user hits a directional key, such as a D-pad direction, the view device will
539 * exit touch mode, and find a view to take focus, so that the user may resume interacting
540 * with the user interface without touching the screen again.
543 * The touch mode state is maintained across {@link android.app.Activity}s. Call
544 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
547 * <a name="Scrolling"></a>
550 * The framework provides basic support for views that wish to internally
551 * scroll their content. This includes keeping track of the X and Y scroll
552 * offset as well as mechanisms for drawing scrollbars. See
553 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
554 * {@link #awakenScrollBars()} for more details.
557 * <a name="Tags"></a>
560 * Unlike IDs, tags are not used to identify views. Tags are essentially an
561 * extra piece of information that can be associated with a view. They are most
562 * often used as a convenience to store data related to views in the views
563 * themselves rather than by putting them in a separate structure.
566 * <a name="Properties"></a>
567 * <h3>Properties</h3>
569 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
570 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
571 * available both in the {@link Property} form as well as in similarly-named setter/getter
572 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
573 * be used to set persistent state associated with these rendering-related properties on the view.
574 * The properties and methods can also be used in conjunction with
575 * {@link android.animation.Animator Animator}-based animations, described more in the
576 * <a href="#Animation">Animation</a> section.
579 * <a name="Animation"></a>
582 * Starting with Android 3.0, the preferred way of animating views is to use the
583 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
584 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
585 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
586 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
587 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
588 * makes animating these View properties particularly easy and efficient.
591 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
592 * You can attach an {@link Animation} object to a view using
593 * {@link #setAnimation(Animation)} or
594 * {@link #startAnimation(Animation)}. The animation can alter the scale,
595 * rotation, translation and alpha of a view over time. If the animation is
596 * attached to a view that has children, the animation will affect the entire
597 * subtree rooted by that node. When an animation is started, the framework will
598 * take care of redrawing the appropriate views until the animation completes.
601 * <a name="Security"></a>
604 * Sometimes it is essential that an application be able to verify that an action
605 * is being performed with the full knowledge and consent of the user, such as
606 * granting a permission request, making a purchase or clicking on an advertisement.
607 * Unfortunately, a malicious application could try to spoof the user into
608 * performing these actions, unaware, by concealing the intended purpose of the view.
609 * As a remedy, the framework offers a touch filtering mechanism that can be used to
610 * improve the security of views that provide access to sensitive functionality.
612 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
613 * android:filterTouchesWhenObscured layout attribute to true. When enabled, the framework
614 * will discard touches that are received whenever the view's window is obscured by
615 * another visible window. As a result, the view will not receive touches whenever a
616 * toast, dialog or other window appears above the view's window.
618 * For more fine-grained control over security, consider overriding the
619 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
620 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
623 * @attr ref android.R.styleable#View_alpha
624 * @attr ref android.R.styleable#View_background
625 * @attr ref android.R.styleable#View_clickable
626 * @attr ref android.R.styleable#View_contentDescription
627 * @attr ref android.R.styleable#View_drawingCacheQuality
628 * @attr ref android.R.styleable#View_duplicateParentState
629 * @attr ref android.R.styleable#View_id
630 * @attr ref android.R.styleable#View_requiresFadingEdge
631 * @attr ref android.R.styleable#View_fadeScrollbars
632 * @attr ref android.R.styleable#View_fadingEdgeLength
633 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
634 * @attr ref android.R.styleable#View_fitsSystemWindows
635 * @attr ref android.R.styleable#View_isScrollContainer
636 * @attr ref android.R.styleable#View_focusable
637 * @attr ref android.R.styleable#View_focusableInTouchMode
638 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
639 * @attr ref android.R.styleable#View_keepScreenOn
640 * @attr ref android.R.styleable#View_layerType
641 * @attr ref android.R.styleable#View_layoutDirection
642 * @attr ref android.R.styleable#View_longClickable
643 * @attr ref android.R.styleable#View_minHeight
644 * @attr ref android.R.styleable#View_minWidth
645 * @attr ref android.R.styleable#View_nextFocusDown
646 * @attr ref android.R.styleable#View_nextFocusLeft
647 * @attr ref android.R.styleable#View_nextFocusRight
648 * @attr ref android.R.styleable#View_nextFocusUp
649 * @attr ref android.R.styleable#View_onClick
650 * @attr ref android.R.styleable#View_padding
651 * @attr ref android.R.styleable#View_paddingBottom
652 * @attr ref android.R.styleable#View_paddingLeft
653 * @attr ref android.R.styleable#View_paddingRight
654 * @attr ref android.R.styleable#View_paddingTop
655 * @attr ref android.R.styleable#View_paddingStart
656 * @attr ref android.R.styleable#View_paddingEnd
657 * @attr ref android.R.styleable#View_saveEnabled
658 * @attr ref android.R.styleable#View_rotation
659 * @attr ref android.R.styleable#View_rotationX
660 * @attr ref android.R.styleable#View_rotationY
661 * @attr ref android.R.styleable#View_scaleX
662 * @attr ref android.R.styleable#View_scaleY
663 * @attr ref android.R.styleable#View_scrollX
664 * @attr ref android.R.styleable#View_scrollY
665 * @attr ref android.R.styleable#View_scrollbarSize
666 * @attr ref android.R.styleable#View_scrollbarStyle
667 * @attr ref android.R.styleable#View_scrollbars
668 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
669 * @attr ref android.R.styleable#View_scrollbarFadeDuration
670 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
671 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
672 * @attr ref android.R.styleable#View_scrollbarThumbVertical
673 * @attr ref android.R.styleable#View_scrollbarTrackVertical
674 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
675 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
676 * @attr ref android.R.styleable#View_stateListAnimator
677 * @attr ref android.R.styleable#View_transitionName
678 * @attr ref android.R.styleable#View_soundEffectsEnabled
679 * @attr ref android.R.styleable#View_tag
680 * @attr ref android.R.styleable#View_textAlignment
681 * @attr ref android.R.styleable#View_textDirection
682 * @attr ref android.R.styleable#View_transformPivotX
683 * @attr ref android.R.styleable#View_transformPivotY
684 * @attr ref android.R.styleable#View_translationX
685 * @attr ref android.R.styleable#View_translationY
686 * @attr ref android.R.styleable#View_translationZ
687 * @attr ref android.R.styleable#View_visibility
689 * @see android.view.ViewGroup
691 public class View implements Drawable.Callback, KeyEvent.Callback,
692 AccessibilityEventSource {
693 private static final boolean DBG = false;
696 * The logging tag used by this class with android.util.Log.
698 protected static final String VIEW_LOG_TAG = "View";
701 * When set to true, apps will draw debugging information about their layouts.
705 public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
708 * When set to true, this view will save its attribute data.
712 public static boolean mDebugViewAttributes = false;
715 * Used to mark a View that has no ID.
717 public static final int NO_ID = -1;
720 * Signals that compatibility booleans have been initialized according to
721 * target SDK versions.
723 private static boolean sCompatibilityDone = false;
726 * Use the old (broken) way of building MeasureSpecs.
728 private static boolean sUseBrokenMakeMeasureSpec = false;
731 * Ignore any optimizations using the measure cache.
733 private static boolean sIgnoreMeasureCache = false;
736 * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
739 private static final int NOT_FOCUSABLE = 0x00000000;
742 * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
745 private static final int FOCUSABLE = 0x00000001;
748 * Mask for use with setFlags indicating bits used for focus.
750 private static final int FOCUSABLE_MASK = 0x00000001;
753 * This view will adjust its padding to fit sytem windows (e.g. status bar)
755 private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
758 @IntDef({VISIBLE, INVISIBLE, GONE})
759 @Retention(RetentionPolicy.SOURCE)
760 public @interface Visibility {}
763 * This view is visible.
764 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
765 * android:visibility}.
767 public static final int VISIBLE = 0x00000000;
770 * This view is invisible, but it still takes up space for layout purposes.
771 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
772 * android:visibility}.
774 public static final int INVISIBLE = 0x00000004;
777 * This view is invisible, and it doesn't take any space for layout
778 * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
779 * android:visibility}.
781 public static final int GONE = 0x00000008;
784 * Mask for use with setFlags indicating bits used for visibility.
787 static final int VISIBILITY_MASK = 0x0000000C;
789 private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
792 * This view is enabled. Interpretation varies by subclass.
793 * Use with ENABLED_MASK when calling setFlags.
796 static final int ENABLED = 0x00000000;
799 * This view is disabled. Interpretation varies by subclass.
800 * Use with ENABLED_MASK when calling setFlags.
803 static final int DISABLED = 0x00000020;
806 * Mask for use with setFlags indicating bits used for indicating whether
807 * this view is enabled
810 static final int ENABLED_MASK = 0x00000020;
813 * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
814 * called and further optimizations will be performed. It is okay to have
815 * this flag set and a background. Use with DRAW_MASK when calling setFlags.
818 static final int WILL_NOT_DRAW = 0x00000080;
821 * Mask for use with setFlags indicating bits used for indicating whether
822 * this view is will draw
825 static final int DRAW_MASK = 0x00000080;
828 * <p>This view doesn't show scrollbars.</p>
831 static final int SCROLLBARS_NONE = 0x00000000;
834 * <p>This view shows horizontal scrollbars.</p>
837 static final int SCROLLBARS_HORIZONTAL = 0x00000100;
840 * <p>This view shows vertical scrollbars.</p>
843 static final int SCROLLBARS_VERTICAL = 0x00000200;
846 * <p>Mask for use with setFlags indicating bits used for indicating which
847 * scrollbars are enabled.</p>
850 static final int SCROLLBARS_MASK = 0x00000300;
853 * Indicates that the view should filter touches when its window is obscured.
854 * Refer to the class comments for more information about this security feature.
857 static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
860 * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
861 * that they are optional and should be skipped if the window has
862 * requested system UI flags that ignore those insets for layout.
864 static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
867 * <p>This view doesn't show fading edges.</p>
870 static final int FADING_EDGE_NONE = 0x00000000;
873 * <p>This view shows horizontal fading edges.</p>
876 static final int FADING_EDGE_HORIZONTAL = 0x00001000;
879 * <p>This view shows vertical fading edges.</p>
882 static final int FADING_EDGE_VERTICAL = 0x00002000;
885 * <p>Mask for use with setFlags indicating bits used for indicating which
886 * fading edges are enabled.</p>
889 static final int FADING_EDGE_MASK = 0x00003000;
892 * <p>Indicates this view can be clicked. When clickable, a View reacts
893 * to clicks by notifying the OnClickListener.<p>
896 static final int CLICKABLE = 0x00004000;
899 * <p>Indicates this view is caching its drawing into a bitmap.</p>
902 static final int DRAWING_CACHE_ENABLED = 0x00008000;
905 * <p>Indicates that no icicle should be saved for this view.<p>
908 static final int SAVE_DISABLED = 0x000010000;
911 * <p>Mask for use with setFlags indicating bits used for the saveEnabled
915 static final int SAVE_DISABLED_MASK = 0x000010000;
918 * <p>Indicates that no drawing cache should ever be created for this view.<p>
921 static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
924 * <p>Indicates this view can take / keep focus when int touch mode.</p>
927 static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
930 @Retention(RetentionPolicy.SOURCE)
931 @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
932 public @interface DrawingCacheQuality {}
935 * <p>Enables low quality mode for the drawing cache.</p>
937 public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
940 * <p>Enables high quality mode for the drawing cache.</p>
942 public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
945 * <p>Enables automatic quality mode for the drawing cache.</p>
947 public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
949 private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
950 DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
954 * <p>Mask for use with setFlags indicating bits used for the cache
955 * quality property.</p>
958 static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
962 * Indicates this view can be long clicked. When long clickable, a View
963 * reacts to long clicks by notifying the OnLongClickListener or showing a
968 static final int LONG_CLICKABLE = 0x00200000;
971 * <p>Indicates that this view gets its drawable states from its direct parent
972 * and ignores its original internal states.</p>
976 static final int DUPLICATE_PARENT_STATE = 0x00400000;
980 SCROLLBARS_INSIDE_OVERLAY,
981 SCROLLBARS_INSIDE_INSET,
982 SCROLLBARS_OUTSIDE_OVERLAY,
983 SCROLLBARS_OUTSIDE_INSET
985 @Retention(RetentionPolicy.SOURCE)
986 public @interface ScrollBarStyle {}
989 * The scrollbar style to display the scrollbars inside the content area,
990 * without increasing the padding. The scrollbars will be overlaid with
991 * translucency on the view's content.
993 public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
996 * The scrollbar style to display the scrollbars inside the padded area,
997 * increasing the padding of the view. The scrollbars will not overlap the
998 * content area of the view.
1000 public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1003 * The scrollbar style to display the scrollbars at the edge of the view,
1004 * without increasing the padding. The scrollbars will be overlaid with
1007 public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1010 * The scrollbar style to display the scrollbars at the edge of the view,
1011 * increasing the padding of the view. The scrollbars will only overlap the
1012 * background, if any.
1014 public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1017 * Mask to check if the scrollbar style is overlay or inset.
1020 static final int SCROLLBARS_INSET_MASK = 0x01000000;
1023 * Mask to check if the scrollbar style is inside or outside.
1026 static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1029 * Mask for scrollbar style.
1032 static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1035 * View flag indicating that the screen should remain on while the
1036 * window containing this view is visible to the user. This effectively
1037 * takes care of automatically setting the WindowManager's
1038 * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1040 public static final int KEEP_SCREEN_ON = 0x04000000;
1043 * View flag indicating whether this view should have sound effects enabled
1044 * for events such as clicking and touching.
1046 public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1049 * View flag indicating whether this view should have haptic feedback
1050 * enabled for events such as long presses.
1052 public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1055 * <p>Indicates that the view hierarchy should stop saving state when
1056 * it reaches this view. If state saving is initiated immediately at
1057 * the view, it will be allowed.
1060 static final int PARENT_SAVE_DISABLED = 0x20000000;
1063 * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1066 static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1069 @IntDef(flag = true,
1072 FOCUSABLES_TOUCH_MODE
1074 @Retention(RetentionPolicy.SOURCE)
1075 public @interface FocusableMode {}
1078 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1079 * should add all focusable Views regardless if they are focusable in touch mode.
1081 public static final int FOCUSABLES_ALL = 0x00000000;
1084 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1085 * should add only Views focusable in touch mode.
1087 public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1098 @Retention(RetentionPolicy.SOURCE)
1099 public @interface FocusDirection {}
1108 @Retention(RetentionPolicy.SOURCE)
1109 public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1112 * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1115 public static final int FOCUS_BACKWARD = 0x00000001;
1118 * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1121 public static final int FOCUS_FORWARD = 0x00000002;
1124 * Use with {@link #focusSearch(int)}. Move focus to the left.
1126 public static final int FOCUS_LEFT = 0x00000011;
1129 * Use with {@link #focusSearch(int)}. Move focus up.
1131 public static final int FOCUS_UP = 0x00000021;
1134 * Use with {@link #focusSearch(int)}. Move focus to the right.
1136 public static final int FOCUS_RIGHT = 0x00000042;
1139 * Use with {@link #focusSearch(int)}. Move focus down.
1141 public static final int FOCUS_DOWN = 0x00000082;
1144 * Bits of {@link #getMeasuredWidthAndState()} and
1145 * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1147 public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1150 * Bits of {@link #getMeasuredWidthAndState()} and
1151 * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1153 public static final int MEASURED_STATE_MASK = 0xff000000;
1156 * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1157 * for functions that combine both width and height into a single int,
1158 * such as {@link #getMeasuredState()} and the childState argument of
1159 * {@link #resolveSizeAndState(int, int, int)}.
1161 public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1164 * Bit of {@link #getMeasuredWidthAndState()} and
1165 * {@link #getMeasuredWidthAndState()} that indicates the measured size
1166 * is smaller that the space the view would like to have.
1168 public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1171 * Base View state sets
1175 * Indicates the view has no states set. States are used with
1176 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1177 * view depending on its state.
1179 * @see android.graphics.drawable.Drawable
1180 * @see #getDrawableState()
1182 protected static final int[] EMPTY_STATE_SET;
1184 * Indicates the view is enabled. States are used with
1185 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1186 * view depending on its state.
1188 * @see android.graphics.drawable.Drawable
1189 * @see #getDrawableState()
1191 protected static final int[] ENABLED_STATE_SET;
1193 * Indicates the view is focused. States are used with
1194 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1195 * view depending on its state.
1197 * @see android.graphics.drawable.Drawable
1198 * @see #getDrawableState()
1200 protected static final int[] FOCUSED_STATE_SET;
1202 * Indicates the view is selected. States are used with
1203 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1204 * view depending on its state.
1206 * @see android.graphics.drawable.Drawable
1207 * @see #getDrawableState()
1209 protected static final int[] SELECTED_STATE_SET;
1211 * Indicates the view is pressed. States are used with
1212 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1213 * view depending on its state.
1215 * @see android.graphics.drawable.Drawable
1216 * @see #getDrawableState()
1218 protected static final int[] PRESSED_STATE_SET;
1220 * Indicates the view's window has focus. States are used with
1221 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1222 * view depending on its state.
1224 * @see android.graphics.drawable.Drawable
1225 * @see #getDrawableState()
1227 protected static final int[] WINDOW_FOCUSED_STATE_SET;
1230 * Indicates the view is enabled and has the focus.
1232 * @see #ENABLED_STATE_SET
1233 * @see #FOCUSED_STATE_SET
1235 protected static final int[] ENABLED_FOCUSED_STATE_SET;
1237 * Indicates the view is enabled and selected.
1239 * @see #ENABLED_STATE_SET
1240 * @see #SELECTED_STATE_SET
1242 protected static final int[] ENABLED_SELECTED_STATE_SET;
1244 * Indicates the view is enabled and that its window has focus.
1246 * @see #ENABLED_STATE_SET
1247 * @see #WINDOW_FOCUSED_STATE_SET
1249 protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1251 * Indicates the view is focused and selected.
1253 * @see #FOCUSED_STATE_SET
1254 * @see #SELECTED_STATE_SET
1256 protected static final int[] FOCUSED_SELECTED_STATE_SET;
1258 * Indicates the view has the focus and that its window has the focus.
1260 * @see #FOCUSED_STATE_SET
1261 * @see #WINDOW_FOCUSED_STATE_SET
1263 protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1265 * Indicates the view is selected and that its window has the focus.
1267 * @see #SELECTED_STATE_SET
1268 * @see #WINDOW_FOCUSED_STATE_SET
1270 protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1273 * Indicates the view is enabled, focused and selected.
1275 * @see #ENABLED_STATE_SET
1276 * @see #FOCUSED_STATE_SET
1277 * @see #SELECTED_STATE_SET
1279 protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1281 * Indicates the view is enabled, focused and its window has the focus.
1283 * @see #ENABLED_STATE_SET
1284 * @see #FOCUSED_STATE_SET
1285 * @see #WINDOW_FOCUSED_STATE_SET
1287 protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1289 * Indicates the view is enabled, selected and its window has the focus.
1291 * @see #ENABLED_STATE_SET
1292 * @see #SELECTED_STATE_SET
1293 * @see #WINDOW_FOCUSED_STATE_SET
1295 protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1297 * Indicates the view is focused, selected and its window has the focus.
1299 * @see #FOCUSED_STATE_SET
1300 * @see #SELECTED_STATE_SET
1301 * @see #WINDOW_FOCUSED_STATE_SET
1303 protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1305 * Indicates the view is enabled, focused, selected and its window
1308 * @see #ENABLED_STATE_SET
1309 * @see #FOCUSED_STATE_SET
1310 * @see #SELECTED_STATE_SET
1311 * @see #WINDOW_FOCUSED_STATE_SET
1313 protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1315 * Indicates the view is pressed and its window has the focus.
1317 * @see #PRESSED_STATE_SET
1318 * @see #WINDOW_FOCUSED_STATE_SET
1320 protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1322 * Indicates the view is pressed and selected.
1324 * @see #PRESSED_STATE_SET
1325 * @see #SELECTED_STATE_SET
1327 protected static final int[] PRESSED_SELECTED_STATE_SET;
1329 * Indicates the view is pressed, selected and its window has the focus.
1331 * @see #PRESSED_STATE_SET
1332 * @see #SELECTED_STATE_SET
1333 * @see #WINDOW_FOCUSED_STATE_SET
1335 protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1337 * Indicates the view is pressed and focused.
1339 * @see #PRESSED_STATE_SET
1340 * @see #FOCUSED_STATE_SET
1342 protected static final int[] PRESSED_FOCUSED_STATE_SET;
1344 * Indicates the view is pressed, focused and its window has the focus.
1346 * @see #PRESSED_STATE_SET
1347 * @see #FOCUSED_STATE_SET
1348 * @see #WINDOW_FOCUSED_STATE_SET
1350 protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1352 * Indicates the view is pressed, focused and selected.
1354 * @see #PRESSED_STATE_SET
1355 * @see #SELECTED_STATE_SET
1356 * @see #FOCUSED_STATE_SET
1358 protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1360 * Indicates the view is pressed, focused, selected and its window has the focus.
1362 * @see #PRESSED_STATE_SET
1363 * @see #FOCUSED_STATE_SET
1364 * @see #SELECTED_STATE_SET
1365 * @see #WINDOW_FOCUSED_STATE_SET
1367 protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1369 * Indicates the view is pressed and enabled.
1371 * @see #PRESSED_STATE_SET
1372 * @see #ENABLED_STATE_SET
1374 protected static final int[] PRESSED_ENABLED_STATE_SET;
1376 * Indicates the view is pressed, enabled and its window has the focus.
1378 * @see #PRESSED_STATE_SET
1379 * @see #ENABLED_STATE_SET
1380 * @see #WINDOW_FOCUSED_STATE_SET
1382 protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1384 * Indicates the view is pressed, enabled and selected.
1386 * @see #PRESSED_STATE_SET
1387 * @see #ENABLED_STATE_SET
1388 * @see #SELECTED_STATE_SET
1390 protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1392 * Indicates the view is pressed, enabled, selected and its window has the
1395 * @see #PRESSED_STATE_SET
1396 * @see #ENABLED_STATE_SET
1397 * @see #SELECTED_STATE_SET
1398 * @see #WINDOW_FOCUSED_STATE_SET
1400 protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1402 * Indicates the view is pressed, enabled and focused.
1404 * @see #PRESSED_STATE_SET
1405 * @see #ENABLED_STATE_SET
1406 * @see #FOCUSED_STATE_SET
1408 protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1410 * Indicates the view is pressed, enabled, focused and its window has the
1413 * @see #PRESSED_STATE_SET
1414 * @see #ENABLED_STATE_SET
1415 * @see #FOCUSED_STATE_SET
1416 * @see #WINDOW_FOCUSED_STATE_SET
1418 protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1420 * Indicates the view is pressed, enabled, focused and selected.
1422 * @see #PRESSED_STATE_SET
1423 * @see #ENABLED_STATE_SET
1424 * @see #SELECTED_STATE_SET
1425 * @see #FOCUSED_STATE_SET
1427 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1429 * Indicates the view is pressed, enabled, focused, selected and its window
1432 * @see #PRESSED_STATE_SET
1433 * @see #ENABLED_STATE_SET
1434 * @see #SELECTED_STATE_SET
1435 * @see #FOCUSED_STATE_SET
1436 * @see #WINDOW_FOCUSED_STATE_SET
1438 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1441 * The order here is very important to {@link #getDrawableState()}
1443 private static final int[][] VIEW_STATE_SETS;
1445 static final int VIEW_STATE_WINDOW_FOCUSED = 1;
1446 static final int VIEW_STATE_SELECTED = 1 << 1;
1447 static final int VIEW_STATE_FOCUSED = 1 << 2;
1448 static final int VIEW_STATE_ENABLED = 1 << 3;
1449 static final int VIEW_STATE_PRESSED = 1 << 4;
1450 static final int VIEW_STATE_ACTIVATED = 1 << 5;
1451 static final int VIEW_STATE_ACCELERATED = 1 << 6;
1452 static final int VIEW_STATE_HOVERED = 1 << 7;
1453 static final int VIEW_STATE_DRAG_CAN_ACCEPT = 1 << 8;
1454 static final int VIEW_STATE_DRAG_HOVERED = 1 << 9;
1456 static final int[] VIEW_STATE_IDS = new int[] {
1457 R.attr.state_window_focused, VIEW_STATE_WINDOW_FOCUSED,
1458 R.attr.state_selected, VIEW_STATE_SELECTED,
1459 R.attr.state_focused, VIEW_STATE_FOCUSED,
1460 R.attr.state_enabled, VIEW_STATE_ENABLED,
1461 R.attr.state_pressed, VIEW_STATE_PRESSED,
1462 R.attr.state_activated, VIEW_STATE_ACTIVATED,
1463 R.attr.state_accelerated, VIEW_STATE_ACCELERATED,
1464 R.attr.state_hovered, VIEW_STATE_HOVERED,
1465 R.attr.state_drag_can_accept, VIEW_STATE_DRAG_CAN_ACCEPT,
1466 R.attr.state_drag_hovered, VIEW_STATE_DRAG_HOVERED
1470 if ((VIEW_STATE_IDS.length/2) != R.styleable.ViewDrawableStates.length) {
1471 throw new IllegalStateException(
1472 "VIEW_STATE_IDs array length does not match ViewDrawableStates style array");
1474 int[] orderedIds = new int[VIEW_STATE_IDS.length];
1475 for (int i = 0; i < R.styleable.ViewDrawableStates.length; i++) {
1476 int viewState = R.styleable.ViewDrawableStates[i];
1477 for (int j = 0; j<VIEW_STATE_IDS.length; j += 2) {
1478 if (VIEW_STATE_IDS[j] == viewState) {
1479 orderedIds[i * 2] = viewState;
1480 orderedIds[i * 2 + 1] = VIEW_STATE_IDS[j + 1];
1484 final int NUM_BITS = VIEW_STATE_IDS.length / 2;
1485 VIEW_STATE_SETS = new int[1 << NUM_BITS][];
1486 for (int i = 0; i < VIEW_STATE_SETS.length; i++) {
1487 int numBits = Integer.bitCount(i);
1488 int[] set = new int[numBits];
1490 for (int j = 0; j < orderedIds.length; j += 2) {
1491 if ((i & orderedIds[j+1]) != 0) {
1492 set[pos++] = orderedIds[j];
1495 VIEW_STATE_SETS[i] = set;
1498 EMPTY_STATE_SET = VIEW_STATE_SETS[0];
1499 WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_WINDOW_FOCUSED];
1500 SELECTED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_SELECTED];
1501 SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1502 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED];
1503 FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_FOCUSED];
1504 FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1505 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED];
1506 FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1507 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED];
1508 FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1509 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1510 | VIEW_STATE_FOCUSED];
1511 ENABLED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_ENABLED];
1512 ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1513 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED];
1514 ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1515 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED];
1516 ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1517 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1518 | VIEW_STATE_ENABLED];
1519 ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1520 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED];
1521 ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1522 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1523 | VIEW_STATE_ENABLED];
1524 ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1525 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1526 | VIEW_STATE_ENABLED];
1527 ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1528 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1529 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED];
1531 PRESSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_PRESSED];
1532 PRESSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1533 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_PRESSED];
1534 PRESSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1535 VIEW_STATE_SELECTED | VIEW_STATE_PRESSED];
1536 PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1537 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1538 | VIEW_STATE_PRESSED];
1539 PRESSED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1540 VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1541 PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1542 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1543 | VIEW_STATE_PRESSED];
1544 PRESSED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1545 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1546 | VIEW_STATE_PRESSED];
1547 PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1548 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1549 | VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1550 PRESSED_ENABLED_STATE_SET = VIEW_STATE_SETS[
1551 VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1552 PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1553 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED
1554 | VIEW_STATE_PRESSED];
1555 PRESSED_ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1556 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED
1557 | VIEW_STATE_PRESSED];
1558 PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1559 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1560 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1561 PRESSED_ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1562 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED
1563 | VIEW_STATE_PRESSED];
1564 PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1565 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1566 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1567 PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1568 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1569 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1570 PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1571 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1572 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED
1573 | VIEW_STATE_PRESSED];
1577 * Accessibility event types that are dispatched for text population.
1579 private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1580 AccessibilityEvent.TYPE_VIEW_CLICKED
1581 | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1582 | AccessibilityEvent.TYPE_VIEW_SELECTED
1583 | AccessibilityEvent.TYPE_VIEW_FOCUSED
1584 | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1585 | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1586 | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1587 | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1588 | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1589 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1590 | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1593 * Temporary Rect currently for use in setBackground(). This will probably
1594 * be extended in the future to hold our own class with more than just
1597 static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1600 * Map used to store views' tags.
1602 private SparseArray<Object> mKeyedTags;
1605 * The next available accessibility id.
1607 private static int sNextAccessibilityViewId;
1610 * The animation currently associated with this view.
1613 protected Animation mCurrentAnimation = null;
1616 * Width as measured during measure pass.
1619 @ViewDebug.ExportedProperty(category = "measurement")
1623 * Height as measured during measure pass.
1626 @ViewDebug.ExportedProperty(category = "measurement")
1627 int mMeasuredHeight;
1630 * Flag to indicate that this view was marked INVALIDATED, or had its display list
1631 * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1632 * its display list. This flag, used only when hw accelerated, allows us to clear the
1633 * flag while retaining this information until it's needed (at getDisplayList() time and
1634 * in drawChild(), when we decide to draw a view's children's display lists into our own).
1638 boolean mRecreateDisplayList = false;
1641 * The view's identifier.
1647 @ViewDebug.ExportedProperty(resolveId = true)
1651 * The stable ID of this view for accessibility purposes.
1653 int mAccessibilityViewId = NO_ID;
1655 private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1657 SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1663 * @see #setTag(Object)
1666 protected Object mTag = null;
1668 // for mPrivateFlags:
1670 static final int PFLAG_WANTS_FOCUS = 0x00000001;
1672 static final int PFLAG_FOCUSED = 0x00000002;
1674 static final int PFLAG_SELECTED = 0x00000004;
1676 static final int PFLAG_IS_ROOT_NAMESPACE = 0x00000008;
1678 static final int PFLAG_HAS_BOUNDS = 0x00000010;
1680 static final int PFLAG_DRAWN = 0x00000020;
1682 * When this flag is set, this view is running an animation on behalf of its
1683 * children and should therefore not cancel invalidate requests, even if they
1684 * lie outside of this view's bounds.
1688 static final int PFLAG_DRAW_ANIMATION = 0x00000040;
1690 static final int PFLAG_SKIP_DRAW = 0x00000080;
1692 static final int PFLAG_ONLY_DRAWS_BACKGROUND = 0x00000100;
1694 static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1696 static final int PFLAG_DRAWABLE_STATE_DIRTY = 0x00000400;
1698 static final int PFLAG_MEASURED_DIMENSION_SET = 0x00000800;
1700 static final int PFLAG_FORCE_LAYOUT = 0x00001000;
1702 static final int PFLAG_LAYOUT_REQUIRED = 0x00002000;
1704 private static final int PFLAG_PRESSED = 0x00004000;
1707 static final int PFLAG_DRAWING_CACHE_VALID = 0x00008000;
1709 * Flag used to indicate that this view should be drawn once more (and only once
1710 * more) after its animation has completed.
1713 static final int PFLAG_ANIMATION_STARTED = 0x00010000;
1715 private static final int PFLAG_SAVE_STATE_CALLED = 0x00020000;
1718 * Indicates that the View returned true when onSetAlpha() was called and that
1719 * the alpha must be restored.
1722 static final int PFLAG_ALPHA_SET = 0x00040000;
1725 * Set by {@link #setScrollContainer(boolean)}.
1727 static final int PFLAG_SCROLL_CONTAINER = 0x00080000;
1730 * Set by {@link #setScrollContainer(boolean)}.
1732 static final int PFLAG_SCROLL_CONTAINER_ADDED = 0x00100000;
1735 * View flag indicating whether this view was invalidated (fully or partially.)
1739 static final int PFLAG_DIRTY = 0x00200000;
1742 * View flag indicating whether this view was invalidated by an opaque
1743 * invalidate request.
1747 static final int PFLAG_DIRTY_OPAQUE = 0x00400000;
1750 * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1754 static final int PFLAG_DIRTY_MASK = 0x00600000;
1757 * Indicates whether the background is opaque.
1761 static final int PFLAG_OPAQUE_BACKGROUND = 0x00800000;
1764 * Indicates whether the scrollbars are opaque.
1768 static final int PFLAG_OPAQUE_SCROLLBARS = 0x01000000;
1771 * Indicates whether the view is opaque.
1775 static final int PFLAG_OPAQUE_MASK = 0x01800000;
1778 * Indicates a prepressed state;
1779 * the short time between ACTION_DOWN and recognizing
1780 * a 'real' press. Prepressed is used to recognize quick taps
1781 * even when they are shorter than ViewConfiguration.getTapTimeout().
1785 private static final int PFLAG_PREPRESSED = 0x02000000;
1788 * Indicates whether the view is temporarily detached.
1792 static final int PFLAG_CANCEL_NEXT_UP_EVENT = 0x04000000;
1795 * Indicates that we should awaken scroll bars once attached
1799 private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1802 * Indicates that the view has received HOVER_ENTER. Cleared on HOVER_EXIT.
1805 private static final int PFLAG_HOVERED = 0x10000000;
1808 * no longer needed, should be reused
1810 private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1813 static final int PFLAG_ACTIVATED = 0x40000000;
1816 * Indicates that this view was specifically invalidated, not just dirtied because some
1817 * child view was invalidated. The flag is used to determine when we need to recreate
1818 * a view's display list (as opposed to just returning a reference to its existing
1823 static final int PFLAG_INVALIDATED = 0x80000000;
1826 * Masks for mPrivateFlags2, as generated by dumpFlags():
1828 * |-------|-------|-------|-------|
1829 * 1 PFLAG2_DRAG_CAN_ACCEPT
1830 * 1 PFLAG2_DRAG_HOVERED
1831 * 11 PFLAG2_LAYOUT_DIRECTION_MASK
1832 * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1833 * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED
1834 * 11 PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1835 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[1]
1836 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[2]
1837 * 11 PFLAG2_TEXT_DIRECTION_FLAGS[3]
1838 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[4]
1839 * 1 1 PFLAG2_TEXT_DIRECTION_FLAGS[5]
1840 * 111 PFLAG2_TEXT_DIRECTION_MASK
1841 * 1 PFLAG2_TEXT_DIRECTION_RESOLVED
1842 * 1 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1843 * 111 PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1844 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1845 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1846 * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1847 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1848 * 1 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1849 * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1850 * 111 PFLAG2_TEXT_ALIGNMENT_MASK
1851 * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1852 * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1853 * 111 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1854 * 111 PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1855 * 11 PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1856 * 1 PFLAG2_ACCESSIBILITY_FOCUSED
1857 * 1 PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1858 * 1 PFLAG2_VIEW_QUICK_REJECTED
1859 * 1 PFLAG2_PADDING_RESOLVED
1860 * 1 PFLAG2_DRAWABLE_RESOLVED
1861 * 1 PFLAG2_HAS_TRANSIENT_STATE
1862 * |-------|-------|-------|-------|
1866 * Indicates that this view has reported that it can accept the current drag's content.
1867 * Cleared when the drag operation concludes.
1870 static final int PFLAG2_DRAG_CAN_ACCEPT = 0x00000001;
1873 * Indicates that this view is currently directly under the drag location in a
1874 * drag-and-drop operation involving content that it can accept. Cleared when
1875 * the drag exits the view, or when the drag operation concludes.
1878 static final int PFLAG2_DRAG_HOVERED = 0x00000002;
1882 LAYOUT_DIRECTION_LTR,
1883 LAYOUT_DIRECTION_RTL,
1884 LAYOUT_DIRECTION_INHERIT,
1885 LAYOUT_DIRECTION_LOCALE
1887 @Retention(RetentionPolicy.SOURCE)
1888 // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1889 public @interface LayoutDir {}
1893 LAYOUT_DIRECTION_LTR,
1894 LAYOUT_DIRECTION_RTL
1896 @Retention(RetentionPolicy.SOURCE)
1897 public @interface ResolvedLayoutDir {}
1900 * Horizontal layout direction of this view is from Left to Right.
1901 * Use with {@link #setLayoutDirection}.
1903 public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1906 * Horizontal layout direction of this view is from Right to Left.
1907 * Use with {@link #setLayoutDirection}.
1909 public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1912 * Horizontal layout direction of this view is inherited from its parent.
1913 * Use with {@link #setLayoutDirection}.
1915 public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1918 * Horizontal layout direction of this view is from deduced from the default language
1919 * script for the locale. Use with {@link #setLayoutDirection}.
1921 public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1924 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1927 static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1930 * Mask for use with private flags indicating bits used for horizontal layout direction.
1933 static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1936 * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1937 * right-to-left direction.
1940 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1943 * Indicates whether the view horizontal layout direction has been resolved.
1946 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1949 * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1952 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1953 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1956 * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1960 private static final int[] LAYOUT_DIRECTION_FLAGS = {
1961 LAYOUT_DIRECTION_LTR,
1962 LAYOUT_DIRECTION_RTL,
1963 LAYOUT_DIRECTION_INHERIT,
1964 LAYOUT_DIRECTION_LOCALE
1968 * Default horizontal layout direction.
1970 private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
1973 * Default horizontal layout direction.
1976 static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
1979 * Text direction is inherited thru {@link ViewGroup}
1981 public static final int TEXT_DIRECTION_INHERIT = 0;
1984 * Text direction is using "first strong algorithm". The first strong directional character
1985 * determines the paragraph direction. If there is no strong directional character, the
1986 * paragraph direction is the view's resolved layout direction.
1988 public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
1991 * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
1992 * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
1993 * If there are neither, the paragraph direction is the view's resolved layout direction.
1995 public static final int TEXT_DIRECTION_ANY_RTL = 2;
1998 * Text direction is forced to LTR.
2000 public static final int TEXT_DIRECTION_LTR = 3;
2003 * Text direction is forced to RTL.
2005 public static final int TEXT_DIRECTION_RTL = 4;
2008 * Text direction is coming from the system Locale.
2010 public static final int TEXT_DIRECTION_LOCALE = 5;
2013 * Default text direction is inherited
2015 private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2018 * Default resolved text direction
2021 static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2024 * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2027 static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2030 * Mask for use with private flags indicating bits used for text direction.
2033 static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2034 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2037 * Array of text direction flags for mapping attribute "textDirection" to correct
2041 private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2042 TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2043 TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2044 TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2045 TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2046 TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2047 TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2051 * Indicates whether the view text direction has been resolved.
2054 static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2055 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2058 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2061 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2064 * Mask for use with private flags indicating bits used for resolved text direction.
2067 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2068 << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2071 * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2074 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2075 TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2079 TEXT_ALIGNMENT_INHERIT,
2080 TEXT_ALIGNMENT_GRAVITY,
2081 TEXT_ALIGNMENT_CENTER,
2082 TEXT_ALIGNMENT_TEXT_START,
2083 TEXT_ALIGNMENT_TEXT_END,
2084 TEXT_ALIGNMENT_VIEW_START,
2085 TEXT_ALIGNMENT_VIEW_END
2087 @Retention(RetentionPolicy.SOURCE)
2088 public @interface TextAlignment {}
2091 * Default text alignment. The text alignment of this View is inherited from its parent.
2092 * Use with {@link #setTextAlignment(int)}
2094 public static final int TEXT_ALIGNMENT_INHERIT = 0;
2097 * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2098 * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2100 * Use with {@link #setTextAlignment(int)}
2102 public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2105 * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2107 * Use with {@link #setTextAlignment(int)}
2109 public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2112 * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2114 * Use with {@link #setTextAlignment(int)}
2116 public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2119 * Center the paragraph, e.g. ALIGN_CENTER.
2121 * Use with {@link #setTextAlignment(int)}
2123 public static final int TEXT_ALIGNMENT_CENTER = 4;
2126 * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2127 * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2129 * Use with {@link #setTextAlignment(int)}
2131 public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2134 * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2135 * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2137 * Use with {@link #setTextAlignment(int)}
2139 public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2142 * Default text alignment is inherited
2144 private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2147 * Default resolved text alignment
2150 static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2153 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2156 static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2159 * Mask for use with private flags indicating bits used for text alignment.
2162 static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2165 * Array of text direction flags for mapping attribute "textAlignment" to correct
2169 private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2170 TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2171 TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2172 TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2173 TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2174 TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2175 TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2176 TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2180 * Indicates whether the view text alignment has been resolved.
2183 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2186 * Bit shift to get the resolved text alignment.
2189 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2192 * Mask for use with private flags indicating bits used for text alignment.
2195 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2196 << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2199 * Indicates whether if the view text alignment has been resolved to gravity
2201 private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2202 TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2204 // Accessiblity constants for mPrivateFlags2
2207 * Shift for the bits in {@link #mPrivateFlags2} related to the
2208 * "importantForAccessibility" attribute.
2210 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2213 * Automatically determine whether a view is important for accessibility.
2215 public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2218 * The view is important for accessibility.
2220 public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2223 * The view is not important for accessibility.
2225 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2228 * The view is not important for accessibility, nor are any of its
2231 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2234 * The default whether the view is important for accessibility.
2236 static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2239 * Mask for obtainig the bits which specify how to determine
2240 * whether a view is important for accessibility.
2242 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2243 | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2244 | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2245 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2248 * Shift for the bits in {@link #mPrivateFlags2} related to the
2249 * "accessibilityLiveRegion" attribute.
2251 static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2254 * Live region mode specifying that accessibility services should not
2255 * automatically announce changes to this view. This is the default live
2256 * region mode for most views.
2258 * Use with {@link #setAccessibilityLiveRegion(int)}.
2260 public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2263 * Live region mode specifying that accessibility services should announce
2264 * changes to this view.
2266 * Use with {@link #setAccessibilityLiveRegion(int)}.
2268 public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2271 * Live region mode specifying that accessibility services should interrupt
2272 * ongoing speech to immediately announce changes to this view.
2274 * Use with {@link #setAccessibilityLiveRegion(int)}.
2276 public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2279 * The default whether the view is important for accessibility.
2281 static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2284 * Mask for obtaining the bits which specify a view's accessibility live
2287 static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2288 | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2289 << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2292 * Flag indicating whether a view has accessibility focus.
2294 static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2297 * Flag whether the accessibility state of the subtree rooted at this view changed.
2299 static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2302 * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2303 * is used to check whether later changes to the view's transform should invalidate the
2304 * view to force the quickReject test to run again.
2306 static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2309 * Flag indicating that start/end padding has been resolved into left/right padding
2310 * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2311 * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2312 * during measurement. In some special cases this is required such as when an adapter-based
2313 * view measures prospective children without attaching them to a window.
2315 static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2318 * Flag indicating that the start/end drawables has been resolved into left/right ones.
2320 static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2323 * Indicates that the view is tracking some sort of transient state
2324 * that the app should not need to be aware of, but that the framework
2325 * should take special care to preserve.
2327 static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2330 * Group of bits indicating that RTL properties resolution is done.
2332 static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2333 PFLAG2_TEXT_DIRECTION_RESOLVED |
2334 PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2335 PFLAG2_PADDING_RESOLVED |
2336 PFLAG2_DRAWABLE_RESOLVED;
2338 // There are a couple of flags left in mPrivateFlags2
2340 /* End of masks for mPrivateFlags2 */
2343 * Masks for mPrivateFlags3, as generated by dumpFlags():
2345 * |-------|-------|-------|-------|
2346 * 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2347 * 1 PFLAG3_VIEW_IS_ANIMATING_ALPHA
2348 * 1 PFLAG3_IS_LAID_OUT
2349 * 1 PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2350 * 1 PFLAG3_CALLED_SUPER
2351 * |-------|-------|-------|-------|
2355 * Flag indicating that view has a transform animation set on it. This is used to track whether
2356 * an animation is cleared between successive frames, in order to tell the associated
2357 * DisplayList to clear its animation matrix.
2359 static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2362 * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2363 * animation is cleared between successive frames, in order to tell the associated
2364 * DisplayList to restore its alpha value.
2366 static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2369 * Flag indicating that the view has been through at least one layout since it
2370 * was last attached to a window.
2372 static final int PFLAG3_IS_LAID_OUT = 0x4;
2375 * Flag indicating that a call to measure() was skipped and should be done
2376 * instead when layout() is invoked.
2378 static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2381 * Flag indicating that an overridden method correctly called down to
2382 * the superclass implementation as required by the API spec.
2384 static final int PFLAG3_CALLED_SUPER = 0x10;
2387 * Flag indicating that we're in the process of applying window insets.
2389 static final int PFLAG3_APPLYING_INSETS = 0x20;
2392 * Flag indicating that we're in the process of fitting system windows using the old method.
2394 static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2397 * Flag indicating that nested scrolling is enabled for this view.
2398 * The view will optionally cooperate with views up its parent chain to allow for
2399 * integrated nested scrolling along the same axis.
2401 static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2404 * Flag indicating that outline was invalidated and should be rebuilt the next time
2405 * the DisplayList is updated.
2407 static final int PFLAG3_OUTLINE_INVALID = 0x100;
2409 /* End of masks for mPrivateFlags3 */
2411 static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2414 * Always allow a user to over-scroll this view, provided it is a
2415 * view that can scroll.
2417 * @see #getOverScrollMode()
2418 * @see #setOverScrollMode(int)
2420 public static final int OVER_SCROLL_ALWAYS = 0;
2423 * Allow a user to over-scroll this view only if the content is large
2424 * enough to meaningfully scroll, provided it is a view that can scroll.
2426 * @see #getOverScrollMode()
2427 * @see #setOverScrollMode(int)
2429 public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2432 * Never allow a user to over-scroll this view.
2434 * @see #getOverScrollMode()
2435 * @see #setOverScrollMode(int)
2437 public static final int OVER_SCROLL_NEVER = 2;
2440 * Special constant for {@link #setSystemUiVisibility(int)}: View has
2441 * requested the system UI (status bar) to be visible (the default).
2443 * @see #setSystemUiVisibility(int)
2445 public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2448 * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2449 * system UI to enter an unobtrusive "low profile" mode.
2451 * <p>This is for use in games, book readers, video players, or any other
2452 * "immersive" application where the usual system chrome is deemed too distracting.
2454 * <p>In low profile mode, the status bar and/or navigation icons may dim.
2456 * @see #setSystemUiVisibility(int)
2458 public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2461 * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2462 * system navigation be temporarily hidden.
2464 * <p>This is an even less obtrusive state than that called for by
2465 * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2466 * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2467 * those to disappear. This is useful (in conjunction with the
2468 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2469 * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2470 * window flags) for displaying content using every last pixel on the display.
2472 * <p>There is a limitation: because navigation controls are so important, the least user
2473 * interaction will cause them to reappear immediately. When this happens, both
2474 * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2475 * so that both elements reappear at the same time.
2477 * @see #setSystemUiVisibility(int)
2479 public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2482 * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2483 * into the normal fullscreen mode so that its content can take over the screen
2484 * while still allowing the user to interact with the application.
2486 * <p>This has the same visual effect as
2487 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2488 * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2489 * meaning that non-critical screen decorations (such as the status bar) will be
2490 * hidden while the user is in the View's window, focusing the experience on
2491 * that content. Unlike the window flag, if you are using ActionBar in
2492 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2493 * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2494 * hide the action bar.
2496 * <p>This approach to going fullscreen is best used over the window flag when
2497 * it is a transient state -- that is, the application does this at certain
2498 * points in its user interaction where it wants to allow the user to focus
2499 * on content, but not as a continuous state. For situations where the application
2500 * would like to simply stay full screen the entire time (such as a game that
2501 * wants to take over the screen), the
2502 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2503 * is usually a better approach. The state set here will be removed by the system
2504 * in various situations (such as the user moving to another application) like
2505 * the other system UI states.
2507 * <p>When using this flag, the application should provide some easy facility
2508 * for the user to go out of it. A common example would be in an e-book
2509 * reader, where tapping on the screen brings back whatever screen and UI
2510 * decorations that had been hidden while the user was immersed in reading
2513 * @see #setSystemUiVisibility(int)
2515 public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2518 * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2519 * flags, we would like a stable view of the content insets given to
2520 * {@link #fitSystemWindows(Rect)}. This means that the insets seen there
2521 * will always represent the worst case that the application can expect
2522 * as a continuous state. In the stock Android UI this is the space for
2523 * the system bar, nav bar, and status bar, but not more transient elements
2524 * such as an input method.
2526 * The stable layout your UI sees is based on the system UI modes you can
2527 * switch to. That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2528 * then you will get a stable layout for changes of the
2529 * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2530 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2531 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2532 * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2533 * with a stable layout. (Note that you should avoid using
2534 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2536 * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2537 * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2538 * then a hidden status bar will be considered a "stable" state for purposes
2539 * here. This allows your UI to continually hide the status bar, while still
2540 * using the system UI flags to hide the action bar while still retaining
2541 * a stable layout. Note that changing the window fullscreen flag will never
2542 * provide a stable layout for a clean transition.
2544 * <p>If you are using ActionBar in
2545 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2546 * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2547 * insets it adds to those given to the application.
2549 public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2552 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2553 * to be layed out as if it has requested
2554 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't. This
2555 * allows it to avoid artifacts when switching in and out of that mode, at
2556 * the expense that some of its user interface may be covered by screen
2557 * decorations when they are shown. You can perform layout of your inner
2558 * UI elements to account for the navigation system UI through the
2559 * {@link #fitSystemWindows(Rect)} method.
2561 public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2564 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2565 * to be layed out as if it has requested
2566 * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't. This
2567 * allows it to avoid artifacts when switching in and out of that mode, at
2568 * the expense that some of its user interface may be covered by screen
2569 * decorations when they are shown. You can perform layout of your inner
2570 * UI elements to account for non-fullscreen system UI through the
2571 * {@link #fitSystemWindows(Rect)} method.
2573 public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2576 * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2577 * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. If this flag is
2578 * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2580 * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2581 * has an effect when used in combination with that flag.</p>
2583 public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2586 * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2587 * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2588 * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. Use this flag to create an immersive
2589 * experience while also hiding the system bars. If this flag is not set,
2590 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2591 * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2592 * if the user swipes from the top of the screen.
2593 * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2594 * system gestures, such as swiping from the top of the screen. These transient system bars
2595 * will overlay app’s content, may have some degree of transparency, and will automatically
2596 * hide after a short timeout.
2597 * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2598 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2599 * with one or both of those flags.</p>
2601 public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2604 * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2606 public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2609 * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2611 public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2616 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2617 * out of the public fields to keep the undefined bits out of the developer's way.
2619 * Flag to make the status bar not expandable. Unless you also
2620 * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2622 public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2627 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2628 * out of the public fields to keep the undefined bits out of the developer's way.
2630 * Flag to hide notification icons and scrolling ticker text.
2632 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2637 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2638 * out of the public fields to keep the undefined bits out of the developer's way.
2640 * Flag to disable incoming notification alerts. This will not block
2641 * icons, but it will block sound, vibrating and other visual or aural notifications.
2643 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2648 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2649 * out of the public fields to keep the undefined bits out of the developer's way.
2651 * Flag to hide only the scrolling ticker. Note that
2652 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2653 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2655 public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2660 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2661 * out of the public fields to keep the undefined bits out of the developer's way.
2663 * Flag to hide the center system info area.
2665 public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2670 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2671 * out of the public fields to keep the undefined bits out of the developer's way.
2673 * Flag to hide only the home button. Don't use this
2674 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2676 public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2681 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2682 * out of the public fields to keep the undefined bits out of the developer's way.
2684 * Flag to hide only the back button. Don't use this
2685 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2687 public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2692 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2693 * out of the public fields to keep the undefined bits out of the developer's way.
2695 * Flag to hide only the clock. You might use this if your activity has
2696 * its own clock making the status bar's clock redundant.
2698 public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2703 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2704 * out of the public fields to keep the undefined bits out of the developer's way.
2706 * Flag to hide only the recent apps button. Don't use this
2707 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2709 public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2714 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2715 * out of the public fields to keep the undefined bits out of the developer's way.
2717 * Flag to disable the global search gesture. Don't use this
2718 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2720 public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2725 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2726 * out of the public fields to keep the undefined bits out of the developer's way.
2728 * Flag to specify that the status bar is displayed in transient mode.
2730 public static final int STATUS_BAR_TRANSIENT = 0x04000000;
2735 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2736 * out of the public fields to keep the undefined bits out of the developer's way.
2738 * Flag to specify that the navigation bar is displayed in transient mode.
2740 public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
2745 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2746 * out of the public fields to keep the undefined bits out of the developer's way.
2748 * Flag to specify that the hidden status bar would like to be shown.
2750 public static final int STATUS_BAR_UNHIDE = 0x10000000;
2755 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2756 * out of the public fields to keep the undefined bits out of the developer's way.
2758 * Flag to specify that the hidden navigation bar would like to be shown.
2760 public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
2765 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2766 * out of the public fields to keep the undefined bits out of the developer's way.
2768 * Flag to specify that the status bar is displayed in translucent mode.
2770 public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
2775 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2776 * out of the public fields to keep the undefined bits out of the developer's way.
2778 * Flag to specify that the navigation bar is displayed in translucent mode.
2780 public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
2785 * Whether Recents is visible or not.
2787 public static final int RECENT_APPS_VISIBLE = 0x00004000;
2792 * Makes system ui transparent.
2794 public static final int SYSTEM_UI_TRANSPARENT = 0x00008000;
2799 public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FFF;
2802 * These are the system UI flags that can be cleared by events outside
2803 * of an application. Currently this is just the ability to tap on the
2804 * screen while hiding the navigation bar to have it return.
2807 public static final int SYSTEM_UI_CLEARABLE_FLAGS =
2808 SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2809 | SYSTEM_UI_FLAG_FULLSCREEN;
2812 * Flags that can impact the layout in relation to system UI.
2814 public static final int SYSTEM_UI_LAYOUT_FLAGS =
2815 SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2816 | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2819 @IntDef(flag = true,
2820 value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
2821 @Retention(RetentionPolicy.SOURCE)
2822 public @interface FindViewFlags {}
2825 * Find views that render the specified text.
2827 * @see #findViewsWithText(ArrayList, CharSequence, int)
2829 public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2832 * Find find views that contain the specified content description.
2834 * @see #findViewsWithText(ArrayList, CharSequence, int)
2836 public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2839 * Find views that contain {@link AccessibilityNodeProvider}. Such
2840 * a View is a root of virtual view hierarchy and may contain the searched
2841 * text. If this flag is set Views with providers are automatically
2842 * added and it is a responsibility of the client to call the APIs of
2843 * the provider to determine whether the virtual tree rooted at this View
2844 * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
2845 * representing the virtual views with this text.
2847 * @see #findViewsWithText(ArrayList, CharSequence, int)
2851 public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
2854 * The undefined cursor position.
2858 public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
2861 * Indicates that the screen has changed state and is now off.
2863 * @see #onScreenStateChanged(int)
2865 public static final int SCREEN_STATE_OFF = 0x0;
2868 * Indicates that the screen has changed state and is now on.
2870 * @see #onScreenStateChanged(int)
2872 public static final int SCREEN_STATE_ON = 0x1;
2875 * Indicates no axis of view scrolling.
2877 public static final int SCROLL_AXIS_NONE = 0;
2880 * Indicates scrolling along the horizontal axis.
2882 public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
2885 * Indicates scrolling along the vertical axis.
2887 public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
2890 * Controls the over-scroll mode for this view.
2891 * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
2892 * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
2893 * and {@link #OVER_SCROLL_NEVER}.
2895 private int mOverScrollMode;
2898 * The parent this view is attached to.
2903 protected ViewParent mParent;
2908 AttachInfo mAttachInfo;
2913 @ViewDebug.ExportedProperty(flagMapping = {
2914 @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
2915 name = "FORCE_LAYOUT"),
2916 @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
2917 name = "LAYOUT_REQUIRED"),
2918 @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
2919 name = "DRAWING_CACHE_INVALID", outputIf = false),
2920 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
2921 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
2922 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
2923 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
2924 }, formatToHexString = true)
2930 * This view's request for the visibility of the status bar.
2933 @ViewDebug.ExportedProperty(flagMapping = {
2934 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
2935 equals = SYSTEM_UI_FLAG_LOW_PROFILE,
2936 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
2937 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2938 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2939 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
2940 @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
2941 equals = SYSTEM_UI_FLAG_VISIBLE,
2942 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
2943 }, formatToHexString = true)
2944 int mSystemUiVisibility;
2947 * Reference count for transient state.
2948 * @see #setHasTransientState(boolean)
2950 int mTransientStateCount = 0;
2953 * Count of how many windows this view has been attached to.
2955 int mWindowAttachCount;
2958 * The layout parameters associated with this view and used by the parent
2959 * {@link android.view.ViewGroup} to determine how this view should be
2963 protected ViewGroup.LayoutParams mLayoutParams;
2966 * The view flags hold various views states.
2969 @ViewDebug.ExportedProperty(formatToHexString = true)
2972 static class TransformationInfo {
2974 * The transform matrix for the View. This transform is calculated internally
2975 * based on the translation, rotation, and scale properties.
2977 * Do *not* use this variable directly; instead call getMatrix(), which will
2978 * load the value from the View's RenderNode.
2980 private final Matrix mMatrix = new Matrix();
2983 * The inverse transform matrix for the View. This transform is calculated
2984 * internally based on the translation, rotation, and scale properties.
2986 * Do *not* use this variable directly; instead call getInverseMatrix(),
2987 * which will load the value from the View's RenderNode.
2989 private Matrix mInverseMatrix;
2992 * The opacity of the View. This is a value from 0 to 1, where 0 means
2993 * completely transparent and 1 means completely opaque.
2995 @ViewDebug.ExportedProperty
2999 * The opacity of the view as manipulated by the Fade transition. This is a hidden
3000 * property only used by transitions, which is composited with the other alpha
3001 * values to calculate the final visual alpha value.
3003 float mTransitionAlpha = 1f;
3006 TransformationInfo mTransformationInfo;
3009 * Current clip bounds. to which all drawing of this view are constrained.
3011 Rect mClipBounds = null;
3013 private boolean mLastIsOpaque;
3016 * The distance in pixels from the left edge of this view's parent
3017 * to the left edge of this view.
3020 @ViewDebug.ExportedProperty(category = "layout")
3021 protected int mLeft;
3023 * The distance in pixels from the left edge of this view's parent
3024 * to the right edge of this view.
3027 @ViewDebug.ExportedProperty(category = "layout")
3028 protected int mRight;
3030 * The distance in pixels from the top edge of this view's parent
3031 * to the top edge of this view.
3034 @ViewDebug.ExportedProperty(category = "layout")
3037 * The distance in pixels from the top edge of this view's parent
3038 * to the bottom edge of this view.
3041 @ViewDebug.ExportedProperty(category = "layout")
3042 protected int mBottom;
3045 * The offset, in pixels, by which the content of this view is scrolled
3049 @ViewDebug.ExportedProperty(category = "scrolling")
3050 protected int mScrollX;
3052 * The offset, in pixels, by which the content of this view is scrolled
3056 @ViewDebug.ExportedProperty(category = "scrolling")
3057 protected int mScrollY;
3060 * The left padding in pixels, that is the distance in pixels between the
3061 * left edge of this view and the left edge of its content.
3064 @ViewDebug.ExportedProperty(category = "padding")
3065 protected int mPaddingLeft = 0;
3067 * The right padding in pixels, that is the distance in pixels between the
3068 * right edge of this view and the right edge of its content.
3071 @ViewDebug.ExportedProperty(category = "padding")
3072 protected int mPaddingRight = 0;
3074 * The top padding in pixels, that is the distance in pixels between the
3075 * top edge of this view and the top edge of its content.
3078 @ViewDebug.ExportedProperty(category = "padding")
3079 protected int mPaddingTop;
3081 * The bottom padding in pixels, that is the distance in pixels between the
3082 * bottom edge of this view and the bottom edge of its content.
3085 @ViewDebug.ExportedProperty(category = "padding")
3086 protected int mPaddingBottom;
3089 * The layout insets in pixels, that is the distance in pixels between the
3090 * visible edges of this view its bounds.
3092 private Insets mLayoutInsets;
3095 * Briefly describes the view and is primarily used for accessibility support.
3097 private CharSequence mContentDescription;
3100 * Specifies the id of a view for which this view serves as a label for
3101 * accessibility purposes.
3103 private int mLabelForId = View.NO_ID;
3106 * Predicate for matching labeled view id with its label for
3107 * accessibility purposes.
3109 private MatchLabelForPredicate mMatchLabelForPredicate;
3112 * Predicate for matching a view by its id.
3114 private MatchIdPredicate mMatchIdPredicate;
3117 * Cache the paddingRight set by the user to append to the scrollbar's size.
3121 @ViewDebug.ExportedProperty(category = "padding")
3122 protected int mUserPaddingRight;
3125 * Cache the paddingBottom set by the user to append to the scrollbar's size.
3129 @ViewDebug.ExportedProperty(category = "padding")
3130 protected int mUserPaddingBottom;
3133 * Cache the paddingLeft set by the user to append to the scrollbar's size.
3137 @ViewDebug.ExportedProperty(category = "padding")
3138 protected int mUserPaddingLeft;
3141 * Cache the paddingStart set by the user to append to the scrollbar's size.
3144 @ViewDebug.ExportedProperty(category = "padding")
3145 int mUserPaddingStart;
3148 * Cache the paddingEnd set by the user to append to the scrollbar's size.
3151 @ViewDebug.ExportedProperty(category = "padding")
3152 int mUserPaddingEnd;
3155 * Cache initial left padding.
3159 int mUserPaddingLeftInitial;
3162 * Cache initial right padding.
3166 int mUserPaddingRightInitial;
3169 * Default undefined padding
3171 private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3174 * Cache if a left padding has been defined
3176 private boolean mLeftPaddingDefined = false;
3179 * Cache if a right padding has been defined
3181 private boolean mRightPaddingDefined = false;
3186 int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3190 int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3192 private LongSparseLongArray mMeasureCache;
3194 @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3195 private Drawable mBackground;
3196 private TintInfo mBackgroundTint;
3199 * RenderNode used for backgrounds.
3201 * When non-null and valid, this is expected to contain an up-to-date copy
3202 * of the background drawable. It is cleared on temporary detach, and reset
3205 private RenderNode mBackgroundRenderNode;
3207 private int mBackgroundResource;
3208 private boolean mBackgroundSizeChanged;
3210 private String mTransitionName;
3212 private static class TintInfo {
3213 ColorStateList mTintList;
3214 PorterDuff.Mode mTintMode;
3215 boolean mHasTintMode;
3216 boolean mHasTintList;
3219 static class ListenerInfo {
3221 * Listener used to dispatch focus change events.
3222 * This field should be made private, so it is hidden from the SDK.
3225 protected OnFocusChangeListener mOnFocusChangeListener;
3228 * Listeners for layout change events.
3230 private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3233 * Listeners for attach events.
3235 private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3238 * Listener used to dispatch click events.
3239 * This field should be made private, so it is hidden from the SDK.
3242 public OnClickListener mOnClickListener;
3245 * Listener used to dispatch long click events.
3246 * This field should be made private, so it is hidden from the SDK.
3249 protected OnLongClickListener mOnLongClickListener;
3252 * Listener used to build the context menu.
3253 * This field should be made private, so it is hidden from the SDK.
3256 protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3258 private OnKeyListener mOnKeyListener;
3260 private OnTouchListener mOnTouchListener;
3262 private OnHoverListener mOnHoverListener;
3264 private OnGenericMotionListener mOnGenericMotionListener;
3266 private OnDragListener mOnDragListener;
3268 private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3270 OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3273 ListenerInfo mListenerInfo;
3276 * The application environment this view lives in.
3277 * This field should be made private, so it is hidden from the SDK.
3280 @ViewDebug.ExportedProperty(deepExport = true)
3281 protected Context mContext;
3283 private final Resources mResources;
3285 private ScrollabilityCache mScrollCache;
3287 private int[] mDrawableState = null;
3289 ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3292 * Animator that automatically runs based on state changes.
3294 private StateListAnimator mStateListAnimator;
3297 * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3298 * the user may specify which view to go to next.
3300 private int mNextFocusLeftId = View.NO_ID;
3303 * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3304 * the user may specify which view to go to next.
3306 private int mNextFocusRightId = View.NO_ID;
3309 * When this view has focus and the next focus is {@link #FOCUS_UP},
3310 * the user may specify which view to go to next.
3312 private int mNextFocusUpId = View.NO_ID;
3315 * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3316 * the user may specify which view to go to next.
3318 private int mNextFocusDownId = View.NO_ID;
3321 * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3322 * the user may specify which view to go to next.
3324 int mNextFocusForwardId = View.NO_ID;
3326 private CheckForLongPress mPendingCheckForLongPress;
3327 private CheckForTap mPendingCheckForTap = null;
3328 private PerformClick mPerformClick;
3329 private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3331 private UnsetPressedState mUnsetPressedState;
3334 * Whether the long press's action has been invoked. The tap's action is invoked on the
3335 * up event while a long press is invoked as soon as the long press duration is reached, so
3336 * a long press could be performed before the tap is checked, in which case the tap's action
3337 * should not be invoked.
3339 private boolean mHasPerformedLongPress;
3342 * The minimum height of the view. We'll try our best to have the height
3343 * of this view to at least this amount.
3345 @ViewDebug.ExportedProperty(category = "measurement")
3346 private int mMinHeight;
3349 * The minimum width of the view. We'll try our best to have the width
3350 * of this view to at least this amount.
3352 @ViewDebug.ExportedProperty(category = "measurement")
3353 private int mMinWidth;
3356 * The delegate to handle touch events that are physically in this view
3357 * but should be handled by another view.
3359 private TouchDelegate mTouchDelegate = null;
3362 * Solid color to use as a background when creating the drawing cache. Enables
3363 * the cache to use 16 bit bitmaps instead of 32 bit.
3365 private int mDrawingCacheBackgroundColor = 0;
3368 * Special tree observer used when mAttachInfo is null.
3370 private ViewTreeObserver mFloatingTreeObserver;
3373 * Cache the touch slop from the context that created the view.
3375 private int mTouchSlop;
3378 * Object that handles automatic animation of view properties.
3380 private ViewPropertyAnimator mAnimator = null;
3383 * Flag indicating that a drag can cross window boundaries. When
3384 * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3385 * with this flag set, all visible applications will be able to participate
3386 * in the drag operation and receive the dragged content.
3390 public static final int DRAG_FLAG_GLOBAL = 1;
3393 * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3395 private float mVerticalScrollFactor;
3398 * Position of the vertical scroll bar.
3400 private int mVerticalScrollbarPosition;
3403 * Position the scroll bar at the default position as determined by the system.
3405 public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3408 * Position the scroll bar along the left edge.
3410 public static final int SCROLLBAR_POSITION_LEFT = 1;
3413 * Position the scroll bar along the right edge.
3415 public static final int SCROLLBAR_POSITION_RIGHT = 2;
3418 * Indicates that the view does not have a layer.
3420 * @see #getLayerType()
3421 * @see #setLayerType(int, android.graphics.Paint)
3422 * @see #LAYER_TYPE_SOFTWARE
3423 * @see #LAYER_TYPE_HARDWARE
3425 public static final int LAYER_TYPE_NONE = 0;
3428 * <p>Indicates that the view has a software layer. A software layer is backed
3429 * by a bitmap and causes the view to be rendered using Android's software
3430 * rendering pipeline, even if hardware acceleration is enabled.</p>
3432 * <p>Software layers have various usages:</p>
3433 * <p>When the application is not using hardware acceleration, a software layer
3434 * is useful to apply a specific color filter and/or blending mode and/or
3435 * translucency to a view and all its children.</p>
3436 * <p>When the application is using hardware acceleration, a software layer
3437 * is useful to render drawing primitives not supported by the hardware
3438 * accelerated pipeline. It can also be used to cache a complex view tree
3439 * into a texture and reduce the complexity of drawing operations. For instance,
3440 * when animating a complex view tree with a translation, a software layer can
3441 * be used to render the view tree only once.</p>
3442 * <p>Software layers should be avoided when the affected view tree updates
3443 * often. Every update will require to re-render the software layer, which can
3444 * potentially be slow (particularly when hardware acceleration is turned on
3445 * since the layer will have to be uploaded into a hardware texture after every
3448 * @see #getLayerType()
3449 * @see #setLayerType(int, android.graphics.Paint)
3450 * @see #LAYER_TYPE_NONE
3451 * @see #LAYER_TYPE_HARDWARE
3453 public static final int LAYER_TYPE_SOFTWARE = 1;
3456 * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3457 * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3458 * OpenGL hardware) and causes the view to be rendered using Android's hardware
3459 * rendering pipeline, but only if hardware acceleration is turned on for the
3460 * view hierarchy. When hardware acceleration is turned off, hardware layers
3461 * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3463 * <p>A hardware layer is useful to apply a specific color filter and/or
3464 * blending mode and/or translucency to a view and all its children.</p>
3465 * <p>A hardware layer can be used to cache a complex view tree into a
3466 * texture and reduce the complexity of drawing operations. For instance,
3467 * when animating a complex view tree with a translation, a hardware layer can
3468 * be used to render the view tree only once.</p>
3469 * <p>A hardware layer can also be used to increase the rendering quality when
3470 * rotation transformations are applied on a view. It can also be used to
3471 * prevent potential clipping issues when applying 3D transforms on a view.</p>
3473 * @see #getLayerType()
3474 * @see #setLayerType(int, android.graphics.Paint)
3475 * @see #LAYER_TYPE_NONE
3476 * @see #LAYER_TYPE_SOFTWARE
3478 public static final int LAYER_TYPE_HARDWARE = 2;
3480 @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3481 @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3482 @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3483 @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3485 int mLayerType = LAYER_TYPE_NONE;
3489 * Set to true when drawing cache is enabled and cannot be created.
3493 public boolean mCachingFailed;
3494 private Bitmap mDrawingCache;
3495 private Bitmap mUnscaledDrawingCache;
3498 * RenderNode holding View properties, potentially holding a DisplayList of View content.
3500 * When non-null and valid, this is expected to contain an up-to-date copy
3501 * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3504 final RenderNode mRenderNode;
3507 * Set to true when the view is sending hover accessibility events because it
3508 * is the innermost hovered view.
3510 private boolean mSendingHoverAccessibilityEvents;
3513 * Delegate for injecting accessibility functionality.
3515 AccessibilityDelegate mAccessibilityDelegate;
3518 * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3519 * and add/remove objects to/from the overlay directly through the Overlay methods.
3521 ViewOverlay mOverlay;
3524 * The currently active parent view for receiving delegated nested scrolling events.
3525 * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3526 * by {@link #stopNestedScroll()} at the same point where we clear
3527 * requestDisallowInterceptTouchEvent.
3529 private ViewParent mNestedScrollingParent;
3532 * Consistency verifier for debugging purposes.
3535 protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3536 InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3537 new InputEventConsistencyVerifier(this, 0) : null;
3539 private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3541 private int[] mTempNestedScrollConsumed;
3544 * An overlay is going to draw this View instead of being drawn as part of this
3545 * View's parent. mGhostView is the View in the Overlay that must be invalidated
3546 * when this view is invalidated.
3548 GhostView mGhostView;
3551 * Holds pairs of adjacent attribute data: attribute name followed by its value.
3554 @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3555 public String[] mAttributes;
3558 * Maps a Resource id to its name.
3560 private static SparseArray<String> mAttributeMap;
3563 * Simple constructor to use when creating a view from code.
3565 * @param context The Context the view is running in, through which it can
3566 * access the current theme, resources, etc.
3568 public View(Context context) {
3570 mResources = context != null ? context.getResources() : null;
3571 mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3572 // Set some flags defaults
3574 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3575 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3576 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3577 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3578 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3579 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3580 mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3581 setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3582 mUserPaddingStart = UNDEFINED_PADDING;
3583 mUserPaddingEnd = UNDEFINED_PADDING;
3584 mRenderNode = RenderNode.create(getClass().getName(), this);
3586 if (!sCompatibilityDone && context != null) {
3587 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3589 // Older apps may need this compatibility hack for measurement.
3590 sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
3592 // Older apps expect onMeasure() to always be called on a layout pass, regardless
3593 // of whether a layout was requested on that View.
3594 sIgnoreMeasureCache = targetSdkVersion < KITKAT;
3596 sCompatibilityDone = true;
3601 * Constructor that is called when inflating a view from XML. This is called
3602 * when a view is being constructed from an XML file, supplying attributes
3603 * that were specified in the XML file. This version uses a default style of
3604 * 0, so the only attribute values applied are those in the Context's Theme
3605 * and the given AttributeSet.
3608 * The method onFinishInflate() will be called after all children have been
3611 * @param context The Context the view is running in, through which it can
3612 * access the current theme, resources, etc.
3613 * @param attrs The attributes of the XML tag that is inflating the view.
3614 * @see #View(Context, AttributeSet, int)
3616 public View(Context context, AttributeSet attrs) {
3617 this(context, attrs, 0);
3621 * Perform inflation from XML and apply a class-specific base style from a
3622 * theme attribute. This constructor of View allows subclasses to use their
3623 * own base style when they are inflating. For example, a Button class's
3624 * constructor would call this version of the super class constructor and
3625 * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
3626 * allows the theme's button style to modify all of the base view attributes
3627 * (in particular its background) as well as the Button class's attributes.
3629 * @param context The Context the view is running in, through which it can
3630 * access the current theme, resources, etc.
3631 * @param attrs The attributes of the XML tag that is inflating the view.
3632 * @param defStyleAttr An attribute in the current theme that contains a
3633 * reference to a style resource that supplies default values for
3634 * the view. Can be 0 to not look for defaults.
3635 * @see #View(Context, AttributeSet)
3637 public View(Context context, AttributeSet attrs, int defStyleAttr) {
3638 this(context, attrs, defStyleAttr, 0);
3642 * Perform inflation from XML and apply a class-specific base style from a
3643 * theme attribute or style resource. This constructor of View allows
3644 * subclasses to use their own base style when they are inflating.
3646 * When determining the final value of a particular attribute, there are
3647 * four inputs that come into play:
3649 * <li>Any attribute values in the given AttributeSet.
3650 * <li>The style resource specified in the AttributeSet (named "style").
3651 * <li>The default style specified by <var>defStyleAttr</var>.
3652 * <li>The default style specified by <var>defStyleRes</var>.
3653 * <li>The base values in this theme.
3656 * Each of these inputs is considered in-order, with the first listed taking
3657 * precedence over the following ones. In other words, if in the
3658 * AttributeSet you have supplied <code><Button * textColor="#ff000000"></code>
3659 * , then the button's text will <em>always</em> be black, regardless of
3660 * what is specified in any of the styles.
3662 * @param context The Context the view is running in, through which it can
3663 * access the current theme, resources, etc.
3664 * @param attrs The attributes of the XML tag that is inflating the view.
3665 * @param defStyleAttr An attribute in the current theme that contains a
3666 * reference to a style resource that supplies default values for
3667 * the view. Can be 0 to not look for defaults.
3668 * @param defStyleRes A resource identifier of a style resource that
3669 * supplies default values for the view, used only if
3670 * defStyleAttr is 0 or can not be found in the theme. Can be 0
3671 * to not look for defaults.
3672 * @see #View(Context, AttributeSet, int)
3674 public View(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
3677 final TypedArray a = context.obtainStyledAttributes(
3678 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
3680 if (mDebugViewAttributes) {
3681 saveAttributeData(attrs, a);
3684 Drawable background = null;
3686 int leftPadding = -1;
3687 int topPadding = -1;
3688 int rightPadding = -1;
3689 int bottomPadding = -1;
3690 int startPadding = UNDEFINED_PADDING;
3691 int endPadding = UNDEFINED_PADDING;
3695 int viewFlagValues = 0;
3696 int viewFlagMasks = 0;
3698 boolean setScrollContainer = false;
3706 float elevation = 0;
3708 float rotationX = 0;
3709 float rotationY = 0;
3712 boolean transformSet = false;
3714 int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
3715 int overScrollMode = mOverScrollMode;
3716 boolean initializeScrollbars = false;
3718 boolean startPaddingDefined = false;
3719 boolean endPaddingDefined = false;
3720 boolean leftPaddingDefined = false;
3721 boolean rightPaddingDefined = false;
3723 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3725 final int N = a.getIndexCount();
3726 for (int i = 0; i < N; i++) {
3727 int attr = a.getIndex(i);
3729 case com.android.internal.R.styleable.View_background:
3730 background = a.getDrawable(attr);
3732 case com.android.internal.R.styleable.View_padding:
3733 padding = a.getDimensionPixelSize(attr, -1);
3734 mUserPaddingLeftInitial = padding;
3735 mUserPaddingRightInitial = padding;
3736 leftPaddingDefined = true;
3737 rightPaddingDefined = true;
3739 case com.android.internal.R.styleable.View_paddingLeft:
3740 leftPadding = a.getDimensionPixelSize(attr, -1);
3741 mUserPaddingLeftInitial = leftPadding;
3742 leftPaddingDefined = true;
3744 case com.android.internal.R.styleable.View_paddingTop:
3745 topPadding = a.getDimensionPixelSize(attr, -1);
3747 case com.android.internal.R.styleable.View_paddingRight:
3748 rightPadding = a.getDimensionPixelSize(attr, -1);
3749 mUserPaddingRightInitial = rightPadding;
3750 rightPaddingDefined = true;
3752 case com.android.internal.R.styleable.View_paddingBottom:
3753 bottomPadding = a.getDimensionPixelSize(attr, -1);
3755 case com.android.internal.R.styleable.View_paddingStart:
3756 startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3757 startPaddingDefined = (startPadding != UNDEFINED_PADDING);
3759 case com.android.internal.R.styleable.View_paddingEnd:
3760 endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3761 endPaddingDefined = (endPadding != UNDEFINED_PADDING);
3763 case com.android.internal.R.styleable.View_scrollX:
3764 x = a.getDimensionPixelOffset(attr, 0);
3766 case com.android.internal.R.styleable.View_scrollY:
3767 y = a.getDimensionPixelOffset(attr, 0);
3769 case com.android.internal.R.styleable.View_alpha:
3770 setAlpha(a.getFloat(attr, 1f));
3772 case com.android.internal.R.styleable.View_transformPivotX:
3773 setPivotX(a.getDimensionPixelOffset(attr, 0));
3775 case com.android.internal.R.styleable.View_transformPivotY:
3776 setPivotY(a.getDimensionPixelOffset(attr, 0));
3778 case com.android.internal.R.styleable.View_translationX:
3779 tx = a.getDimensionPixelOffset(attr, 0);
3780 transformSet = true;
3782 case com.android.internal.R.styleable.View_translationY:
3783 ty = a.getDimensionPixelOffset(attr, 0);
3784 transformSet = true;
3786 case com.android.internal.R.styleable.View_translationZ:
3787 tz = a.getDimensionPixelOffset(attr, 0);
3788 transformSet = true;
3790 case com.android.internal.R.styleable.View_elevation:
3791 elevation = a.getDimensionPixelOffset(attr, 0);
3792 transformSet = true;
3794 case com.android.internal.R.styleable.View_rotation:
3795 rotation = a.getFloat(attr, 0);
3796 transformSet = true;
3798 case com.android.internal.R.styleable.View_rotationX:
3799 rotationX = a.getFloat(attr, 0);
3800 transformSet = true;
3802 case com.android.internal.R.styleable.View_rotationY:
3803 rotationY = a.getFloat(attr, 0);
3804 transformSet = true;
3806 case com.android.internal.R.styleable.View_scaleX:
3807 sx = a.getFloat(attr, 1f);
3808 transformSet = true;
3810 case com.android.internal.R.styleable.View_scaleY:
3811 sy = a.getFloat(attr, 1f);
3812 transformSet = true;
3814 case com.android.internal.R.styleable.View_id:
3815 mID = a.getResourceId(attr, NO_ID);
3817 case com.android.internal.R.styleable.View_tag:
3818 mTag = a.getText(attr);
3820 case com.android.internal.R.styleable.View_fitsSystemWindows:
3821 if (a.getBoolean(attr, false)) {
3822 viewFlagValues |= FITS_SYSTEM_WINDOWS;
3823 viewFlagMasks |= FITS_SYSTEM_WINDOWS;
3826 case com.android.internal.R.styleable.View_focusable:
3827 if (a.getBoolean(attr, false)) {
3828 viewFlagValues |= FOCUSABLE;
3829 viewFlagMasks |= FOCUSABLE_MASK;
3832 case com.android.internal.R.styleable.View_focusableInTouchMode:
3833 if (a.getBoolean(attr, false)) {
3834 viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
3835 viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
3838 case com.android.internal.R.styleable.View_clickable:
3839 if (a.getBoolean(attr, false)) {
3840 viewFlagValues |= CLICKABLE;
3841 viewFlagMasks |= CLICKABLE;
3844 case com.android.internal.R.styleable.View_longClickable:
3845 if (a.getBoolean(attr, false)) {
3846 viewFlagValues |= LONG_CLICKABLE;
3847 viewFlagMasks |= LONG_CLICKABLE;
3850 case com.android.internal.R.styleable.View_saveEnabled:
3851 if (!a.getBoolean(attr, true)) {
3852 viewFlagValues |= SAVE_DISABLED;
3853 viewFlagMasks |= SAVE_DISABLED_MASK;
3856 case com.android.internal.R.styleable.View_duplicateParentState:
3857 if (a.getBoolean(attr, false)) {
3858 viewFlagValues |= DUPLICATE_PARENT_STATE;
3859 viewFlagMasks |= DUPLICATE_PARENT_STATE;
3862 case com.android.internal.R.styleable.View_visibility:
3863 final int visibility = a.getInt(attr, 0);
3864 if (visibility != 0) {
3865 viewFlagValues |= VISIBILITY_FLAGS[visibility];
3866 viewFlagMasks |= VISIBILITY_MASK;
3869 case com.android.internal.R.styleable.View_layoutDirection:
3870 // Clear any layout direction flags (included resolved bits) already set
3872 ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
3873 // Set the layout direction flags depending on the value of the attribute
3874 final int layoutDirection = a.getInt(attr, -1);
3875 final int value = (layoutDirection != -1) ?
3876 LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
3877 mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
3879 case com.android.internal.R.styleable.View_drawingCacheQuality:
3880 final int cacheQuality = a.getInt(attr, 0);
3881 if (cacheQuality != 0) {
3882 viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
3883 viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
3886 case com.android.internal.R.styleable.View_contentDescription:
3887 setContentDescription(a.getString(attr));
3889 case com.android.internal.R.styleable.View_labelFor:
3890 setLabelFor(a.getResourceId(attr, NO_ID));
3892 case com.android.internal.R.styleable.View_soundEffectsEnabled:
3893 if (!a.getBoolean(attr, true)) {
3894 viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
3895 viewFlagMasks |= SOUND_EFFECTS_ENABLED;
3898 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
3899 if (!a.getBoolean(attr, true)) {
3900 viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
3901 viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
3904 case R.styleable.View_scrollbars:
3905 final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
3906 if (scrollbars != SCROLLBARS_NONE) {
3907 viewFlagValues |= scrollbars;
3908 viewFlagMasks |= SCROLLBARS_MASK;
3909 initializeScrollbars = true;
3912 //noinspection deprecation
3913 case R.styleable.View_fadingEdge:
3914 if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
3915 // Ignore the attribute starting with ICS
3918 // With builds < ICS, fall through and apply fading edges
3919 case R.styleable.View_requiresFadingEdge:
3920 final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
3921 if (fadingEdge != FADING_EDGE_NONE) {
3922 viewFlagValues |= fadingEdge;
3923 viewFlagMasks |= FADING_EDGE_MASK;
3924 initializeFadingEdgeInternal(a);
3927 case R.styleable.View_scrollbarStyle:
3928 scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
3929 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3930 viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
3931 viewFlagMasks |= SCROLLBARS_STYLE_MASK;
3934 case R.styleable.View_isScrollContainer:
3935 setScrollContainer = true;
3936 if (a.getBoolean(attr, false)) {
3937 setScrollContainer(true);
3940 case com.android.internal.R.styleable.View_keepScreenOn:
3941 if (a.getBoolean(attr, false)) {
3942 viewFlagValues |= KEEP_SCREEN_ON;
3943 viewFlagMasks |= KEEP_SCREEN_ON;
3946 case R.styleable.View_filterTouchesWhenObscured:
3947 if (a.getBoolean(attr, false)) {
3948 viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
3949 viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
3952 case R.styleable.View_nextFocusLeft:
3953 mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
3955 case R.styleable.View_nextFocusRight:
3956 mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
3958 case R.styleable.View_nextFocusUp:
3959 mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
3961 case R.styleable.View_nextFocusDown:
3962 mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
3964 case R.styleable.View_nextFocusForward:
3965 mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
3967 case R.styleable.View_minWidth:
3968 mMinWidth = a.getDimensionPixelSize(attr, 0);
3970 case R.styleable.View_minHeight:
3971 mMinHeight = a.getDimensionPixelSize(attr, 0);
3973 case R.styleable.View_onClick:
3974 if (context.isRestricted()) {
3975 throw new IllegalStateException("The android:onClick attribute cannot "
3976 + "be used within a restricted context");
3979 final String handlerName = a.getString(attr);
3980 if (handlerName != null) {
3981 setOnClickListener(new OnClickListener() {
3982 private Method mHandler;
3984 public void onClick(View v) {
3985 if (mHandler == null) {
3987 mHandler = getContext().getClass().getMethod(handlerName,
3989 } catch (NoSuchMethodException e) {
3991 String idText = id == NO_ID ? "" : " with id '"
3992 + getContext().getResources().getResourceEntryName(
3994 throw new IllegalStateException("Could not find a method " +
3995 handlerName + "(View) in the activity "
3996 + getContext().getClass() + " for onClick handler"
3997 + " on view " + View.this.getClass() + idText, e);
4002 mHandler.invoke(getContext(), View.this);
4003 } catch (IllegalAccessException e) {
4004 throw new IllegalStateException("Could not execute non "
4005 + "public method of the activity", e);
4006 } catch (InvocationTargetException e) {
4007 throw new IllegalStateException("Could not execute "
4008 + "method of the activity", e);
4014 case R.styleable.View_overScrollMode:
4015 overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4017 case R.styleable.View_verticalScrollbarPosition:
4018 mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4020 case R.styleable.View_layerType:
4021 setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4023 case R.styleable.View_textDirection:
4024 // Clear any text direction flag already set
4025 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4026 // Set the text direction flags depending on the value of the attribute
4027 final int textDirection = a.getInt(attr, -1);
4028 if (textDirection != -1) {
4029 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4032 case R.styleable.View_textAlignment:
4033 // Clear any text alignment flag already set
4034 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4035 // Set the text alignment flag depending on the value of the attribute
4036 final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4037 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4039 case R.styleable.View_importantForAccessibility:
4040 setImportantForAccessibility(a.getInt(attr,
4041 IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4043 case R.styleable.View_accessibilityLiveRegion:
4044 setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4046 case R.styleable.View_transitionName:
4047 setTransitionName(a.getString(attr));
4049 case R.styleable.View_nestedScrollingEnabled:
4050 setNestedScrollingEnabled(a.getBoolean(attr, false));
4052 case R.styleable.View_stateListAnimator:
4053 setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4054 a.getResourceId(attr, 0)));
4056 case R.styleable.View_backgroundTint:
4057 // This will get applied later during setBackground().
4058 if (mBackgroundTint == null) {
4059 mBackgroundTint = new TintInfo();
4061 mBackgroundTint.mTintList = a.getColorStateList(
4062 R.styleable.View_backgroundTint);
4063 mBackgroundTint.mHasTintList = true;
4065 case R.styleable.View_backgroundTintMode:
4066 // This will get applied later during setBackground().
4067 if (mBackgroundTint == null) {
4068 mBackgroundTint = new TintInfo();
4070 mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4071 R.styleable.View_backgroundTintMode, -1), null);
4072 mBackgroundTint.mHasTintMode = true;
4074 case R.styleable.View_outlineProvider:
4075 setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4076 PROVIDER_BACKGROUND));
4081 setOverScrollMode(overScrollMode);
4083 // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4084 // the resolved layout direction). Those cached values will be used later during padding
4086 mUserPaddingStart = startPadding;
4087 mUserPaddingEnd = endPadding;
4089 if (background != null) {
4090 setBackground(background);
4093 // setBackground above will record that padding is currently provided by the background.
4094 // If we have padding specified via xml, record that here instead and use it.
4095 mLeftPaddingDefined = leftPaddingDefined;
4096 mRightPaddingDefined = rightPaddingDefined;
4099 leftPadding = padding;
4100 topPadding = padding;
4101 rightPadding = padding;
4102 bottomPadding = padding;
4103 mUserPaddingLeftInitial = padding;
4104 mUserPaddingRightInitial = padding;
4107 if (isRtlCompatibilityMode()) {
4108 // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4109 // left / right padding are used if defined (meaning here nothing to do). If they are not
4110 // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4111 // start / end and resolve them as left / right (layout direction is not taken into account).
4112 // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4113 // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4115 if (!mLeftPaddingDefined && startPaddingDefined) {
4116 leftPadding = startPadding;
4118 mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4119 if (!mRightPaddingDefined && endPaddingDefined) {
4120 rightPadding = endPadding;
4122 mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4124 // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4125 // values defined. Otherwise, left /right values are used.
4126 // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4127 // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4129 final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4131 if (mLeftPaddingDefined && !hasRelativePadding) {
4132 mUserPaddingLeftInitial = leftPadding;
4134 if (mRightPaddingDefined && !hasRelativePadding) {
4135 mUserPaddingRightInitial = rightPadding;
4140 mUserPaddingLeftInitial,
4141 topPadding >= 0 ? topPadding : mPaddingTop,
4142 mUserPaddingRightInitial,
4143 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4145 if (viewFlagMasks != 0) {
4146 setFlags(viewFlagValues, viewFlagMasks);
4149 if (initializeScrollbars) {
4150 initializeScrollbarsInternal(a);
4155 // Needs to be called after mViewFlags is set
4156 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4160 if (x != 0 || y != 0) {
4165 setTranslationX(tx);
4166 setTranslationY(ty);
4167 setTranslationZ(tz);
4168 setElevation(elevation);
4169 setRotation(rotation);
4170 setRotationX(rotationX);
4171 setRotationY(rotationY);
4176 if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4177 setScrollContainer(true);
4180 computeOpaqueFlags();
4184 * Non-public constructor for use in testing
4188 mRenderNode = RenderNode.create(getClass().getName(), this);
4191 private static SparseArray<String> getAttributeMap() {
4192 if (mAttributeMap == null) {
4193 mAttributeMap = new SparseArray<String>();
4195 return mAttributeMap;
4198 private void saveAttributeData(AttributeSet attrs, TypedArray a) {
4199 int length = ((attrs == null ? 0 : attrs.getAttributeCount()) + a.getIndexCount()) * 2;
4200 mAttributes = new String[length];
4203 if (attrs != null) {
4204 for (i = 0; i < attrs.getAttributeCount(); i += 2) {
4205 mAttributes[i] = attrs.getAttributeName(i);
4206 mAttributes[i + 1] = attrs.getAttributeValue(i);
4211 SparseArray<String> attributeMap = getAttributeMap();
4212 for (int j = 0; j < a.length(); ++j) {
4213 if (a.hasValue(j)) {
4215 int resourceId = a.getResourceId(j, 0);
4216 if (resourceId == 0) {
4220 String resourceName = attributeMap.get(resourceId);
4221 if (resourceName == null) {
4222 resourceName = a.getResources().getResourceName(resourceId);
4223 attributeMap.put(resourceId, resourceName);
4226 mAttributes[i] = resourceName;
4227 mAttributes[i + 1] = a.getText(j).toString();
4229 } catch (Resources.NotFoundException e) {
4230 // if we can't get the resource name, we just ignore it
4236 public String toString() {
4237 StringBuilder out = new StringBuilder(128);
4238 out.append(getClass().getName());
4240 out.append(Integer.toHexString(System.identityHashCode(this)));
4242 switch (mViewFlags&VISIBILITY_MASK) {
4243 case VISIBLE: out.append('V'); break;
4244 case INVISIBLE: out.append('I'); break;
4245 case GONE: out.append('G'); break;
4246 default: out.append('.'); break;
4248 out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4249 out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4250 out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4251 out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4252 out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4253 out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4254 out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4256 out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4257 out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4258 out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4259 if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4262 out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4264 out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4265 out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4266 out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4267 out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4275 out.append(mBottom);
4276 final int id = getId();
4279 out.append(Integer.toHexString(id));
4280 final Resources r = mResources;
4281 if (Resources.resourceHasPackage(id) && r != null) {
4284 switch (id&0xff000000) {
4292 pkgname = r.getResourcePackageName(id);
4295 String typename = r.getResourceTypeName(id);
4296 String entryname = r.getResourceEntryName(id);
4298 out.append(pkgname);
4300 out.append(typename);
4302 out.append(entryname);
4303 } catch (Resources.NotFoundException e) {
4308 return out.toString();
4313 * Initializes the fading edges from a given set of styled attributes. This
4314 * method should be called by subclasses that need fading edges and when an
4315 * instance of these subclasses is created programmatically rather than
4316 * being inflated from XML. This method is automatically called when the XML
4320 * @param a the styled attributes set to initialize the fading edges from
4324 protected void initializeFadingEdge(TypedArray a) {
4325 // This method probably shouldn't have been included in the SDK to begin with.
4326 // It relies on 'a' having been initialized using an attribute filter array that is
4327 // not publicly available to the SDK. The old method has been renamed
4328 // to initializeFadingEdgeInternal and hidden for framework use only;
4329 // this one initializes using defaults to make it safe to call for apps.
4331 TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4333 initializeFadingEdgeInternal(arr);
4340 * Initializes the fading edges from a given set of styled attributes. This
4341 * method should be called by subclasses that need fading edges and when an
4342 * instance of these subclasses is created programmatically rather than
4343 * being inflated from XML. This method is automatically called when the XML
4347 * @param a the styled attributes set to initialize the fading edges from
4348 * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4350 protected void initializeFadingEdgeInternal(TypedArray a) {
4353 mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4354 R.styleable.View_fadingEdgeLength,
4355 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4359 * Returns the size of the vertical faded edges used to indicate that more
4360 * content in this view is visible.
4362 * @return The size in pixels of the vertical faded edge or 0 if vertical
4363 * faded edges are not enabled for this view.
4364 * @attr ref android.R.styleable#View_fadingEdgeLength
4366 public int getVerticalFadingEdgeLength() {
4367 if (isVerticalFadingEdgeEnabled()) {
4368 ScrollabilityCache cache = mScrollCache;
4369 if (cache != null) {
4370 return cache.fadingEdgeLength;
4377 * Set the size of the faded edge used to indicate that more content in this
4378 * view is available. Will not change whether the fading edge is enabled; use
4379 * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4380 * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4381 * for the vertical or horizontal fading edges.
4383 * @param length The size in pixels of the faded edge used to indicate that more
4384 * content in this view is visible.
4386 public void setFadingEdgeLength(int length) {
4388 mScrollCache.fadingEdgeLength = length;
4392 * Returns the size of the horizontal faded edges used to indicate that more
4393 * content in this view is visible.
4395 * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4396 * faded edges are not enabled for this view.
4397 * @attr ref android.R.styleable#View_fadingEdgeLength
4399 public int getHorizontalFadingEdgeLength() {
4400 if (isHorizontalFadingEdgeEnabled()) {
4401 ScrollabilityCache cache = mScrollCache;
4402 if (cache != null) {
4403 return cache.fadingEdgeLength;
4410 * Returns the width of the vertical scrollbar.
4412 * @return The width in pixels of the vertical scrollbar or 0 if there
4413 * is no vertical scrollbar.
4415 public int getVerticalScrollbarWidth() {
4416 ScrollabilityCache cache = mScrollCache;
4417 if (cache != null) {
4418 ScrollBarDrawable scrollBar = cache.scrollBar;
4419 if (scrollBar != null) {
4420 int size = scrollBar.getSize(true);
4422 size = cache.scrollBarSize;
4432 * Returns the height of the horizontal scrollbar.
4434 * @return The height in pixels of the horizontal scrollbar or 0 if
4435 * there is no horizontal scrollbar.
4437 protected int getHorizontalScrollbarHeight() {
4438 ScrollabilityCache cache = mScrollCache;
4439 if (cache != null) {
4440 ScrollBarDrawable scrollBar = cache.scrollBar;
4441 if (scrollBar != null) {
4442 int size = scrollBar.getSize(false);
4444 size = cache.scrollBarSize;
4455 * Initializes the scrollbars from a given set of styled attributes. This
4456 * method should be called by subclasses that need scrollbars and when an
4457 * instance of these subclasses is created programmatically rather than
4458 * being inflated from XML. This method is automatically called when the XML
4462 * @param a the styled attributes set to initialize the scrollbars from
4466 protected void initializeScrollbars(TypedArray a) {
4467 // It's not safe to use this method from apps. The parameter 'a' must have been obtained
4468 // using the View filter array which is not available to the SDK. As such, internal
4469 // framework usage now uses initializeScrollbarsInternal and we grab a default
4470 // TypedArray with the right filter instead here.
4471 TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4473 initializeScrollbarsInternal(arr);
4475 // We ignored the method parameter. Recycle the one we actually did use.
4481 * Initializes the scrollbars from a given set of styled attributes. This
4482 * method should be called by subclasses that need scrollbars and when an
4483 * instance of these subclasses is created programmatically rather than
4484 * being inflated from XML. This method is automatically called when the XML
4488 * @param a the styled attributes set to initialize the scrollbars from
4491 protected void initializeScrollbarsInternal(TypedArray a) {
4494 final ScrollabilityCache scrollabilityCache = mScrollCache;
4496 if (scrollabilityCache.scrollBar == null) {
4497 scrollabilityCache.scrollBar = new ScrollBarDrawable();
4500 final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
4502 if (!fadeScrollbars) {
4503 scrollabilityCache.state = ScrollabilityCache.ON;
4505 scrollabilityCache.fadeScrollBars = fadeScrollbars;
4508 scrollabilityCache.scrollBarFadeDuration = a.getInt(
4509 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
4510 .getScrollBarFadeDuration());
4511 scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
4512 R.styleable.View_scrollbarDefaultDelayBeforeFade,
4513 ViewConfiguration.getScrollDefaultDelay());
4516 scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
4517 com.android.internal.R.styleable.View_scrollbarSize,
4518 ViewConfiguration.get(mContext).getScaledScrollBarSize());
4520 Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
4521 scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
4523 Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
4524 if (thumb != null) {
4525 scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
4528 boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
4531 scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
4534 track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
4535 scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
4537 thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
4538 if (thumb != null) {
4539 scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
4542 alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
4545 scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
4548 // Apply layout direction to the new Drawables if needed
4549 final int layoutDirection = getLayoutDirection();
4550 if (track != null) {
4551 track.setLayoutDirection(layoutDirection);
4553 if (thumb != null) {
4554 thumb.setLayoutDirection(layoutDirection);
4557 // Re-apply user/background padding so that scrollbar(s) get added
4563 * Initalizes the scrollability cache if necessary.
4566 private void initScrollCache() {
4567 if (mScrollCache == null) {
4568 mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
4572 private ScrollabilityCache getScrollCache() {
4574 return mScrollCache;
4578 * Set the position of the vertical scroll bar. Should be one of
4579 * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
4580 * {@link #SCROLLBAR_POSITION_RIGHT}.
4582 * @param position Where the vertical scroll bar should be positioned.
4584 public void setVerticalScrollbarPosition(int position) {
4585 if (mVerticalScrollbarPosition != position) {
4586 mVerticalScrollbarPosition = position;
4587 computeOpaqueFlags();
4593 * @return The position where the vertical scroll bar will show, if applicable.
4594 * @see #setVerticalScrollbarPosition(int)
4596 public int getVerticalScrollbarPosition() {
4597 return mVerticalScrollbarPosition;
4600 ListenerInfo getListenerInfo() {
4601 if (mListenerInfo != null) {
4602 return mListenerInfo;
4604 mListenerInfo = new ListenerInfo();
4605 return mListenerInfo;
4609 * Register a callback to be invoked when focus of this view changed.
4611 * @param l The callback that will run.
4613 public void setOnFocusChangeListener(OnFocusChangeListener l) {
4614 getListenerInfo().mOnFocusChangeListener = l;
4618 * Add a listener that will be called when the bounds of the view change due to
4619 * layout processing.
4621 * @param listener The listener that will be called when layout bounds change.
4623 public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
4624 ListenerInfo li = getListenerInfo();
4625 if (li.mOnLayoutChangeListeners == null) {
4626 li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
4628 if (!li.mOnLayoutChangeListeners.contains(listener)) {
4629 li.mOnLayoutChangeListeners.add(listener);
4634 * Remove a listener for layout changes.
4636 * @param listener The listener for layout bounds change.
4638 public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
4639 ListenerInfo li = mListenerInfo;
4640 if (li == null || li.mOnLayoutChangeListeners == null) {
4643 li.mOnLayoutChangeListeners.remove(listener);
4647 * Add a listener for attach state changes.
4649 * This listener will be called whenever this view is attached or detached
4650 * from a window. Remove the listener using
4651 * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
4653 * @param listener Listener to attach
4654 * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
4656 public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4657 ListenerInfo li = getListenerInfo();
4658 if (li.mOnAttachStateChangeListeners == null) {
4659 li.mOnAttachStateChangeListeners
4660 = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
4662 li.mOnAttachStateChangeListeners.add(listener);
4666 * Remove a listener for attach state changes. The listener will receive no further
4667 * notification of window attach/detach events.
4669 * @param listener Listener to remove
4670 * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
4672 public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4673 ListenerInfo li = mListenerInfo;
4674 if (li == null || li.mOnAttachStateChangeListeners == null) {
4677 li.mOnAttachStateChangeListeners.remove(listener);
4681 * Returns the focus-change callback registered for this view.
4683 * @return The callback, or null if one is not registered.
4685 public OnFocusChangeListener getOnFocusChangeListener() {
4686 ListenerInfo li = mListenerInfo;
4687 return li != null ? li.mOnFocusChangeListener : null;
4691 * Register a callback to be invoked when this view is clicked. If this view is not
4692 * clickable, it becomes clickable.
4694 * @param l The callback that will run
4696 * @see #setClickable(boolean)
4698 public void setOnClickListener(OnClickListener l) {
4699 if (!isClickable()) {
4702 getListenerInfo().mOnClickListener = l;
4706 * Return whether this view has an attached OnClickListener. Returns
4707 * true if there is a listener, false if there is none.
4709 public boolean hasOnClickListeners() {
4710 ListenerInfo li = mListenerInfo;
4711 return (li != null && li.mOnClickListener != null);
4715 * Register a callback to be invoked when this view is clicked and held. If this view is not
4716 * long clickable, it becomes long clickable.
4718 * @param l The callback that will run
4720 * @see #setLongClickable(boolean)
4722 public void setOnLongClickListener(OnLongClickListener l) {
4723 if (!isLongClickable()) {
4724 setLongClickable(true);
4726 getListenerInfo().mOnLongClickListener = l;
4730 * Register a callback to be invoked when the context menu for this view is
4731 * being built. If this view is not long clickable, it becomes long clickable.
4733 * @param l The callback that will run
4736 public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
4737 if (!isLongClickable()) {
4738 setLongClickable(true);
4740 getListenerInfo().mOnCreateContextMenuListener = l;
4744 * Call this view's OnClickListener, if it is defined. Performs all normal
4745 * actions associated with clicking: reporting accessibility event, playing
4748 * @return True there was an assigned OnClickListener that was called, false
4749 * otherwise is returned.
4751 public boolean performClick() {
4752 final boolean result;
4753 final ListenerInfo li = mListenerInfo;
4754 if (li != null && li.mOnClickListener != null) {
4755 playSoundEffect(SoundEffectConstants.CLICK);
4756 li.mOnClickListener.onClick(this);
4762 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
4767 * Directly call any attached OnClickListener. Unlike {@link #performClick()},
4768 * this only calls the listener, and does not do any associated clicking
4769 * actions like reporting an accessibility event.
4771 * @return True there was an assigned OnClickListener that was called, false
4772 * otherwise is returned.
4774 public boolean callOnClick() {
4775 ListenerInfo li = mListenerInfo;
4776 if (li != null && li.mOnClickListener != null) {
4777 li.mOnClickListener.onClick(this);
4784 * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
4785 * OnLongClickListener did not consume the event.
4787 * @return True if one of the above receivers consumed the event, false otherwise.
4789 public boolean performLongClick() {
4790 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
4792 boolean handled = false;
4793 ListenerInfo li = mListenerInfo;
4794 if (li != null && li.mOnLongClickListener != null) {
4795 handled = li.mOnLongClickListener.onLongClick(View.this);
4798 handled = showContextMenu();
4801 performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
4807 * Performs button-related actions during a touch down event.
4809 * @param event The event.
4810 * @return True if the down was consumed.
4814 protected boolean performButtonActionOnTouchDown(MotionEvent event) {
4815 if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
4816 if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) {
4824 * Bring up the context menu for this view.
4826 * @return Whether a context menu was displayed.
4828 public boolean showContextMenu() {
4829 return getParent().showContextMenuForChild(this);
4833 * Bring up the context menu for this view, referring to the item under the specified point.
4835 * @param x The referenced x coordinate.
4836 * @param y The referenced y coordinate.
4837 * @param metaState The keyboard modifiers that were pressed.
4838 * @return Whether a context menu was displayed.
4842 public boolean showContextMenu(float x, float y, int metaState) {
4843 return showContextMenu();
4847 * Start an action mode.
4849 * @param callback Callback that will control the lifecycle of the action mode
4850 * @return The new action mode if it is started, null otherwise
4854 public ActionMode startActionMode(ActionMode.Callback callback) {
4855 ViewParent parent = getParent();
4856 if (parent == null) return null;
4857 return parent.startActionModeForChild(this, callback);
4861 * Register a callback to be invoked when a hardware key is pressed in this view.
4862 * Key presses in software input methods will generally not trigger the methods of
4864 * @param l the key listener to attach to this view
4866 public void setOnKeyListener(OnKeyListener l) {
4867 getListenerInfo().mOnKeyListener = l;
4871 * Register a callback to be invoked when a touch event is sent to this view.
4872 * @param l the touch listener to attach to this view
4874 public void setOnTouchListener(OnTouchListener l) {
4875 getListenerInfo().mOnTouchListener = l;
4879 * Register a callback to be invoked when a generic motion event is sent to this view.
4880 * @param l the generic motion listener to attach to this view
4882 public void setOnGenericMotionListener(OnGenericMotionListener l) {
4883 getListenerInfo().mOnGenericMotionListener = l;
4887 * Register a callback to be invoked when a hover event is sent to this view.
4888 * @param l the hover listener to attach to this view
4890 public void setOnHoverListener(OnHoverListener l) {
4891 getListenerInfo().mOnHoverListener = l;
4895 * Register a drag event listener callback object for this View. The parameter is
4896 * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
4897 * View, the system calls the
4898 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
4899 * @param l An implementation of {@link android.view.View.OnDragListener}.
4901 public void setOnDragListener(OnDragListener l) {
4902 getListenerInfo().mOnDragListener = l;
4906 * Give this view focus. This will cause
4907 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
4909 * Note: this does not check whether this {@link View} should get focus, it just
4910 * gives it focus no matter what. It should only be called internally by framework
4911 * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
4913 * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
4914 * {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
4915 * focus moved when requestFocus() is called. It may not always
4916 * apply, in which case use the default View.FOCUS_DOWN.
4917 * @param previouslyFocusedRect The rectangle of the view that had focus
4918 * prior in this View's coordinate system.
4920 void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
4922 System.out.println(this + " requestFocus()");
4925 if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
4926 mPrivateFlags |= PFLAG_FOCUSED;
4928 View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
4930 if (mParent != null) {
4931 mParent.requestChildFocus(this, this);
4934 if (mAttachInfo != null) {
4935 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
4938 onFocusChanged(true, direction, previouslyFocusedRect);
4939 refreshDrawableState();
4944 * Populates <code>outRect</code> with the hotspot bounds. By default,
4945 * the hotspot bounds are identical to the screen bounds.
4947 * @param outRect rect to populate with hotspot bounds
4948 * @hide Only for internal use by views and widgets.
4950 public void getHotspotBounds(Rect outRect) {
4951 final Drawable background = getBackground();
4952 if (background != null) {
4953 background.getHotspotBounds(outRect);
4955 getBoundsOnScreen(outRect);
4960 * Request that a rectangle of this view be visible on the screen,
4961 * scrolling if necessary just enough.
4963 * <p>A View should call this if it maintains some notion of which part
4964 * of its content is interesting. For example, a text editing view
4965 * should call this when its cursor moves.
4967 * @param rectangle The rectangle.
4968 * @return Whether any parent scrolled.
4970 public boolean requestRectangleOnScreen(Rect rectangle) {
4971 return requestRectangleOnScreen(rectangle, false);
4975 * Request that a rectangle of this view be visible on the screen,
4976 * scrolling if necessary just enough.
4978 * <p>A View should call this if it maintains some notion of which part
4979 * of its content is interesting. For example, a text editing view
4980 * should call this when its cursor moves.
4982 * <p>When <code>immediate</code> is set to true, scrolling will not be
4985 * @param rectangle The rectangle.
4986 * @param immediate True to forbid animated scrolling, false otherwise
4987 * @return Whether any parent scrolled.
4989 public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
4990 if (mParent == null) {
4996 RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
4997 position.set(rectangle);
4999 ViewParent parent = mParent;
5000 boolean scrolled = false;
5001 while (parent != null) {
5002 rectangle.set((int) position.left, (int) position.top,
5003 (int) position.right, (int) position.bottom);
5005 scrolled |= parent.requestChildRectangleOnScreen(child,
5006 rectangle, immediate);
5008 if (!child.hasIdentityMatrix()) {
5009 child.getMatrix().mapRect(position);
5012 position.offset(child.mLeft, child.mTop);
5014 if (!(parent instanceof View)) {
5018 View parentView = (View) parent;
5020 position.offset(-parentView.getScrollX(), -parentView.getScrollY());
5023 parent = child.getParent();
5030 * Called when this view wants to give up focus. If focus is cleared
5031 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
5033 * <strong>Note:</strong> When a View clears focus the framework is trying
5034 * to give focus to the first focusable View from the top. Hence, if this
5035 * View is the first from the top that can take focus, then all callbacks
5036 * related to clearing focus will be invoked after which the framework will
5037 * give focus to this view.
5040 public void clearFocus() {
5042 System.out.println(this + " clearFocus()");
5045 clearFocusInternal(null, true, true);
5049 * Clears focus from the view, optionally propagating the change up through
5050 * the parent hierarchy and requesting that the root view place new focus.
5052 * @param propagate whether to propagate the change up through the parent
5054 * @param refocus when propagate is true, specifies whether to request the
5055 * root view place new focus
5057 void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
5058 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
5059 mPrivateFlags &= ~PFLAG_FOCUSED;
5061 if (propagate && mParent != null) {
5062 mParent.clearChildFocus(this);
5065 onFocusChanged(false, 0, null);
5066 refreshDrawableState();
5068 if (propagate && (!refocus || !rootViewRequestFocus())) {
5069 notifyGlobalFocusCleared(this);
5074 void notifyGlobalFocusCleared(View oldFocus) {
5075 if (oldFocus != null && mAttachInfo != null) {
5076 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
5080 boolean rootViewRequestFocus() {
5081 final View root = getRootView();
5082 return root != null && root.requestFocus();
5086 * Called internally by the view system when a new view is getting focus.
5087 * This is what clears the old focus.
5089 * <b>NOTE:</b> The parent view's focused child must be updated manually
5090 * after calling this method. Otherwise, the view hierarchy may be left in
5091 * an inconstent state.
5093 void unFocus(View focused) {
5095 System.out.println(this + " unFocus()");
5098 clearFocusInternal(focused, false, false);
5102 * Returns true if this view has focus iteself, or is the ancestor of the
5103 * view that has focus.
5105 * @return True if this view has or contains focus, false otherwise.
5107 @ViewDebug.ExportedProperty(category = "focus")
5108 public boolean hasFocus() {
5109 return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5113 * Returns true if this view is focusable or if it contains a reachable View
5114 * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
5115 * is a View whose parents do not block descendants focus.
5117 * Only {@link #VISIBLE} views are considered focusable.
5119 * @return True if the view is focusable or if the view contains a focusable
5120 * View, false otherwise.
5122 * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
5123 * @see ViewGroup#getTouchscreenBlocksFocus()
5125 public boolean hasFocusable() {
5126 if (!isFocusableInTouchMode()) {
5127 for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
5128 final ViewGroup g = (ViewGroup) p;
5129 if (g.shouldBlockFocusForTouchscreen()) {
5134 return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
5138 * Called by the view system when the focus state of this view changes.
5139 * When the focus change event is caused by directional navigation, direction
5140 * and previouslyFocusedRect provide insight into where the focus is coming from.
5141 * When overriding, be sure to call up through to the super class so that
5142 * the standard focus handling will occur.
5144 * @param gainFocus True if the View has focus; false otherwise.
5145 * @param direction The direction focus has moved when requestFocus()
5146 * is called to give this view focus. Values are
5147 * {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
5148 * {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
5149 * It may not always apply, in which case use the default.
5150 * @param previouslyFocusedRect The rectangle, in this view's coordinate
5151 * system, of the previously focused view. If applicable, this will be
5152 * passed in as finer grained information about where the focus is coming
5153 * from (in addition to direction). Will be <code>null</code> otherwise.
5155 protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
5156 @Nullable Rect previouslyFocusedRect) {
5158 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
5160 notifyViewAccessibilityStateChangedIfNeeded(
5161 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5164 InputMethodManager imm = InputMethodManager.peekInstance();
5169 if (imm != null && mAttachInfo != null
5170 && mAttachInfo.mHasWindowFocus) {
5174 } else if (imm != null && mAttachInfo != null
5175 && mAttachInfo.mHasWindowFocus) {
5180 ListenerInfo li = mListenerInfo;
5181 if (li != null && li.mOnFocusChangeListener != null) {
5182 li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
5185 if (mAttachInfo != null) {
5186 mAttachInfo.mKeyDispatchState.reset(this);
5191 * Sends an accessibility event of the given type. If accessibility is
5192 * not enabled this method has no effect. The default implementation calls
5193 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
5194 * to populate information about the event source (this View), then calls
5195 * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
5196 * populate the text content of the event source including its descendants,
5198 * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
5199 * on its parent to resuest sending of the event to interested parties.
5201 * If an {@link AccessibilityDelegate} has been specified via calling
5202 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5203 * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
5204 * responsible for handling this call.
5207 * @param eventType The type of the event to send, as defined by several types from
5208 * {@link android.view.accessibility.AccessibilityEvent}, such as
5209 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
5210 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
5212 * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5213 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5214 * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
5215 * @see AccessibilityDelegate
5217 public void sendAccessibilityEvent(int eventType) {
5218 if (mAccessibilityDelegate != null) {
5219 mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
5221 sendAccessibilityEventInternal(eventType);
5226 * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
5227 * {@link AccessibilityEvent} to make an announcement which is related to some
5228 * sort of a context change for which none of the events representing UI transitions
5229 * is a good fit. For example, announcing a new page in a book. If accessibility
5230 * is not enabled this method does nothing.
5232 * @param text The announcement text.
5234 public void announceForAccessibility(CharSequence text) {
5235 if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
5236 AccessibilityEvent event = AccessibilityEvent.obtain(
5237 AccessibilityEvent.TYPE_ANNOUNCEMENT);
5238 onInitializeAccessibilityEvent(event);
5239 event.getText().add(text);
5240 event.setContentDescription(null);
5241 mParent.requestSendAccessibilityEvent(this, event);
5246 * @see #sendAccessibilityEvent(int)
5248 * Note: Called from the default {@link AccessibilityDelegate}.
5250 void sendAccessibilityEventInternal(int eventType) {
5251 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
5252 sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
5257 * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
5258 * takes as an argument an empty {@link AccessibilityEvent} and does not
5259 * perform a check whether accessibility is enabled.
5261 * If an {@link AccessibilityDelegate} has been specified via calling
5262 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5263 * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
5264 * is responsible for handling this call.
5267 * @param event The event to send.
5269 * @see #sendAccessibilityEvent(int)
5271 public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
5272 if (mAccessibilityDelegate != null) {
5273 mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
5275 sendAccessibilityEventUncheckedInternal(event);
5280 * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
5282 * Note: Called from the default {@link AccessibilityDelegate}.
5284 void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
5288 onInitializeAccessibilityEvent(event);
5289 // Only a subset of accessibility events populates text content.
5290 if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
5291 dispatchPopulateAccessibilityEvent(event);
5293 // In the beginning we called #isShown(), so we know that getParent() is not null.
5294 getParent().requestSendAccessibilityEvent(this, event);
5298 * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
5299 * to its children for adding their text content to the event. Note that the
5300 * event text is populated in a separate dispatch path since we add to the
5301 * event not only the text of the source but also the text of all its descendants.
5302 * A typical implementation will call
5303 * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
5304 * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5305 * on each child. Override this method if custom population of the event text
5306 * content is required.
5308 * If an {@link AccessibilityDelegate} has been specified via calling
5309 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5310 * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
5311 * is responsible for handling this call.
5314 * <em>Note:</em> Accessibility events of certain types are not dispatched for
5315 * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
5318 * @param event The event.
5320 * @return True if the event population was completed.
5322 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
5323 if (mAccessibilityDelegate != null) {
5324 return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
5326 return dispatchPopulateAccessibilityEventInternal(event);
5331 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5333 * Note: Called from the default {@link AccessibilityDelegate}.
5335 boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5336 onPopulateAccessibilityEvent(event);
5341 * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5342 * giving a chance to this View to populate the accessibility event with its
5343 * text content. While this method is free to modify event
5344 * attributes other than text content, doing so should normally be performed in
5345 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
5347 * Example: Adding formatted date string to an accessibility event in addition
5348 * to the text added by the super implementation:
5349 * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5350 * super.onPopulateAccessibilityEvent(event);
5351 * final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
5352 * String selectedDateUtterance = DateUtils.formatDateTime(mContext,
5353 * mCurrentDate.getTimeInMillis(), flags);
5354 * event.getText().add(selectedDateUtterance);
5357 * If an {@link AccessibilityDelegate} has been specified via calling
5358 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5359 * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
5360 * is responsible for handling this call.
5362 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5363 * information to the event, in case the default implementation has basic information to add.
5366 * @param event The accessibility event which to populate.
5368 * @see #sendAccessibilityEvent(int)
5369 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5371 public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5372 if (mAccessibilityDelegate != null) {
5373 mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
5375 onPopulateAccessibilityEventInternal(event);
5380 * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
5382 * Note: Called from the default {@link AccessibilityDelegate}.
5384 void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5388 * Initializes an {@link AccessibilityEvent} with information about
5389 * this View which is the event source. In other words, the source of
5390 * an accessibility event is the view whose state change triggered firing
5393 * Example: Setting the password property of an event in addition
5394 * to properties set by the super implementation:
5395 * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5396 * super.onInitializeAccessibilityEvent(event);
5397 * event.setPassword(true);
5400 * If an {@link AccessibilityDelegate} has been specified via calling
5401 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5402 * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
5403 * is responsible for handling this call.
5405 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5406 * information to the event, in case the default implementation has basic information to add.
5408 * @param event The event to initialize.
5410 * @see #sendAccessibilityEvent(int)
5411 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5413 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5414 if (mAccessibilityDelegate != null) {
5415 mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
5417 onInitializeAccessibilityEventInternal(event);
5422 * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5424 * Note: Called from the default {@link AccessibilityDelegate}.
5426 void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
5427 event.setSource(this);
5428 event.setClassName(View.class.getName());
5429 event.setPackageName(getContext().getPackageName());
5430 event.setEnabled(isEnabled());
5431 event.setContentDescription(mContentDescription);
5433 switch (event.getEventType()) {
5434 case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
5435 ArrayList<View> focusablesTempList = (mAttachInfo != null)
5436 ? mAttachInfo.mTempArrayList : new ArrayList<View>();
5437 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
5438 event.setItemCount(focusablesTempList.size());
5439 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
5440 if (mAttachInfo != null) {
5441 focusablesTempList.clear();
5444 case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
5445 CharSequence text = getIterableTextForAccessibility();
5446 if (text != null && text.length() > 0) {
5447 event.setFromIndex(getAccessibilitySelectionStart());
5448 event.setToIndex(getAccessibilitySelectionEnd());
5449 event.setItemCount(text.length());
5456 * Returns an {@link AccessibilityNodeInfo} representing this view from the
5457 * point of view of an {@link android.accessibilityservice.AccessibilityService}.
5458 * This method is responsible for obtaining an accessibility node info from a
5459 * pool of reusable instances and calling
5460 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
5461 * initialize the former.
5463 * Note: The client is responsible for recycling the obtained instance by calling
5464 * {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
5467 * @return A populated {@link AccessibilityNodeInfo}.
5469 * @see AccessibilityNodeInfo
5471 public AccessibilityNodeInfo createAccessibilityNodeInfo() {
5472 if (mAccessibilityDelegate != null) {
5473 return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
5475 return createAccessibilityNodeInfoInternal();
5480 * @see #createAccessibilityNodeInfo()
5482 AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
5483 AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
5484 if (provider != null) {
5485 return provider.createAccessibilityNodeInfo(View.NO_ID);
5487 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
5488 onInitializeAccessibilityNodeInfo(info);
5494 * Initializes an {@link AccessibilityNodeInfo} with information about this view.
5495 * The base implementation sets:
5497 * <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
5498 * <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
5499 * <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
5500 * <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
5501 * <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
5502 * <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
5503 * <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
5504 * <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
5505 * <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
5506 * <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
5507 * <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
5508 * <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
5511 * Subclasses should override this method, call the super implementation,
5512 * and set additional attributes.
5515 * If an {@link AccessibilityDelegate} has been specified via calling
5516 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5517 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
5518 * is responsible for handling this call.
5521 * @param info The instance to initialize.
5523 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
5524 if (mAccessibilityDelegate != null) {
5525 mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
5527 onInitializeAccessibilityNodeInfoInternal(info);
5532 * Gets the location of this view in screen coordintates.
5534 * @param outRect The output location
5537 public void getBoundsOnScreen(Rect outRect) {
5538 if (mAttachInfo == null) {
5542 RectF position = mAttachInfo.mTmpTransformRect;
5543 position.set(0, 0, mRight - mLeft, mBottom - mTop);
5545 if (!hasIdentityMatrix()) {
5546 getMatrix().mapRect(position);
5549 position.offset(mLeft, mTop);
5551 ViewParent parent = mParent;
5552 while (parent instanceof View) {
5553 View parentView = (View) parent;
5555 position.offset(-parentView.mScrollX, -parentView.mScrollY);
5557 if (!parentView.hasIdentityMatrix()) {
5558 parentView.getMatrix().mapRect(position);
5561 position.offset(parentView.mLeft, parentView.mTop);
5563 parent = parentView.mParent;
5566 if (parent instanceof ViewRootImpl) {
5567 ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
5568 position.offset(0, -viewRootImpl.mCurScrollY);
5571 position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
5573 outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
5574 (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
5578 * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
5580 * Note: Called from the default {@link AccessibilityDelegate}.
5582 void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
5583 Rect bounds = mAttachInfo.mTmpInvalRect;
5585 getDrawingRect(bounds);
5586 info.setBoundsInParent(bounds);
5588 getBoundsOnScreen(bounds);
5589 info.setBoundsInScreen(bounds);
5591 ViewParent parent = getParentForAccessibility();
5592 if (parent instanceof View) {
5593 info.setParent((View) parent);
5596 if (mID != View.NO_ID) {
5597 View rootView = getRootView();
5598 if (rootView == null) {
5601 View label = rootView.findLabelForView(this, mID);
5602 if (label != null) {
5603 info.setLabeledBy(label);
5606 if ((mAttachInfo.mAccessibilityFetchFlags
5607 & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
5608 && Resources.resourceHasPackage(mID)) {
5610 String viewId = getResources().getResourceName(mID);
5611 info.setViewIdResourceName(viewId);
5612 } catch (Resources.NotFoundException nfe) {
5618 if (mLabelForId != View.NO_ID) {
5619 View rootView = getRootView();
5620 if (rootView == null) {
5623 View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
5624 if (labeled != null) {
5625 info.setLabelFor(labeled);
5629 info.setVisibleToUser(isVisibleToUser());
5631 info.setPackageName(mContext.getPackageName());
5632 info.setClassName(View.class.getName());
5633 info.setContentDescription(getContentDescription());
5635 info.setEnabled(isEnabled());
5636 info.setClickable(isClickable());
5637 info.setFocusable(isFocusable());
5638 info.setFocused(isFocused());
5639 info.setAccessibilityFocused(isAccessibilityFocused());
5640 info.setSelected(isSelected());
5641 info.setLongClickable(isLongClickable());
5642 info.setLiveRegion(getAccessibilityLiveRegion());
5644 // TODO: These make sense only if we are in an AdapterView but all
5645 // views can be selected. Maybe from accessibility perspective
5646 // we should report as selectable view in an AdapterView.
5647 info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
5648 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
5650 if (isFocusable()) {
5652 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
5654 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
5658 if (!isAccessibilityFocused()) {
5659 info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
5661 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
5664 if (isClickable() && isEnabled()) {
5665 info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
5668 if (isLongClickable() && isEnabled()) {
5669 info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
5672 CharSequence text = getIterableTextForAccessibility();
5673 if (text != null && text.length() > 0) {
5674 info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
5676 info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
5677 info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
5678 info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
5679 info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
5680 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
5681 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
5685 private View findLabelForView(View view, int labeledId) {
5686 if (mMatchLabelForPredicate == null) {
5687 mMatchLabelForPredicate = new MatchLabelForPredicate();
5689 mMatchLabelForPredicate.mLabeledId = labeledId;
5690 return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
5694 * Computes whether this view is visible to the user. Such a view is
5695 * attached, visible, all its predecessors are visible, it is not clipped
5696 * entirely by its predecessors, and has an alpha greater than zero.
5698 * @return Whether the view is visible on the screen.
5702 protected boolean isVisibleToUser() {
5703 return isVisibleToUser(null);
5707 * Computes whether the given portion of this view is visible to the user.
5708 * Such a view is attached, visible, all its predecessors are visible,
5709 * has an alpha greater than zero, and the specified portion is not
5710 * clipped entirely by its predecessors.
5712 * @param boundInView the portion of the view to test; coordinates should be relative; may be
5713 * <code>null</code>, and the entire view will be tested in this case.
5714 * When <code>true</code> is returned by the function, the actual visible
5715 * region will be stored in this parameter; that is, if boundInView is fully
5716 * contained within the view, no modification will be made, otherwise regions
5717 * outside of the visible area of the view will be clipped.
5719 * @return Whether the specified portion of the view is visible on the screen.
5723 protected boolean isVisibleToUser(Rect boundInView) {
5724 if (mAttachInfo != null) {
5725 // Attached to invisible window means this view is not visible.
5726 if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
5729 // An invisible predecessor or one with alpha zero means
5730 // that this view is not visible to the user.
5731 Object current = this;
5732 while (current instanceof View) {
5733 View view = (View) current;
5734 // We have attach info so this view is attached and there is no
5735 // need to check whether we reach to ViewRootImpl on the way up.
5736 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
5737 view.getVisibility() != VISIBLE) {
5740 current = view.mParent;
5742 // Check if the view is entirely covered by its predecessors.
5743 Rect visibleRect = mAttachInfo.mTmpInvalRect;
5744 Point offset = mAttachInfo.mPoint;
5745 if (!getGlobalVisibleRect(visibleRect, offset)) {
5748 // Check if the visible portion intersects the rectangle of interest.
5749 if (boundInView != null) {
5750 visibleRect.offset(-offset.x, -offset.y);
5751 return boundInView.intersect(visibleRect);
5759 * Computes a point on which a sequence of a down/up event can be sent to
5760 * trigger clicking this view. This method is for the exclusive use by the
5761 * accessibility layer to determine where to send a click event in explore
5764 * @param interactiveRegion The interactive portion of this window.
5765 * @param outPoint The point to populate.
5766 * @return True of such a point exists.
5768 boolean computeClickPointInScreenForAccessibility(Region interactiveRegion,
5770 // Since the interactive portion of the view is a region but as a view
5771 // may have a transformation matrix which cannot be applied to a
5772 // region we compute the view bounds rectangle and all interactive
5773 // predecessor's and sibling's (siblings of predecessors included)
5774 // rectangles that intersect the view bounds. At the
5775 // end if the view was partially covered by another interactive
5776 // view we compute the view's interactive region and pick a point
5777 // on its boundary path as regions do not offer APIs to get inner
5778 // points. Note that the the code is optimized to fail early and
5779 // avoid unnecessary allocations plus computations.
5781 // The current approach has edge cases that may produce false
5782 // positives or false negatives. For example, a portion of the
5783 // view may be covered by an interactive descendant of a
5784 // predecessor, which we do not compute. Also a view may be handling
5785 // raw touch events instead registering click listeners, which
5786 // we cannot compute. Despite these limitations this approach will
5787 // work most of the time and it is a huge improvement over just
5788 // blindly sending the down and up events in the center of the
5791 // Cannot click on an unattached view.
5792 if (mAttachInfo == null) {
5796 // Attached to an invisible window means this view is not visible.
5797 if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
5801 RectF bounds = mAttachInfo.mTmpTransformRect;
5802 bounds.set(0, 0, getWidth(), getHeight());
5803 List<RectF> intersections = mAttachInfo.mTmpRectList;
5804 intersections.clear();
5806 if (mParent instanceof ViewGroup) {
5807 ViewGroup parentGroup = (ViewGroup) mParent;
5808 if (!parentGroup.translateBoundsAndIntersectionsInWindowCoordinates(
5809 this, bounds, intersections)) {
5810 intersections.clear();
5815 // Take into account the window location.
5816 final int dx = mAttachInfo.mWindowLeft;
5817 final int dy = mAttachInfo.mWindowTop;
5818 bounds.offset(dx, dy);
5819 offsetRects(intersections, dx, dy);
5821 if (intersections.isEmpty() && interactiveRegion == null) {
5822 outPoint.set((int) bounds.centerX(), (int) bounds.centerY());
5824 // This view is partially covered by other views, then compute
5825 // the not covered region and pick a point on its boundary.
5826 Region region = new Region();
5827 region.set((int) bounds.left, (int) bounds.top,
5828 (int) bounds.right, (int) bounds.bottom);
5830 final int intersectionCount = intersections.size();
5831 for (int i = intersectionCount - 1; i >= 0; i--) {
5832 RectF intersection = intersections.remove(i);
5833 region.op((int) intersection.left, (int) intersection.top,
5834 (int) intersection.right, (int) intersection.bottom,
5835 Region.Op.DIFFERENCE);
5838 // If the view is completely covered, done.
5839 if (region.isEmpty()) {
5843 // Take into account the interactive portion of the window
5844 // as the rest is covered by other windows. If no such a region
5845 // then the whole window is interactive.
5846 if (interactiveRegion != null) {
5847 region.op(interactiveRegion, Region.Op.INTERSECT);
5850 // If the view is completely covered, done.
5851 if (region.isEmpty()) {
5855 // Try a shortcut here.
5856 if (region.isRect()) {
5857 Rect regionBounds = mAttachInfo.mTmpInvalRect;
5858 region.getBounds(regionBounds);
5859 outPoint.set(regionBounds.centerX(), regionBounds.centerY());
5863 // Get the a point on the region boundary path.
5864 Path path = region.getBoundaryPath();
5865 PathMeasure pathMeasure = new PathMeasure(path, false);
5866 final float[] coordinates = mAttachInfo.mTmpTransformLocation;
5868 // Without loss of generality pick a point.
5869 final float point = pathMeasure.getLength() * 0.01f;
5870 if (!pathMeasure.getPosTan(point, coordinates, null)) {
5874 outPoint.set(Math.round(coordinates[0]), Math.round(coordinates[1]));
5880 static void offsetRects(List<RectF> rects, float offsetX, float offsetY) {
5881 final int rectCount = rects.size();
5882 for (int i = 0; i < rectCount; i++) {
5883 RectF intersection = rects.get(i);
5884 intersection.offset(offsetX, offsetY);
5889 * Returns the delegate for implementing accessibility support via
5890 * composition. For more details see {@link AccessibilityDelegate}.
5892 * @return The delegate, or null if none set.
5896 public AccessibilityDelegate getAccessibilityDelegate() {
5897 return mAccessibilityDelegate;
5901 * Sets a delegate for implementing accessibility support via composition as
5902 * opposed to inheritance. The delegate's primary use is for implementing
5903 * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
5905 * @param delegate The delegate instance.
5907 * @see AccessibilityDelegate
5909 public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
5910 mAccessibilityDelegate = delegate;
5914 * Gets the provider for managing a virtual view hierarchy rooted at this View
5915 * and reported to {@link android.accessibilityservice.AccessibilityService}s
5916 * that explore the window content.
5918 * If this method returns an instance, this instance is responsible for managing
5919 * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
5920 * View including the one representing the View itself. Similarly the returned
5921 * instance is responsible for performing accessibility actions on any virtual
5922 * view or the root view itself.
5925 * If an {@link AccessibilityDelegate} has been specified via calling
5926 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5927 * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
5928 * is responsible for handling this call.
5931 * @return The provider.
5933 * @see AccessibilityNodeProvider
5935 public AccessibilityNodeProvider getAccessibilityNodeProvider() {
5936 if (mAccessibilityDelegate != null) {
5937 return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
5944 * Gets the unique identifier of this view on the screen for accessibility purposes.
5945 * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
5947 * @return The view accessibility id.
5951 public int getAccessibilityViewId() {
5952 if (mAccessibilityViewId == NO_ID) {
5953 mAccessibilityViewId = sNextAccessibilityViewId++;
5955 return mAccessibilityViewId;
5959 * Gets the unique identifier of the window in which this View reseides.
5961 * @return The window accessibility id.
5965 public int getAccessibilityWindowId() {
5966 return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
5967 : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
5971 * Gets the {@link View} description. It briefly describes the view and is
5972 * primarily used for accessibility support. Set this property to enable
5973 * better accessibility support for your application. This is especially
5974 * true for views that do not have textual representation (For example,
5977 * @return The content description.
5979 * @attr ref android.R.styleable#View_contentDescription
5981 @ViewDebug.ExportedProperty(category = "accessibility")
5982 public CharSequence getContentDescription() {
5983 return mContentDescription;
5987 * Sets the {@link View} description. It briefly describes the view and is
5988 * primarily used for accessibility support. Set this property to enable
5989 * better accessibility support for your application. This is especially
5990 * true for views that do not have textual representation (For example,
5993 * @param contentDescription The content description.
5995 * @attr ref android.R.styleable#View_contentDescription
5997 @RemotableViewMethod
5998 public void setContentDescription(CharSequence contentDescription) {
5999 if (mContentDescription == null) {
6000 if (contentDescription == null) {
6003 } else if (mContentDescription.equals(contentDescription)) {
6006 mContentDescription = contentDescription;
6007 final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
6008 if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
6009 setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
6010 notifySubtreeAccessibilityStateChangedIfNeeded();
6012 notifyViewAccessibilityStateChangedIfNeeded(
6013 AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
6018 * Gets the id of a view for which this view serves as a label for
6019 * accessibility purposes.
6021 * @return The labeled view id.
6023 @ViewDebug.ExportedProperty(category = "accessibility")
6024 public int getLabelFor() {
6029 * Sets the id of a view for which this view serves as a label for
6030 * accessibility purposes.
6032 * @param id The labeled view id.
6034 @RemotableViewMethod
6035 public void setLabelFor(int id) {
6037 if (mLabelForId != View.NO_ID
6038 && mID == View.NO_ID) {
6039 mID = generateViewId();
6044 * Invoked whenever this view loses focus, either by losing window focus or by losing
6045 * focus within its window. This method can be used to clear any state tied to the
6046 * focus. For instance, if a button is held pressed with the trackball and the window
6047 * loses focus, this method can be used to cancel the press.
6049 * Subclasses of View overriding this method should always call super.onFocusLost().
6051 * @see #onFocusChanged(boolean, int, android.graphics.Rect)
6052 * @see #onWindowFocusChanged(boolean)
6054 * @hide pending API council approval
6056 protected void onFocusLost() {
6057 resetPressedState();
6060 private void resetPressedState() {
6061 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
6068 if (!mHasPerformedLongPress) {
6069 removeLongPressCallback();
6075 * Returns true if this view has focus
6077 * @return True if this view has focus, false otherwise.
6079 @ViewDebug.ExportedProperty(category = "focus")
6080 public boolean isFocused() {
6081 return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6085 * Find the view in the hierarchy rooted at this view that currently has
6088 * @return The view that currently has focus, or null if no focused view can
6091 public View findFocus() {
6092 return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
6096 * Indicates whether this view is one of the set of scrollable containers in
6099 * @return whether this view is one of the set of scrollable containers in
6102 * @attr ref android.R.styleable#View_isScrollContainer
6104 public boolean isScrollContainer() {
6105 return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
6109 * Change whether this view is one of the set of scrollable containers in
6110 * its window. This will be used to determine whether the window can
6111 * resize or must pan when a soft input area is open -- scrollable
6112 * containers allow the window to use resize mode since the container
6113 * will appropriately shrink.
6115 * @attr ref android.R.styleable#View_isScrollContainer
6117 public void setScrollContainer(boolean isScrollContainer) {
6118 if (isScrollContainer) {
6119 if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
6120 mAttachInfo.mScrollContainers.add(this);
6121 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
6123 mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
6125 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
6126 mAttachInfo.mScrollContainers.remove(this);
6128 mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
6133 * Returns the quality of the drawing cache.
6135 * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6136 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6138 * @see #setDrawingCacheQuality(int)
6139 * @see #setDrawingCacheEnabled(boolean)
6140 * @see #isDrawingCacheEnabled()
6142 * @attr ref android.R.styleable#View_drawingCacheQuality
6144 @DrawingCacheQuality
6145 public int getDrawingCacheQuality() {
6146 return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
6150 * Set the drawing cache quality of this view. This value is used only when the
6151 * drawing cache is enabled
6153 * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6154 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6156 * @see #getDrawingCacheQuality()
6157 * @see #setDrawingCacheEnabled(boolean)
6158 * @see #isDrawingCacheEnabled()
6160 * @attr ref android.R.styleable#View_drawingCacheQuality
6162 public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
6163 setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
6167 * Returns whether the screen should remain on, corresponding to the current
6168 * value of {@link #KEEP_SCREEN_ON}.
6170 * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
6172 * @see #setKeepScreenOn(boolean)
6174 * @attr ref android.R.styleable#View_keepScreenOn
6176 public boolean getKeepScreenOn() {
6177 return (mViewFlags & KEEP_SCREEN_ON) != 0;
6181 * Controls whether the screen should remain on, modifying the
6182 * value of {@link #KEEP_SCREEN_ON}.
6184 * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
6186 * @see #getKeepScreenOn()
6188 * @attr ref android.R.styleable#View_keepScreenOn
6190 public void setKeepScreenOn(boolean keepScreenOn) {
6191 setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
6195 * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6196 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6198 * @attr ref android.R.styleable#View_nextFocusLeft
6200 public int getNextFocusLeftId() {
6201 return mNextFocusLeftId;
6205 * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6206 * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
6207 * decide automatically.
6209 * @attr ref android.R.styleable#View_nextFocusLeft
6211 public void setNextFocusLeftId(int nextFocusLeftId) {
6212 mNextFocusLeftId = nextFocusLeftId;
6216 * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6217 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6219 * @attr ref android.R.styleable#View_nextFocusRight
6221 public int getNextFocusRightId() {
6222 return mNextFocusRightId;
6226 * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6227 * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
6228 * decide automatically.
6230 * @attr ref android.R.styleable#View_nextFocusRight
6232 public void setNextFocusRightId(int nextFocusRightId) {
6233 mNextFocusRightId = nextFocusRightId;
6237 * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6238 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6240 * @attr ref android.R.styleable#View_nextFocusUp
6242 public int getNextFocusUpId() {
6243 return mNextFocusUpId;
6247 * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6248 * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
6249 * decide automatically.
6251 * @attr ref android.R.styleable#View_nextFocusUp
6253 public void setNextFocusUpId(int nextFocusUpId) {
6254 mNextFocusUpId = nextFocusUpId;
6258 * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
6259 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6261 * @attr ref android.R.styleable#View_nextFocusDown
6263 public int getNextFocusDownId() {
6264 return mNextFocusDownId;
6268 * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
6269 * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
6270 * decide automatically.
6272 * @attr ref android.R.styleable#View_nextFocusDown
6274 public void setNextFocusDownId(int nextFocusDownId) {
6275 mNextFocusDownId = nextFocusDownId;
6279 * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
6280 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6282 * @attr ref android.R.styleable#View_nextFocusForward
6284 public int getNextFocusForwardId() {
6285 return mNextFocusForwardId;
6289 * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
6290 * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
6291 * decide automatically.
6293 * @attr ref android.R.styleable#View_nextFocusForward
6295 public void setNextFocusForwardId(int nextFocusForwardId) {
6296 mNextFocusForwardId = nextFocusForwardId;
6300 * Returns the visibility of this view and all of its ancestors
6302 * @return True if this view and all of its ancestors are {@link #VISIBLE}
6304 public boolean isShown() {
6305 View current = this;
6306 //noinspection ConstantConditions
6308 if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6311 ViewParent parent = current.mParent;
6312 if (parent == null) {
6313 return false; // We are not attached to the view root
6315 if (!(parent instanceof View)) {
6318 current = (View) parent;
6319 } while (current != null);
6325 * Called by the view hierarchy when the content insets for a window have
6326 * changed, to allow it to adjust its content to fit within those windows.
6327 * The content insets tell you the space that the status bar, input method,
6328 * and other system windows infringe on the application's window.
6330 * <p>You do not normally need to deal with this function, since the default
6331 * window decoration given to applications takes care of applying it to the
6332 * content of the window. If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
6333 * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
6334 * and your content can be placed under those system elements. You can then
6335 * use this method within your view hierarchy if you have parts of your UI
6336 * which you would like to ensure are not being covered.
6338 * <p>The default implementation of this method simply applies the content
6339 * insets to the view's padding, consuming that content (modifying the
6340 * insets to be 0), and returning true. This behavior is off by default, but can
6341 * be enabled through {@link #setFitsSystemWindows(boolean)}.
6343 * <p>This function's traversal down the hierarchy is depth-first. The same content
6344 * insets object is propagated down the hierarchy, so any changes made to it will
6345 * be seen by all following views (including potentially ones above in
6346 * the hierarchy since this is a depth-first traversal). The first view
6347 * that returns true will abort the entire traversal.
6349 * <p>The default implementation works well for a situation where it is
6350 * used with a container that covers the entire window, allowing it to
6351 * apply the appropriate insets to its content on all edges. If you need
6352 * a more complicated layout (such as two different views fitting system
6353 * windows, one on the top of the window, and one on the bottom),
6354 * you can override the method and handle the insets however you would like.
6355 * Note that the insets provided by the framework are always relative to the
6356 * far edges of the window, not accounting for the location of the called view
6357 * within that window. (In fact when this method is called you do not yet know
6358 * where the layout will place the view, as it is done before layout happens.)
6360 * <p>Note: unlike many View methods, there is no dispatch phase to this
6361 * call. If you are overriding it in a ViewGroup and want to allow the
6362 * call to continue to your children, you must be sure to call the super
6365 * <p>Here is a sample layout that makes use of fitting system windows
6366 * to have controls for a video view placed inside of the window decorations
6367 * that it hides and shows. This can be used with code like the second
6368 * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
6370 * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
6372 * @param insets Current content insets of the window. Prior to
6373 * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
6374 * the insets or else you and Android will be unhappy.
6376 * @return {@code true} if this view applied the insets and it should not
6377 * continue propagating further down the hierarchy, {@code false} otherwise.
6378 * @see #getFitsSystemWindows()
6379 * @see #setFitsSystemWindows(boolean)
6380 * @see #setSystemUiVisibility(int)
6382 * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
6383 * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
6384 * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
6385 * to implement handling their own insets.
6387 protected boolean fitSystemWindows(Rect insets) {
6388 if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
6389 if (insets == null) {
6390 // Null insets by definition have already been consumed.
6391 // This call cannot apply insets since there are none to apply,
6395 // If we're not in the process of dispatching the newer apply insets call,
6396 // that means we're not in the compatibility path. Dispatch into the newer
6397 // apply insets path and take things from there.
6399 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
6400 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
6402 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
6405 // We're being called from the newer apply insets path.
6406 // Perform the standard fallback behavior.
6407 return fitSystemWindowsInt(insets);
6411 private boolean fitSystemWindowsInt(Rect insets) {
6412 if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
6413 mUserPaddingStart = UNDEFINED_PADDING;
6414 mUserPaddingEnd = UNDEFINED_PADDING;
6415 Rect localInsets = sThreadLocal.get();
6416 if (localInsets == null) {
6417 localInsets = new Rect();
6418 sThreadLocal.set(localInsets);
6420 boolean res = computeFitSystemWindows(insets, localInsets);
6421 mUserPaddingLeftInitial = localInsets.left;
6422 mUserPaddingRightInitial = localInsets.right;
6423 internalSetPadding(localInsets.left, localInsets.top,
6424 localInsets.right, localInsets.bottom);
6431 * Called when the view should apply {@link WindowInsets} according to its internal policy.
6433 * <p>This method should be overridden by views that wish to apply a policy different from or
6434 * in addition to the default behavior. Clients that wish to force a view subtree
6435 * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
6437 * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
6438 * it will be called during dispatch instead of this method. The listener may optionally
6439 * call this method from its own implementation if it wishes to apply the view's default
6440 * insets policy in addition to its own.</p>
6442 * <p>Implementations of this method should either return the insets parameter unchanged
6443 * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
6444 * that this view applied itself. This allows new inset types added in future platform
6445 * versions to pass through existing implementations unchanged without being erroneously
6448 * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
6449 * property is set then the view will consume the system window insets and apply them
6450 * as padding for the view.</p>
6452 * @param insets Insets to apply
6453 * @return The supplied insets with any applied insets consumed
6455 public WindowInsets onApplyWindowInsets(WindowInsets insets) {
6456 if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
6457 // We weren't called from within a direct call to fitSystemWindows,
6458 // call into it as a fallback in case we're in a class that overrides it
6459 // and has logic to perform.
6460 if (fitSystemWindows(insets.getSystemWindowInsets())) {
6461 return insets.consumeSystemWindowInsets();
6464 // We were called from within a direct call to fitSystemWindows.
6465 if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
6466 return insets.consumeSystemWindowInsets();
6473 * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
6474 * window insets to this view. The listener's
6475 * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
6476 * method will be called instead of the view's
6477 * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
6479 * @param listener Listener to set
6481 * @see #onApplyWindowInsets(WindowInsets)
6483 public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
6484 getListenerInfo().mOnApplyWindowInsetsListener = listener;
6488 * Request to apply the given window insets to this view or another view in its subtree.
6490 * <p>This method should be called by clients wishing to apply insets corresponding to areas
6491 * obscured by window decorations or overlays. This can include the status and navigation bars,
6492 * action bars, input methods and more. New inset categories may be added in the future.
6493 * The method returns the insets provided minus any that were applied by this view or its
6496 * <p>Clients wishing to provide custom behavior should override the
6497 * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
6498 * {@link OnApplyWindowInsetsListener} via the
6499 * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
6502 * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
6505 * @param insets Insets to apply
6506 * @return The provided insets minus the insets that were consumed
6508 public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
6510 mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
6511 if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
6512 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
6514 return onApplyWindowInsets(insets);
6517 mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
6522 * @hide Compute the insets that should be consumed by this view and the ones
6523 * that should propagate to those under it.
6525 protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
6526 if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
6527 || mAttachInfo == null
6528 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
6529 && !mAttachInfo.mOverscanRequested)) {
6530 outLocalInsets.set(inoutInsets);
6531 inoutInsets.set(0, 0, 0, 0);
6534 // The application wants to take care of fitting system window for
6535 // the content... however we still need to take care of any overscan here.
6536 final Rect overscan = mAttachInfo.mOverscanInsets;
6537 outLocalInsets.set(overscan);
6538 inoutInsets.left -= overscan.left;
6539 inoutInsets.top -= overscan.top;
6540 inoutInsets.right -= overscan.right;
6541 inoutInsets.bottom -= overscan.bottom;
6547 * Compute insets that should be consumed by this view and the ones that should propagate
6548 * to those under it.
6550 * @param in Insets currently being processed by this View, likely received as a parameter
6551 * to {@link #onApplyWindowInsets(WindowInsets)}.
6552 * @param outLocalInsets A Rect that will receive the insets that should be consumed
6554 * @return Insets that should be passed along to views under this one
6556 public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
6557 if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
6558 || mAttachInfo == null
6559 || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
6560 outLocalInsets.set(in.getSystemWindowInsets());
6561 return in.consumeSystemWindowInsets();
6563 outLocalInsets.set(0, 0, 0, 0);
6569 * Sets whether or not this view should account for system screen decorations
6570 * such as the status bar and inset its content; that is, controlling whether
6571 * the default implementation of {@link #fitSystemWindows(Rect)} will be
6572 * executed. See that method for more details.
6574 * <p>Note that if you are providing your own implementation of
6575 * {@link #fitSystemWindows(Rect)}, then there is no need to set this
6576 * flag to true -- your implementation will be overriding the default
6577 * implementation that checks this flag.
6579 * @param fitSystemWindows If true, then the default implementation of
6580 * {@link #fitSystemWindows(Rect)} will be executed.
6582 * @attr ref android.R.styleable#View_fitsSystemWindows
6583 * @see #getFitsSystemWindows()
6584 * @see #fitSystemWindows(Rect)
6585 * @see #setSystemUiVisibility(int)
6587 public void setFitsSystemWindows(boolean fitSystemWindows) {
6588 setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
6592 * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
6593 * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
6596 * @return {@code true} if the default implementation of
6597 * {@link #fitSystemWindows(Rect)} will be executed.
6599 * @attr ref android.R.styleable#View_fitsSystemWindows
6600 * @see #setFitsSystemWindows(boolean)
6601 * @see #fitSystemWindows(Rect)
6602 * @see #setSystemUiVisibility(int)
6604 @ViewDebug.ExportedProperty
6605 public boolean getFitsSystemWindows() {
6606 return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
6610 public boolean fitsSystemWindows() {
6611 return getFitsSystemWindows();
6615 * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
6616 * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
6618 public void requestFitSystemWindows() {
6619 if (mParent != null) {
6620 mParent.requestFitSystemWindows();
6625 * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
6627 public void requestApplyInsets() {
6628 requestFitSystemWindows();
6632 * For use by PhoneWindow to make its own system window fitting optional.
6635 public void makeOptionalFitsSystemWindows() {
6636 setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
6640 * Returns the visibility status for this view.
6642 * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
6643 * @attr ref android.R.styleable#View_visibility
6645 @ViewDebug.ExportedProperty(mapping = {
6646 @ViewDebug.IntToString(from = VISIBLE, to = "VISIBLE"),
6647 @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
6648 @ViewDebug.IntToString(from = GONE, to = "GONE")
6651 public int getVisibility() {
6652 return mViewFlags & VISIBILITY_MASK;
6656 * Set the enabled state of this view.
6658 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
6659 * @attr ref android.R.styleable#View_visibility
6661 @RemotableViewMethod
6662 public void setVisibility(@Visibility int visibility) {
6663 setFlags(visibility, VISIBILITY_MASK);
6664 if (mBackground != null) mBackground.setVisible(visibility == VISIBLE, false);
6668 * Returns the enabled status for this view. The interpretation of the
6669 * enabled state varies by subclass.
6671 * @return True if this view is enabled, false otherwise.
6673 @ViewDebug.ExportedProperty
6674 public boolean isEnabled() {
6675 return (mViewFlags & ENABLED_MASK) == ENABLED;
6679 * Set the enabled state of this view. The interpretation of the enabled
6680 * state varies by subclass.
6682 * @param enabled True if this view is enabled, false otherwise.
6684 @RemotableViewMethod
6685 public void setEnabled(boolean enabled) {
6686 if (enabled == isEnabled()) return;
6688 setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
6691 * The View most likely has to change its appearance, so refresh
6692 * the drawable state.
6694 refreshDrawableState();
6696 // Invalidate too, since the default behavior for views is to be
6697 // be drawn at 50% alpha rather than to change the drawable.
6701 cancelPendingInputEvents();
6706 * Set whether this view can receive the focus.
6708 * Setting this to false will also ensure that this view is not focusable
6711 * @param focusable If true, this view can receive the focus.
6713 * @see #setFocusableInTouchMode(boolean)
6714 * @attr ref android.R.styleable#View_focusable
6716 public void setFocusable(boolean focusable) {
6718 setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
6720 setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
6724 * Set whether this view can receive focus while in touch mode.
6726 * Setting this to true will also ensure that this view is focusable.
6728 * @param focusableInTouchMode If true, this view can receive the focus while
6731 * @see #setFocusable(boolean)
6732 * @attr ref android.R.styleable#View_focusableInTouchMode
6734 public void setFocusableInTouchMode(boolean focusableInTouchMode) {
6735 // Focusable in touch mode should always be set before the focusable flag
6736 // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
6737 // which, in touch mode, will not successfully request focus on this view
6738 // because the focusable in touch mode flag is not set
6739 setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
6740 if (focusableInTouchMode) {
6741 setFlags(FOCUSABLE, FOCUSABLE_MASK);
6746 * Set whether this view should have sound effects enabled for events such as
6747 * clicking and touching.
6749 * <p>You may wish to disable sound effects for a view if you already play sounds,
6750 * for instance, a dial key that plays dtmf tones.
6752 * @param soundEffectsEnabled whether sound effects are enabled for this view.
6753 * @see #isSoundEffectsEnabled()
6754 * @see #playSoundEffect(int)
6755 * @attr ref android.R.styleable#View_soundEffectsEnabled
6757 public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
6758 setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
6762 * @return whether this view should have sound effects enabled for events such as
6763 * clicking and touching.
6765 * @see #setSoundEffectsEnabled(boolean)
6766 * @see #playSoundEffect(int)
6767 * @attr ref android.R.styleable#View_soundEffectsEnabled
6769 @ViewDebug.ExportedProperty
6770 public boolean isSoundEffectsEnabled() {
6771 return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
6775 * Set whether this view should have haptic feedback for events such as
6778 * <p>You may wish to disable haptic feedback if your view already controls
6779 * its own haptic feedback.
6781 * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
6782 * @see #isHapticFeedbackEnabled()
6783 * @see #performHapticFeedback(int)
6784 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
6786 public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
6787 setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
6791 * @return whether this view should have haptic feedback enabled for events
6794 * @see #setHapticFeedbackEnabled(boolean)
6795 * @see #performHapticFeedback(int)
6796 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
6798 @ViewDebug.ExportedProperty
6799 public boolean isHapticFeedbackEnabled() {
6800 return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
6804 * Returns the layout direction for this view.
6806 * @return One of {@link #LAYOUT_DIRECTION_LTR},
6807 * {@link #LAYOUT_DIRECTION_RTL},
6808 * {@link #LAYOUT_DIRECTION_INHERIT} or
6809 * {@link #LAYOUT_DIRECTION_LOCALE}.
6811 * @attr ref android.R.styleable#View_layoutDirection
6815 @ViewDebug.ExportedProperty(category = "layout", mapping = {
6816 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "LTR"),
6817 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RTL"),
6818 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
6819 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE, to = "LOCALE")
6822 public int getRawLayoutDirection() {
6823 return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
6827 * Set the layout direction for this view. This will propagate a reset of layout direction
6828 * resolution to the view's children and resolve layout direction for this view.
6830 * @param layoutDirection the layout direction to set. Should be one of:
6832 * {@link #LAYOUT_DIRECTION_LTR},
6833 * {@link #LAYOUT_DIRECTION_RTL},
6834 * {@link #LAYOUT_DIRECTION_INHERIT},
6835 * {@link #LAYOUT_DIRECTION_LOCALE}.
6837 * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
6838 * proceeds up the parent chain of the view to get the value. If there is no parent, then it
6839 * will return the default {@link #LAYOUT_DIRECTION_LTR}.
6841 * @attr ref android.R.styleable#View_layoutDirection
6843 @RemotableViewMethod
6844 public void setLayoutDirection(@LayoutDir int layoutDirection) {
6845 if (getRawLayoutDirection() != layoutDirection) {
6846 // Reset the current layout direction and the resolved one
6847 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
6848 resetRtlProperties();
6849 // Set the new layout direction (filtered)
6851 ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
6852 // We need to resolve all RTL properties as they all depend on layout direction
6853 resolveRtlPropertiesIfNeeded();
6860 * Returns the resolved layout direction for this view.
6862 * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
6863 * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
6865 * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
6866 * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
6868 * @attr ref android.R.styleable#View_layoutDirection
6870 @ViewDebug.ExportedProperty(category = "layout", mapping = {
6871 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
6872 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
6875 public int getLayoutDirection() {
6876 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
6877 if (targetSdkVersion < JELLY_BEAN_MR1) {
6878 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
6879 return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
6881 return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
6882 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
6886 * Indicates whether or not this view's layout is right-to-left. This is resolved from
6887 * layout attribute and/or the inherited value from the parent
6889 * @return true if the layout is right-to-left.
6893 @ViewDebug.ExportedProperty(category = "layout")
6894 public boolean isLayoutRtl() {
6895 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
6899 * Indicates whether the view is currently tracking transient state that the
6900 * app should not need to concern itself with saving and restoring, but that
6901 * the framework should take special note to preserve when possible.
6903 * <p>A view with transient state cannot be trivially rebound from an external
6904 * data source, such as an adapter binding item views in a list. This may be
6905 * because the view is performing an animation, tracking user selection
6906 * of content, or similar.</p>
6908 * @return true if the view has transient state
6910 @ViewDebug.ExportedProperty(category = "layout")
6911 public boolean hasTransientState() {
6912 return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
6916 * Set whether this view is currently tracking transient state that the
6917 * framework should attempt to preserve when possible. This flag is reference counted,
6918 * so every call to setHasTransientState(true) should be paired with a later call
6919 * to setHasTransientState(false).
6921 * <p>A view with transient state cannot be trivially rebound from an external
6922 * data source, such as an adapter binding item views in a list. This may be
6923 * because the view is performing an animation, tracking user selection
6924 * of content, or similar.</p>
6926 * @param hasTransientState true if this view has transient state
6928 public void setHasTransientState(boolean hasTransientState) {
6929 mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
6930 mTransientStateCount - 1;
6931 if (mTransientStateCount < 0) {
6932 mTransientStateCount = 0;
6933 Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
6934 "unmatched pair of setHasTransientState calls");
6935 } else if ((hasTransientState && mTransientStateCount == 1) ||
6936 (!hasTransientState && mTransientStateCount == 0)) {
6937 // update flag if we've just incremented up from 0 or decremented down to 0
6938 mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
6939 (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
6940 if (mParent != null) {
6942 mParent.childHasTransientStateChanged(this, hasTransientState);
6943 } catch (AbstractMethodError e) {
6944 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
6945 " does not fully implement ViewParent", e);
6952 * Returns true if this view is currently attached to a window.
6954 public boolean isAttachedToWindow() {
6955 return mAttachInfo != null;
6959 * Returns true if this view has been through at least one layout since it
6960 * was last attached to or detached from a window.
6962 public boolean isLaidOut() {
6963 return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
6967 * If this view doesn't do any drawing on its own, set this flag to
6968 * allow further optimizations. By default, this flag is not set on
6969 * View, but could be set on some View subclasses such as ViewGroup.
6971 * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
6972 * you should clear this flag.
6974 * @param willNotDraw whether or not this View draw on its own
6976 public void setWillNotDraw(boolean willNotDraw) {
6977 setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
6981 * Returns whether or not this View draws on its own.
6983 * @return true if this view has nothing to draw, false otherwise
6985 @ViewDebug.ExportedProperty(category = "drawing")
6986 public boolean willNotDraw() {
6987 return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
6991 * When a View's drawing cache is enabled, drawing is redirected to an
6992 * offscreen bitmap. Some views, like an ImageView, must be able to
6993 * bypass this mechanism if they already draw a single bitmap, to avoid
6994 * unnecessary usage of the memory.
6996 * @param willNotCacheDrawing true if this view does not cache its
6997 * drawing, false otherwise
6999 public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
7000 setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
7004 * Returns whether or not this View can cache its drawing or not.
7006 * @return true if this view does not cache its drawing, false otherwise
7008 @ViewDebug.ExportedProperty(category = "drawing")
7009 public boolean willNotCacheDrawing() {
7010 return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
7014 * Indicates whether this view reacts to click events or not.
7016 * @return true if the view is clickable, false otherwise
7018 * @see #setClickable(boolean)
7019 * @attr ref android.R.styleable#View_clickable
7021 @ViewDebug.ExportedProperty
7022 public boolean isClickable() {
7023 return (mViewFlags & CLICKABLE) == CLICKABLE;
7027 * Enables or disables click events for this view. When a view
7028 * is clickable it will change its state to "pressed" on every click.
7029 * Subclasses should set the view clickable to visually react to
7032 * @param clickable true to make the view clickable, false otherwise
7034 * @see #isClickable()
7035 * @attr ref android.R.styleable#View_clickable
7037 public void setClickable(boolean clickable) {
7038 setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
7042 * Indicates whether this view reacts to long click events or not.
7044 * @return true if the view is long clickable, false otherwise
7046 * @see #setLongClickable(boolean)
7047 * @attr ref android.R.styleable#View_longClickable
7049 public boolean isLongClickable() {
7050 return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
7054 * Enables or disables long click events for this view. When a view is long
7055 * clickable it reacts to the user holding down the button for a longer
7056 * duration than a tap. This event can either launch the listener or a
7059 * @param longClickable true to make the view long clickable, false otherwise
7060 * @see #isLongClickable()
7061 * @attr ref android.R.styleable#View_longClickable
7063 public void setLongClickable(boolean longClickable) {
7064 setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
7068 * Sets the pressed state for this view and provides a touch coordinate for
7069 * animation hinting.
7071 * @param pressed Pass true to set the View's internal state to "pressed",
7072 * or false to reverts the View's internal state from a
7073 * previously set "pressed" state.
7074 * @param x The x coordinate of the touch that caused the press
7075 * @param y The y coordinate of the touch that caused the press
7077 private void setPressed(boolean pressed, float x, float y) {
7079 drawableHotspotChanged(x, y);
7082 setPressed(pressed);
7086 * Sets the pressed state for this view.
7088 * @see #isClickable()
7089 * @see #setClickable(boolean)
7091 * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
7092 * the View's internal state from a previously set "pressed" state.
7094 public void setPressed(boolean pressed) {
7095 final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
7098 mPrivateFlags |= PFLAG_PRESSED;
7100 mPrivateFlags &= ~PFLAG_PRESSED;
7104 refreshDrawableState();
7106 dispatchSetPressed(pressed);
7110 * Dispatch setPressed to all of this View's children.
7112 * @see #setPressed(boolean)
7114 * @param pressed The new pressed state
7116 protected void dispatchSetPressed(boolean pressed) {
7120 * Indicates whether the view is currently in pressed state. Unless
7121 * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
7122 * the pressed state.
7124 * @see #setPressed(boolean)
7125 * @see #isClickable()
7126 * @see #setClickable(boolean)
7128 * @return true if the view is currently pressed, false otherwise
7130 @ViewDebug.ExportedProperty
7131 public boolean isPressed() {
7132 return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
7136 * Indicates whether this view will save its state (that is,
7137 * whether its {@link #onSaveInstanceState} method will be called).
7139 * @return Returns true if the view state saving is enabled, else false.
7141 * @see #setSaveEnabled(boolean)
7142 * @attr ref android.R.styleable#View_saveEnabled
7144 public boolean isSaveEnabled() {
7145 return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
7149 * Controls whether the saving of this view's state is
7150 * enabled (that is, whether its {@link #onSaveInstanceState} method
7151 * will be called). Note that even if freezing is enabled, the
7152 * view still must have an id assigned to it (via {@link #setId(int)})
7153 * for its state to be saved. This flag can only disable the
7154 * saving of this view; any child views may still have their state saved.
7156 * @param enabled Set to false to <em>disable</em> state saving, or true
7157 * (the default) to allow it.
7159 * @see #isSaveEnabled()
7161 * @see #onSaveInstanceState()
7162 * @attr ref android.R.styleable#View_saveEnabled
7164 public void setSaveEnabled(boolean enabled) {
7165 setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
7169 * Gets whether the framework should discard touches when the view's
7170 * window is obscured by another visible window.
7171 * Refer to the {@link View} security documentation for more details.
7173 * @return True if touch filtering is enabled.
7175 * @see #setFilterTouchesWhenObscured(boolean)
7176 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
7178 @ViewDebug.ExportedProperty
7179 public boolean getFilterTouchesWhenObscured() {
7180 return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
7184 * Sets whether the framework should discard touches when the view's
7185 * window is obscured by another visible window.
7186 * Refer to the {@link View} security documentation for more details.
7188 * @param enabled True if touch filtering should be enabled.
7190 * @see #getFilterTouchesWhenObscured
7191 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
7193 public void setFilterTouchesWhenObscured(boolean enabled) {
7194 setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
7195 FILTER_TOUCHES_WHEN_OBSCURED);
7199 * Indicates whether the entire hierarchy under this view will save its
7200 * state when a state saving traversal occurs from its parent. The default
7201 * is true; if false, these views will not be saved unless
7202 * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
7204 * @return Returns true if the view state saving from parent is enabled, else false.
7206 * @see #setSaveFromParentEnabled(boolean)
7208 public boolean isSaveFromParentEnabled() {
7209 return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
7213 * Controls whether the entire hierarchy under this view will save its
7214 * state when a state saving traversal occurs from its parent. The default
7215 * is true; if false, these views will not be saved unless
7216 * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
7218 * @param enabled Set to false to <em>disable</em> state saving, or true
7219 * (the default) to allow it.
7221 * @see #isSaveFromParentEnabled()
7223 * @see #onSaveInstanceState()
7225 public void setSaveFromParentEnabled(boolean enabled) {
7226 setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
7231 * Returns whether this View is able to take focus.
7233 * @return True if this view can take focus, or false otherwise.
7234 * @attr ref android.R.styleable#View_focusable
7236 @ViewDebug.ExportedProperty(category = "focus")
7237 public final boolean isFocusable() {
7238 return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
7242 * When a view is focusable, it may not want to take focus when in touch mode.
7243 * For example, a button would like focus when the user is navigating via a D-pad
7244 * so that the user can click on it, but once the user starts touching the screen,
7245 * the button shouldn't take focus
7246 * @return Whether the view is focusable in touch mode.
7247 * @attr ref android.R.styleable#View_focusableInTouchMode
7249 @ViewDebug.ExportedProperty
7250 public final boolean isFocusableInTouchMode() {
7251 return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
7255 * Find the nearest view in the specified direction that can take focus.
7256 * This does not actually give focus to that view.
7258 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7260 * @return The nearest focusable in the specified direction, or null if none
7263 public View focusSearch(@FocusRealDirection int direction) {
7264 if (mParent != null) {
7265 return mParent.focusSearch(this, direction);
7272 * This method is the last chance for the focused view and its ancestors to
7273 * respond to an arrow key. This is called when the focused view did not
7274 * consume the key internally, nor could the view system find a new view in
7275 * the requested direction to give focus to.
7277 * @param focused The currently focused view.
7278 * @param direction The direction focus wants to move. One of FOCUS_UP,
7279 * FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
7280 * @return True if the this view consumed this unhandled move.
7282 public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
7287 * If a user manually specified the next view id for a particular direction,
7288 * use the root to look up the view.
7289 * @param root The root view of the hierarchy containing this view.
7290 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
7291 * or FOCUS_BACKWARD.
7292 * @return The user specified next view, or null if there is none.
7294 View findUserSetNextFocus(View root, @FocusDirection int direction) {
7295 switch (direction) {
7297 if (mNextFocusLeftId == View.NO_ID) return null;
7298 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
7300 if (mNextFocusRightId == View.NO_ID) return null;
7301 return findViewInsideOutShouldExist(root, mNextFocusRightId);
7303 if (mNextFocusUpId == View.NO_ID) return null;
7304 return findViewInsideOutShouldExist(root, mNextFocusUpId);
7306 if (mNextFocusDownId == View.NO_ID) return null;
7307 return findViewInsideOutShouldExist(root, mNextFocusDownId);
7309 if (mNextFocusForwardId == View.NO_ID) return null;
7310 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
7311 case FOCUS_BACKWARD: {
7312 if (mID == View.NO_ID) return null;
7314 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
7316 public boolean apply(View t) {
7317 return t.mNextFocusForwardId == id;
7325 private View findViewInsideOutShouldExist(View root, int id) {
7326 if (mMatchIdPredicate == null) {
7327 mMatchIdPredicate = new MatchIdPredicate();
7329 mMatchIdPredicate.mId = id;
7330 View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
7331 if (result == null) {
7332 Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
7338 * Find and return all focusable views that are descendants of this view,
7339 * possibly including this view if it is focusable itself.
7341 * @param direction The direction of the focus
7342 * @return A list of focusable views
7344 public ArrayList<View> getFocusables(@FocusDirection int direction) {
7345 ArrayList<View> result = new ArrayList<View>(24);
7346 addFocusables(result, direction);
7351 * Add any focusable views that are descendants of this view (possibly
7352 * including this view if it is focusable itself) to views. If we are in touch mode,
7353 * only add views that are also focusable in touch mode.
7355 * @param views Focusable views found so far
7356 * @param direction The direction of the focus
7358 public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
7359 addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
7363 * Adds any focusable views that are descendants of this view (possibly
7364 * including this view if it is focusable itself) to views. This method
7365 * adds all focusable views regardless if we are in touch mode or
7366 * only views focusable in touch mode if we are in touch mode or
7367 * only views that can take accessibility focus if accessibility is enabeld
7368 * depending on the focusable mode paramater.
7370 * @param views Focusable views found so far or null if all we are interested is
7371 * the number of focusables.
7372 * @param direction The direction of the focus.
7373 * @param focusableMode The type of focusables to be added.
7375 * @see #FOCUSABLES_ALL
7376 * @see #FOCUSABLES_TOUCH_MODE
7378 public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
7379 @FocusableMode int focusableMode) {
7380 if (views == null) {
7383 if (!isFocusable()) {
7386 if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
7387 && isInTouchMode() && !isFocusableInTouchMode()) {
7394 * Finds the Views that contain given text. The containment is case insensitive.
7395 * The search is performed by either the text that the View renders or the content
7396 * description that describes the view for accessibility purposes and the view does
7397 * not render or both. Clients can specify how the search is to be performed via
7398 * passing the {@link #FIND_VIEWS_WITH_TEXT} and
7399 * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
7401 * @param outViews The output list of matching Views.
7402 * @param searched The text to match against.
7404 * @see #FIND_VIEWS_WITH_TEXT
7405 * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
7406 * @see #setContentDescription(CharSequence)
7408 public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
7409 @FindViewFlags int flags) {
7410 if (getAccessibilityNodeProvider() != null) {
7411 if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
7414 } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
7415 && (searched != null && searched.length() > 0)
7416 && (mContentDescription != null && mContentDescription.length() > 0)) {
7417 String searchedLowerCase = searched.toString().toLowerCase();
7418 String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
7419 if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
7426 * Find and return all touchable views that are descendants of this view,
7427 * possibly including this view if it is touchable itself.
7429 * @return A list of touchable views
7431 public ArrayList<View> getTouchables() {
7432 ArrayList<View> result = new ArrayList<View>();
7433 addTouchables(result);
7438 * Add any touchable views that are descendants of this view (possibly
7439 * including this view if it is touchable itself) to views.
7441 * @param views Touchable views found so far
7443 public void addTouchables(ArrayList<View> views) {
7444 final int viewFlags = mViewFlags;
7446 if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
7447 && (viewFlags & ENABLED_MASK) == ENABLED) {
7453 * Returns whether this View is accessibility focused.
7455 * @return True if this View is accessibility focused.
7457 public boolean isAccessibilityFocused() {
7458 return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
7462 * Call this to try to give accessibility focus to this view.
7464 * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
7465 * returns false or the view is no visible or the view already has accessibility
7468 * See also {@link #focusSearch(int)}, which is what you call to say that you
7469 * have focus, and you want your parent to look for the next one.
7471 * @return Whether this view actually took accessibility focus.
7475 public boolean requestAccessibilityFocus() {
7476 AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
7477 if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
7480 if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7483 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
7484 mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
7485 ViewRootImpl viewRootImpl = getViewRootImpl();
7486 if (viewRootImpl != null) {
7487 viewRootImpl.setAccessibilityFocus(this, null);
7490 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
7497 * Call this to try to clear accessibility focus of this view.
7499 * See also {@link #focusSearch(int)}, which is what you call to say that you
7500 * have focus, and you want your parent to look for the next one.
7504 public void clearAccessibilityFocus() {
7505 clearAccessibilityFocusNoCallbacks();
7506 // Clear the global reference of accessibility focus if this
7507 // view or any of its descendants had accessibility focus.
7508 ViewRootImpl viewRootImpl = getViewRootImpl();
7509 if (viewRootImpl != null) {
7510 View focusHost = viewRootImpl.getAccessibilityFocusedHost();
7511 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
7512 viewRootImpl.setAccessibilityFocus(null, null);
7517 private void sendAccessibilityHoverEvent(int eventType) {
7518 // Since we are not delivering to a client accessibility events from not
7519 // important views (unless the clinet request that) we need to fire the
7520 // event from the deepest view exposed to the client. As a consequence if
7521 // the user crosses a not exposed view the client will see enter and exit
7522 // of the exposed predecessor followed by and enter and exit of that same
7523 // predecessor when entering and exiting the not exposed descendant. This
7524 // is fine since the client has a clear idea which view is hovered at the
7525 // price of a couple more events being sent. This is a simple and
7526 // working solution.
7529 if (source.includeForAccessibility()) {
7530 source.sendAccessibilityEvent(eventType);
7533 ViewParent parent = source.getParent();
7534 if (parent instanceof View) {
7535 source = (View) parent;
7543 * Clears accessibility focus without calling any callback methods
7544 * normally invoked in {@link #clearAccessibilityFocus()}. This method
7545 * is used for clearing accessibility focus when giving this focus to
7548 void clearAccessibilityFocusNoCallbacks() {
7549 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
7550 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
7552 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
7557 * Call this to try to give focus to a specific view or to one of its
7560 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7561 * false), or if it is focusable and it is not focusable in touch mode
7562 * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7564 * See also {@link #focusSearch(int)}, which is what you call to say that you
7565 * have focus, and you want your parent to look for the next one.
7567 * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
7568 * {@link #FOCUS_DOWN} and <code>null</code>.
7570 * @return Whether this view or one of its descendants actually took focus.
7572 public final boolean requestFocus() {
7573 return requestFocus(View.FOCUS_DOWN);
7577 * Call this to try to give focus to a specific view or to one of its
7578 * descendants and give it a hint about what direction focus is heading.
7580 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7581 * false), or if it is focusable and it is not focusable in touch mode
7582 * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7584 * See also {@link #focusSearch(int)}, which is what you call to say that you
7585 * have focus, and you want your parent to look for the next one.
7587 * This is equivalent to calling {@link #requestFocus(int, Rect)} with
7588 * <code>null</code> set for the previously focused rectangle.
7590 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7591 * @return Whether this view or one of its descendants actually took focus.
7593 public final boolean requestFocus(int direction) {
7594 return requestFocus(direction, null);
7598 * Call this to try to give focus to a specific view or to one of its descendants
7599 * and give it hints about the direction and a specific rectangle that the focus
7600 * is coming from. The rectangle can help give larger views a finer grained hint
7601 * about where focus is coming from, and therefore, where to show selection, or
7602 * forward focus change internally.
7604 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7605 * false), or if it is focusable and it is not focusable in touch mode
7606 * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7608 * A View will not take focus if it is not visible.
7610 * A View will not take focus if one of its parents has
7611 * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
7612 * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
7614 * See also {@link #focusSearch(int)}, which is what you call to say that you
7615 * have focus, and you want your parent to look for the next one.
7617 * You may wish to override this method if your custom {@link View} has an internal
7618 * {@link View} that it wishes to forward the request to.
7620 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7621 * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
7622 * to give a finer grained hint about where focus is coming from. May be null
7623 * if there is no hint.
7624 * @return Whether this view or one of its descendants actually took focus.
7626 public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
7627 return requestFocusNoSearch(direction, previouslyFocusedRect);
7630 private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
7631 // need to be focusable
7632 if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
7633 (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7637 // need to be focusable in touch mode if in touch mode
7638 if (isInTouchMode() &&
7639 (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
7643 // need to not have any parents blocking us
7644 if (hasAncestorThatBlocksDescendantFocus()) {
7648 handleFocusGainInternal(direction, previouslyFocusedRect);
7653 * Call this to try to give focus to a specific view or to one of its descendants. This is a
7654 * special variant of {@link #requestFocus() } that will allow views that are not focuable in
7655 * touch mode to request focus when they are touched.
7657 * @return Whether this view or one of its descendants actually took focus.
7659 * @see #isInTouchMode()
7662 public final boolean requestFocusFromTouch() {
7663 // Leave touch mode if we need to
7664 if (isInTouchMode()) {
7665 ViewRootImpl viewRoot = getViewRootImpl();
7666 if (viewRoot != null) {
7667 viewRoot.ensureTouchMode(false);
7670 return requestFocus(View.FOCUS_DOWN);
7674 * @return Whether any ancestor of this view blocks descendant focus.
7676 private boolean hasAncestorThatBlocksDescendantFocus() {
7677 final boolean focusableInTouchMode = isFocusableInTouchMode();
7678 ViewParent ancestor = mParent;
7679 while (ancestor instanceof ViewGroup) {
7680 final ViewGroup vgAncestor = (ViewGroup) ancestor;
7681 if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
7682 || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
7685 ancestor = vgAncestor.getParent();
7692 * Gets the mode for determining whether this View is important for accessibility
7693 * which is if it fires accessibility events and if it is reported to
7694 * accessibility services that query the screen.
7696 * @return The mode for determining whether a View is important for accessibility.
7698 * @attr ref android.R.styleable#View_importantForAccessibility
7700 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
7701 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
7702 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
7703 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
7705 @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
7706 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
7707 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
7708 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
7709 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
7710 to = "noHideDescendants")
7712 public int getImportantForAccessibility() {
7713 return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
7714 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
7718 * Sets the live region mode for this view. This indicates to accessibility
7719 * services whether they should automatically notify the user about changes
7720 * to the view's content description or text, or to the content descriptions
7721 * or text of the view's children (where applicable).
7723 * For example, in a login screen with a TextView that displays an "incorrect
7724 * password" notification, that view should be marked as a live region with
7725 * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
7727 * To disable change notifications for this view, use
7728 * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
7729 * mode for most views.
7731 * To indicate that the user should be notified of changes, use
7732 * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
7734 * If the view's changes should interrupt ongoing speech and notify the user
7735 * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
7737 * @param mode The live region mode for this view, one of:
7739 * <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
7740 * <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
7741 * <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
7743 * @attr ref android.R.styleable#View_accessibilityLiveRegion
7745 public void setAccessibilityLiveRegion(int mode) {
7746 if (mode != getAccessibilityLiveRegion()) {
7747 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
7748 mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
7749 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
7750 notifyViewAccessibilityStateChangedIfNeeded(
7751 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7756 * Gets the live region mode for this View.
7758 * @return The live region mode for the view.
7760 * @attr ref android.R.styleable#View_accessibilityLiveRegion
7762 * @see #setAccessibilityLiveRegion(int)
7764 public int getAccessibilityLiveRegion() {
7765 return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
7766 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
7770 * Sets how to determine whether this view is important for accessibility
7771 * which is if it fires accessibility events and if it is reported to
7772 * accessibility services that query the screen.
7774 * @param mode How to determine whether this view is important for accessibility.
7776 * @attr ref android.R.styleable#View_importantForAccessibility
7778 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
7779 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
7780 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
7781 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
7783 public void setImportantForAccessibility(int mode) {
7784 final int oldMode = getImportantForAccessibility();
7785 if (mode != oldMode) {
7786 // If we're moving between AUTO and another state, we might not need
7787 // to send a subtree changed notification. We'll store the computed
7788 // importance, since we'll need to check it later to make sure.
7789 final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
7790 || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
7791 final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
7792 mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
7793 mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
7794 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
7795 if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
7796 notifySubtreeAccessibilityStateChangedIfNeeded();
7798 notifyViewAccessibilityStateChangedIfNeeded(
7799 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7805 * Computes whether this view should be exposed for accessibility. In
7806 * general, views that are interactive or provide information are exposed
7807 * while views that serve only as containers are hidden.
7809 * If an ancestor of this view has importance
7810 * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
7811 * returns <code>false</code>.
7813 * Otherwise, the value is computed according to the view's
7814 * {@link #getImportantForAccessibility()} value:
7816 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
7817 * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
7819 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
7820 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
7821 * view satisfies any of the following:
7823 * <li>Is actionable, e.g. {@link #isClickable()},
7824 * {@link #isLongClickable()}, or {@link #isFocusable()}
7825 * <li>Has an {@link AccessibilityDelegate}
7826 * <li>Has an interaction listener, e.g. {@link OnTouchListener},
7827 * {@link OnKeyListener}, etc.
7828 * <li>Is an accessibility live region, e.g.
7829 * {@link #getAccessibilityLiveRegion()} is not
7830 * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
7834 * @return Whether the view is exposed for accessibility.
7835 * @see #setImportantForAccessibility(int)
7836 * @see #getImportantForAccessibility()
7838 public boolean isImportantForAccessibility() {
7839 final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
7840 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
7841 if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
7842 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
7846 // Check parent mode to ensure we're not hidden.
7847 ViewParent parent = mParent;
7848 while (parent instanceof View) {
7849 if (((View) parent).getImportantForAccessibility()
7850 == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
7853 parent = parent.getParent();
7856 return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
7857 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
7858 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
7862 * Gets the parent for accessibility purposes. Note that the parent for
7863 * accessibility is not necessary the immediate parent. It is the first
7864 * predecessor that is important for accessibility.
7866 * @return The parent for accessibility purposes.
7868 public ViewParent getParentForAccessibility() {
7869 if (mParent instanceof View) {
7870 View parentView = (View) mParent;
7871 if (parentView.includeForAccessibility()) {
7874 return mParent.getParentForAccessibility();
7881 * Adds the children of a given View for accessibility. Since some Views are
7882 * not important for accessibility the children for accessibility are not
7883 * necessarily direct children of the view, rather they are the first level of
7884 * descendants important for accessibility.
7886 * @param children The list of children for accessibility.
7888 public void addChildrenForAccessibility(ArrayList<View> children) {
7893 * Whether to regard this view for accessibility. A view is regarded for
7894 * accessibility if it is important for accessibility or the querying
7895 * accessibility service has explicitly requested that view not
7896 * important for accessibility are regarded.
7898 * @return Whether to regard the view for accessibility.
7902 public boolean includeForAccessibility() {
7903 if (mAttachInfo != null) {
7904 return (mAttachInfo.mAccessibilityFetchFlags
7905 & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
7906 || isImportantForAccessibility();
7912 * Returns whether the View is considered actionable from
7913 * accessibility perspective. Such view are important for
7916 * @return True if the view is actionable for accessibility.
7920 public boolean isActionableForAccessibility() {
7921 return (isClickable() || isLongClickable() || isFocusable());
7925 * Returns whether the View has registered callbacks which makes it
7926 * important for accessibility.
7928 * @return True if the view is actionable for accessibility.
7930 private boolean hasListenersForAccessibility() {
7931 ListenerInfo info = getListenerInfo();
7932 return mTouchDelegate != null || info.mOnKeyListener != null
7933 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
7934 || info.mOnHoverListener != null || info.mOnDragListener != null;
7938 * Notifies that the accessibility state of this view changed. The change
7939 * is local to this view and does not represent structural changes such
7940 * as children and parent. For example, the view became focusable. The
7941 * notification is at at most once every
7942 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
7943 * to avoid unnecessary load to the system. Also once a view has a pending
7944 * notification this method is a NOP until the notification has been sent.
7948 public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
7949 if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
7952 if (mSendViewStateChangedAccessibilityEvent == null) {
7953 mSendViewStateChangedAccessibilityEvent =
7954 new SendViewStateChangedAccessibilityEvent();
7956 mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
7960 * Notifies that the accessibility state of this view changed. The change
7961 * is *not* local to this view and does represent structural changes such
7962 * as children and parent. For example, the view size changed. The
7963 * notification is at at most once every
7964 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
7965 * to avoid unnecessary load to the system. Also once a view has a pending
7966 * notification this method is a NOP until the notification has been sent.
7970 public void notifySubtreeAccessibilityStateChangedIfNeeded() {
7971 if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
7974 if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
7975 mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
7976 if (mParent != null) {
7978 mParent.notifySubtreeAccessibilityStateChanged(
7979 this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
7980 } catch (AbstractMethodError e) {
7981 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
7982 " does not fully implement ViewParent", e);
7989 * Reset the flag indicating the accessibility state of the subtree rooted
7990 * at this view changed.
7992 void resetSubtreeAccessibilityStateChanged() {
7993 mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
7997 * Performs the specified accessibility action on the view. For
7998 * possible accessibility actions look at {@link AccessibilityNodeInfo}.
8000 * If an {@link AccessibilityDelegate} has been specified via calling
8001 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8002 * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
8003 * is responsible for handling this call.
8006 * @param action The action to perform.
8007 * @param arguments Optional action arguments.
8008 * @return Whether the action was performed.
8010 public boolean performAccessibilityAction(int action, Bundle arguments) {
8011 if (mAccessibilityDelegate != null) {
8012 return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
8014 return performAccessibilityActionInternal(action, arguments);
8019 * @see #performAccessibilityAction(int, Bundle)
8021 * Note: Called from the default {@link AccessibilityDelegate}.
8023 boolean performAccessibilityActionInternal(int action, Bundle arguments) {
8025 case AccessibilityNodeInfo.ACTION_CLICK: {
8026 if (isClickable()) {
8031 case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
8032 if (isLongClickable()) {
8037 case AccessibilityNodeInfo.ACTION_FOCUS: {
8039 // Get out of touch mode since accessibility
8040 // wants to move focus around.
8041 getViewRootImpl().ensureTouchMode(false);
8042 return requestFocus();
8045 case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
8048 return !isFocused();
8051 case AccessibilityNodeInfo.ACTION_SELECT: {
8052 if (!isSelected()) {
8054 return isSelected();
8057 case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
8060 return !isSelected();
8063 case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
8064 if (!isAccessibilityFocused()) {
8065 return requestAccessibilityFocus();
8068 case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
8069 if (isAccessibilityFocused()) {
8070 clearAccessibilityFocus();
8074 case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
8075 if (arguments != null) {
8076 final int granularity = arguments.getInt(
8077 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8078 final boolean extendSelection = arguments.getBoolean(
8079 AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8080 return traverseAtGranularity(granularity, true, extendSelection);
8083 case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
8084 if (arguments != null) {
8085 final int granularity = arguments.getInt(
8086 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8087 final boolean extendSelection = arguments.getBoolean(
8088 AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8089 return traverseAtGranularity(granularity, false, extendSelection);
8092 case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
8093 CharSequence text = getIterableTextForAccessibility();
8097 final int start = (arguments != null) ? arguments.getInt(
8098 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
8099 final int end = (arguments != null) ? arguments.getInt(
8100 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
8101 // Only cursor position can be specified (selection length == 0)
8102 if ((getAccessibilitySelectionStart() != start
8103 || getAccessibilitySelectionEnd() != end)
8104 && (start == end)) {
8105 setAccessibilitySelection(start, end);
8106 notifyViewAccessibilityStateChangedIfNeeded(
8107 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8115 private boolean traverseAtGranularity(int granularity, boolean forward,
8116 boolean extendSelection) {
8117 CharSequence text = getIterableTextForAccessibility();
8118 if (text == null || text.length() == 0) {
8121 TextSegmentIterator iterator = getIteratorForGranularity(granularity);
8122 if (iterator == null) {
8125 int current = getAccessibilitySelectionEnd();
8126 if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
8127 current = forward ? 0 : text.length();
8129 final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
8130 if (range == null) {
8133 final int segmentStart = range[0];
8134 final int segmentEnd = range[1];
8137 if (extendSelection && isAccessibilitySelectionExtendable()) {
8138 selectionStart = getAccessibilitySelectionStart();
8139 if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
8140 selectionStart = forward ? segmentStart : segmentEnd;
8142 selectionEnd = forward ? segmentEnd : segmentStart;
8144 selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
8146 setAccessibilitySelection(selectionStart, selectionEnd);
8147 final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
8148 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
8149 sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
8154 * Gets the text reported for accessibility purposes.
8156 * @return The accessibility text.
8160 public CharSequence getIterableTextForAccessibility() {
8161 return getContentDescription();
8165 * Gets whether accessibility selection can be extended.
8167 * @return If selection is extensible.
8171 public boolean isAccessibilitySelectionExtendable() {
8178 public int getAccessibilitySelectionStart() {
8179 return mAccessibilityCursorPosition;
8185 public int getAccessibilitySelectionEnd() {
8186 return getAccessibilitySelectionStart();
8192 public void setAccessibilitySelection(int start, int end) {
8193 if (start == end && end == mAccessibilityCursorPosition) {
8196 if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
8197 mAccessibilityCursorPosition = start;
8199 mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
8201 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
8204 private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
8205 int fromIndex, int toIndex) {
8206 if (mParent == null) {
8209 AccessibilityEvent event = AccessibilityEvent.obtain(
8210 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
8211 onInitializeAccessibilityEvent(event);
8212 onPopulateAccessibilityEvent(event);
8213 event.setFromIndex(fromIndex);
8214 event.setToIndex(toIndex);
8215 event.setAction(action);
8216 event.setMovementGranularity(granularity);
8217 mParent.requestSendAccessibilityEvent(this, event);
8223 public TextSegmentIterator getIteratorForGranularity(int granularity) {
8224 switch (granularity) {
8225 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
8226 CharSequence text = getIterableTextForAccessibility();
8227 if (text != null && text.length() > 0) {
8228 CharacterTextSegmentIterator iterator =
8229 CharacterTextSegmentIterator.getInstance(
8230 mContext.getResources().getConfiguration().locale);
8231 iterator.initialize(text.toString());
8235 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
8236 CharSequence text = getIterableTextForAccessibility();
8237 if (text != null && text.length() > 0) {
8238 WordTextSegmentIterator iterator =
8239 WordTextSegmentIterator.getInstance(
8240 mContext.getResources().getConfiguration().locale);
8241 iterator.initialize(text.toString());
8245 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
8246 CharSequence text = getIterableTextForAccessibility();
8247 if (text != null && text.length() > 0) {
8248 ParagraphTextSegmentIterator iterator =
8249 ParagraphTextSegmentIterator.getInstance();
8250 iterator.initialize(text.toString());
8261 public void dispatchStartTemporaryDetach() {
8262 onStartTemporaryDetach();
8266 * This is called when a container is going to temporarily detach a child, with
8267 * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
8268 * It will either be followed by {@link #onFinishTemporaryDetach()} or
8269 * {@link #onDetachedFromWindow()} when the container is done.
8271 public void onStartTemporaryDetach() {
8272 removeUnsetPressCallback();
8273 mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
8279 public void dispatchFinishTemporaryDetach() {
8280 onFinishTemporaryDetach();
8284 * Called after {@link #onStartTemporaryDetach} when the container is done
8285 * changing the view.
8287 public void onFinishTemporaryDetach() {
8291 * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
8292 * for this view's window. Returns null if the view is not currently attached
8293 * to the window. Normally you will not need to use this directly, but
8294 * just use the standard high-level event callbacks like
8295 * {@link #onKeyDown(int, KeyEvent)}.
8297 public KeyEvent.DispatcherState getKeyDispatcherState() {
8298 return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
8302 * Dispatch a key event before it is processed by any input method
8303 * associated with the view hierarchy. This can be used to intercept
8304 * key events in special situations before the IME consumes them; a
8305 * typical example would be handling the BACK key to update the application's
8306 * UI instead of allowing the IME to see it and close itself.
8308 * @param event The key event to be dispatched.
8309 * @return True if the event was handled, false otherwise.
8311 public boolean dispatchKeyEventPreIme(KeyEvent event) {
8312 return onKeyPreIme(event.getKeyCode(), event);
8316 * Dispatch a key event to the next view on the focus path. This path runs
8317 * from the top of the view tree down to the currently focused view. If this
8318 * view has focus, it will dispatch to itself. Otherwise it will dispatch
8319 * the next node down the focus path. This method also fires any key
8322 * @param event The key event to be dispatched.
8323 * @return True if the event was handled, false otherwise.
8325 public boolean dispatchKeyEvent(KeyEvent event) {
8326 if (mInputEventConsistencyVerifier != null) {
8327 mInputEventConsistencyVerifier.onKeyEvent(event, 0);
8330 // Give any attached key listener a first crack at the event.
8331 //noinspection SimplifiableIfStatement
8332 ListenerInfo li = mListenerInfo;
8333 if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
8334 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
8338 if (event.dispatch(this, mAttachInfo != null
8339 ? mAttachInfo.mKeyDispatchState : null, this)) {
8343 if (mInputEventConsistencyVerifier != null) {
8344 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8350 * Dispatches a key shortcut event.
8352 * @param event The key event to be dispatched.
8353 * @return True if the event was handled by the view, false otherwise.
8355 public boolean dispatchKeyShortcutEvent(KeyEvent event) {
8356 return onKeyShortcut(event.getKeyCode(), event);
8360 * Pass the touch screen motion event down to the target view, or this
8361 * view if it is the target.
8363 * @param event The motion event to be dispatched.
8364 * @return True if the event was handled by the view, false otherwise.
8366 public boolean dispatchTouchEvent(MotionEvent event) {
8367 boolean result = false;
8369 if (mInputEventConsistencyVerifier != null) {
8370 mInputEventConsistencyVerifier.onTouchEvent(event, 0);
8373 final int actionMasked = event.getActionMasked();
8374 if (actionMasked == MotionEvent.ACTION_DOWN) {
8375 // Defensive cleanup for new gesture
8379 if (onFilterTouchEventForSecurity(event)) {
8380 //noinspection SimplifiableIfStatement
8381 ListenerInfo li = mListenerInfo;
8382 if (li != null && li.mOnTouchListener != null
8383 && (mViewFlags & ENABLED_MASK) == ENABLED
8384 && li.mOnTouchListener.onTouch(this, event)) {
8388 if (!result && onTouchEvent(event)) {
8393 if (!result && mInputEventConsistencyVerifier != null) {
8394 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8397 // Clean up after nested scrolls if this is the end of a gesture;
8398 // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
8400 if (actionMasked == MotionEvent.ACTION_UP ||
8401 actionMasked == MotionEvent.ACTION_CANCEL ||
8402 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
8410 * Filter the touch event to apply security policies.
8412 * @param event The motion event to be filtered.
8413 * @return True if the event should be dispatched, false if the event should be dropped.
8415 * @see #getFilterTouchesWhenObscured
8417 public boolean onFilterTouchEventForSecurity(MotionEvent event) {
8418 //noinspection RedundantIfStatement
8419 if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
8420 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
8421 // Window is obscured, drop this touch.
8428 * Pass a trackball motion event down to the focused view.
8430 * @param event The motion event to be dispatched.
8431 * @return True if the event was handled by the view, false otherwise.
8433 public boolean dispatchTrackballEvent(MotionEvent event) {
8434 if (mInputEventConsistencyVerifier != null) {
8435 mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
8438 return onTrackballEvent(event);
8442 * Dispatch a generic motion event.
8444 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
8445 * are delivered to the view under the pointer. All other generic motion events are
8446 * delivered to the focused view. Hover events are handled specially and are delivered
8447 * to {@link #onHoverEvent(MotionEvent)}.
8450 * @param event The motion event to be dispatched.
8451 * @return True if the event was handled by the view, false otherwise.
8453 public boolean dispatchGenericMotionEvent(MotionEvent event) {
8454 if (mInputEventConsistencyVerifier != null) {
8455 mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
8458 final int source = event.getSource();
8459 if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
8460 final int action = event.getAction();
8461 if (action == MotionEvent.ACTION_HOVER_ENTER
8462 || action == MotionEvent.ACTION_HOVER_MOVE
8463 || action == MotionEvent.ACTION_HOVER_EXIT) {
8464 if (dispatchHoverEvent(event)) {
8467 } else if (dispatchGenericPointerEvent(event)) {
8470 } else if (dispatchGenericFocusedEvent(event)) {
8474 if (dispatchGenericMotionEventInternal(event)) {
8478 if (mInputEventConsistencyVerifier != null) {
8479 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8484 private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
8485 //noinspection SimplifiableIfStatement
8486 ListenerInfo li = mListenerInfo;
8487 if (li != null && li.mOnGenericMotionListener != null
8488 && (mViewFlags & ENABLED_MASK) == ENABLED
8489 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
8493 if (onGenericMotionEvent(event)) {
8497 if (mInputEventConsistencyVerifier != null) {
8498 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8504 * Dispatch a hover event.
8506 * Do not call this method directly.
8507 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8510 * @param event The motion event to be dispatched.
8511 * @return True if the event was handled by the view, false otherwise.
8513 protected boolean dispatchHoverEvent(MotionEvent event) {
8514 ListenerInfo li = mListenerInfo;
8515 //noinspection SimplifiableIfStatement
8516 if (li != null && li.mOnHoverListener != null
8517 && (mViewFlags & ENABLED_MASK) == ENABLED
8518 && li.mOnHoverListener.onHover(this, event)) {
8522 return onHoverEvent(event);
8526 * Returns true if the view has a child to which it has recently sent
8527 * {@link MotionEvent#ACTION_HOVER_ENTER}. If this view is hovered and
8528 * it does not have a hovered child, then it must be the innermost hovered view.
8531 protected boolean hasHoveredChild() {
8536 * Dispatch a generic motion event to the view under the first pointer.
8538 * Do not call this method directly.
8539 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8542 * @param event The motion event to be dispatched.
8543 * @return True if the event was handled by the view, false otherwise.
8545 protected boolean dispatchGenericPointerEvent(MotionEvent event) {
8550 * Dispatch a generic motion event to the currently focused view.
8552 * Do not call this method directly.
8553 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8556 * @param event The motion event to be dispatched.
8557 * @return True if the event was handled by the view, false otherwise.
8559 protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
8564 * Dispatch a pointer event.
8566 * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
8567 * other events to {@link #onGenericMotionEvent(MotionEvent)}. This separation of concerns
8568 * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
8569 * and should not be expected to handle other pointing device features.
8572 * @param event The motion event to be dispatched.
8573 * @return True if the event was handled by the view, false otherwise.
8576 public final boolean dispatchPointerEvent(MotionEvent event) {
8577 if (event.isTouchEvent()) {
8578 return dispatchTouchEvent(event);
8580 return dispatchGenericMotionEvent(event);
8585 * Called when the window containing this view gains or loses window focus.
8586 * ViewGroups should override to route to their children.
8588 * @param hasFocus True if the window containing this view now has focus,
8591 public void dispatchWindowFocusChanged(boolean hasFocus) {
8592 onWindowFocusChanged(hasFocus);
8596 * Called when the window containing this view gains or loses focus. Note
8597 * that this is separate from view focus: to receive key events, both
8598 * your view and its window must have focus. If a window is displayed
8599 * on top of yours that takes input focus, then your own window will lose
8600 * focus but the view focus will remain unchanged.
8602 * @param hasWindowFocus True if the window containing this view now has
8603 * focus, false otherwise.
8605 public void onWindowFocusChanged(boolean hasWindowFocus) {
8606 InputMethodManager imm = InputMethodManager.peekInstance();
8607 if (!hasWindowFocus) {
8611 if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
8614 removeLongPressCallback();
8615 removeTapCallback();
8617 } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
8620 refreshDrawableState();
8624 * Returns true if this view is in a window that currently has window focus.
8625 * Note that this is not the same as the view itself having focus.
8627 * @return True if this view is in a window that currently has window focus.
8629 public boolean hasWindowFocus() {
8630 return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
8634 * Dispatch a view visibility change down the view hierarchy.
8635 * ViewGroups should override to route to their children.
8636 * @param changedView The view whose visibility changed. Could be 'this' or
8638 * @param visibility The new visibility of changedView: {@link #VISIBLE},
8639 * {@link #INVISIBLE} or {@link #GONE}.
8641 protected void dispatchVisibilityChanged(@NonNull View changedView,
8642 @Visibility int visibility) {
8643 onVisibilityChanged(changedView, visibility);
8647 * Called when the visibility of the view or an ancestor of the view is changed.
8648 * @param changedView The view whose visibility changed. Could be 'this' or
8650 * @param visibility The new visibility of changedView: {@link #VISIBLE},
8651 * {@link #INVISIBLE} or {@link #GONE}.
8653 protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
8654 if (visibility == VISIBLE) {
8655 if (mAttachInfo != null) {
8656 initialAwakenScrollBars();
8658 mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
8664 * Dispatch a hint about whether this view is displayed. For instance, when
8665 * a View moves out of the screen, it might receives a display hint indicating
8666 * the view is not displayed. Applications should not <em>rely</em> on this hint
8667 * as there is no guarantee that they will receive one.
8669 * @param hint A hint about whether or not this view is displayed:
8670 * {@link #VISIBLE} or {@link #INVISIBLE}.
8672 public void dispatchDisplayHint(@Visibility int hint) {
8673 onDisplayHint(hint);
8677 * Gives this view a hint about whether is displayed or not. For instance, when
8678 * a View moves out of the screen, it might receives a display hint indicating
8679 * the view is not displayed. Applications should not <em>rely</em> on this hint
8680 * as there is no guarantee that they will receive one.
8682 * @param hint A hint about whether or not this view is displayed:
8683 * {@link #VISIBLE} or {@link #INVISIBLE}.
8685 protected void onDisplayHint(@Visibility int hint) {
8689 * Dispatch a window visibility change down the view hierarchy.
8690 * ViewGroups should override to route to their children.
8692 * @param visibility The new visibility of the window.
8694 * @see #onWindowVisibilityChanged(int)
8696 public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
8697 onWindowVisibilityChanged(visibility);
8701 * Called when the window containing has change its visibility
8702 * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}). Note
8703 * that this tells you whether or not your window is being made visible
8704 * to the window manager; this does <em>not</em> tell you whether or not
8705 * your window is obscured by other windows on the screen, even if it
8706 * is itself visible.
8708 * @param visibility The new visibility of the window.
8710 protected void onWindowVisibilityChanged(@Visibility int visibility) {
8711 if (visibility == VISIBLE) {
8712 initialAwakenScrollBars();
8717 * Returns the current visibility of the window this view is attached to
8718 * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
8720 * @return Returns the current visibility of the view's window.
8723 public int getWindowVisibility() {
8724 return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
8728 * Retrieve the overall visible display size in which the window this view is
8729 * attached to has been positioned in. This takes into account screen
8730 * decorations above the window, for both cases where the window itself
8731 * is being position inside of them or the window is being placed under
8732 * then and covered insets are used for the window to position its content
8733 * inside. In effect, this tells you the available area where content can
8734 * be placed and remain visible to users.
8736 * <p>This function requires an IPC back to the window manager to retrieve
8737 * the requested information, so should not be used in performance critical
8738 * code like drawing.
8740 * @param outRect Filled in with the visible display frame. If the view
8741 * is not attached to a window, this is simply the raw display size.
8743 public void getWindowVisibleDisplayFrame(Rect outRect) {
8744 if (mAttachInfo != null) {
8746 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
8747 } catch (RemoteException e) {
8750 // XXX This is really broken, and probably all needs to be done
8751 // in the window manager, and we need to know more about whether
8752 // we want the area behind or in front of the IME.
8753 final Rect insets = mAttachInfo.mVisibleInsets;
8754 outRect.left += insets.left;
8755 outRect.top += insets.top;
8756 outRect.right -= insets.right;
8757 outRect.bottom -= insets.bottom;
8760 // The view is not attached to a display so we don't have a context.
8761 // Make a best guess about the display size.
8762 Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
8763 d.getRectSize(outRect);
8767 * Dispatch a notification about a resource configuration change down
8768 * the view hierarchy.
8769 * ViewGroups should override to route to their children.
8771 * @param newConfig The new resource configuration.
8773 * @see #onConfigurationChanged(android.content.res.Configuration)
8775 public void dispatchConfigurationChanged(Configuration newConfig) {
8776 onConfigurationChanged(newConfig);
8780 * Called when the current configuration of the resources being used
8781 * by the application have changed. You can use this to decide when
8782 * to reload resources that can changed based on orientation and other
8783 * configuration characterstics. You only need to use this if you are
8784 * not relying on the normal {@link android.app.Activity} mechanism of
8785 * recreating the activity instance upon a configuration change.
8787 * @param newConfig The new resource configuration.
8789 protected void onConfigurationChanged(Configuration newConfig) {
8793 * Private function to aggregate all per-view attributes in to the view
8796 void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
8797 performCollectViewAttributes(attachInfo, visibility);
8800 void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
8801 if ((visibility & VISIBILITY_MASK) == VISIBLE) {
8802 if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
8803 attachInfo.mKeepScreenOn = true;
8805 attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
8806 ListenerInfo li = mListenerInfo;
8807 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
8808 attachInfo.mHasSystemUiListeners = true;
8813 void needGlobalAttributesUpdate(boolean force) {
8814 final AttachInfo ai = mAttachInfo;
8815 if (ai != null && !ai.mRecomputeGlobalAttributes) {
8816 if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
8817 || ai.mHasSystemUiListeners) {
8818 ai.mRecomputeGlobalAttributes = true;
8824 * Returns whether the device is currently in touch mode. Touch mode is entered
8825 * once the user begins interacting with the device by touch, and affects various
8826 * things like whether focus is always visible to the user.
8828 * @return Whether the device is in touch mode.
8830 @ViewDebug.ExportedProperty
8831 public boolean isInTouchMode() {
8832 if (mAttachInfo != null) {
8833 return mAttachInfo.mInTouchMode;
8835 return ViewRootImpl.isInTouchMode();
8840 * Returns the context the view is running in, through which it can
8841 * access the current theme, resources, etc.
8843 * @return The view's Context.
8845 @ViewDebug.CapturedViewProperty
8846 public final Context getContext() {
8851 * Handle a key event before it is processed by any input method
8852 * associated with the view hierarchy. This can be used to intercept
8853 * key events in special situations before the IME consumes them; a
8854 * typical example would be handling the BACK key to update the application's
8855 * UI instead of allowing the IME to see it and close itself.
8857 * @param keyCode The value in event.getKeyCode().
8858 * @param event Description of the key event.
8859 * @return If you handled the event, return true. If you want to allow the
8860 * event to be handled by the next receiver, return false.
8862 public boolean onKeyPreIme(int keyCode, KeyEvent event) {
8867 * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
8868 * KeyEvent.Callback.onKeyDown()}: perform press of the view
8869 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
8870 * is released, if the view is enabled and clickable.
8872 * <p>Key presses in software keyboards will generally NOT trigger this listener,
8873 * although some may elect to do so in some situations. Do not rely on this to
8874 * catch software key presses.
8876 * @param keyCode A key code that represents the button pressed, from
8877 * {@link android.view.KeyEvent}.
8878 * @param event The KeyEvent object that defines the button action.
8880 public boolean onKeyDown(int keyCode, KeyEvent event) {
8881 boolean result = false;
8883 if (KeyEvent.isConfirmKey(keyCode)) {
8884 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8887 // Long clickable items don't necessarily have to be clickable
8888 if (((mViewFlags & CLICKABLE) == CLICKABLE ||
8889 (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
8890 (event.getRepeatCount() == 0)) {
8892 checkForLongClick(0);
8900 * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
8901 * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
8903 * <p>Key presses in software keyboards will generally NOT trigger this listener,
8904 * although some may elect to do so in some situations. Do not rely on this to
8905 * catch software key presses.
8907 public boolean onKeyLongPress(int keyCode, KeyEvent event) {
8912 * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
8913 * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
8914 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
8915 * {@link KeyEvent#KEYCODE_ENTER} is released.
8916 * <p>Key presses in software keyboards will generally NOT trigger this listener,
8917 * although some may elect to do so in some situations. Do not rely on this to
8918 * catch software key presses.
8920 * @param keyCode A key code that represents the button pressed, from
8921 * {@link android.view.KeyEvent}.
8922 * @param event The KeyEvent object that defines the button action.
8924 public boolean onKeyUp(int keyCode, KeyEvent event) {
8925 if (KeyEvent.isConfirmKey(keyCode)) {
8926 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8929 if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
8932 if (!mHasPerformedLongPress) {
8933 // This is a tap, so remove the longpress check
8934 removeLongPressCallback();
8935 return performClick();
8943 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
8944 * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
8946 * <p>Key presses in software keyboards will generally NOT trigger this listener,
8947 * although some may elect to do so in some situations. Do not rely on this to
8948 * catch software key presses.
8950 * @param keyCode A key code that represents the button pressed, from
8951 * {@link android.view.KeyEvent}.
8952 * @param repeatCount The number of times the action was made.
8953 * @param event The KeyEvent object that defines the button action.
8955 public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
8960 * Called on the focused view when a key shortcut event is not handled.
8961 * Override this method to implement local key shortcuts for the View.
8962 * Key shortcuts can also be implemented by setting the
8963 * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
8965 * @param keyCode The value in event.getKeyCode().
8966 * @param event Description of the key event.
8967 * @return If you handled the event, return true. If you want to allow the
8968 * event to be handled by the next receiver, return false.
8970 public boolean onKeyShortcut(int keyCode, KeyEvent event) {
8975 * Check whether the called view is a text editor, in which case it
8976 * would make sense to automatically display a soft input window for
8977 * it. Subclasses should override this if they implement
8978 * {@link #onCreateInputConnection(EditorInfo)} to return true if
8979 * a call on that method would return a non-null InputConnection, and
8980 * they are really a first-class editor that the user would normally
8981 * start typing on when the go into a window containing your view.
8983 * <p>The default implementation always returns false. This does
8984 * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
8985 * will not be called or the user can not otherwise perform edits on your
8986 * view; it is just a hint to the system that this is not the primary
8987 * purpose of this view.
8989 * @return Returns true if this view is a text editor, else false.
8991 public boolean onCheckIsTextEditor() {
8996 * Create a new InputConnection for an InputMethod to interact
8997 * with the view. The default implementation returns null, since it doesn't
8998 * support input methods. You can override this to implement such support.
8999 * This is only needed for views that take focus and text input.
9001 * <p>When implementing this, you probably also want to implement
9002 * {@link #onCheckIsTextEditor()} to indicate you will return a
9003 * non-null InputConnection.</p>
9005 * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
9006 * object correctly and in its entirety, so that the connected IME can rely
9007 * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
9008 * and {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
9009 * must be filled in with the correct cursor position for IMEs to work correctly
9010 * with your application.</p>
9012 * @param outAttrs Fill in with attribute information about the connection.
9014 public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
9019 * Called by the {@link android.view.inputmethod.InputMethodManager}
9020 * when a view who is not the current
9021 * input connection target is trying to make a call on the manager. The
9022 * default implementation returns false; you can override this to return
9023 * true for certain views if you are performing InputConnection proxying
9025 * @param view The View that is making the InputMethodManager call.
9026 * @return Return true to allow the call, false to reject.
9028 public boolean checkInputConnectionProxy(View view) {
9033 * Show the context menu for this view. It is not safe to hold on to the
9034 * menu after returning from this method.
9036 * You should normally not overload this method. Overload
9037 * {@link #onCreateContextMenu(ContextMenu)} or define an
9038 * {@link OnCreateContextMenuListener} to add items to the context menu.
9040 * @param menu The context menu to populate
9042 public void createContextMenu(ContextMenu menu) {
9043 ContextMenuInfo menuInfo = getContextMenuInfo();
9045 // Sets the current menu info so all items added to menu will have
9046 // my extra info set.
9047 ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
9049 onCreateContextMenu(menu);
9050 ListenerInfo li = mListenerInfo;
9051 if (li != null && li.mOnCreateContextMenuListener != null) {
9052 li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
9055 // Clear the extra information so subsequent items that aren't mine don't
9056 // have my extra info.
9057 ((MenuBuilder)menu).setCurrentMenuInfo(null);
9059 if (mParent != null) {
9060 mParent.createContextMenu(menu);
9065 * Views should implement this if they have extra information to associate
9066 * with the context menu. The return result is supplied as a parameter to
9067 * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
9070 * @return Extra information about the item for which the context menu
9071 * should be shown. This information will vary across different
9072 * subclasses of View.
9074 protected ContextMenuInfo getContextMenuInfo() {
9079 * Views should implement this if the view itself is going to add items to
9082 * @param menu the context menu to populate
9084 protected void onCreateContextMenu(ContextMenu menu) {
9088 * Implement this method to handle trackball motion events. The
9089 * <em>relative</em> movement of the trackball since the last event
9090 * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
9091 * {@link MotionEvent#getY MotionEvent.getY()}. These are normalized so
9092 * that a movement of 1 corresponds to the user pressing one DPAD key (so
9093 * they will often be fractional values, representing the more fine-grained
9094 * movement information available from a trackball).
9096 * @param event The motion event.
9097 * @return True if the event was handled, false otherwise.
9099 public boolean onTrackballEvent(MotionEvent event) {
9104 * Implement this method to handle generic motion events.
9106 * Generic motion events describe joystick movements, mouse hovers, track pad
9107 * touches, scroll wheel movements and other input events. The
9108 * {@link MotionEvent#getSource() source} of the motion event specifies
9109 * the class of input that was received. Implementations of this method
9110 * must examine the bits in the source before processing the event.
9111 * The following code example shows how this is done.
9113 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
9114 * are delivered to the view under the pointer. All other generic motion events are
9115 * delivered to the focused view.
9117 * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
9118 * if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
9119 * if (event.getAction() == MotionEvent.ACTION_MOVE) {
9120 * // process the joystick movement...
9124 * if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
9125 * switch (event.getAction()) {
9126 * case MotionEvent.ACTION_HOVER_MOVE:
9127 * // process the mouse hover movement...
9129 * case MotionEvent.ACTION_SCROLL:
9130 * // process the scroll wheel movement...
9134 * return super.onGenericMotionEvent(event);
9137 * @param event The generic motion event being processed.
9138 * @return True if the event was handled, false otherwise.
9140 public boolean onGenericMotionEvent(MotionEvent event) {
9145 * Implement this method to handle hover events.
9147 * This method is called whenever a pointer is hovering into, over, or out of the
9148 * bounds of a view and the view is not currently being touched.
9149 * Hover events are represented as pointer events with action
9150 * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
9151 * or {@link MotionEvent#ACTION_HOVER_EXIT}.
9154 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
9155 * when the pointer enters the bounds of the view.</li>
9156 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
9157 * when the pointer has already entered the bounds of the view and has moved.</li>
9158 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
9159 * when the pointer has exited the bounds of the view or when the pointer is
9160 * about to go down due to a button click, tap, or similar user action that
9161 * causes the view to be touched.</li>
9164 * The view should implement this method to return true to indicate that it is
9165 * handling the hover event, such as by changing its drawable state.
9167 * The default implementation calls {@link #setHovered} to update the hovered state
9168 * of the view when a hover enter or hover exit event is received, if the view
9169 * is enabled and is clickable. The default implementation also sends hover
9170 * accessibility events.
9173 * @param event The motion event that describes the hover.
9174 * @return True if the view handled the hover event.
9178 * @see #onHoverChanged
9180 public boolean onHoverEvent(MotionEvent event) {
9181 // The root view may receive hover (or touch) events that are outside the bounds of
9182 // the window. This code ensures that we only send accessibility events for
9183 // hovers that are actually within the bounds of the root view.
9184 final int action = event.getActionMasked();
9185 if (!mSendingHoverAccessibilityEvents) {
9186 if ((action == MotionEvent.ACTION_HOVER_ENTER
9187 || action == MotionEvent.ACTION_HOVER_MOVE)
9188 && !hasHoveredChild()
9189 && pointInView(event.getX(), event.getY())) {
9190 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
9191 mSendingHoverAccessibilityEvents = true;
9194 if (action == MotionEvent.ACTION_HOVER_EXIT
9195 || (action == MotionEvent.ACTION_MOVE
9196 && !pointInView(event.getX(), event.getY()))) {
9197 mSendingHoverAccessibilityEvents = false;
9198 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
9202 if (isHoverable()) {
9204 case MotionEvent.ACTION_HOVER_ENTER:
9207 case MotionEvent.ACTION_HOVER_EXIT:
9212 // Dispatch the event to onGenericMotionEvent before returning true.
9213 // This is to provide compatibility with existing applications that
9214 // handled HOVER_MOVE events in onGenericMotionEvent and that would
9215 // break because of the new default handling for hoverable views
9217 // Note that onGenericMotionEvent will be called by default when
9218 // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
9219 dispatchGenericMotionEventInternal(event);
9220 // The event was already handled by calling setHovered(), so always
9229 * Returns true if the view should handle {@link #onHoverEvent}
9230 * by calling {@link #setHovered} to change its hovered state.
9232 * @return True if the view is hoverable.
9234 private boolean isHoverable() {
9235 final int viewFlags = mViewFlags;
9236 if ((viewFlags & ENABLED_MASK) == DISABLED) {
9240 return (viewFlags & CLICKABLE) == CLICKABLE
9241 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
9245 * Returns true if the view is currently hovered.
9247 * @return True if the view is currently hovered.
9250 * @see #onHoverChanged
9252 @ViewDebug.ExportedProperty
9253 public boolean isHovered() {
9254 return (mPrivateFlags & PFLAG_HOVERED) != 0;
9258 * Sets whether the view is currently hovered.
9260 * Calling this method also changes the drawable state of the view. This
9261 * enables the view to react to hover by using different drawable resources
9262 * to change its appearance.
9264 * The {@link #onHoverChanged} method is called when the hovered state changes.
9267 * @param hovered True if the view is hovered.
9270 * @see #onHoverChanged
9272 public void setHovered(boolean hovered) {
9274 if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
9275 mPrivateFlags |= PFLAG_HOVERED;
9276 refreshDrawableState();
9277 onHoverChanged(true);
9280 if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
9281 mPrivateFlags &= ~PFLAG_HOVERED;
9282 refreshDrawableState();
9283 onHoverChanged(false);
9289 * Implement this method to handle hover state changes.
9291 * This method is called whenever the hover state changes as a result of a
9292 * call to {@link #setHovered}.
9295 * @param hovered The current hover state, as returned by {@link #isHovered}.
9300 public void onHoverChanged(boolean hovered) {
9304 * Implement this method to handle touch screen motion events.
9306 * If this method is used to detect click actions, it is recommended that
9307 * the actions be performed by implementing and calling
9308 * {@link #performClick()}. This will ensure consistent system behavior,
9311 * <li>obeying click sound preferences
9312 * <li>dispatching OnClickListener calls
9313 * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
9314 * accessibility features are enabled
9317 * @param event The motion event.
9318 * @return True if the event was handled, false otherwise.
9320 public boolean onTouchEvent(MotionEvent event) {
9321 final float x = event.getX();
9322 final float y = event.getY();
9323 final int viewFlags = mViewFlags;
9325 if ((viewFlags & ENABLED_MASK) == DISABLED) {
9326 if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
9329 // A disabled view that is clickable still consumes the touch
9330 // events, it just doesn't respond to them.
9331 return (((viewFlags & CLICKABLE) == CLICKABLE ||
9332 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
9335 if (mTouchDelegate != null) {
9336 if (mTouchDelegate.onTouchEvent(event)) {
9341 if (((viewFlags & CLICKABLE) == CLICKABLE ||
9342 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
9343 switch (event.getAction()) {
9344 case MotionEvent.ACTION_UP:
9345 boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
9346 if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
9347 // take focus if we don't have it already and we should in
9349 boolean focusTaken = false;
9350 if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
9351 focusTaken = requestFocus();
9355 // The button is being released before we actually
9356 // showed it as pressed. Make it show the pressed
9357 // state now (before scheduling the click) to ensure
9358 // the user sees it.
9359 setPressed(true, x, y);
9362 if (!mHasPerformedLongPress) {
9363 // This is a tap, so remove the longpress check
9364 removeLongPressCallback();
9366 // Only perform take click actions if we were in the pressed state
9368 // Use a Runnable and post this rather than calling
9369 // performClick directly. This lets other visual state
9370 // of the view update before click actions start.
9371 if (mPerformClick == null) {
9372 mPerformClick = new PerformClick();
9374 if (!post(mPerformClick)) {
9380 if (mUnsetPressedState == null) {
9381 mUnsetPressedState = new UnsetPressedState();
9385 postDelayed(mUnsetPressedState,
9386 ViewConfiguration.getPressedStateDuration());
9387 } else if (!post(mUnsetPressedState)) {
9388 // If the post failed, unpress right now
9389 mUnsetPressedState.run();
9392 removeTapCallback();
9396 case MotionEvent.ACTION_DOWN:
9397 mHasPerformedLongPress = false;
9399 if (performButtonActionOnTouchDown(event)) {
9403 // Walk up the hierarchy to determine if we're inside a scrolling container.
9404 boolean isInScrollingContainer = isInScrollingContainer();
9406 // For views inside a scrolling container, delay the pressed feedback for
9407 // a short period in case this is a scroll.
9408 if (isInScrollingContainer) {
9409 mPrivateFlags |= PFLAG_PREPRESSED;
9410 if (mPendingCheckForTap == null) {
9411 mPendingCheckForTap = new CheckForTap();
9413 mPendingCheckForTap.x = event.getX();
9414 mPendingCheckForTap.y = event.getY();
9415 postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
9417 // Not inside a scrolling container, so show the feedback right away
9418 setPressed(true, x, y);
9419 checkForLongClick(0);
9423 case MotionEvent.ACTION_CANCEL:
9425 removeTapCallback();
9426 removeLongPressCallback();
9429 case MotionEvent.ACTION_MOVE:
9430 drawableHotspotChanged(x, y);
9432 // Be lenient about moving outside of buttons
9433 if (!pointInView(x, y, mTouchSlop)) {
9435 removeTapCallback();
9436 if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
9437 // Remove any future long press/tap checks
9438 removeLongPressCallback();
9455 public boolean isInScrollingContainer() {
9456 ViewParent p = getParent();
9457 while (p != null && p instanceof ViewGroup) {
9458 if (((ViewGroup) p).shouldDelayChildPressedState()) {
9467 * Remove the longpress detection timer.
9469 private void removeLongPressCallback() {
9470 if (mPendingCheckForLongPress != null) {
9471 removeCallbacks(mPendingCheckForLongPress);
9476 * Remove the pending click action
9478 private void removePerformClickCallback() {
9479 if (mPerformClick != null) {
9480 removeCallbacks(mPerformClick);
9485 * Remove the prepress detection timer.
9487 private void removeUnsetPressCallback() {
9488 if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
9490 removeCallbacks(mUnsetPressedState);
9495 * Remove the tap detection timer.
9497 private void removeTapCallback() {
9498 if (mPendingCheckForTap != null) {
9499 mPrivateFlags &= ~PFLAG_PREPRESSED;
9500 removeCallbacks(mPendingCheckForTap);
9505 * Cancels a pending long press. Your subclass can use this if you
9506 * want the context menu to come up if the user presses and holds
9507 * at the same place, but you don't want it to come up if they press
9508 * and then move around enough to cause scrolling.
9510 public void cancelLongPress() {
9511 removeLongPressCallback();
9514 * The prepressed state handled by the tap callback is a display
9515 * construct, but the tap callback will post a long press callback
9516 * less its own timeout. Remove it here.
9518 removeTapCallback();
9522 * Remove the pending callback for sending a
9523 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
9525 private void removeSendViewScrolledAccessibilityEventCallback() {
9526 if (mSendViewScrolledAccessibilityEvent != null) {
9527 removeCallbacks(mSendViewScrolledAccessibilityEvent);
9528 mSendViewScrolledAccessibilityEvent.mIsPending = false;
9533 * Sets the TouchDelegate for this View.
9535 public void setTouchDelegate(TouchDelegate delegate) {
9536 mTouchDelegate = delegate;
9540 * Gets the TouchDelegate for this View.
9542 public TouchDelegate getTouchDelegate() {
9543 return mTouchDelegate;
9547 * Request unbuffered dispatch of the given stream of MotionEvents to this View.
9549 * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
9550 * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
9551 * available. This method should only be called for touch events.
9553 * <p class="note">This api is not intended for most applications. Buffered dispatch
9554 * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
9555 * streams will not improve your input latency. Side effects include: increased latency,
9556 * jittery scrolls and inability to take advantage of system resampling. Talk to your input
9557 * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
9560 public final void requestUnbufferedDispatch(MotionEvent event) {
9561 final int action = event.getAction();
9562 if (mAttachInfo == null
9563 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
9564 || !event.isTouchEvent()) {
9567 mAttachInfo.mUnbufferedDispatchRequested = true;
9571 * Set flags controlling behavior of this view.
9573 * @param flags Constant indicating the value which should be set
9574 * @param mask Constant indicating the bit range that should be changed
9576 void setFlags(int flags, int mask) {
9577 final boolean accessibilityEnabled =
9578 AccessibilityManager.getInstance(mContext).isEnabled();
9579 final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
9581 int old = mViewFlags;
9582 mViewFlags = (mViewFlags & ~mask) | (flags & mask);
9584 int changed = mViewFlags ^ old;
9588 int privateFlags = mPrivateFlags;
9590 /* Check if the FOCUSABLE bit has changed */
9591 if (((changed & FOCUSABLE_MASK) != 0) &&
9592 ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
9593 if (((old & FOCUSABLE_MASK) == FOCUSABLE)
9594 && ((privateFlags & PFLAG_FOCUSED) != 0)) {
9595 /* Give up focus if we are no longer focusable */
9597 } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
9598 && ((privateFlags & PFLAG_FOCUSED) == 0)) {
9600 * Tell the view system that we are now available to take focus
9601 * if no one else already has it.
9603 if (mParent != null) mParent.focusableViewAvailable(this);
9607 final int newVisibility = flags & VISIBILITY_MASK;
9608 if (newVisibility == VISIBLE) {
9609 if ((changed & VISIBILITY_MASK) != 0) {
9611 * If this view is becoming visible, invalidate it in case it changed while
9612 * it was not visible. Marking it drawn ensures that the invalidation will
9615 mPrivateFlags |= PFLAG_DRAWN;
9618 needGlobalAttributesUpdate(true);
9620 // a view becoming visible is worth notifying the parent
9621 // about in case nothing has focus. even if this specific view
9622 // isn't focusable, it may contain something that is, so let
9623 // the root view try to give this focus if nothing else does.
9624 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
9625 mParent.focusableViewAvailable(this);
9630 /* Check if the GONE bit has changed */
9631 if ((changed & GONE) != 0) {
9632 needGlobalAttributesUpdate(false);
9635 if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
9636 if (hasFocus()) clearFocus();
9637 clearAccessibilityFocus();
9638 destroyDrawingCache();
9639 if (mParent instanceof View) {
9640 // GONE views noop invalidation, so invalidate the parent
9641 ((View) mParent).invalidate(true);
9643 // Mark the view drawn to ensure that it gets invalidated properly the next
9644 // time it is visible and gets invalidated
9645 mPrivateFlags |= PFLAG_DRAWN;
9647 if (mAttachInfo != null) {
9648 mAttachInfo.mViewVisibilityChanged = true;
9652 /* Check if the VISIBLE bit has changed */
9653 if ((changed & INVISIBLE) != 0) {
9654 needGlobalAttributesUpdate(false);
9656 * If this view is becoming invisible, set the DRAWN flag so that
9657 * the next invalidate() will not be skipped.
9659 mPrivateFlags |= PFLAG_DRAWN;
9661 if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
9662 // root view becoming invisible shouldn't clear focus and accessibility focus
9663 if (getRootView() != this) {
9664 if (hasFocus()) clearFocus();
9665 clearAccessibilityFocus();
9668 if (mAttachInfo != null) {
9669 mAttachInfo.mViewVisibilityChanged = true;
9673 if ((changed & VISIBILITY_MASK) != 0) {
9674 // If the view is invisible, cleanup its display list to free up resources
9675 if (newVisibility != VISIBLE && mAttachInfo != null) {
9679 if (mParent instanceof ViewGroup) {
9680 ((ViewGroup) mParent).onChildVisibilityChanged(this,
9681 (changed & VISIBILITY_MASK), newVisibility);
9682 ((View) mParent).invalidate(true);
9683 } else if (mParent != null) {
9684 mParent.invalidateChild(this, null);
9686 dispatchVisibilityChanged(this, newVisibility);
9688 notifySubtreeAccessibilityStateChangedIfNeeded();
9691 if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
9692 destroyDrawingCache();
9695 if ((changed & DRAWING_CACHE_ENABLED) != 0) {
9696 destroyDrawingCache();
9697 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
9698 invalidateParentCaches();
9701 if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
9702 destroyDrawingCache();
9703 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
9706 if ((changed & DRAW_MASK) != 0) {
9707 if ((mViewFlags & WILL_NOT_DRAW) != 0) {
9708 if (mBackground != null) {
9709 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
9710 mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
9712 mPrivateFlags |= PFLAG_SKIP_DRAW;
9715 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
9721 if ((changed & KEEP_SCREEN_ON) != 0) {
9722 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
9723 mParent.recomputeViewAttributes(this);
9727 if (accessibilityEnabled) {
9728 if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
9729 || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0) {
9730 if (oldIncludeForAccessibility != includeForAccessibility()) {
9731 notifySubtreeAccessibilityStateChangedIfNeeded();
9733 notifyViewAccessibilityStateChangedIfNeeded(
9734 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9736 } else if ((changed & ENABLED_MASK) != 0) {
9737 notifyViewAccessibilityStateChangedIfNeeded(
9738 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9744 * Change the view's z order in the tree, so it's on top of other sibling
9745 * views. This ordering change may affect layout, if the parent container
9746 * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
9747 * to {@link android.os.Build.VERSION_CODES#KITKAT} this
9748 * method should be followed by calls to {@link #requestLayout()} and
9749 * {@link View#invalidate()} on the view's parent to force the parent to redraw
9750 * with the new child ordering.
9752 * @see ViewGroup#bringChildToFront(View)
9754 public void bringToFront() {
9755 if (mParent != null) {
9756 mParent.bringChildToFront(this);
9761 * This is called in response to an internal scroll in this view (i.e., the
9762 * view scrolled its own contents). This is typically as a result of
9763 * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
9766 * @param l Current horizontal scroll origin.
9767 * @param t Current vertical scroll origin.
9768 * @param oldl Previous horizontal scroll origin.
9769 * @param oldt Previous vertical scroll origin.
9771 protected void onScrollChanged(int l, int t, int oldl, int oldt) {
9772 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
9773 postSendViewScrolledAccessibilityEventCallback();
9776 mBackgroundSizeChanged = true;
9778 final AttachInfo ai = mAttachInfo;
9780 ai.mViewScrollChanged = true;
9785 * Interface definition for a callback to be invoked when the layout bounds of a view
9786 * changes due to layout processing.
9788 public interface OnLayoutChangeListener {
9790 * Called when the layout bounds of a view changes due to layout processing.
9792 * @param v The view whose bounds have changed.
9793 * @param left The new value of the view's left property.
9794 * @param top The new value of the view's top property.
9795 * @param right The new value of the view's right property.
9796 * @param bottom The new value of the view's bottom property.
9797 * @param oldLeft The previous value of the view's left property.
9798 * @param oldTop The previous value of the view's top property.
9799 * @param oldRight The previous value of the view's right property.
9800 * @param oldBottom The previous value of the view's bottom property.
9802 void onLayoutChange(View v, int left, int top, int right, int bottom,
9803 int oldLeft, int oldTop, int oldRight, int oldBottom);
9807 * This is called during layout when the size of this view has changed. If
9808 * you were just added to the view hierarchy, you're called with the old
9811 * @param w Current width of this view.
9812 * @param h Current height of this view.
9813 * @param oldw Old width of this view.
9814 * @param oldh Old height of this view.
9816 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
9820 * Called by draw to draw the child views. This may be overridden
9821 * by derived classes to gain control just before its children are drawn
9822 * (but after its own view has been drawn).
9823 * @param canvas the canvas on which to draw the view
9825 protected void dispatchDraw(Canvas canvas) {
9830 * Gets the parent of this view. Note that the parent is a
9831 * ViewParent and not necessarily a View.
9833 * @return Parent of this view.
9835 public final ViewParent getParent() {
9840 * Set the horizontal scrolled position of your view. This will cause a call to
9841 * {@link #onScrollChanged(int, int, int, int)} and the view will be
9843 * @param value the x position to scroll to
9845 public void setScrollX(int value) {
9846 scrollTo(value, mScrollY);
9850 * Set the vertical scrolled position of your view. This will cause a call to
9851 * {@link #onScrollChanged(int, int, int, int)} and the view will be
9853 * @param value the y position to scroll to
9855 public void setScrollY(int value) {
9856 scrollTo(mScrollX, value);
9860 * Return the scrolled left position of this view. This is the left edge of
9861 * the displayed part of your view. You do not need to draw any pixels
9862 * farther left, since those are outside of the frame of your view on
9865 * @return The left edge of the displayed part of your view, in pixels.
9867 public final int getScrollX() {
9872 * Return the scrolled top position of this view. This is the top edge of
9873 * the displayed part of your view. You do not need to draw any pixels above
9874 * it, since those are outside of the frame of your view on screen.
9876 * @return The top edge of the displayed part of your view, in pixels.
9878 public final int getScrollY() {
9883 * Return the width of the your view.
9885 * @return The width of your view, in pixels.
9887 @ViewDebug.ExportedProperty(category = "layout")
9888 public final int getWidth() {
9889 return mRight - mLeft;
9893 * Return the height of your view.
9895 * @return The height of your view, in pixels.
9897 @ViewDebug.ExportedProperty(category = "layout")
9898 public final int getHeight() {
9899 return mBottom - mTop;
9903 * Return the visible drawing bounds of your view. Fills in the output
9904 * rectangle with the values from getScrollX(), getScrollY(),
9905 * getWidth(), and getHeight(). These bounds do not account for any
9906 * transformation properties currently set on the view, such as
9907 * {@link #setScaleX(float)} or {@link #setRotation(float)}.
9909 * @param outRect The (scrolled) drawing bounds of the view.
9911 public void getDrawingRect(Rect outRect) {
9912 outRect.left = mScrollX;
9913 outRect.top = mScrollY;
9914 outRect.right = mScrollX + (mRight - mLeft);
9915 outRect.bottom = mScrollY + (mBottom - mTop);
9919 * Like {@link #getMeasuredWidthAndState()}, but only returns the
9920 * raw width component (that is the result is masked by
9921 * {@link #MEASURED_SIZE_MASK}).
9923 * @return The raw measured width of this view.
9925 public final int getMeasuredWidth() {
9926 return mMeasuredWidth & MEASURED_SIZE_MASK;
9930 * Return the full width measurement information for this view as computed
9931 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask
9932 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
9933 * This should be used during measurement and layout calculations only. Use
9934 * {@link #getWidth()} to see how wide a view is after layout.
9936 * @return The measured width of this view as a bit mask.
9938 public final int getMeasuredWidthAndState() {
9939 return mMeasuredWidth;
9943 * Like {@link #getMeasuredHeightAndState()}, but only returns the
9944 * raw width component (that is the result is masked by
9945 * {@link #MEASURED_SIZE_MASK}).
9947 * @return The raw measured height of this view.
9949 public final int getMeasuredHeight() {
9950 return mMeasuredHeight & MEASURED_SIZE_MASK;
9954 * Return the full height measurement information for this view as computed
9955 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask
9956 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
9957 * This should be used during measurement and layout calculations only. Use
9958 * {@link #getHeight()} to see how wide a view is after layout.
9960 * @return The measured width of this view as a bit mask.
9962 public final int getMeasuredHeightAndState() {
9963 return mMeasuredHeight;
9967 * Return only the state bits of {@link #getMeasuredWidthAndState()}
9968 * and {@link #getMeasuredHeightAndState()}, combined into one integer.
9969 * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
9970 * and the height component is at the shifted bits
9971 * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
9973 public final int getMeasuredState() {
9974 return (mMeasuredWidth&MEASURED_STATE_MASK)
9975 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
9976 & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
9980 * The transform matrix of this view, which is calculated based on the current
9981 * rotation, scale, and pivot properties.
9983 * @see #getRotation()
9988 * @return The current transform matrix for the view
9990 public Matrix getMatrix() {
9991 ensureTransformationInfo();
9992 final Matrix matrix = mTransformationInfo.mMatrix;
9993 mRenderNode.getMatrix(matrix);
9998 * Returns true if the transform matrix is the identity matrix.
9999 * Recomputes the matrix if necessary.
10001 * @return True if the transform matrix is the identity matrix, false otherwise.
10003 final boolean hasIdentityMatrix() {
10004 return mRenderNode.hasIdentityMatrix();
10007 void ensureTransformationInfo() {
10008 if (mTransformationInfo == null) {
10009 mTransformationInfo = new TransformationInfo();
10014 * Utility method to retrieve the inverse of the current mMatrix property.
10015 * We cache the matrix to avoid recalculating it when transform properties
10016 * have not changed.
10018 * @return The inverse of the current matrix of this view.
10021 public final Matrix getInverseMatrix() {
10022 ensureTransformationInfo();
10023 if (mTransformationInfo.mInverseMatrix == null) {
10024 mTransformationInfo.mInverseMatrix = new Matrix();
10026 final Matrix matrix = mTransformationInfo.mInverseMatrix;
10027 mRenderNode.getInverseMatrix(matrix);
10032 * Gets the distance along the Z axis from the camera to this view.
10034 * @see #setCameraDistance(float)
10036 * @return The distance along the Z axis.
10038 public float getCameraDistance() {
10039 final float dpi = mResources.getDisplayMetrics().densityDpi;
10040 return -(mRenderNode.getCameraDistance() * dpi);
10044 * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
10045 * views are drawn) from the camera to this view. The camera's distance
10046 * affects 3D transformations, for instance rotations around the X and Y
10047 * axis. If the rotationX or rotationY properties are changed and this view is
10048 * large (more than half the size of the screen), it is recommended to always
10049 * use a camera distance that's greater than the height (X axis rotation) or
10050 * the width (Y axis rotation) of this view.</p>
10052 * <p>The distance of the camera from the view plane can have an affect on the
10053 * perspective distortion of the view when it is rotated around the x or y axis.
10054 * For example, a large distance will result in a large viewing angle, and there
10055 * will not be much perspective distortion of the view as it rotates. A short
10056 * distance may cause much more perspective distortion upon rotation, and can
10057 * also result in some drawing artifacts if the rotated view ends up partially
10058 * behind the camera (which is why the recommendation is to use a distance at
10059 * least as far as the size of the view, if the view is to be rotated.)</p>
10061 * <p>The distance is expressed in "depth pixels." The default distance depends
10062 * on the screen density. For instance, on a medium density display, the
10063 * default distance is 1280. On a high density display, the default distance
10066 * <p>If you want to specify a distance that leads to visually consistent
10067 * results across various densities, use the following formula:</p>
10069 * float scale = context.getResources().getDisplayMetrics().density;
10070 * view.setCameraDistance(distance * scale);
10073 * <p>The density scale factor of a high density display is 1.5,
10074 * and 1920 = 1280 * 1.5.</p>
10076 * @param distance The distance in "depth pixels", if negative the opposite
10079 * @see #setRotationX(float)
10080 * @see #setRotationY(float)
10082 public void setCameraDistance(float distance) {
10083 final float dpi = mResources.getDisplayMetrics().densityDpi;
10085 invalidateViewProperty(true, false);
10086 mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
10087 invalidateViewProperty(false, false);
10089 invalidateParentIfNeededAndWasQuickRejected();
10093 * The degrees that the view is rotated around the pivot point.
10095 * @see #setRotation(float)
10096 * @see #getPivotX()
10097 * @see #getPivotY()
10099 * @return The degrees of rotation.
10101 @ViewDebug.ExportedProperty(category = "drawing")
10102 public float getRotation() {
10103 return mRenderNode.getRotation();
10107 * Sets the degrees that the view is rotated around the pivot point. Increasing values
10108 * result in clockwise rotation.
10110 * @param rotation The degrees of rotation.
10112 * @see #getRotation()
10113 * @see #getPivotX()
10114 * @see #getPivotY()
10115 * @see #setRotationX(float)
10116 * @see #setRotationY(float)
10118 * @attr ref android.R.styleable#View_rotation
10120 public void setRotation(float rotation) {
10121 if (rotation != getRotation()) {
10122 // Double-invalidation is necessary to capture view's old and new areas
10123 invalidateViewProperty(true, false);
10124 mRenderNode.setRotation(rotation);
10125 invalidateViewProperty(false, true);
10127 invalidateParentIfNeededAndWasQuickRejected();
10128 notifySubtreeAccessibilityStateChangedIfNeeded();
10133 * The degrees that the view is rotated around the vertical axis through the pivot point.
10135 * @see #getPivotX()
10136 * @see #getPivotY()
10137 * @see #setRotationY(float)
10139 * @return The degrees of Y rotation.
10141 @ViewDebug.ExportedProperty(category = "drawing")
10142 public float getRotationY() {
10143 return mRenderNode.getRotationY();
10147 * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
10148 * Increasing values result in counter-clockwise rotation from the viewpoint of looking
10151 * When rotating large views, it is recommended to adjust the camera distance
10152 * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
10154 * @param rotationY The degrees of Y rotation.
10156 * @see #getRotationY()
10157 * @see #getPivotX()
10158 * @see #getPivotY()
10159 * @see #setRotation(float)
10160 * @see #setRotationX(float)
10161 * @see #setCameraDistance(float)
10163 * @attr ref android.R.styleable#View_rotationY
10165 public void setRotationY(float rotationY) {
10166 if (rotationY != getRotationY()) {
10167 invalidateViewProperty(true, false);
10168 mRenderNode.setRotationY(rotationY);
10169 invalidateViewProperty(false, true);
10171 invalidateParentIfNeededAndWasQuickRejected();
10172 notifySubtreeAccessibilityStateChangedIfNeeded();
10177 * The degrees that the view is rotated around the horizontal axis through the pivot point.
10179 * @see #getPivotX()
10180 * @see #getPivotY()
10181 * @see #setRotationX(float)
10183 * @return The degrees of X rotation.
10185 @ViewDebug.ExportedProperty(category = "drawing")
10186 public float getRotationX() {
10187 return mRenderNode.getRotationX();
10191 * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
10192 * Increasing values result in clockwise rotation from the viewpoint of looking down the
10195 * When rotating large views, it is recommended to adjust the camera distance
10196 * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
10198 * @param rotationX The degrees of X rotation.
10200 * @see #getRotationX()
10201 * @see #getPivotX()
10202 * @see #getPivotY()
10203 * @see #setRotation(float)
10204 * @see #setRotationY(float)
10205 * @see #setCameraDistance(float)
10207 * @attr ref android.R.styleable#View_rotationX
10209 public void setRotationX(float rotationX) {
10210 if (rotationX != getRotationX()) {
10211 invalidateViewProperty(true, false);
10212 mRenderNode.setRotationX(rotationX);
10213 invalidateViewProperty(false, true);
10215 invalidateParentIfNeededAndWasQuickRejected();
10216 notifySubtreeAccessibilityStateChangedIfNeeded();
10221 * The amount that the view is scaled in x around the pivot point, as a proportion of
10222 * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
10224 * <p>By default, this is 1.0f.
10226 * @see #getPivotX()
10227 * @see #getPivotY()
10228 * @return The scaling factor.
10230 @ViewDebug.ExportedProperty(category = "drawing")
10231 public float getScaleX() {
10232 return mRenderNode.getScaleX();
10236 * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
10237 * the view's unscaled width. A value of 1 means that no scaling is applied.
10239 * @param scaleX The scaling factor.
10240 * @see #getPivotX()
10241 * @see #getPivotY()
10243 * @attr ref android.R.styleable#View_scaleX
10245 public void setScaleX(float scaleX) {
10246 if (scaleX != getScaleX()) {
10247 invalidateViewProperty(true, false);
10248 mRenderNode.setScaleX(scaleX);
10249 invalidateViewProperty(false, true);
10251 invalidateParentIfNeededAndWasQuickRejected();
10252 notifySubtreeAccessibilityStateChangedIfNeeded();
10257 * The amount that the view is scaled in y around the pivot point, as a proportion of
10258 * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
10260 * <p>By default, this is 1.0f.
10262 * @see #getPivotX()
10263 * @see #getPivotY()
10264 * @return The scaling factor.
10266 @ViewDebug.ExportedProperty(category = "drawing")
10267 public float getScaleY() {
10268 return mRenderNode.getScaleY();
10272 * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
10273 * the view's unscaled width. A value of 1 means that no scaling is applied.
10275 * @param scaleY The scaling factor.
10276 * @see #getPivotX()
10277 * @see #getPivotY()
10279 * @attr ref android.R.styleable#View_scaleY
10281 public void setScaleY(float scaleY) {
10282 if (scaleY != getScaleY()) {
10283 invalidateViewProperty(true, false);
10284 mRenderNode.setScaleY(scaleY);
10285 invalidateViewProperty(false, true);
10287 invalidateParentIfNeededAndWasQuickRejected();
10288 notifySubtreeAccessibilityStateChangedIfNeeded();
10293 * The x location of the point around which the view is {@link #setRotation(float) rotated}
10294 * and {@link #setScaleX(float) scaled}.
10296 * @see #getRotation()
10297 * @see #getScaleX()
10298 * @see #getScaleY()
10299 * @see #getPivotY()
10300 * @return The x location of the pivot point.
10302 * @attr ref android.R.styleable#View_transformPivotX
10304 @ViewDebug.ExportedProperty(category = "drawing")
10305 public float getPivotX() {
10306 return mRenderNode.getPivotX();
10310 * Sets the x location of the point around which the view is
10311 * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
10312 * By default, the pivot point is centered on the object.
10313 * Setting this property disables this behavior and causes the view to use only the
10314 * explicitly set pivotX and pivotY values.
10316 * @param pivotX The x location of the pivot point.
10317 * @see #getRotation()
10318 * @see #getScaleX()
10319 * @see #getScaleY()
10320 * @see #getPivotY()
10322 * @attr ref android.R.styleable#View_transformPivotX
10324 public void setPivotX(float pivotX) {
10325 if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
10326 invalidateViewProperty(true, false);
10327 mRenderNode.setPivotX(pivotX);
10328 invalidateViewProperty(false, true);
10330 invalidateParentIfNeededAndWasQuickRejected();
10335 * The y location of the point around which the view is {@link #setRotation(float) rotated}
10336 * and {@link #setScaleY(float) scaled}.
10338 * @see #getRotation()
10339 * @see #getScaleX()
10340 * @see #getScaleY()
10341 * @see #getPivotY()
10342 * @return The y location of the pivot point.
10344 * @attr ref android.R.styleable#View_transformPivotY
10346 @ViewDebug.ExportedProperty(category = "drawing")
10347 public float getPivotY() {
10348 return mRenderNode.getPivotY();
10352 * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
10353 * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
10354 * Setting this property disables this behavior and causes the view to use only the
10355 * explicitly set pivotX and pivotY values.
10357 * @param pivotY The y location of the pivot point.
10358 * @see #getRotation()
10359 * @see #getScaleX()
10360 * @see #getScaleY()
10361 * @see #getPivotY()
10363 * @attr ref android.R.styleable#View_transformPivotY
10365 public void setPivotY(float pivotY) {
10366 if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
10367 invalidateViewProperty(true, false);
10368 mRenderNode.setPivotY(pivotY);
10369 invalidateViewProperty(false, true);
10371 invalidateParentIfNeededAndWasQuickRejected();
10376 * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
10377 * completely transparent and 1 means the view is completely opaque.
10379 * <p>By default this is 1.0f.
10380 * @return The opacity of the view.
10382 @ViewDebug.ExportedProperty(category = "drawing")
10383 public float getAlpha() {
10384 return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
10388 * Returns whether this View has content which overlaps.
10390 * <p>This function, intended to be overridden by specific View types, is an optimization when
10391 * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
10392 * an offscreen buffer and then composited into place, which can be expensive. If the view has
10393 * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
10394 * directly. An example of overlapping rendering is a TextView with a background image, such as
10395 * a Button. An example of non-overlapping rendering is a TextView with no background, or an
10396 * ImageView with only the foreground image. The default implementation returns true; subclasses
10397 * should override if they have cases which can be optimized.</p>
10399 * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
10400 * necessitates that a View return true if it uses the methods internally without passing the
10401 * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
10403 * @return true if the content in this view might overlap, false otherwise.
10405 @ViewDebug.ExportedProperty(category = "drawing")
10406 public boolean hasOverlappingRendering() {
10411 * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
10412 * completely transparent and 1 means the view is completely opaque.</p>
10414 * <p> Note that setting alpha to a translucent value (0 < alpha < 1) can have significant
10415 * performance implications, especially for large views. It is best to use the alpha property
10416 * sparingly and transiently, as in the case of fading animations.</p>
10418 * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
10419 * strongly recommended for performance reasons to either override
10420 * {@link #hasOverlappingRendering()} to return false if appropriate, or setting a
10421 * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view.</p>
10423 * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
10424 * responsible for applying the opacity itself.</p>
10426 * <p>Note that if the view is backed by a
10427 * {@link #setLayerType(int, android.graphics.Paint) layer} and is associated with a
10428 * {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an alpha value less than
10429 * 1.0 will supercede the alpha of the layer paint.</p>
10431 * @param alpha The opacity of the view.
10433 * @see #hasOverlappingRendering()
10434 * @see #setLayerType(int, android.graphics.Paint)
10436 * @attr ref android.R.styleable#View_alpha
10438 public void setAlpha(float alpha) {
10439 ensureTransformationInfo();
10440 if (mTransformationInfo.mAlpha != alpha) {
10441 mTransformationInfo.mAlpha = alpha;
10442 if (onSetAlpha((int) (alpha * 255))) {
10443 mPrivateFlags |= PFLAG_ALPHA_SET;
10444 // subclass is handling alpha - don't optimize rendering cache invalidation
10445 invalidateParentCaches();
10448 mPrivateFlags &= ~PFLAG_ALPHA_SET;
10449 invalidateViewProperty(true, false);
10450 mRenderNode.setAlpha(getFinalAlpha());
10451 notifyViewAccessibilityStateChangedIfNeeded(
10452 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10458 * Faster version of setAlpha() which performs the same steps except there are
10459 * no calls to invalidate(). The caller of this function should perform proper invalidation
10460 * on the parent and this object. The return value indicates whether the subclass handles
10461 * alpha (the return value for onSetAlpha()).
10463 * @param alpha The new value for the alpha property
10464 * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
10465 * the new value for the alpha property is different from the old value
10467 boolean setAlphaNoInvalidation(float alpha) {
10468 ensureTransformationInfo();
10469 if (mTransformationInfo.mAlpha != alpha) {
10470 mTransformationInfo.mAlpha = alpha;
10471 boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
10472 if (subclassHandlesAlpha) {
10473 mPrivateFlags |= PFLAG_ALPHA_SET;
10476 mPrivateFlags &= ~PFLAG_ALPHA_SET;
10477 mRenderNode.setAlpha(getFinalAlpha());
10484 * This property is hidden and intended only for use by the Fade transition, which
10485 * animates it to produce a visual translucency that does not side-effect (or get
10486 * affected by) the real alpha property. This value is composited with the other
10487 * alpha value (and the AlphaAnimation value, when that is present) to produce
10488 * a final visual translucency result, which is what is passed into the DisplayList.
10492 public void setTransitionAlpha(float alpha) {
10493 ensureTransformationInfo();
10494 if (mTransformationInfo.mTransitionAlpha != alpha) {
10495 mTransformationInfo.mTransitionAlpha = alpha;
10496 mPrivateFlags &= ~PFLAG_ALPHA_SET;
10497 invalidateViewProperty(true, false);
10498 mRenderNode.setAlpha(getFinalAlpha());
10503 * Calculates the visual alpha of this view, which is a combination of the actual
10504 * alpha value and the transitionAlpha value (if set).
10506 private float getFinalAlpha() {
10507 if (mTransformationInfo != null) {
10508 return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
10514 * This property is hidden and intended only for use by the Fade transition, which
10515 * animates it to produce a visual translucency that does not side-effect (or get
10516 * affected by) the real alpha property. This value is composited with the other
10517 * alpha value (and the AlphaAnimation value, when that is present) to produce
10518 * a final visual translucency result, which is what is passed into the DisplayList.
10522 @ViewDebug.ExportedProperty(category = "drawing")
10523 public float getTransitionAlpha() {
10524 return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
10528 * Top position of this view relative to its parent.
10530 * @return The top of this view, in pixels.
10532 @ViewDebug.CapturedViewProperty
10533 public final int getTop() {
10538 * Sets the top position of this view relative to its parent. This method is meant to be called
10539 * by the layout system and should not generally be called otherwise, because the property
10540 * may be changed at any time by the layout.
10542 * @param top The top of this view, in pixels.
10544 public final void setTop(int top) {
10546 final boolean matrixIsIdentity = hasIdentityMatrix();
10547 if (matrixIsIdentity) {
10548 if (mAttachInfo != null) {
10558 invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
10561 // Double-invalidation is necessary to capture view's old and new areas
10565 int width = mRight - mLeft;
10566 int oldHeight = mBottom - mTop;
10569 mRenderNode.setTop(mTop);
10571 sizeChange(width, mBottom - mTop, width, oldHeight);
10573 if (!matrixIsIdentity) {
10574 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10577 mBackgroundSizeChanged = true;
10578 invalidateParentIfNeeded();
10579 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10580 // View was rejected last time it was drawn by its parent; this may have changed
10581 invalidateParentIfNeeded();
10587 * Bottom position of this view relative to its parent.
10589 * @return The bottom of this view, in pixels.
10591 @ViewDebug.CapturedViewProperty
10592 public final int getBottom() {
10597 * True if this view has changed since the last time being drawn.
10599 * @return The dirty state of this view.
10601 public boolean isDirty() {
10602 return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
10606 * Sets the bottom position of this view relative to its parent. This method is meant to be
10607 * called by the layout system and should not generally be called otherwise, because the
10608 * property may be changed at any time by the layout.
10610 * @param bottom The bottom of this view, in pixels.
10612 public final void setBottom(int bottom) {
10613 if (bottom != mBottom) {
10614 final boolean matrixIsIdentity = hasIdentityMatrix();
10615 if (matrixIsIdentity) {
10616 if (mAttachInfo != null) {
10618 if (bottom < mBottom) {
10619 maxBottom = mBottom;
10621 maxBottom = bottom;
10623 invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
10626 // Double-invalidation is necessary to capture view's old and new areas
10630 int width = mRight - mLeft;
10631 int oldHeight = mBottom - mTop;
10634 mRenderNode.setBottom(mBottom);
10636 sizeChange(width, mBottom - mTop, width, oldHeight);
10638 if (!matrixIsIdentity) {
10639 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10642 mBackgroundSizeChanged = true;
10643 invalidateParentIfNeeded();
10644 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10645 // View was rejected last time it was drawn by its parent; this may have changed
10646 invalidateParentIfNeeded();
10652 * Left position of this view relative to its parent.
10654 * @return The left edge of this view, in pixels.
10656 @ViewDebug.CapturedViewProperty
10657 public final int getLeft() {
10662 * Sets the left position of this view relative to its parent. This method is meant to be called
10663 * by the layout system and should not generally be called otherwise, because the property
10664 * may be changed at any time by the layout.
10666 * @param left The left of this view, in pixels.
10668 public final void setLeft(int left) {
10669 if (left != mLeft) {
10670 final boolean matrixIsIdentity = hasIdentityMatrix();
10671 if (matrixIsIdentity) {
10672 if (mAttachInfo != null) {
10675 if (left < mLeft) {
10677 xLoc = left - mLeft;
10682 invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
10685 // Double-invalidation is necessary to capture view's old and new areas
10689 int oldWidth = mRight - mLeft;
10690 int height = mBottom - mTop;
10693 mRenderNode.setLeft(left);
10695 sizeChange(mRight - mLeft, height, oldWidth, height);
10697 if (!matrixIsIdentity) {
10698 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10701 mBackgroundSizeChanged = true;
10702 invalidateParentIfNeeded();
10703 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10704 // View was rejected last time it was drawn by its parent; this may have changed
10705 invalidateParentIfNeeded();
10711 * Right position of this view relative to its parent.
10713 * @return The right edge of this view, in pixels.
10715 @ViewDebug.CapturedViewProperty
10716 public final int getRight() {
10721 * Sets the right position of this view relative to its parent. This method is meant to be called
10722 * by the layout system and should not generally be called otherwise, because the property
10723 * may be changed at any time by the layout.
10725 * @param right The right of this view, in pixels.
10727 public final void setRight(int right) {
10728 if (right != mRight) {
10729 final boolean matrixIsIdentity = hasIdentityMatrix();
10730 if (matrixIsIdentity) {
10731 if (mAttachInfo != null) {
10733 if (right < mRight) {
10738 invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
10741 // Double-invalidation is necessary to capture view's old and new areas
10745 int oldWidth = mRight - mLeft;
10746 int height = mBottom - mTop;
10749 mRenderNode.setRight(mRight);
10751 sizeChange(mRight - mLeft, height, oldWidth, height);
10753 if (!matrixIsIdentity) {
10754 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10757 mBackgroundSizeChanged = true;
10758 invalidateParentIfNeeded();
10759 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10760 // View was rejected last time it was drawn by its parent; this may have changed
10761 invalidateParentIfNeeded();
10767 * The visual x position of this view, in pixels. This is equivalent to the
10768 * {@link #setTranslationX(float) translationX} property plus the current
10769 * {@link #getLeft() left} property.
10771 * @return The visual x position of this view, in pixels.
10773 @ViewDebug.ExportedProperty(category = "drawing")
10774 public float getX() {
10775 return mLeft + getTranslationX();
10779 * Sets the visual x position of this view, in pixels. This is equivalent to setting the
10780 * {@link #setTranslationX(float) translationX} property to be the difference between
10781 * the x value passed in and the current {@link #getLeft() left} property.
10783 * @param x The visual x position of this view, in pixels.
10785 public void setX(float x) {
10786 setTranslationX(x - mLeft);
10790 * The visual y position of this view, in pixels. This is equivalent to the
10791 * {@link #setTranslationY(float) translationY} property plus the current
10792 * {@link #getTop() top} property.
10794 * @return The visual y position of this view, in pixels.
10796 @ViewDebug.ExportedProperty(category = "drawing")
10797 public float getY() {
10798 return mTop + getTranslationY();
10802 * Sets the visual y position of this view, in pixels. This is equivalent to setting the
10803 * {@link #setTranslationY(float) translationY} property to be the difference between
10804 * the y value passed in and the current {@link #getTop() top} property.
10806 * @param y The visual y position of this view, in pixels.
10808 public void setY(float y) {
10809 setTranslationY(y - mTop);
10813 * The visual z position of this view, in pixels. This is equivalent to the
10814 * {@link #setTranslationZ(float) translationZ} property plus the current
10815 * {@link #getElevation() elevation} property.
10817 * @return The visual z position of this view, in pixels.
10819 @ViewDebug.ExportedProperty(category = "drawing")
10820 public float getZ() {
10821 return getElevation() + getTranslationZ();
10825 * Sets the visual z position of this view, in pixels. This is equivalent to setting the
10826 * {@link #setTranslationZ(float) translationZ} property to be the difference between
10827 * the x value passed in and the current {@link #getElevation() elevation} property.
10829 * @param z The visual z position of this view, in pixels.
10831 public void setZ(float z) {
10832 setTranslationZ(z - getElevation());
10836 * The base elevation of this view relative to its parent, in pixels.
10838 * @return The base depth position of the view, in pixels.
10840 @ViewDebug.ExportedProperty(category = "drawing")
10841 public float getElevation() {
10842 return mRenderNode.getElevation();
10846 * Sets the base elevation of this view, in pixels.
10848 * @attr ref android.R.styleable#View_elevation
10850 public void setElevation(float elevation) {
10851 if (elevation != getElevation()) {
10852 invalidateViewProperty(true, false);
10853 mRenderNode.setElevation(elevation);
10854 invalidateViewProperty(false, true);
10856 invalidateParentIfNeededAndWasQuickRejected();
10861 * The horizontal location of this view relative to its {@link #getLeft() left} position.
10862 * This position is post-layout, in addition to wherever the object's
10863 * layout placed it.
10865 * @return The horizontal position of this view relative to its left position, in pixels.
10867 @ViewDebug.ExportedProperty(category = "drawing")
10868 public float getTranslationX() {
10869 return mRenderNode.getTranslationX();
10873 * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
10874 * This effectively positions the object post-layout, in addition to wherever the object's
10875 * layout placed it.
10877 * @param translationX The horizontal position of this view relative to its left position,
10880 * @attr ref android.R.styleable#View_translationX
10882 public void setTranslationX(float translationX) {
10883 if (translationX != getTranslationX()) {
10884 invalidateViewProperty(true, false);
10885 mRenderNode.setTranslationX(translationX);
10886 invalidateViewProperty(false, true);
10888 invalidateParentIfNeededAndWasQuickRejected();
10889 notifySubtreeAccessibilityStateChangedIfNeeded();
10894 * The vertical location of this view relative to its {@link #getTop() top} position.
10895 * This position is post-layout, in addition to wherever the object's
10896 * layout placed it.
10898 * @return The vertical position of this view relative to its top position,
10901 @ViewDebug.ExportedProperty(category = "drawing")
10902 public float getTranslationY() {
10903 return mRenderNode.getTranslationY();
10907 * Sets the vertical location of this view relative to its {@link #getTop() top} position.
10908 * This effectively positions the object post-layout, in addition to wherever the object's
10909 * layout placed it.
10911 * @param translationY The vertical position of this view relative to its top position,
10914 * @attr ref android.R.styleable#View_translationY
10916 public void setTranslationY(float translationY) {
10917 if (translationY != getTranslationY()) {
10918 invalidateViewProperty(true, false);
10919 mRenderNode.setTranslationY(translationY);
10920 invalidateViewProperty(false, true);
10922 invalidateParentIfNeededAndWasQuickRejected();
10927 * The depth location of this view relative to its {@link #getElevation() elevation}.
10929 * @return The depth of this view relative to its elevation.
10931 @ViewDebug.ExportedProperty(category = "drawing")
10932 public float getTranslationZ() {
10933 return mRenderNode.getTranslationZ();
10937 * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
10939 * @attr ref android.R.styleable#View_translationZ
10941 public void setTranslationZ(float translationZ) {
10942 if (translationZ != getTranslationZ()) {
10943 invalidateViewProperty(true, false);
10944 mRenderNode.setTranslationZ(translationZ);
10945 invalidateViewProperty(false, true);
10947 invalidateParentIfNeededAndWasQuickRejected();
10952 public void setAnimationMatrix(Matrix matrix) {
10953 invalidateViewProperty(true, false);
10954 mRenderNode.setAnimationMatrix(matrix);
10955 invalidateViewProperty(false, true);
10957 invalidateParentIfNeededAndWasQuickRejected();
10961 * Returns the current StateListAnimator if exists.
10963 * @return StateListAnimator or null if it does not exists
10964 * @see #setStateListAnimator(android.animation.StateListAnimator)
10966 public StateListAnimator getStateListAnimator() {
10967 return mStateListAnimator;
10971 * Attaches the provided StateListAnimator to this View.
10973 * Any previously attached StateListAnimator will be detached.
10975 * @param stateListAnimator The StateListAnimator to update the view
10976 * @see {@link android.animation.StateListAnimator}
10978 public void setStateListAnimator(StateListAnimator stateListAnimator) {
10979 if (mStateListAnimator == stateListAnimator) {
10982 if (mStateListAnimator != null) {
10983 mStateListAnimator.setTarget(null);
10985 mStateListAnimator = stateListAnimator;
10986 if (stateListAnimator != null) {
10987 stateListAnimator.setTarget(this);
10988 if (isAttachedToWindow()) {
10989 stateListAnimator.setState(getDrawableState());
10995 * Returns whether the Outline should be used to clip the contents of the View.
10997 * Note that this flag will only be respected if the View's Outline returns true from
10998 * {@link Outline#canClip()}.
11000 * @see #setOutlineProvider(ViewOutlineProvider)
11001 * @see #setClipToOutline(boolean)
11003 public final boolean getClipToOutline() {
11004 return mRenderNode.getClipToOutline();
11008 * Sets whether the View's Outline should be used to clip the contents of the View.
11010 * Only a single non-rectangular clip can be applied on a View at any time.
11011 * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
11012 * circular reveal} animation take priority over Outline clipping, and
11013 * child Outline clipping takes priority over Outline clipping done by a
11016 * Note that this flag will only be respected if the View's Outline returns true from
11017 * {@link Outline#canClip()}.
11019 * @see #setOutlineProvider(ViewOutlineProvider)
11020 * @see #getClipToOutline()
11022 public void setClipToOutline(boolean clipToOutline) {
11024 if (getClipToOutline() != clipToOutline) {
11025 mRenderNode.setClipToOutline(clipToOutline);
11029 // correspond to the enum values of View_outlineProvider
11030 private static final int PROVIDER_BACKGROUND = 0;
11031 private static final int PROVIDER_NONE = 1;
11032 private static final int PROVIDER_BOUNDS = 2;
11033 private static final int PROVIDER_PADDED_BOUNDS = 3;
11034 private void setOutlineProviderFromAttribute(int providerInt) {
11035 switch (providerInt) {
11036 case PROVIDER_BACKGROUND:
11037 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
11039 case PROVIDER_NONE:
11040 setOutlineProvider(null);
11042 case PROVIDER_BOUNDS:
11043 setOutlineProvider(ViewOutlineProvider.BOUNDS);
11045 case PROVIDER_PADDED_BOUNDS:
11046 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
11052 * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
11053 * the shape of the shadow it casts, and enables outline clipping.
11055 * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
11056 * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
11057 * outline provider with this method allows this behavior to be overridden.
11059 * If the ViewOutlineProvider is null, if querying it for an outline returns false,
11060 * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
11062 * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
11064 * @see #setClipToOutline(boolean)
11065 * @see #getClipToOutline()
11066 * @see #getOutlineProvider()
11068 public void setOutlineProvider(ViewOutlineProvider provider) {
11069 mOutlineProvider = provider;
11070 invalidateOutline();
11074 * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
11075 * that defines the shape of the shadow it casts, and enables outline clipping.
11077 * @see #setOutlineProvider(ViewOutlineProvider)
11079 public ViewOutlineProvider getOutlineProvider() {
11080 return mOutlineProvider;
11084 * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
11086 * @see #setOutlineProvider(ViewOutlineProvider)
11088 public void invalidateOutline() {
11089 mPrivateFlags3 |= PFLAG3_OUTLINE_INVALID;
11091 notifySubtreeAccessibilityStateChangedIfNeeded();
11092 invalidateViewProperty(false, false);
11096 * Internal version of {@link #invalidateOutline()} which invalidates the
11097 * outline without invalidating the view itself. This is intended to be called from
11098 * within methods in the View class itself which are the result of the view being
11099 * invalidated already. For example, when we are drawing the background of a View,
11100 * we invalidate the outline in case it changed in the meantime, but we do not
11101 * need to invalidate the view because we're already drawing the background as part
11102 * of drawing the view in response to an earlier invalidation of the view.
11104 private void rebuildOutline() {
11105 // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
11106 if (mAttachInfo == null) return;
11108 if (mOutlineProvider == null) {
11109 // no provider, remove outline
11110 mRenderNode.setOutline(null);
11112 final Outline outline = mAttachInfo.mTmpOutline;
11113 outline.setEmpty();
11114 outline.setAlpha(1.0f);
11116 mOutlineProvider.getOutline(this, outline);
11117 mRenderNode.setOutline(outline);
11122 * HierarchyViewer only
11126 @ViewDebug.ExportedProperty(category = "drawing")
11127 public boolean hasShadow() {
11128 return mRenderNode.hasShadow();
11133 public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
11134 mRenderNode.setRevealClip(shouldClip, x, y, radius);
11135 invalidateViewProperty(false, false);
11139 * Hit rectangle in parent's coordinates
11141 * @param outRect The hit rectangle of the view.
11143 public void getHitRect(Rect outRect) {
11144 if (hasIdentityMatrix() || mAttachInfo == null) {
11145 outRect.set(mLeft, mTop, mRight, mBottom);
11147 final RectF tmpRect = mAttachInfo.mTmpTransformRect;
11148 tmpRect.set(0, 0, getWidth(), getHeight());
11149 getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
11150 outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
11151 (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
11156 * Determines whether the given point, in local coordinates is inside the view.
11158 /*package*/ final boolean pointInView(float localX, float localY) {
11159 return localX >= 0 && localX < (mRight - mLeft)
11160 && localY >= 0 && localY < (mBottom - mTop);
11164 * Utility method to determine whether the given point, in local coordinates,
11165 * is inside the view, where the area of the view is expanded by the slop factor.
11166 * This method is called while processing touch-move events to determine if the event
11167 * is still within the view.
11171 public boolean pointInView(float localX, float localY, float slop) {
11172 return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
11173 localY < ((mBottom - mTop) + slop);
11177 * When a view has focus and the user navigates away from it, the next view is searched for
11178 * starting from the rectangle filled in by this method.
11180 * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
11181 * of the view. However, if your view maintains some idea of internal selection,
11182 * such as a cursor, or a selected row or column, you should override this method and
11183 * fill in a more specific rectangle.
11185 * @param r The rectangle to fill in, in this view's coordinates.
11187 public void getFocusedRect(Rect r) {
11192 * If some part of this view is not clipped by any of its parents, then
11193 * return that area in r in global (root) coordinates. To convert r to local
11194 * coordinates (without taking possible View rotations into account), offset
11195 * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
11196 * If the view is completely clipped or translated out, return false.
11198 * @param r If true is returned, r holds the global coordinates of the
11199 * visible portion of this view.
11200 * @param globalOffset If true is returned, globalOffset holds the dx,dy
11201 * between this view and its root. globalOffet may be null.
11202 * @return true if r is non-empty (i.e. part of the view is visible at the
11205 public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
11206 int width = mRight - mLeft;
11207 int height = mBottom - mTop;
11208 if (width > 0 && height > 0) {
11209 r.set(0, 0, width, height);
11210 if (globalOffset != null) {
11211 globalOffset.set(-mScrollX, -mScrollY);
11213 return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
11218 public final boolean getGlobalVisibleRect(Rect r) {
11219 return getGlobalVisibleRect(r, null);
11222 public final boolean getLocalVisibleRect(Rect r) {
11223 final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
11224 if (getGlobalVisibleRect(r, offset)) {
11225 r.offset(-offset.x, -offset.y); // make r local
11232 * Offset this view's vertical location by the specified number of pixels.
11234 * @param offset the number of pixels to offset the view by
11236 public void offsetTopAndBottom(int offset) {
11238 final boolean matrixIsIdentity = hasIdentityMatrix();
11239 if (matrixIsIdentity) {
11240 if (isHardwareAccelerated()) {
11241 invalidateViewProperty(false, false);
11243 final ViewParent p = mParent;
11244 if (p != null && mAttachInfo != null) {
11245 final Rect r = mAttachInfo.mTmpInvalRect;
11250 minTop = mTop + offset;
11251 maxBottom = mBottom;
11255 maxBottom = mBottom + offset;
11258 r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
11259 p.invalidateChild(this, r);
11263 invalidateViewProperty(false, false);
11268 mRenderNode.offsetTopAndBottom(offset);
11269 if (isHardwareAccelerated()) {
11270 invalidateViewProperty(false, false);
11272 if (!matrixIsIdentity) {
11273 invalidateViewProperty(false, true);
11275 invalidateParentIfNeeded();
11277 notifySubtreeAccessibilityStateChangedIfNeeded();
11282 * Offset this view's horizontal location by the specified amount of pixels.
11284 * @param offset the number of pixels to offset the view by
11286 public void offsetLeftAndRight(int offset) {
11288 final boolean matrixIsIdentity = hasIdentityMatrix();
11289 if (matrixIsIdentity) {
11290 if (isHardwareAccelerated()) {
11291 invalidateViewProperty(false, false);
11293 final ViewParent p = mParent;
11294 if (p != null && mAttachInfo != null) {
11295 final Rect r = mAttachInfo.mTmpInvalRect;
11299 minLeft = mLeft + offset;
11303 maxRight = mRight + offset;
11305 r.set(0, 0, maxRight - minLeft, mBottom - mTop);
11306 p.invalidateChild(this, r);
11310 invalidateViewProperty(false, false);
11315 mRenderNode.offsetLeftAndRight(offset);
11316 if (isHardwareAccelerated()) {
11317 invalidateViewProperty(false, false);
11319 if (!matrixIsIdentity) {
11320 invalidateViewProperty(false, true);
11322 invalidateParentIfNeeded();
11324 notifySubtreeAccessibilityStateChangedIfNeeded();
11329 * Get the LayoutParams associated with this view. All views should have
11330 * layout parameters. These supply parameters to the <i>parent</i> of this
11331 * view specifying how it should be arranged. There are many subclasses of
11332 * ViewGroup.LayoutParams, and these correspond to the different subclasses
11333 * of ViewGroup that are responsible for arranging their children.
11335 * This method may return null if this View is not attached to a parent
11336 * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
11337 * was not invoked successfully. When a View is attached to a parent
11338 * ViewGroup, this method must not return null.
11340 * @return The LayoutParams associated with this view, or null if no
11341 * parameters have been set yet
11343 @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
11344 public ViewGroup.LayoutParams getLayoutParams() {
11345 return mLayoutParams;
11349 * Set the layout parameters associated with this view. These supply
11350 * parameters to the <i>parent</i> of this view specifying how it should be
11351 * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
11352 * correspond to the different subclasses of ViewGroup that are responsible
11353 * for arranging their children.
11355 * @param params The layout parameters for this view, cannot be null
11357 public void setLayoutParams(ViewGroup.LayoutParams params) {
11358 if (params == null) {
11359 throw new NullPointerException("Layout parameters cannot be null");
11361 mLayoutParams = params;
11362 resolveLayoutParams();
11363 if (mParent instanceof ViewGroup) {
11364 ((ViewGroup) mParent).onSetLayoutParams(this, params);
11370 * Resolve the layout parameters depending on the resolved layout direction
11374 public void resolveLayoutParams() {
11375 if (mLayoutParams != null) {
11376 mLayoutParams.resolveLayoutDirection(getLayoutDirection());
11381 * Set the scrolled position of your view. This will cause a call to
11382 * {@link #onScrollChanged(int, int, int, int)} and the view will be
11384 * @param x the x position to scroll to
11385 * @param y the y position to scroll to
11387 public void scrollTo(int x, int y) {
11388 if (mScrollX != x || mScrollY != y) {
11389 int oldX = mScrollX;
11390 int oldY = mScrollY;
11393 invalidateParentCaches();
11394 onScrollChanged(mScrollX, mScrollY, oldX, oldY);
11395 if (!awakenScrollBars()) {
11396 postInvalidateOnAnimation();
11402 * Move the scrolled position of your view. This will cause a call to
11403 * {@link #onScrollChanged(int, int, int, int)} and the view will be
11405 * @param x the amount of pixels to scroll by horizontally
11406 * @param y the amount of pixels to scroll by vertically
11408 public void scrollBy(int x, int y) {
11409 scrollTo(mScrollX + x, mScrollY + y);
11413 * <p>Trigger the scrollbars to draw. When invoked this method starts an
11414 * animation to fade the scrollbars out after a default delay. If a subclass
11415 * provides animated scrolling, the start delay should equal the duration
11416 * of the scrolling animation.</p>
11418 * <p>The animation starts only if at least one of the scrollbars is
11419 * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
11420 * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11421 * this method returns true, and false otherwise. If the animation is
11422 * started, this method calls {@link #invalidate()}; in that case the
11423 * caller should not call {@link #invalidate()}.</p>
11425 * <p>This method should be invoked every time a subclass directly updates
11426 * the scroll parameters.</p>
11428 * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
11429 * and {@link #scrollTo(int, int)}.</p>
11431 * @return true if the animation is played, false otherwise
11433 * @see #awakenScrollBars(int)
11434 * @see #scrollBy(int, int)
11435 * @see #scrollTo(int, int)
11436 * @see #isHorizontalScrollBarEnabled()
11437 * @see #isVerticalScrollBarEnabled()
11438 * @see #setHorizontalScrollBarEnabled(boolean)
11439 * @see #setVerticalScrollBarEnabled(boolean)
11441 protected boolean awakenScrollBars() {
11442 return mScrollCache != null &&
11443 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
11447 * Trigger the scrollbars to draw.
11448 * This method differs from awakenScrollBars() only in its default duration.
11449 * initialAwakenScrollBars() will show the scroll bars for longer than
11450 * usual to give the user more of a chance to notice them.
11452 * @return true if the animation is played, false otherwise.
11454 private boolean initialAwakenScrollBars() {
11455 return mScrollCache != null &&
11456 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
11461 * Trigger the scrollbars to draw. When invoked this method starts an
11462 * animation to fade the scrollbars out after a fixed delay. If a subclass
11463 * provides animated scrolling, the start delay should equal the duration of
11464 * the scrolling animation.
11468 * The animation starts only if at least one of the scrollbars is enabled,
11469 * as specified by {@link #isHorizontalScrollBarEnabled()} and
11470 * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11471 * this method returns true, and false otherwise. If the animation is
11472 * started, this method calls {@link #invalidate()}; in that case the caller
11473 * should not call {@link #invalidate()}.
11477 * This method should be invoked everytime a subclass directly updates the
11478 * scroll parameters.
11481 * @param startDelay the delay, in milliseconds, after which the animation
11482 * should start; when the delay is 0, the animation starts
11484 * @return true if the animation is played, false otherwise
11486 * @see #scrollBy(int, int)
11487 * @see #scrollTo(int, int)
11488 * @see #isHorizontalScrollBarEnabled()
11489 * @see #isVerticalScrollBarEnabled()
11490 * @see #setHorizontalScrollBarEnabled(boolean)
11491 * @see #setVerticalScrollBarEnabled(boolean)
11493 protected boolean awakenScrollBars(int startDelay) {
11494 return awakenScrollBars(startDelay, true);
11499 * Trigger the scrollbars to draw. When invoked this method starts an
11500 * animation to fade the scrollbars out after a fixed delay. If a subclass
11501 * provides animated scrolling, the start delay should equal the duration of
11502 * the scrolling animation.
11506 * The animation starts only if at least one of the scrollbars is enabled,
11507 * as specified by {@link #isHorizontalScrollBarEnabled()} and
11508 * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11509 * this method returns true, and false otherwise. If the animation is
11510 * started, this method calls {@link #invalidate()} if the invalidate parameter
11511 * is set to true; in that case the caller
11512 * should not call {@link #invalidate()}.
11516 * This method should be invoked everytime a subclass directly updates the
11517 * scroll parameters.
11520 * @param startDelay the delay, in milliseconds, after which the animation
11521 * should start; when the delay is 0, the animation starts
11524 * @param invalidate Wheter this method should call invalidate
11526 * @return true if the animation is played, false otherwise
11528 * @see #scrollBy(int, int)
11529 * @see #scrollTo(int, int)
11530 * @see #isHorizontalScrollBarEnabled()
11531 * @see #isVerticalScrollBarEnabled()
11532 * @see #setHorizontalScrollBarEnabled(boolean)
11533 * @see #setVerticalScrollBarEnabled(boolean)
11535 protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
11536 final ScrollabilityCache scrollCache = mScrollCache;
11538 if (scrollCache == null || !scrollCache.fadeScrollBars) {
11542 if (scrollCache.scrollBar == null) {
11543 scrollCache.scrollBar = new ScrollBarDrawable();
11546 if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
11549 // Invalidate to show the scrollbars
11550 postInvalidateOnAnimation();
11553 if (scrollCache.state == ScrollabilityCache.OFF) {
11554 // FIXME: this is copied from WindowManagerService.
11555 // We should get this value from the system when it
11556 // is possible to do so.
11557 final int KEY_REPEAT_FIRST_DELAY = 750;
11558 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
11561 // Tell mScrollCache when we should start fading. This may
11562 // extend the fade start time if one was already scheduled
11563 long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
11564 scrollCache.fadeStartTime = fadeStartTime;
11565 scrollCache.state = ScrollabilityCache.ON;
11567 // Schedule our fader to run, unscheduling any old ones first
11568 if (mAttachInfo != null) {
11569 mAttachInfo.mHandler.removeCallbacks(scrollCache);
11570 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
11580 * Do not invalidate views which are not visible and which are not running an animation. They
11581 * will not get drawn and they should not set dirty flags as if they will be drawn
11583 private boolean skipInvalidate() {
11584 return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
11585 (!(mParent instanceof ViewGroup) ||
11586 !((ViewGroup) mParent).isViewTransitioning(this));
11590 * Mark the area defined by dirty as needing to be drawn. If the view is
11591 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
11592 * point in the future.
11594 * This must be called from a UI thread. To call from a non-UI thread, call
11595 * {@link #postInvalidate()}.
11597 * <b>WARNING:</b> In API 19 and below, this method may be destructive to
11600 * @param dirty the rectangle representing the bounds of the dirty region
11602 public void invalidate(Rect dirty) {
11603 final int scrollX = mScrollX;
11604 final int scrollY = mScrollY;
11605 invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
11606 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
11610 * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
11611 * coordinates of the dirty rect are relative to the view. If the view is
11612 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
11613 * point in the future.
11615 * This must be called from a UI thread. To call from a non-UI thread, call
11616 * {@link #postInvalidate()}.
11618 * @param l the left position of the dirty region
11619 * @param t the top position of the dirty region
11620 * @param r the right position of the dirty region
11621 * @param b the bottom position of the dirty region
11623 public void invalidate(int l, int t, int r, int b) {
11624 final int scrollX = mScrollX;
11625 final int scrollY = mScrollY;
11626 invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
11630 * Invalidate the whole view. If the view is visible,
11631 * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
11634 * This must be called from a UI thread. To call from a non-UI thread, call
11635 * {@link #postInvalidate()}.
11637 public void invalidate() {
11642 * This is where the invalidate() work actually happens. A full invalidate()
11643 * causes the drawing cache to be invalidated, but this function can be
11644 * called with invalidateCache set to false to skip that invalidation step
11645 * for cases that do not need it (for example, a component that remains at
11646 * the same dimensions with the same content).
11648 * @param invalidateCache Whether the drawing cache for this view should be
11649 * invalidated as well. This is usually true for a full
11650 * invalidate, but may be set to false if the View's contents or
11651 * dimensions have not changed.
11653 void invalidate(boolean invalidateCache) {
11654 invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
11657 void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
11658 boolean fullInvalidate) {
11659 if (mGhostView != null) {
11660 mGhostView.invalidate(invalidateCache);
11664 if (skipInvalidate()) {
11668 if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
11669 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
11670 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
11671 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
11672 if (fullInvalidate) {
11673 mLastIsOpaque = isOpaque();
11674 mPrivateFlags &= ~PFLAG_DRAWN;
11677 mPrivateFlags |= PFLAG_DIRTY;
11679 if (invalidateCache) {
11680 mPrivateFlags |= PFLAG_INVALIDATED;
11681 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11684 // Propagate the damage rectangle to the parent view.
11685 final AttachInfo ai = mAttachInfo;
11686 final ViewParent p = mParent;
11687 if (p != null && ai != null && l < r && t < b) {
11688 final Rect damage = ai.mTmpInvalRect;
11689 damage.set(l, t, r, b);
11690 p.invalidateChild(this, damage);
11693 // Damage the entire projection receiver, if necessary.
11694 if (mBackground != null && mBackground.isProjected()) {
11695 final View receiver = getProjectionReceiver();
11696 if (receiver != null) {
11697 receiver.damageInParent();
11701 // Damage the entire IsolatedZVolume receiving this view's shadow.
11702 if (isHardwareAccelerated() && getZ() != 0) {
11703 damageShadowReceiver();
11709 * @return this view's projection receiver, or {@code null} if none exists
11711 private View getProjectionReceiver() {
11712 ViewParent p = getParent();
11713 while (p != null && p instanceof View) {
11714 final View v = (View) p;
11715 if (v.isProjectionReceiver()) {
11725 * @return whether the view is a projection receiver
11727 private boolean isProjectionReceiver() {
11728 return mBackground != null;
11732 * Damage area of the screen that can be covered by this View's shadow.
11734 * This method will guarantee that any changes to shadows cast by a View
11735 * are damaged on the screen for future redraw.
11737 private void damageShadowReceiver() {
11738 final AttachInfo ai = mAttachInfo;
11740 ViewParent p = getParent();
11741 if (p != null && p instanceof ViewGroup) {
11742 final ViewGroup vg = (ViewGroup) p;
11743 vg.damageInParent();
11749 * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
11750 * set any flags or handle all of the cases handled by the default invalidation methods.
11751 * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
11752 * dirty rect. This method calls into fast invalidation methods in ViewGroup that
11753 * walk up the hierarchy, transforming the dirty rect as necessary.
11755 * The method also handles normal invalidation logic if display list properties are not
11756 * being used in this view. The invalidateParent and forceRedraw flags are used by that
11757 * backup approach, to handle these cases used in the various property-setting methods.
11759 * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
11760 * are not being used in this view
11761 * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
11762 * list properties are not being used in this view
11764 void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
11765 if (!isHardwareAccelerated()
11766 || !mRenderNode.isValid()
11767 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
11768 if (invalidateParent) {
11769 invalidateParentCaches();
11772 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11778 if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
11779 damageShadowReceiver();
11784 * Tells the parent view to damage this view's bounds.
11788 protected void damageInParent() {
11789 final AttachInfo ai = mAttachInfo;
11790 final ViewParent p = mParent;
11791 if (p != null && ai != null) {
11792 final Rect r = ai.mTmpInvalRect;
11793 r.set(0, 0, mRight - mLeft, mBottom - mTop);
11794 if (mParent instanceof ViewGroup) {
11795 ((ViewGroup) mParent).damageChild(this, r);
11797 mParent.invalidateChild(this, r);
11803 * Utility method to transform a given Rect by the current matrix of this view.
11805 void transformRect(final Rect rect) {
11806 if (!getMatrix().isIdentity()) {
11807 RectF boundingRect = mAttachInfo.mTmpTransformRect;
11808 boundingRect.set(rect);
11809 getMatrix().mapRect(boundingRect);
11810 rect.set((int) Math.floor(boundingRect.left),
11811 (int) Math.floor(boundingRect.top),
11812 (int) Math.ceil(boundingRect.right),
11813 (int) Math.ceil(boundingRect.bottom));
11818 * Used to indicate that the parent of this view should clear its caches. This functionality
11819 * is used to force the parent to rebuild its display list (when hardware-accelerated),
11820 * which is necessary when various parent-managed properties of the view change, such as
11821 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
11822 * clears the parent caches and does not causes an invalidate event.
11826 protected void invalidateParentCaches() {
11827 if (mParent instanceof View) {
11828 ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
11833 * Used to indicate that the parent of this view should be invalidated. This functionality
11834 * is used to force the parent to rebuild its display list (when hardware-accelerated),
11835 * which is necessary when various parent-managed properties of the view change, such as
11836 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
11837 * an invalidation event to the parent.
11841 protected void invalidateParentIfNeeded() {
11842 if (isHardwareAccelerated() && mParent instanceof View) {
11843 ((View) mParent).invalidate(true);
11850 protected void invalidateParentIfNeededAndWasQuickRejected() {
11851 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
11852 // View was rejected last time it was drawn by its parent; this may have changed
11853 invalidateParentIfNeeded();
11858 * Indicates whether this View is opaque. An opaque View guarantees that it will
11859 * draw all the pixels overlapping its bounds using a fully opaque color.
11861 * Subclasses of View should override this method whenever possible to indicate
11862 * whether an instance is opaque. Opaque Views are treated in a special way by
11863 * the View hierarchy, possibly allowing it to perform optimizations during
11864 * invalidate/draw passes.
11866 * @return True if this View is guaranteed to be fully opaque, false otherwise.
11868 @ViewDebug.ExportedProperty(category = "drawing")
11869 public boolean isOpaque() {
11870 return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
11871 getFinalAlpha() >= 1.0f;
11877 protected void computeOpaqueFlags() {
11879 // - Has a background
11880 // - Background is opaque
11881 // - Doesn't have scrollbars or scrollbars overlay
11883 if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
11884 mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
11886 mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
11889 final int flags = mViewFlags;
11890 if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
11891 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
11892 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
11893 mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
11895 mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
11902 protected boolean hasOpaqueScrollbars() {
11903 return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
11907 * @return A handler associated with the thread running the View. This
11908 * handler can be used to pump events in the UI events queue.
11910 public Handler getHandler() {
11911 final AttachInfo attachInfo = mAttachInfo;
11912 if (attachInfo != null) {
11913 return attachInfo.mHandler;
11919 * Gets the view root associated with the View.
11920 * @return The view root, or null if none.
11923 public ViewRootImpl getViewRootImpl() {
11924 if (mAttachInfo != null) {
11925 return mAttachInfo.mViewRootImpl;
11933 public HardwareRenderer getHardwareRenderer() {
11934 return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
11938 * <p>Causes the Runnable to be added to the message queue.
11939 * The runnable will be run on the user interface thread.</p>
11941 * @param action The Runnable that will be executed.
11943 * @return Returns true if the Runnable was successfully placed in to the
11944 * message queue. Returns false on failure, usually because the
11945 * looper processing the message queue is exiting.
11947 * @see #postDelayed
11948 * @see #removeCallbacks
11950 public boolean post(Runnable action) {
11951 final AttachInfo attachInfo = mAttachInfo;
11952 if (attachInfo != null) {
11953 return attachInfo.mHandler.post(action);
11955 // Assume that post will succeed later
11956 ViewRootImpl.getRunQueue().post(action);
11961 * <p>Causes the Runnable to be added to the message queue, to be run
11962 * after the specified amount of time elapses.
11963 * The runnable will be run on the user interface thread.</p>
11965 * @param action The Runnable that will be executed.
11966 * @param delayMillis The delay (in milliseconds) until the Runnable
11967 * will be executed.
11969 * @return true if the Runnable was successfully placed in to the
11970 * message queue. Returns false on failure, usually because the
11971 * looper processing the message queue is exiting. Note that a
11972 * result of true does not mean the Runnable will be processed --
11973 * if the looper is quit before the delivery time of the message
11974 * occurs then the message will be dropped.
11977 * @see #removeCallbacks
11979 public boolean postDelayed(Runnable action, long delayMillis) {
11980 final AttachInfo attachInfo = mAttachInfo;
11981 if (attachInfo != null) {
11982 return attachInfo.mHandler.postDelayed(action, delayMillis);
11984 // Assume that post will succeed later
11985 ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
11990 * <p>Causes the Runnable to execute on the next animation time step.
11991 * The runnable will be run on the user interface thread.</p>
11993 * @param action The Runnable that will be executed.
11995 * @see #postOnAnimationDelayed
11996 * @see #removeCallbacks
11998 public void postOnAnimation(Runnable action) {
11999 final AttachInfo attachInfo = mAttachInfo;
12000 if (attachInfo != null) {
12001 attachInfo.mViewRootImpl.mChoreographer.postCallback(
12002 Choreographer.CALLBACK_ANIMATION, action, null);
12004 // Assume that post will succeed later
12005 ViewRootImpl.getRunQueue().post(action);
12010 * <p>Causes the Runnable to execute on the next animation time step,
12011 * after the specified amount of time elapses.
12012 * The runnable will be run on the user interface thread.</p>
12014 * @param action The Runnable that will be executed.
12015 * @param delayMillis The delay (in milliseconds) until the Runnable
12016 * will be executed.
12018 * @see #postOnAnimation
12019 * @see #removeCallbacks
12021 public void postOnAnimationDelayed(Runnable action, long delayMillis) {
12022 final AttachInfo attachInfo = mAttachInfo;
12023 if (attachInfo != null) {
12024 attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
12025 Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
12027 // Assume that post will succeed later
12028 ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
12033 * <p>Removes the specified Runnable from the message queue.</p>
12035 * @param action The Runnable to remove from the message handling queue
12037 * @return true if this view could ask the Handler to remove the Runnable,
12038 * false otherwise. When the returned value is true, the Runnable
12039 * may or may not have been actually removed from the message queue
12040 * (for instance, if the Runnable was not in the queue already.)
12043 * @see #postDelayed
12044 * @see #postOnAnimation
12045 * @see #postOnAnimationDelayed
12047 public boolean removeCallbacks(Runnable action) {
12048 if (action != null) {
12049 final AttachInfo attachInfo = mAttachInfo;
12050 if (attachInfo != null) {
12051 attachInfo.mHandler.removeCallbacks(action);
12052 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
12053 Choreographer.CALLBACK_ANIMATION, action, null);
12055 // Assume that post will succeed later
12056 ViewRootImpl.getRunQueue().removeCallbacks(action);
12062 * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
12063 * Use this to invalidate the View from a non-UI thread.</p>
12065 * <p>This method can be invoked from outside of the UI thread
12066 * only when this View is attached to a window.</p>
12068 * @see #invalidate()
12069 * @see #postInvalidateDelayed(long)
12071 public void postInvalidate() {
12072 postInvalidateDelayed(0);
12076 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
12077 * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
12079 * <p>This method can be invoked from outside of the UI thread
12080 * only when this View is attached to a window.</p>
12082 * @param left The left coordinate of the rectangle to invalidate.
12083 * @param top The top coordinate of the rectangle to invalidate.
12084 * @param right The right coordinate of the rectangle to invalidate.
12085 * @param bottom The bottom coordinate of the rectangle to invalidate.
12087 * @see #invalidate(int, int, int, int)
12088 * @see #invalidate(Rect)
12089 * @see #postInvalidateDelayed(long, int, int, int, int)
12091 public void postInvalidate(int left, int top, int right, int bottom) {
12092 postInvalidateDelayed(0, left, top, right, bottom);
12096 * <p>Cause an invalidate to happen on a subsequent cycle through the event
12097 * loop. Waits for the specified amount of time.</p>
12099 * <p>This method can be invoked from outside of the UI thread
12100 * only when this View is attached to a window.</p>
12102 * @param delayMilliseconds the duration in milliseconds to delay the
12105 * @see #invalidate()
12106 * @see #postInvalidate()
12108 public void postInvalidateDelayed(long delayMilliseconds) {
12109 // We try only with the AttachInfo because there's no point in invalidating
12110 // if we are not attached to our window
12111 final AttachInfo attachInfo = mAttachInfo;
12112 if (attachInfo != null) {
12113 attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
12118 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
12119 * through the event loop. Waits for the specified amount of time.</p>
12121 * <p>This method can be invoked from outside of the UI thread
12122 * only when this View is attached to a window.</p>
12124 * @param delayMilliseconds the duration in milliseconds to delay the
12126 * @param left The left coordinate of the rectangle to invalidate.
12127 * @param top The top coordinate of the rectangle to invalidate.
12128 * @param right The right coordinate of the rectangle to invalidate.
12129 * @param bottom The bottom coordinate of the rectangle to invalidate.
12131 * @see #invalidate(int, int, int, int)
12132 * @see #invalidate(Rect)
12133 * @see #postInvalidate(int, int, int, int)
12135 public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
12136 int right, int bottom) {
12138 // We try only with the AttachInfo because there's no point in invalidating
12139 // if we are not attached to our window
12140 final AttachInfo attachInfo = mAttachInfo;
12141 if (attachInfo != null) {
12142 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
12143 info.target = this;
12146 info.right = right;
12147 info.bottom = bottom;
12149 attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
12154 * <p>Cause an invalidate to happen on the next animation time step, typically the
12155 * next display frame.</p>
12157 * <p>This method can be invoked from outside of the UI thread
12158 * only when this View is attached to a window.</p>
12160 * @see #invalidate()
12162 public void postInvalidateOnAnimation() {
12163 // We try only with the AttachInfo because there's no point in invalidating
12164 // if we are not attached to our window
12165 final AttachInfo attachInfo = mAttachInfo;
12166 if (attachInfo != null) {
12167 attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
12172 * <p>Cause an invalidate of the specified area to happen on the next animation
12173 * time step, typically the next display frame.</p>
12175 * <p>This method can be invoked from outside of the UI thread
12176 * only when this View is attached to a window.</p>
12178 * @param left The left coordinate of the rectangle to invalidate.
12179 * @param top The top coordinate of the rectangle to invalidate.
12180 * @param right The right coordinate of the rectangle to invalidate.
12181 * @param bottom The bottom coordinate of the rectangle to invalidate.
12183 * @see #invalidate(int, int, int, int)
12184 * @see #invalidate(Rect)
12186 public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
12187 // We try only with the AttachInfo because there's no point in invalidating
12188 // if we are not attached to our window
12189 final AttachInfo attachInfo = mAttachInfo;
12190 if (attachInfo != null) {
12191 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
12192 info.target = this;
12195 info.right = right;
12196 info.bottom = bottom;
12198 attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
12203 * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
12204 * This event is sent at most once every
12205 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
12207 private void postSendViewScrolledAccessibilityEventCallback() {
12208 if (mSendViewScrolledAccessibilityEvent == null) {
12209 mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
12211 if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
12212 mSendViewScrolledAccessibilityEvent.mIsPending = true;
12213 postDelayed(mSendViewScrolledAccessibilityEvent,
12214 ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
12219 * Called by a parent to request that a child update its values for mScrollX
12220 * and mScrollY if necessary. This will typically be done if the child is
12221 * animating a scroll using a {@link android.widget.Scroller Scroller}
12224 public void computeScroll() {
12228 * <p>Indicate whether the horizontal edges are faded when the view is
12229 * scrolled horizontally.</p>
12231 * @return true if the horizontal edges should are faded on scroll, false
12234 * @see #setHorizontalFadingEdgeEnabled(boolean)
12236 * @attr ref android.R.styleable#View_requiresFadingEdge
12238 public boolean isHorizontalFadingEdgeEnabled() {
12239 return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
12243 * <p>Define whether the horizontal edges should be faded when this view
12244 * is scrolled horizontally.</p>
12246 * @param horizontalFadingEdgeEnabled true if the horizontal edges should
12247 * be faded when the view is scrolled
12250 * @see #isHorizontalFadingEdgeEnabled()
12252 * @attr ref android.R.styleable#View_requiresFadingEdge
12254 public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
12255 if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
12256 if (horizontalFadingEdgeEnabled) {
12260 mViewFlags ^= FADING_EDGE_HORIZONTAL;
12265 * <p>Indicate whether the vertical edges are faded when the view is
12266 * scrolled horizontally.</p>
12268 * @return true if the vertical edges should are faded on scroll, false
12271 * @see #setVerticalFadingEdgeEnabled(boolean)
12273 * @attr ref android.R.styleable#View_requiresFadingEdge
12275 public boolean isVerticalFadingEdgeEnabled() {
12276 return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
12280 * <p>Define whether the vertical edges should be faded when this view
12281 * is scrolled vertically.</p>
12283 * @param verticalFadingEdgeEnabled true if the vertical edges should
12284 * be faded when the view is scrolled
12287 * @see #isVerticalFadingEdgeEnabled()
12289 * @attr ref android.R.styleable#View_requiresFadingEdge
12291 public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
12292 if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
12293 if (verticalFadingEdgeEnabled) {
12297 mViewFlags ^= FADING_EDGE_VERTICAL;
12302 * Returns the strength, or intensity, of the top faded edge. The strength is
12303 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12304 * returns 0.0 or 1.0 but no value in between.
12306 * Subclasses should override this method to provide a smoother fade transition
12307 * when scrolling occurs.
12309 * @return the intensity of the top fade as a float between 0.0f and 1.0f
12311 protected float getTopFadingEdgeStrength() {
12312 return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
12316 * Returns the strength, or intensity, of the bottom faded edge. The strength is
12317 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12318 * returns 0.0 or 1.0 but no value in between.
12320 * Subclasses should override this method to provide a smoother fade transition
12321 * when scrolling occurs.
12323 * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
12325 protected float getBottomFadingEdgeStrength() {
12326 return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
12327 computeVerticalScrollRange() ? 1.0f : 0.0f;
12331 * Returns the strength, or intensity, of the left faded edge. The strength is
12332 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12333 * returns 0.0 or 1.0 but no value in between.
12335 * Subclasses should override this method to provide a smoother fade transition
12336 * when scrolling occurs.
12338 * @return the intensity of the left fade as a float between 0.0f and 1.0f
12340 protected float getLeftFadingEdgeStrength() {
12341 return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
12345 * Returns the strength, or intensity, of the right faded edge. The strength is
12346 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12347 * returns 0.0 or 1.0 but no value in between.
12349 * Subclasses should override this method to provide a smoother fade transition
12350 * when scrolling occurs.
12352 * @return the intensity of the right fade as a float between 0.0f and 1.0f
12354 protected float getRightFadingEdgeStrength() {
12355 return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
12356 computeHorizontalScrollRange() ? 1.0f : 0.0f;
12360 * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
12361 * scrollbar is not drawn by default.</p>
12363 * @return true if the horizontal scrollbar should be painted, false
12366 * @see #setHorizontalScrollBarEnabled(boolean)
12368 public boolean isHorizontalScrollBarEnabled() {
12369 return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
12373 * <p>Define whether the horizontal scrollbar should be drawn or not. The
12374 * scrollbar is not drawn by default.</p>
12376 * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
12379 * @see #isHorizontalScrollBarEnabled()
12381 public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
12382 if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
12383 mViewFlags ^= SCROLLBARS_HORIZONTAL;
12384 computeOpaqueFlags();
12390 * <p>Indicate whether the vertical scrollbar should be drawn or not. The
12391 * scrollbar is not drawn by default.</p>
12393 * @return true if the vertical scrollbar should be painted, false
12396 * @see #setVerticalScrollBarEnabled(boolean)
12398 public boolean isVerticalScrollBarEnabled() {
12399 return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
12403 * <p>Define whether the vertical scrollbar should be drawn or not. The
12404 * scrollbar is not drawn by default.</p>
12406 * @param verticalScrollBarEnabled true if the vertical scrollbar should
12409 * @see #isVerticalScrollBarEnabled()
12411 public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
12412 if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
12413 mViewFlags ^= SCROLLBARS_VERTICAL;
12414 computeOpaqueFlags();
12422 protected void recomputePadding() {
12423 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
12427 * Define whether scrollbars will fade when the view is not scrolling.
12429 * @param fadeScrollbars wheter to enable fading
12431 * @attr ref android.R.styleable#View_fadeScrollbars
12433 public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
12435 final ScrollabilityCache scrollabilityCache = mScrollCache;
12436 scrollabilityCache.fadeScrollBars = fadeScrollbars;
12437 if (fadeScrollbars) {
12438 scrollabilityCache.state = ScrollabilityCache.OFF;
12440 scrollabilityCache.state = ScrollabilityCache.ON;
12446 * Returns true if scrollbars will fade when this view is not scrolling
12448 * @return true if scrollbar fading is enabled
12450 * @attr ref android.R.styleable#View_fadeScrollbars
12452 public boolean isScrollbarFadingEnabled() {
12453 return mScrollCache != null && mScrollCache.fadeScrollBars;
12458 * Returns the delay before scrollbars fade.
12460 * @return the delay before scrollbars fade
12462 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
12464 public int getScrollBarDefaultDelayBeforeFade() {
12465 return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
12466 mScrollCache.scrollBarDefaultDelayBeforeFade;
12470 * Define the delay before scrollbars fade.
12472 * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
12474 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
12476 public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
12477 getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
12482 * Returns the scrollbar fade duration.
12484 * @return the scrollbar fade duration
12486 * @attr ref android.R.styleable#View_scrollbarFadeDuration
12488 public int getScrollBarFadeDuration() {
12489 return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
12490 mScrollCache.scrollBarFadeDuration;
12494 * Define the scrollbar fade duration.
12496 * @param scrollBarFadeDuration - the scrollbar fade duration
12498 * @attr ref android.R.styleable#View_scrollbarFadeDuration
12500 public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
12501 getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
12506 * Returns the scrollbar size.
12508 * @return the scrollbar size
12510 * @attr ref android.R.styleable#View_scrollbarSize
12512 public int getScrollBarSize() {
12513 return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
12514 mScrollCache.scrollBarSize;
12518 * Define the scrollbar size.
12520 * @param scrollBarSize - the scrollbar size
12522 * @attr ref android.R.styleable#View_scrollbarSize
12524 public void setScrollBarSize(int scrollBarSize) {
12525 getScrollCache().scrollBarSize = scrollBarSize;
12529 * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
12530 * inset. When inset, they add to the padding of the view. And the scrollbars
12531 * can be drawn inside the padding area or on the edge of the view. For example,
12532 * if a view has a background drawable and you want to draw the scrollbars
12533 * inside the padding specified by the drawable, you can use
12534 * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
12535 * appear at the edge of the view, ignoring the padding, then you can use
12536 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
12537 * @param style the style of the scrollbars. Should be one of
12538 * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
12539 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
12540 * @see #SCROLLBARS_INSIDE_OVERLAY
12541 * @see #SCROLLBARS_INSIDE_INSET
12542 * @see #SCROLLBARS_OUTSIDE_OVERLAY
12543 * @see #SCROLLBARS_OUTSIDE_INSET
12545 * @attr ref android.R.styleable#View_scrollbarStyle
12547 public void setScrollBarStyle(@ScrollBarStyle int style) {
12548 if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
12549 mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
12550 computeOpaqueFlags();
12556 * <p>Returns the current scrollbar style.</p>
12557 * @return the current scrollbar style
12558 * @see #SCROLLBARS_INSIDE_OVERLAY
12559 * @see #SCROLLBARS_INSIDE_INSET
12560 * @see #SCROLLBARS_OUTSIDE_OVERLAY
12561 * @see #SCROLLBARS_OUTSIDE_INSET
12563 * @attr ref android.R.styleable#View_scrollbarStyle
12565 @ViewDebug.ExportedProperty(mapping = {
12566 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
12567 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
12568 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
12569 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
12572 public int getScrollBarStyle() {
12573 return mViewFlags & SCROLLBARS_STYLE_MASK;
12577 * <p>Compute the horizontal range that the horizontal scrollbar
12580 * <p>The range is expressed in arbitrary units that must be the same as the
12581 * units used by {@link #computeHorizontalScrollExtent()} and
12582 * {@link #computeHorizontalScrollOffset()}.</p>
12584 * <p>The default range is the drawing width of this view.</p>
12586 * @return the total horizontal range represented by the horizontal
12589 * @see #computeHorizontalScrollExtent()
12590 * @see #computeHorizontalScrollOffset()
12591 * @see android.widget.ScrollBarDrawable
12593 protected int computeHorizontalScrollRange() {
12598 * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
12599 * within the horizontal range. This value is used to compute the position
12600 * of the thumb within the scrollbar's track.</p>
12602 * <p>The range is expressed in arbitrary units that must be the same as the
12603 * units used by {@link #computeHorizontalScrollRange()} and
12604 * {@link #computeHorizontalScrollExtent()}.</p>
12606 * <p>The default offset is the scroll offset of this view.</p>
12608 * @return the horizontal offset of the scrollbar's thumb
12610 * @see #computeHorizontalScrollRange()
12611 * @see #computeHorizontalScrollExtent()
12612 * @see android.widget.ScrollBarDrawable
12614 protected int computeHorizontalScrollOffset() {
12619 * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
12620 * within the horizontal range. This value is used to compute the length
12621 * of the thumb within the scrollbar's track.</p>
12623 * <p>The range is expressed in arbitrary units that must be the same as the
12624 * units used by {@link #computeHorizontalScrollRange()} and
12625 * {@link #computeHorizontalScrollOffset()}.</p>
12627 * <p>The default extent is the drawing width of this view.</p>
12629 * @return the horizontal extent of the scrollbar's thumb
12631 * @see #computeHorizontalScrollRange()
12632 * @see #computeHorizontalScrollOffset()
12633 * @see android.widget.ScrollBarDrawable
12635 protected int computeHorizontalScrollExtent() {
12640 * <p>Compute the vertical range that the vertical scrollbar represents.</p>
12642 * <p>The range is expressed in arbitrary units that must be the same as the
12643 * units used by {@link #computeVerticalScrollExtent()} and
12644 * {@link #computeVerticalScrollOffset()}.</p>
12646 * @return the total vertical range represented by the vertical scrollbar
12648 * <p>The default range is the drawing height of this view.</p>
12650 * @see #computeVerticalScrollExtent()
12651 * @see #computeVerticalScrollOffset()
12652 * @see android.widget.ScrollBarDrawable
12654 protected int computeVerticalScrollRange() {
12655 return getHeight();
12659 * <p>Compute the vertical offset of the vertical scrollbar's thumb
12660 * within the horizontal range. This value is used to compute the position
12661 * of the thumb within the scrollbar's track.</p>
12663 * <p>The range is expressed in arbitrary units that must be the same as the
12664 * units used by {@link #computeVerticalScrollRange()} and
12665 * {@link #computeVerticalScrollExtent()}.</p>
12667 * <p>The default offset is the scroll offset of this view.</p>
12669 * @return the vertical offset of the scrollbar's thumb
12671 * @see #computeVerticalScrollRange()
12672 * @see #computeVerticalScrollExtent()
12673 * @see android.widget.ScrollBarDrawable
12675 protected int computeVerticalScrollOffset() {
12680 * <p>Compute the vertical extent of the vertical scrollbar's thumb
12681 * within the vertical range. This value is used to compute the length
12682 * of the thumb within the scrollbar's track.</p>
12684 * <p>The range is expressed in arbitrary units that must be the same as the
12685 * units used by {@link #computeVerticalScrollRange()} and
12686 * {@link #computeVerticalScrollOffset()}.</p>
12688 * <p>The default extent is the drawing height of this view.</p>
12690 * @return the vertical extent of the scrollbar's thumb
12692 * @see #computeVerticalScrollRange()
12693 * @see #computeVerticalScrollOffset()
12694 * @see android.widget.ScrollBarDrawable
12696 protected int computeVerticalScrollExtent() {
12697 return getHeight();
12701 * Check if this view can be scrolled horizontally in a certain direction.
12703 * @param direction Negative to check scrolling left, positive to check scrolling right.
12704 * @return true if this view can be scrolled in the specified direction, false otherwise.
12706 public boolean canScrollHorizontally(int direction) {
12707 final int offset = computeHorizontalScrollOffset();
12708 final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
12709 if (range == 0) return false;
12710 if (direction < 0) {
12713 return offset < range - 1;
12718 * Check if this view can be scrolled vertically in a certain direction.
12720 * @param direction Negative to check scrolling up, positive to check scrolling down.
12721 * @return true if this view can be scrolled in the specified direction, false otherwise.
12723 public boolean canScrollVertically(int direction) {
12724 final int offset = computeVerticalScrollOffset();
12725 final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
12726 if (range == 0) return false;
12727 if (direction < 0) {
12730 return offset < range - 1;
12735 * <p>Request the drawing of the horizontal and the vertical scrollbar. The
12736 * scrollbars are painted only if they have been awakened first.</p>
12738 * @param canvas the canvas on which to draw the scrollbars
12740 * @see #awakenScrollBars(int)
12742 protected final void onDrawScrollBars(Canvas canvas) {
12743 // scrollbars are drawn only when the animation is running
12744 final ScrollabilityCache cache = mScrollCache;
12745 if (cache != null) {
12747 int state = cache.state;
12749 if (state == ScrollabilityCache.OFF) {
12753 boolean invalidate = false;
12755 if (state == ScrollabilityCache.FADING) {
12756 // We're fading -- get our fade interpolation
12757 if (cache.interpolatorValues == null) {
12758 cache.interpolatorValues = new float[1];
12761 float[] values = cache.interpolatorValues;
12763 // Stops the animation if we're done
12764 if (cache.scrollBarInterpolator.timeToValues(values) ==
12765 Interpolator.Result.FREEZE_END) {
12766 cache.state = ScrollabilityCache.OFF;
12768 cache.scrollBar.setAlpha(Math.round(values[0]));
12771 // This will make the scroll bars inval themselves after
12772 // drawing. We only want this when we're fading so that
12773 // we prevent excessive redraws
12776 // We're just on -- but we may have been fading before so
12778 cache.scrollBar.setAlpha(255);
12782 final int viewFlags = mViewFlags;
12784 final boolean drawHorizontalScrollBar =
12785 (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
12786 final boolean drawVerticalScrollBar =
12787 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
12788 && !isVerticalScrollBarHidden();
12790 if (drawVerticalScrollBar || drawHorizontalScrollBar) {
12791 final int width = mRight - mLeft;
12792 final int height = mBottom - mTop;
12794 final ScrollBarDrawable scrollBar = cache.scrollBar;
12796 final int scrollX = mScrollX;
12797 final int scrollY = mScrollY;
12798 final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
12805 if (drawHorizontalScrollBar) {
12806 int size = scrollBar.getSize(false);
12808 size = cache.scrollBarSize;
12811 scrollBar.setParameters(computeHorizontalScrollRange(),
12812 computeHorizontalScrollOffset(),
12813 computeHorizontalScrollExtent(), false);
12814 final int verticalScrollBarGap = drawVerticalScrollBar ?
12815 getVerticalScrollbarWidth() : 0;
12816 top = scrollY + height - size - (mUserPaddingBottom & inside);
12817 left = scrollX + (mPaddingLeft & inside);
12818 right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
12819 bottom = top + size;
12820 onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
12822 invalidate(left, top, right, bottom);
12826 if (drawVerticalScrollBar) {
12827 int size = scrollBar.getSize(true);
12829 size = cache.scrollBarSize;
12832 scrollBar.setParameters(computeVerticalScrollRange(),
12833 computeVerticalScrollOffset(),
12834 computeVerticalScrollExtent(), true);
12835 int verticalScrollbarPosition = mVerticalScrollbarPosition;
12836 if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
12837 verticalScrollbarPosition = isLayoutRtl() ?
12838 SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
12840 switch (verticalScrollbarPosition) {
12842 case SCROLLBAR_POSITION_RIGHT:
12843 left = scrollX + width - size - (mUserPaddingRight & inside);
12845 case SCROLLBAR_POSITION_LEFT:
12846 left = scrollX + (mUserPaddingLeft & inside);
12849 top = scrollY + (mPaddingTop & inside);
12850 right = left + size;
12851 bottom = scrollY + height - (mUserPaddingBottom & inside);
12852 onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
12854 invalidate(left, top, right, bottom);
12862 * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
12863 * FastScroller is visible.
12864 * @return whether to temporarily hide the vertical scrollbar
12867 protected boolean isVerticalScrollBarHidden() {
12872 * <p>Draw the horizontal scrollbar if
12873 * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
12875 * @param canvas the canvas on which to draw the scrollbar
12876 * @param scrollBar the scrollbar's drawable
12878 * @see #isHorizontalScrollBarEnabled()
12879 * @see #computeHorizontalScrollRange()
12880 * @see #computeHorizontalScrollExtent()
12881 * @see #computeHorizontalScrollOffset()
12882 * @see android.widget.ScrollBarDrawable
12885 protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
12886 int l, int t, int r, int b) {
12887 scrollBar.setBounds(l, t, r, b);
12888 scrollBar.draw(canvas);
12892 * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
12893 * returns true.</p>
12895 * @param canvas the canvas on which to draw the scrollbar
12896 * @param scrollBar the scrollbar's drawable
12898 * @see #isVerticalScrollBarEnabled()
12899 * @see #computeVerticalScrollRange()
12900 * @see #computeVerticalScrollExtent()
12901 * @see #computeVerticalScrollOffset()
12902 * @see android.widget.ScrollBarDrawable
12905 protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
12906 int l, int t, int r, int b) {
12907 scrollBar.setBounds(l, t, r, b);
12908 scrollBar.draw(canvas);
12912 * Implement this to do your drawing.
12914 * @param canvas the canvas on which the background will be drawn
12916 protected void onDraw(Canvas canvas) {
12920 * Caller is responsible for calling requestLayout if necessary.
12921 * (This allows addViewInLayout to not request a new layout.)
12923 void assignParent(ViewParent parent) {
12924 if (mParent == null) {
12926 } else if (parent == null) {
12929 throw new RuntimeException("view " + this + " being added, but"
12930 + " it already has a parent");
12935 * This is called when the view is attached to a window. At this point it
12936 * has a Surface and will start drawing. Note that this function is
12937 * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
12938 * however it may be called any time before the first onDraw -- including
12939 * before or after {@link #onMeasure(int, int)}.
12941 * @see #onDetachedFromWindow()
12943 protected void onAttachedToWindow() {
12944 if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
12945 mParent.requestTransparentRegion(this);
12948 if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
12949 initialAwakenScrollBars();
12950 mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
12953 mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
12955 jumpDrawablesToCurrentState();
12957 resetSubtreeAccessibilityStateChanged();
12959 // rebuild, since Outline not maintained while View is detached
12963 InputMethodManager imm = InputMethodManager.peekInstance();
12969 * Resolve all RTL related properties.
12971 * @return true if resolution of RTL properties has been done
12975 public boolean resolveRtlPropertiesIfNeeded() {
12976 if (!needRtlPropertiesResolution()) return false;
12978 // Order is important here: LayoutDirection MUST be resolved first
12979 if (!isLayoutDirectionResolved()) {
12980 resolveLayoutDirection();
12981 resolveLayoutParams();
12983 // ... then we can resolve the others properties depending on the resolved LayoutDirection.
12984 if (!isTextDirectionResolved()) {
12985 resolveTextDirection();
12987 if (!isTextAlignmentResolved()) {
12988 resolveTextAlignment();
12990 // Should resolve Drawables before Padding because we need the layout direction of the
12991 // Drawable to correctly resolve Padding.
12992 if (!isDrawablesResolved()) {
12993 resolveDrawables();
12995 if (!isPaddingResolved()) {
12998 onRtlPropertiesChanged(getLayoutDirection());
13003 * Reset resolution of all RTL related properties.
13007 public void resetRtlProperties() {
13008 resetResolvedLayoutDirection();
13009 resetResolvedTextDirection();
13010 resetResolvedTextAlignment();
13011 resetResolvedPadding();
13012 resetResolvedDrawables();
13016 * @see #onScreenStateChanged(int)
13018 void dispatchScreenStateChanged(int screenState) {
13019 onScreenStateChanged(screenState);
13023 * This method is called whenever the state of the screen this view is
13024 * attached to changes. A state change will usually occurs when the screen
13025 * turns on or off (whether it happens automatically or the user does it
13028 * @param screenState The new state of the screen. Can be either
13029 * {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
13031 public void onScreenStateChanged(int screenState) {
13035 * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
13037 private boolean hasRtlSupport() {
13038 return mContext.getApplicationInfo().hasRtlSupport();
13042 * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
13043 * RTL not supported)
13045 private boolean isRtlCompatibilityMode() {
13046 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
13047 return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
13051 * @return true if RTL properties need resolution.
13054 private boolean needRtlPropertiesResolution() {
13055 return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
13059 * Called when any RTL property (layout direction or text direction or text alignment) has
13062 * Subclasses need to override this method to take care of cached information that depends on the
13063 * resolved layout direction, or to inform child views that inherit their layout direction.
13065 * The default implementation does nothing.
13067 * @param layoutDirection the direction of the layout
13069 * @see #LAYOUT_DIRECTION_LTR
13070 * @see #LAYOUT_DIRECTION_RTL
13072 public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
13076 * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
13077 * that the parent directionality can and will be resolved before its children.
13079 * @return true if resolution has been done, false otherwise.
13083 public boolean resolveLayoutDirection() {
13084 // Clear any previous layout direction resolution
13085 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
13087 if (hasRtlSupport()) {
13088 // Set resolved depending on layout direction
13089 switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
13090 PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
13091 case LAYOUT_DIRECTION_INHERIT:
13092 // We cannot resolve yet. LTR is by default and let the resolution happen again
13093 // later to get the correct resolved value
13094 if (!canResolveLayoutDirection()) return false;
13096 // Parent has not yet resolved, LTR is still the default
13098 if (!mParent.isLayoutDirectionResolved()) return false;
13100 if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
13101 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13103 } catch (AbstractMethodError e) {
13104 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13105 " does not fully implement ViewParent", e);
13108 case LAYOUT_DIRECTION_RTL:
13109 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13111 case LAYOUT_DIRECTION_LOCALE:
13112 if((LAYOUT_DIRECTION_RTL ==
13113 TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
13114 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13118 // Nothing to do, LTR by default
13123 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
13128 * Check if layout direction resolution can be done.
13130 * @return true if layout direction resolution can be done otherwise return false.
13132 public boolean canResolveLayoutDirection() {
13133 switch (getRawLayoutDirection()) {
13134 case LAYOUT_DIRECTION_INHERIT:
13135 if (mParent != null) {
13137 return mParent.canResolveLayoutDirection();
13138 } catch (AbstractMethodError e) {
13139 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13140 " does not fully implement ViewParent", e);
13151 * Reset the resolved layout direction. Layout direction will be resolved during a call to
13152 * {@link #onMeasure(int, int)}.
13156 public void resetResolvedLayoutDirection() {
13157 // Reset the current resolved bits
13158 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
13162 * @return true if the layout direction is inherited.
13166 public boolean isLayoutDirectionInherited() {
13167 return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
13171 * @return true if layout direction has been resolved.
13173 public boolean isLayoutDirectionResolved() {
13174 return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
13178 * Return if padding has been resolved
13182 boolean isPaddingResolved() {
13183 return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
13187 * Resolves padding depending on layout direction, if applicable, and
13188 * recomputes internal padding values to adjust for scroll bars.
13192 public void resolvePadding() {
13193 final int resolvedLayoutDirection = getLayoutDirection();
13195 if (!isRtlCompatibilityMode()) {
13196 // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
13197 // If start / end padding are defined, they will be resolved (hence overriding) to
13198 // left / right or right / left depending on the resolved layout direction.
13199 // If start / end padding are not defined, use the left / right ones.
13200 if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
13201 Rect padding = sThreadLocal.get();
13202 if (padding == null) {
13203 padding = new Rect();
13204 sThreadLocal.set(padding);
13206 mBackground.getPadding(padding);
13207 if (!mLeftPaddingDefined) {
13208 mUserPaddingLeftInitial = padding.left;
13210 if (!mRightPaddingDefined) {
13211 mUserPaddingRightInitial = padding.right;
13214 switch (resolvedLayoutDirection) {
13215 case LAYOUT_DIRECTION_RTL:
13216 if (mUserPaddingStart != UNDEFINED_PADDING) {
13217 mUserPaddingRight = mUserPaddingStart;
13219 mUserPaddingRight = mUserPaddingRightInitial;
13221 if (mUserPaddingEnd != UNDEFINED_PADDING) {
13222 mUserPaddingLeft = mUserPaddingEnd;
13224 mUserPaddingLeft = mUserPaddingLeftInitial;
13227 case LAYOUT_DIRECTION_LTR:
13229 if (mUserPaddingStart != UNDEFINED_PADDING) {
13230 mUserPaddingLeft = mUserPaddingStart;
13232 mUserPaddingLeft = mUserPaddingLeftInitial;
13234 if (mUserPaddingEnd != UNDEFINED_PADDING) {
13235 mUserPaddingRight = mUserPaddingEnd;
13237 mUserPaddingRight = mUserPaddingRightInitial;
13241 mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
13244 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
13245 onRtlPropertiesChanged(resolvedLayoutDirection);
13247 mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
13251 * Reset the resolved layout direction.
13255 public void resetResolvedPadding() {
13256 mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
13260 * This is called when the view is detached from a window. At this point it
13261 * no longer has a surface for drawing.
13263 * @see #onAttachedToWindow()
13265 protected void onDetachedFromWindow() {
13269 * This is a framework-internal mirror of onDetachedFromWindow() that's called
13270 * after onDetachedFromWindow().
13272 * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
13273 * The super method should be called at the end of the overriden method to ensure
13274 * subclasses are destroyed first
13278 protected void onDetachedFromWindowInternal() {
13279 mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
13280 mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
13282 removeUnsetPressCallback();
13283 removeLongPressCallback();
13284 removePerformClickCallback();
13285 removeSendViewScrolledAccessibilityEventCallback();
13286 stopNestedScroll();
13288 // Anything that started animating right before detach should already
13289 // be in its final state when re-attached.
13290 jumpDrawablesToCurrentState();
13292 destroyDrawingCache();
13295 mCurrentAnimation = null;
13298 private void cleanupDraw() {
13299 resetDisplayList();
13300 if (mAttachInfo != null) {
13301 mAttachInfo.mViewRootImpl.cancelInvalidate(this);
13305 void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
13309 * @return The number of times this view has been attached to a window
13311 protected int getWindowAttachCount() {
13312 return mWindowAttachCount;
13316 * Retrieve a unique token identifying the window this view is attached to.
13317 * @return Return the window's token for use in
13318 * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
13320 public IBinder getWindowToken() {
13321 return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
13325 * Retrieve the {@link WindowId} for the window this view is
13326 * currently attached to.
13328 public WindowId getWindowId() {
13329 if (mAttachInfo == null) {
13332 if (mAttachInfo.mWindowId == null) {
13334 mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
13335 mAttachInfo.mWindowToken);
13336 mAttachInfo.mWindowId = new WindowId(
13337 mAttachInfo.mIWindowId);
13338 } catch (RemoteException e) {
13341 return mAttachInfo.mWindowId;
13345 * Retrieve a unique token identifying the top-level "real" window of
13346 * the window that this view is attached to. That is, this is like
13347 * {@link #getWindowToken}, except if the window this view in is a panel
13348 * window (attached to another containing window), then the token of
13349 * the containing window is returned instead.
13351 * @return Returns the associated window token, either
13352 * {@link #getWindowToken()} or the containing window's token.
13354 public IBinder getApplicationWindowToken() {
13355 AttachInfo ai = mAttachInfo;
13357 IBinder appWindowToken = ai.mPanelParentWindowToken;
13358 if (appWindowToken == null) {
13359 appWindowToken = ai.mWindowToken;
13361 return appWindowToken;
13367 * Gets the logical display to which the view's window has been attached.
13369 * @return The logical display, or null if the view is not currently attached to a window.
13371 public Display getDisplay() {
13372 return mAttachInfo != null ? mAttachInfo.mDisplay : null;
13376 * Retrieve private session object this view hierarchy is using to
13377 * communicate with the window manager.
13378 * @return the session object to communicate with the window manager
13380 /*package*/ IWindowSession getWindowSession() {
13381 return mAttachInfo != null ? mAttachInfo.mSession : null;
13385 * @param info the {@link android.view.View.AttachInfo} to associated with
13388 void dispatchAttachedToWindow(AttachInfo info, int visibility) {
13389 //System.out.println("Attached! " + this);
13390 mAttachInfo = info;
13391 if (mOverlay != null) {
13392 mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
13394 mWindowAttachCount++;
13395 // We will need to evaluate the drawable state at least once.
13396 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
13397 if (mFloatingTreeObserver != null) {
13398 info.mTreeObserver.merge(mFloatingTreeObserver);
13399 mFloatingTreeObserver = null;
13401 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
13402 mAttachInfo.mScrollContainers.add(this);
13403 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
13405 performCollectViewAttributes(mAttachInfo, visibility);
13406 onAttachedToWindow();
13408 ListenerInfo li = mListenerInfo;
13409 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
13410 li != null ? li.mOnAttachStateChangeListeners : null;
13411 if (listeners != null && listeners.size() > 0) {
13412 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
13413 // perform the dispatching. The iterator is a safe guard against listeners that
13414 // could mutate the list by calling the various add/remove methods. This prevents
13415 // the array from being modified while we iterate it.
13416 for (OnAttachStateChangeListener listener : listeners) {
13417 listener.onViewAttachedToWindow(this);
13421 int vis = info.mWindowVisibility;
13423 onWindowVisibilityChanged(vis);
13425 if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
13426 // If nobody has evaluated the drawable state yet, then do it now.
13427 refreshDrawableState();
13429 needGlobalAttributesUpdate(false);
13432 void dispatchDetachedFromWindow() {
13433 AttachInfo info = mAttachInfo;
13434 if (info != null) {
13435 int vis = info.mWindowVisibility;
13437 onWindowVisibilityChanged(GONE);
13441 onDetachedFromWindow();
13442 onDetachedFromWindowInternal();
13444 ListenerInfo li = mListenerInfo;
13445 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
13446 li != null ? li.mOnAttachStateChangeListeners : null;
13447 if (listeners != null && listeners.size() > 0) {
13448 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
13449 // perform the dispatching. The iterator is a safe guard against listeners that
13450 // could mutate the list by calling the various add/remove methods. This prevents
13451 // the array from being modified while we iterate it.
13452 for (OnAttachStateChangeListener listener : listeners) {
13453 listener.onViewDetachedFromWindow(this);
13457 if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
13458 mAttachInfo.mScrollContainers.remove(this);
13459 mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
13462 mAttachInfo = null;
13463 if (mOverlay != null) {
13464 mOverlay.getOverlayView().dispatchDetachedFromWindow();
13469 * Cancel any deferred high-level input events that were previously posted to the event queue.
13471 * <p>Many views post high-level events such as click handlers to the event queue
13472 * to run deferred in order to preserve a desired user experience - clearing visible
13473 * pressed states before executing, etc. This method will abort any events of this nature
13474 * that are currently in flight.</p>
13476 * <p>Custom views that generate their own high-level deferred input events should override
13477 * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
13479 * <p>This will also cancel pending input events for any child views.</p>
13481 * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
13482 * This will not impact newer events posted after this call that may occur as a result of
13483 * lower-level input events still waiting in the queue. If you are trying to prevent
13484 * double-submitted events for the duration of some sort of asynchronous transaction
13485 * you should also take other steps to protect against unexpected double inputs e.g. calling
13486 * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
13487 * the transaction completes, tracking already submitted transaction IDs, etc.</p>
13489 public final void cancelPendingInputEvents() {
13490 dispatchCancelPendingInputEvents();
13494 * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
13495 * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
13497 void dispatchCancelPendingInputEvents() {
13498 mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
13499 onCancelPendingInputEvents();
13500 if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
13501 throw new SuperNotCalledException("View " + getClass().getSimpleName() +
13502 " did not call through to super.onCancelPendingInputEvents()");
13507 * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
13510 * <p>This method is responsible for removing any pending high-level input events that were
13511 * posted to the event queue to run later. Custom view classes that post their own deferred
13512 * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
13513 * {@link android.os.Handler} should override this method, call
13514 * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
13517 public void onCancelPendingInputEvents() {
13518 removePerformClickCallback();
13520 mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
13524 * Store this view hierarchy's frozen state into the given container.
13526 * @param container The SparseArray in which to save the view's state.
13528 * @see #restoreHierarchyState(android.util.SparseArray)
13529 * @see #dispatchSaveInstanceState(android.util.SparseArray)
13530 * @see #onSaveInstanceState()
13532 public void saveHierarchyState(SparseArray<Parcelable> container) {
13533 dispatchSaveInstanceState(container);
13537 * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
13538 * this view and its children. May be overridden to modify how freezing happens to a
13539 * view's children; for example, some views may want to not store state for their children.
13541 * @param container The SparseArray in which to save the view's state.
13543 * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13544 * @see #saveHierarchyState(android.util.SparseArray)
13545 * @see #onSaveInstanceState()
13547 protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
13548 if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
13549 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
13550 Parcelable state = onSaveInstanceState();
13551 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
13552 throw new IllegalStateException(
13553 "Derived class did not call super.onSaveInstanceState()");
13555 if (state != null) {
13556 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
13557 // + ": " + state);
13558 container.put(mID, state);
13564 * Hook allowing a view to generate a representation of its internal state
13565 * that can later be used to create a new instance with that same state.
13566 * This state should only contain information that is not persistent or can
13567 * not be reconstructed later. For example, you will never store your
13568 * current position on screen because that will be computed again when a
13569 * new instance of the view is placed in its view hierarchy.
13571 * Some examples of things you may store here: the current cursor position
13572 * in a text view (but usually not the text itself since that is stored in a
13573 * content provider or other persistent storage), the currently selected
13574 * item in a list view.
13576 * @return Returns a Parcelable object containing the view's current dynamic
13577 * state, or null if there is nothing interesting to save. The
13578 * default implementation returns null.
13579 * @see #onRestoreInstanceState(android.os.Parcelable)
13580 * @see #saveHierarchyState(android.util.SparseArray)
13581 * @see #dispatchSaveInstanceState(android.util.SparseArray)
13582 * @see #setSaveEnabled(boolean)
13584 protected Parcelable onSaveInstanceState() {
13585 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
13586 return BaseSavedState.EMPTY_STATE;
13590 * Restore this view hierarchy's frozen state from the given container.
13592 * @param container The SparseArray which holds previously frozen states.
13594 * @see #saveHierarchyState(android.util.SparseArray)
13595 * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13596 * @see #onRestoreInstanceState(android.os.Parcelable)
13598 public void restoreHierarchyState(SparseArray<Parcelable> container) {
13599 dispatchRestoreInstanceState(container);
13603 * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
13604 * state for this view and its children. May be overridden to modify how restoring
13605 * happens to a view's children; for example, some views may want to not store state
13606 * for their children.
13608 * @param container The SparseArray which holds previously saved state.
13610 * @see #dispatchSaveInstanceState(android.util.SparseArray)
13611 * @see #restoreHierarchyState(android.util.SparseArray)
13612 * @see #onRestoreInstanceState(android.os.Parcelable)
13614 protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
13615 if (mID != NO_ID) {
13616 Parcelable state = container.get(mID);
13617 if (state != null) {
13618 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
13619 // + ": " + state);
13620 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
13621 onRestoreInstanceState(state);
13622 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
13623 throw new IllegalStateException(
13624 "Derived class did not call super.onRestoreInstanceState()");
13631 * Hook allowing a view to re-apply a representation of its internal state that had previously
13632 * been generated by {@link #onSaveInstanceState}. This function will never be called with a
13635 * @param state The frozen state that had previously been returned by
13636 * {@link #onSaveInstanceState}.
13638 * @see #onSaveInstanceState()
13639 * @see #restoreHierarchyState(android.util.SparseArray)
13640 * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13642 protected void onRestoreInstanceState(Parcelable state) {
13643 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
13644 if (state != BaseSavedState.EMPTY_STATE && state != null) {
13645 throw new IllegalArgumentException("Wrong state class, expecting View State but "
13646 + "received " + state.getClass().toString() + " instead. This usually happens "
13647 + "when two views of different type have the same id in the same hierarchy. "
13648 + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
13649 + "other views do not use the same id.");
13654 * <p>Return the time at which the drawing of the view hierarchy started.</p>
13656 * @return the drawing start time in milliseconds
13658 public long getDrawingTime() {
13659 return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
13663 * <p>Enables or disables the duplication of the parent's state into this view. When
13664 * duplication is enabled, this view gets its drawable state from its parent rather
13665 * than from its own internal properties.</p>
13667 * <p>Note: in the current implementation, setting this property to true after the
13668 * view was added to a ViewGroup might have no effect at all. This property should
13669 * always be used from XML or set to true before adding this view to a ViewGroup.</p>
13671 * <p>Note: if this view's parent addStateFromChildren property is enabled and this
13672 * property is enabled, an exception will be thrown.</p>
13674 * <p>Note: if the child view uses and updates additionnal states which are unknown to the
13675 * parent, these states should not be affected by this method.</p>
13677 * @param enabled True to enable duplication of the parent's drawable state, false
13680 * @see #getDrawableState()
13681 * @see #isDuplicateParentStateEnabled()
13683 public void setDuplicateParentStateEnabled(boolean enabled) {
13684 setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
13688 * <p>Indicates whether this duplicates its drawable state from its parent.</p>
13690 * @return True if this view's drawable state is duplicated from the parent,
13693 * @see #getDrawableState()
13694 * @see #setDuplicateParentStateEnabled(boolean)
13696 public boolean isDuplicateParentStateEnabled() {
13697 return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
13701 * <p>Specifies the type of layer backing this view. The layer can be
13702 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
13703 * {@link #LAYER_TYPE_HARDWARE}.</p>
13705 * <p>A layer is associated with an optional {@link android.graphics.Paint}
13706 * instance that controls how the layer is composed on screen. The following
13707 * properties of the paint are taken into account when composing the layer:</p>
13709 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
13710 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
13711 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
13714 * <p>If this view has an alpha value set to < 1.0 by calling
13715 * {@link #setAlpha(float)}, the alpha value of the layer's paint is superceded
13716 * by this view's alpha value.</p>
13718 * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
13719 * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
13720 * for more information on when and how to use layers.</p>
13722 * @param layerType The type of layer to use with this view, must be one of
13723 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
13724 * {@link #LAYER_TYPE_HARDWARE}
13725 * @param paint The paint used to compose the layer. This argument is optional
13726 * and can be null. It is ignored when the layer type is
13727 * {@link #LAYER_TYPE_NONE}
13729 * @see #getLayerType()
13730 * @see #LAYER_TYPE_NONE
13731 * @see #LAYER_TYPE_SOFTWARE
13732 * @see #LAYER_TYPE_HARDWARE
13733 * @see #setAlpha(float)
13735 * @attr ref android.R.styleable#View_layerType
13737 public void setLayerType(int layerType, Paint paint) {
13738 if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
13739 throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
13740 + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
13743 boolean typeChanged = mRenderNode.setLayerType(layerType);
13745 if (!typeChanged) {
13746 setLayerPaint(paint);
13750 // Destroy any previous software drawing cache if needed
13751 if (mLayerType == LAYER_TYPE_SOFTWARE) {
13752 destroyDrawingCache();
13755 mLayerType = layerType;
13756 final boolean layerDisabled = (mLayerType == LAYER_TYPE_NONE);
13757 mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
13758 mRenderNode.setLayerPaint(mLayerPaint);
13760 // draw() behaves differently if we are on a layer, so we need to
13761 // invalidate() here
13762 invalidateParentCaches();
13767 * Updates the {@link Paint} object used with the current layer (used only if the current
13768 * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
13769 * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
13770 * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
13771 * ensure that the view gets redrawn immediately.
13773 * <p>A layer is associated with an optional {@link android.graphics.Paint}
13774 * instance that controls how the layer is composed on screen. The following
13775 * properties of the paint are taken into account when composing the layer:</p>
13777 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
13778 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
13779 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
13782 * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
13783 * alpha value of the layer's paint is superceded by this view's alpha value.</p>
13785 * @param paint The paint used to compose the layer. This argument is optional
13786 * and can be null. It is ignored when the layer type is
13787 * {@link #LAYER_TYPE_NONE}
13789 * @see #setLayerType(int, android.graphics.Paint)
13791 public void setLayerPaint(Paint paint) {
13792 int layerType = getLayerType();
13793 if (layerType != LAYER_TYPE_NONE) {
13794 mLayerPaint = paint == null ? new Paint() : paint;
13795 if (layerType == LAYER_TYPE_HARDWARE) {
13796 if (mRenderNode.setLayerPaint(mLayerPaint)) {
13797 invalidateViewProperty(false, false);
13806 * Indicates whether this view has a static layer. A view with layer type
13807 * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
13810 boolean hasStaticLayer() {
13815 * Indicates what type of layer is currently associated with this view. By default
13816 * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
13817 * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
13818 * for more information on the different types of layers.
13820 * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
13821 * {@link #LAYER_TYPE_HARDWARE}
13823 * @see #setLayerType(int, android.graphics.Paint)
13824 * @see #buildLayer()
13825 * @see #LAYER_TYPE_NONE
13826 * @see #LAYER_TYPE_SOFTWARE
13827 * @see #LAYER_TYPE_HARDWARE
13829 public int getLayerType() {
13834 * Forces this view's layer to be created and this view to be rendered
13835 * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
13836 * invoking this method will have no effect.
13838 * This method can for instance be used to render a view into its layer before
13839 * starting an animation. If this view is complex, rendering into the layer
13840 * before starting the animation will avoid skipping frames.
13842 * @throws IllegalStateException If this view is not attached to a window
13844 * @see #setLayerType(int, android.graphics.Paint)
13846 public void buildLayer() {
13847 if (mLayerType == LAYER_TYPE_NONE) return;
13849 final AttachInfo attachInfo = mAttachInfo;
13850 if (attachInfo == null) {
13851 throw new IllegalStateException("This view must be attached to a window first");
13854 if (getWidth() == 0 || getHeight() == 0) {
13858 switch (mLayerType) {
13859 case LAYER_TYPE_HARDWARE:
13860 updateDisplayListIfDirty();
13861 if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
13862 attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
13865 case LAYER_TYPE_SOFTWARE:
13866 buildDrawingCache(true);
13872 * If this View draws with a HardwareLayer, returns it.
13873 * Otherwise returns null
13875 * TODO: Only TextureView uses this, can we eliminate it?
13877 HardwareLayer getHardwareLayer() {
13882 * Destroys all hardware rendering resources. This method is invoked
13883 * when the system needs to reclaim resources. Upon execution of this
13884 * method, you should free any OpenGL resources created by the view.
13886 * Note: you <strong>must</strong> call
13887 * <code>super.destroyHardwareResources()</code> when overriding
13892 protected void destroyHardwareResources() {
13893 // Although the Layer will be destroyed by RenderNode, we want to release
13894 // the staging display list, which is also a signal to RenderNode that it's
13895 // safe to free its copy of the display list as it knows that we will
13896 // push an updated DisplayList if we try to draw again
13897 resetDisplayList();
13901 * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
13902 * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
13903 * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
13904 * the cache is enabled. To benefit from the cache, you must request the drawing cache by
13905 * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
13908 * <p>Enabling the drawing cache is similar to
13909 * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
13910 * acceleration is turned off. When hardware acceleration is turned on, enabling the
13911 * drawing cache has no effect on rendering because the system uses a different mechanism
13912 * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
13913 * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
13914 * for information on how to enable software and hardware layers.</p>
13916 * <p>This API can be used to manually generate
13917 * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
13918 * {@link #getDrawingCache()}.</p>
13920 * @param enabled true to enable the drawing cache, false otherwise
13922 * @see #isDrawingCacheEnabled()
13923 * @see #getDrawingCache()
13924 * @see #buildDrawingCache()
13925 * @see #setLayerType(int, android.graphics.Paint)
13927 public void setDrawingCacheEnabled(boolean enabled) {
13928 mCachingFailed = false;
13929 setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
13933 * <p>Indicates whether the drawing cache is enabled for this view.</p>
13935 * @return true if the drawing cache is enabled
13937 * @see #setDrawingCacheEnabled(boolean)
13938 * @see #getDrawingCache()
13940 @ViewDebug.ExportedProperty(category = "drawing")
13941 public boolean isDrawingCacheEnabled() {
13942 return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
13946 * Debugging utility which recursively outputs the dirty state of a view and its
13951 @SuppressWarnings({"UnusedDeclaration"})
13952 public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
13953 Log.d("View", indent + this + " DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
13954 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
13955 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
13956 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
13958 mPrivateFlags &= clearMask;
13960 if (this instanceof ViewGroup) {
13961 ViewGroup parent = (ViewGroup) this;
13962 final int count = parent.getChildCount();
13963 for (int i = 0; i < count; i++) {
13964 final View child = parent.getChildAt(i);
13965 child.outputDirtyFlags(indent + " ", clear, clearMask);
13971 * This method is used by ViewGroup to cause its children to restore or recreate their
13972 * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
13973 * to recreate its own display list, which would happen if it went through the normal
13974 * draw/dispatchDraw mechanisms.
13978 protected void dispatchGetDisplayList() {}
13981 * A view that is not attached or hardware accelerated cannot create a display list.
13982 * This method checks these conditions and returns the appropriate result.
13984 * @return true if view has the ability to create a display list, false otherwise.
13988 public boolean canHaveDisplayList() {
13989 return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
13992 private void updateDisplayListIfDirty() {
13993 final RenderNode renderNode = mRenderNode;
13994 if (!canHaveDisplayList()) {
13995 // can't populate RenderNode, don't try
13999 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
14000 || !renderNode.isValid()
14001 || (mRecreateDisplayList)) {
14002 // Don't need to recreate the display list, just need to tell our
14003 // children to restore/recreate theirs
14004 if (renderNode.isValid()
14005 && !mRecreateDisplayList) {
14006 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
14007 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14008 dispatchGetDisplayList();
14010 return; // no work needed
14013 // If we got here, we're recreating it. Mark it as such to ensure that
14014 // we copy in child display lists into ours in drawChild()
14015 mRecreateDisplayList = true;
14017 int width = mRight - mLeft;
14018 int height = mBottom - mTop;
14019 int layerType = getLayerType();
14021 final HardwareCanvas canvas = renderNode.start(width, height);
14022 canvas.setHighContrastText(mAttachInfo.mHighContrastText);
14025 final HardwareLayer layer = getHardwareLayer();
14026 if (layer != null && layer.isValid()) {
14027 canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
14028 } else if (layerType == LAYER_TYPE_SOFTWARE) {
14029 buildDrawingCache(true);
14030 Bitmap cache = getDrawingCache(true);
14031 if (cache != null) {
14032 canvas.drawBitmap(cache, 0, 0, mLayerPaint);
14037 canvas.translate(-mScrollX, -mScrollY);
14038 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
14039 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14041 // Fast path for layouts with no backgrounds
14042 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14043 dispatchDraw(canvas);
14044 if (mOverlay != null && !mOverlay.isEmpty()) {
14045 mOverlay.getOverlayView().draw(canvas);
14050 drawAccessibilityFocus(canvas);
14053 renderNode.end(canvas);
14054 setDisplayListProperties(renderNode);
14057 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
14058 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14063 * Returns a RenderNode with View draw content recorded, which can be
14064 * used to draw this view again without executing its draw method.
14066 * @return A RenderNode ready to replay, or null if caching is not enabled.
14070 public RenderNode getDisplayList() {
14071 updateDisplayListIfDirty();
14072 return mRenderNode;
14075 private void resetDisplayList() {
14076 if (mRenderNode.isValid()) {
14077 mRenderNode.destroyDisplayListData();
14080 if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
14081 mBackgroundRenderNode.destroyDisplayListData();
14086 * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
14088 * @return A non-scaled bitmap representing this view or null if cache is disabled.
14090 * @see #getDrawingCache(boolean)
14092 public Bitmap getDrawingCache() {
14093 return getDrawingCache(false);
14097 * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
14098 * is null when caching is disabled. If caching is enabled and the cache is not ready,
14099 * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
14100 * draw from the cache when the cache is enabled. To benefit from the cache, you must
14101 * request the drawing cache by calling this method and draw it on screen if the
14102 * returned bitmap is not null.</p>
14104 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
14105 * this method will create a bitmap of the same size as this view. Because this bitmap
14106 * will be drawn scaled by the parent ViewGroup, the result on screen might show
14107 * scaling artifacts. To avoid such artifacts, you should call this method by setting
14108 * the auto scaling to true. Doing so, however, will generate a bitmap of a different
14109 * size than the view. This implies that your application must be able to handle this
14112 * @param autoScale Indicates whether the generated bitmap should be scaled based on
14113 * the current density of the screen when the application is in compatibility
14116 * @return A bitmap representing this view or null if cache is disabled.
14118 * @see #setDrawingCacheEnabled(boolean)
14119 * @see #isDrawingCacheEnabled()
14120 * @see #buildDrawingCache(boolean)
14121 * @see #destroyDrawingCache()
14123 public Bitmap getDrawingCache(boolean autoScale) {
14124 if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
14127 if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
14128 buildDrawingCache(autoScale);
14130 return autoScale ? mDrawingCache : mUnscaledDrawingCache;
14134 * <p>Frees the resources used by the drawing cache. If you call
14135 * {@link #buildDrawingCache()} manually without calling
14136 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
14137 * should cleanup the cache with this method afterwards.</p>
14139 * @see #setDrawingCacheEnabled(boolean)
14140 * @see #buildDrawingCache()
14141 * @see #getDrawingCache()
14143 public void destroyDrawingCache() {
14144 if (mDrawingCache != null) {
14145 mDrawingCache.recycle();
14146 mDrawingCache = null;
14148 if (mUnscaledDrawingCache != null) {
14149 mUnscaledDrawingCache.recycle();
14150 mUnscaledDrawingCache = null;
14155 * Setting a solid background color for the drawing cache's bitmaps will improve
14156 * performance and memory usage. Note, though that this should only be used if this
14157 * view will always be drawn on top of a solid color.
14159 * @param color The background color to use for the drawing cache's bitmap
14161 * @see #setDrawingCacheEnabled(boolean)
14162 * @see #buildDrawingCache()
14163 * @see #getDrawingCache()
14165 public void setDrawingCacheBackgroundColor(int color) {
14166 if (color != mDrawingCacheBackgroundColor) {
14167 mDrawingCacheBackgroundColor = color;
14168 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
14173 * @see #setDrawingCacheBackgroundColor(int)
14175 * @return The background color to used for the drawing cache's bitmap
14177 public int getDrawingCacheBackgroundColor() {
14178 return mDrawingCacheBackgroundColor;
14182 * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
14184 * @see #buildDrawingCache(boolean)
14186 public void buildDrawingCache() {
14187 buildDrawingCache(false);
14191 * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
14193 * <p>If you call {@link #buildDrawingCache()} manually without calling
14194 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
14195 * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
14197 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
14198 * this method will create a bitmap of the same size as this view. Because this bitmap
14199 * will be drawn scaled by the parent ViewGroup, the result on screen might show
14200 * scaling artifacts. To avoid such artifacts, you should call this method by setting
14201 * the auto scaling to true. Doing so, however, will generate a bitmap of a different
14202 * size than the view. This implies that your application must be able to handle this
14205 * <p>You should avoid calling this method when hardware acceleration is enabled. If
14206 * you do not need the drawing cache bitmap, calling this method will increase memory
14207 * usage and cause the view to be rendered in software once, thus negatively impacting
14210 * @see #getDrawingCache()
14211 * @see #destroyDrawingCache()
14213 public void buildDrawingCache(boolean autoScale) {
14214 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
14215 mDrawingCache == null : mUnscaledDrawingCache == null)) {
14216 mCachingFailed = false;
14218 int width = mRight - mLeft;
14219 int height = mBottom - mTop;
14221 final AttachInfo attachInfo = mAttachInfo;
14222 final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
14224 if (autoScale && scalingRequired) {
14225 width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
14226 height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
14229 final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
14230 final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
14231 final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
14233 final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
14234 final long drawingCacheSize =
14235 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
14236 if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
14237 if (width > 0 && height > 0) {
14238 Log.w(VIEW_LOG_TAG, "View too large to fit into drawing cache, needs "
14239 + projectedBitmapSize + " bytes, only "
14240 + drawingCacheSize + " available");
14242 destroyDrawingCache();
14243 mCachingFailed = true;
14247 boolean clear = true;
14248 Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
14250 if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
14251 Bitmap.Config quality;
14253 // Never pick ARGB_4444 because it looks awful
14254 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
14255 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
14256 case DRAWING_CACHE_QUALITY_AUTO:
14257 case DRAWING_CACHE_QUALITY_LOW:
14258 case DRAWING_CACHE_QUALITY_HIGH:
14260 quality = Bitmap.Config.ARGB_8888;
14264 // Optimization for translucent windows
14265 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
14266 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
14269 // Try to cleanup memory
14270 if (bitmap != null) bitmap.recycle();
14273 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
14274 width, height, quality);
14275 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
14277 mDrawingCache = bitmap;
14279 mUnscaledDrawingCache = bitmap;
14281 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
14282 } catch (OutOfMemoryError e) {
14283 // If there is not enough memory to create the bitmap cache, just
14284 // ignore the issue as bitmap caches are not required to draw the
14287 mDrawingCache = null;
14289 mUnscaledDrawingCache = null;
14291 mCachingFailed = true;
14295 clear = drawingCacheBackgroundColor != 0;
14299 if (attachInfo != null) {
14300 canvas = attachInfo.mCanvas;
14301 if (canvas == null) {
14302 canvas = new Canvas();
14304 canvas.setBitmap(bitmap);
14305 // Temporarily clobber the cached Canvas in case one of our children
14306 // is also using a drawing cache. Without this, the children would
14307 // steal the canvas by attaching their own bitmap to it and bad, bad
14308 // thing would happen (invisible views, corrupted drawings, etc.)
14309 attachInfo.mCanvas = null;
14311 // This case should hopefully never or seldom happen
14312 canvas = new Canvas(bitmap);
14316 bitmap.eraseColor(drawingCacheBackgroundColor);
14320 final int restoreCount = canvas.save();
14322 if (autoScale && scalingRequired) {
14323 final float scale = attachInfo.mApplicationScale;
14324 canvas.scale(scale, scale);
14327 canvas.translate(-mScrollX, -mScrollY);
14329 mPrivateFlags |= PFLAG_DRAWN;
14330 if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
14331 mLayerType != LAYER_TYPE_NONE) {
14332 mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
14335 // Fast path for layouts with no backgrounds
14336 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14337 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14338 dispatchDraw(canvas);
14339 if (mOverlay != null && !mOverlay.isEmpty()) {
14340 mOverlay.getOverlayView().draw(canvas);
14345 drawAccessibilityFocus(canvas);
14347 canvas.restoreToCount(restoreCount);
14348 canvas.setBitmap(null);
14350 if (attachInfo != null) {
14351 // Restore the cached Canvas for our siblings
14352 attachInfo.mCanvas = canvas;
14358 * Create a snapshot of the view into a bitmap. We should probably make
14359 * some form of this public, but should think about the API.
14361 Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
14362 int width = mRight - mLeft;
14363 int height = mBottom - mTop;
14365 final AttachInfo attachInfo = mAttachInfo;
14366 final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
14367 width = (int) ((width * scale) + 0.5f);
14368 height = (int) ((height * scale) + 0.5f);
14370 Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
14371 width > 0 ? width : 1, height > 0 ? height : 1, quality);
14372 if (bitmap == null) {
14373 throw new OutOfMemoryError();
14376 Resources resources = getResources();
14377 if (resources != null) {
14378 bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
14382 if (attachInfo != null) {
14383 canvas = attachInfo.mCanvas;
14384 if (canvas == null) {
14385 canvas = new Canvas();
14387 canvas.setBitmap(bitmap);
14388 // Temporarily clobber the cached Canvas in case one of our children
14389 // is also using a drawing cache. Without this, the children would
14390 // steal the canvas by attaching their own bitmap to it and bad, bad
14391 // things would happen (invisible views, corrupted drawings, etc.)
14392 attachInfo.mCanvas = null;
14394 // This case should hopefully never or seldom happen
14395 canvas = new Canvas(bitmap);
14398 if ((backgroundColor & 0xff000000) != 0) {
14399 bitmap.eraseColor(backgroundColor);
14403 final int restoreCount = canvas.save();
14404 canvas.scale(scale, scale);
14405 canvas.translate(-mScrollX, -mScrollY);
14407 // Temporarily remove the dirty mask
14408 int flags = mPrivateFlags;
14409 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14411 // Fast path for layouts with no backgrounds
14412 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14413 dispatchDraw(canvas);
14414 if (mOverlay != null && !mOverlay.isEmpty()) {
14415 mOverlay.getOverlayView().draw(canvas);
14420 drawAccessibilityFocus(canvas);
14422 mPrivateFlags = flags;
14424 canvas.restoreToCount(restoreCount);
14425 canvas.setBitmap(null);
14427 if (attachInfo != null) {
14428 // Restore the cached Canvas for our siblings
14429 attachInfo.mCanvas = canvas;
14436 * Indicates whether this View is currently in edit mode. A View is usually
14437 * in edit mode when displayed within a developer tool. For instance, if
14438 * this View is being drawn by a visual user interface builder, this method
14439 * should return true.
14441 * Subclasses should check the return value of this method to provide
14442 * different behaviors if their normal behavior might interfere with the
14443 * host environment. For instance: the class spawns a thread in its
14444 * constructor, the drawing code relies on device-specific features, etc.
14446 * This method is usually checked in the drawing code of custom widgets.
14448 * @return True if this View is in edit mode, false otherwise.
14450 public boolean isInEditMode() {
14455 * If the View draws content inside its padding and enables fading edges,
14456 * it needs to support padding offsets. Padding offsets are added to the
14457 * fading edges to extend the length of the fade so that it covers pixels
14458 * drawn inside the padding.
14460 * Subclasses of this class should override this method if they need
14461 * to draw content inside the padding.
14463 * @return True if padding offset must be applied, false otherwise.
14465 * @see #getLeftPaddingOffset()
14466 * @see #getRightPaddingOffset()
14467 * @see #getTopPaddingOffset()
14468 * @see #getBottomPaddingOffset()
14472 protected boolean isPaddingOffsetRequired() {
14477 * Amount by which to extend the left fading region. Called only when
14478 * {@link #isPaddingOffsetRequired()} returns true.
14480 * @return The left padding offset in pixels.
14482 * @see #isPaddingOffsetRequired()
14486 protected int getLeftPaddingOffset() {
14491 * Amount by which to extend the right fading region. Called only when
14492 * {@link #isPaddingOffsetRequired()} returns true.
14494 * @return The right padding offset in pixels.
14496 * @see #isPaddingOffsetRequired()
14500 protected int getRightPaddingOffset() {
14505 * Amount by which to extend the top fading region. Called only when
14506 * {@link #isPaddingOffsetRequired()} returns true.
14508 * @return The top padding offset in pixels.
14510 * @see #isPaddingOffsetRequired()
14514 protected int getTopPaddingOffset() {
14519 * Amount by which to extend the bottom fading region. Called only when
14520 * {@link #isPaddingOffsetRequired()} returns true.
14522 * @return The bottom padding offset in pixels.
14524 * @see #isPaddingOffsetRequired()
14528 protected int getBottomPaddingOffset() {
14534 * @param offsetRequired
14536 protected int getFadeTop(boolean offsetRequired) {
14537 int top = mPaddingTop;
14538 if (offsetRequired) top += getTopPaddingOffset();
14544 * @param offsetRequired
14546 protected int getFadeHeight(boolean offsetRequired) {
14547 int padding = mPaddingTop;
14548 if (offsetRequired) padding += getTopPaddingOffset();
14549 return mBottom - mTop - mPaddingBottom - padding;
14553 * <p>Indicates whether this view is attached to a hardware accelerated
14554 * window or not.</p>
14556 * <p>Even if this method returns true, it does not mean that every call
14557 * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
14558 * accelerated {@link android.graphics.Canvas}. For instance, if this view
14559 * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
14560 * window is hardware accelerated,
14561 * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
14562 * return false, and this method will return true.</p>
14564 * @return True if the view is attached to a window and the window is
14565 * hardware accelerated; false in any other case.
14567 @ViewDebug.ExportedProperty(category = "drawing")
14568 public boolean isHardwareAccelerated() {
14569 return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
14573 * Sets a rectangular area on this view to which the view will be clipped
14574 * when it is drawn. Setting the value to null will remove the clip bounds
14575 * and the view will draw normally, using its full bounds.
14577 * @param clipBounds The rectangular area, in the local coordinates of
14578 * this view, to which future drawing operations will be clipped.
14580 public void setClipBounds(Rect clipBounds) {
14581 if (clipBounds != null) {
14582 if (clipBounds.equals(mClipBounds)) {
14585 if (mClipBounds == null) {
14587 mClipBounds = new Rect(clipBounds);
14589 invalidate(Math.min(mClipBounds.left, clipBounds.left),
14590 Math.min(mClipBounds.top, clipBounds.top),
14591 Math.max(mClipBounds.right, clipBounds.right),
14592 Math.max(mClipBounds.bottom, clipBounds.bottom));
14593 mClipBounds.set(clipBounds);
14596 if (mClipBounds != null) {
14598 mClipBounds = null;
14601 mRenderNode.setClipBounds(mClipBounds);
14605 * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
14607 * @return A copy of the current clip bounds if clip bounds are set,
14610 public Rect getClipBounds() {
14611 return (mClipBounds != null) ? new Rect(mClipBounds) : null;
14615 * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
14616 * case of an active Animation being run on the view.
14618 private boolean drawAnimation(ViewGroup parent, long drawingTime,
14619 Animation a, boolean scalingRequired) {
14620 Transformation invalidationTransform;
14621 final int flags = parent.mGroupFlags;
14622 final boolean initialized = a.isInitialized();
14623 if (!initialized) {
14624 a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
14625 a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
14626 if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
14627 onAnimationStart();
14630 final Transformation t = parent.getChildTransformation();
14631 boolean more = a.getTransformation(drawingTime, t, 1f);
14632 if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
14633 if (parent.mInvalidationTransformation == null) {
14634 parent.mInvalidationTransformation = new Transformation();
14636 invalidationTransform = parent.mInvalidationTransformation;
14637 a.getTransformation(drawingTime, invalidationTransform, 1f);
14639 invalidationTransform = t;
14643 if (!a.willChangeBounds()) {
14644 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
14645 ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
14646 parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
14647 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
14648 // The child need to draw an animation, potentially offscreen, so
14649 // make sure we do not cancel invalidate requests
14650 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
14651 parent.invalidate(mLeft, mTop, mRight, mBottom);
14654 if (parent.mInvalidateRegion == null) {
14655 parent.mInvalidateRegion = new RectF();
14657 final RectF region = parent.mInvalidateRegion;
14658 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
14659 invalidationTransform);
14661 // The child need to draw an animation, potentially offscreen, so
14662 // make sure we do not cancel invalidate requests
14663 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
14665 final int left = mLeft + (int) region.left;
14666 final int top = mTop + (int) region.top;
14667 parent.invalidate(left, top, left + (int) (region.width() + .5f),
14668 top + (int) (region.height() + .5f));
14675 * This method is called by getDisplayList() when a display list is recorded for a View.
14676 * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
14678 void setDisplayListProperties(RenderNode renderNode) {
14679 if (renderNode != null) {
14680 if ((mPrivateFlags3 & PFLAG3_OUTLINE_INVALID) != 0) {
14682 mPrivateFlags3 &= ~PFLAG3_OUTLINE_INVALID;
14684 renderNode.setHasOverlappingRendering(hasOverlappingRendering());
14685 if (mParent instanceof ViewGroup) {
14686 renderNode.setClipToBounds(
14687 (((ViewGroup) mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0);
14690 if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
14691 ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
14692 ViewGroup parentVG = (ViewGroup) mParent;
14693 final Transformation t = parentVG.getChildTransformation();
14694 if (parentVG.getChildStaticTransformation(this, t)) {
14695 final int transformType = t.getTransformationType();
14696 if (transformType != Transformation.TYPE_IDENTITY) {
14697 if ((transformType & Transformation.TYPE_ALPHA) != 0) {
14698 alpha = t.getAlpha();
14700 if ((transformType & Transformation.TYPE_MATRIX) != 0) {
14701 renderNode.setStaticMatrix(t.getMatrix());
14706 if (mTransformationInfo != null) {
14707 alpha *= getFinalAlpha();
14709 final int multipliedAlpha = (int) (255 * alpha);
14710 if (onSetAlpha(multipliedAlpha)) {
14714 renderNode.setAlpha(alpha);
14715 } else if (alpha < 1) {
14716 renderNode.setAlpha(alpha);
14722 * This method is called by ViewGroup.drawChild() to have each child view draw itself.
14723 * This draw() method is an implementation detail and is not intended to be overridden or
14724 * to be called from anywhere else other than ViewGroup.drawChild().
14726 boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
14727 boolean usingRenderNodeProperties = mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
14728 boolean more = false;
14729 final boolean childHasIdentityMatrix = hasIdentityMatrix();
14730 final int flags = parent.mGroupFlags;
14732 if ((flags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) == ViewGroup.FLAG_CLEAR_TRANSFORMATION) {
14733 parent.getChildTransformation().clear();
14734 parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
14737 Transformation transformToApply = null;
14738 boolean concatMatrix = false;
14740 boolean scalingRequired = false;
14742 int layerType = getLayerType();
14744 final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
14745 if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 ||
14746 (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) {
14748 // Auto-scaled apps are not hw-accelerated, no need to set scaling flag on DisplayList
14749 if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
14751 caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated;
14754 final Animation a = getAnimation();
14756 more = drawAnimation(parent, drawingTime, a, scalingRequired);
14757 concatMatrix = a.willChangeTransformationMatrix();
14758 if (concatMatrix) {
14759 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
14761 transformToApply = parent.getChildTransformation();
14763 if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
14764 // No longer animating: clear out old animation matrix
14765 mRenderNode.setAnimationMatrix(null);
14766 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
14768 if (!usingRenderNodeProperties &&
14769 (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
14770 final Transformation t = parent.getChildTransformation();
14771 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
14772 if (hasTransform) {
14773 final int transformType = t.getTransformationType();
14774 transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
14775 concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
14780 concatMatrix |= !childHasIdentityMatrix;
14782 // Sets the flag as early as possible to allow draw() implementations
14783 // to call invalidate() successfully when doing animations
14784 mPrivateFlags |= PFLAG_DRAWN;
14786 if (!concatMatrix &&
14787 (flags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
14788 ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
14789 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
14790 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
14791 mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
14794 mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
14796 if (hardwareAccelerated) {
14797 // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
14798 // retain the flag's value temporarily in the mRecreateDisplayList flag
14799 mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) == PFLAG_INVALIDATED;
14800 mPrivateFlags &= ~PFLAG_INVALIDATED;
14803 RenderNode renderNode = null;
14804 Bitmap cache = null;
14805 boolean hasDisplayList = false;
14807 if (!hardwareAccelerated) {
14808 if (layerType != LAYER_TYPE_NONE) {
14809 layerType = LAYER_TYPE_SOFTWARE;
14810 buildDrawingCache(true);
14812 cache = getDrawingCache(true);
14814 switch (layerType) {
14815 case LAYER_TYPE_SOFTWARE:
14816 if (usingRenderNodeProperties) {
14817 hasDisplayList = canHaveDisplayList();
14819 buildDrawingCache(true);
14820 cache = getDrawingCache(true);
14823 case LAYER_TYPE_HARDWARE:
14824 if (usingRenderNodeProperties) {
14825 hasDisplayList = canHaveDisplayList();
14828 case LAYER_TYPE_NONE:
14829 // Delay getting the display list until animation-driven alpha values are
14830 // set up and possibly passed on to the view
14831 hasDisplayList = canHaveDisplayList();
14836 usingRenderNodeProperties &= hasDisplayList;
14837 if (usingRenderNodeProperties) {
14838 renderNode = getDisplayList();
14839 if (!renderNode.isValid()) {
14840 // Uncommon, but possible. If a view is removed from the hierarchy during the call
14841 // to getDisplayList(), the display list will be marked invalid and we should not
14842 // try to use it again.
14844 hasDisplayList = false;
14845 usingRenderNodeProperties = false;
14851 if (!hasDisplayList) {
14857 final boolean hasNoCache = cache == null || hasDisplayList;
14858 final boolean offsetForScroll = cache == null && !hasDisplayList &&
14859 layerType != LAYER_TYPE_HARDWARE;
14861 int restoreTo = -1;
14862 if (!usingRenderNodeProperties || transformToApply != null) {
14863 restoreTo = canvas.save();
14865 if (offsetForScroll) {
14866 canvas.translate(mLeft - sx, mTop - sy);
14868 if (!usingRenderNodeProperties) {
14869 canvas.translate(mLeft, mTop);
14871 if (scalingRequired) {
14872 if (usingRenderNodeProperties) {
14873 // TODO: Might not need this if we put everything inside the DL
14874 restoreTo = canvas.save();
14876 // mAttachInfo cannot be null, otherwise scalingRequired == false
14877 final float scale = 1.0f / mAttachInfo.mApplicationScale;
14878 canvas.scale(scale, scale);
14882 float alpha = usingRenderNodeProperties ? 1 : (getAlpha() * getTransitionAlpha());
14883 if (transformToApply != null || alpha < 1 || !hasIdentityMatrix() ||
14884 (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
14885 if (transformToApply != null || !childHasIdentityMatrix) {
14889 if (offsetForScroll) {
14894 if (transformToApply != null) {
14895 if (concatMatrix) {
14896 if (usingRenderNodeProperties) {
14897 renderNode.setAnimationMatrix(transformToApply.getMatrix());
14899 // Undo the scroll translation, apply the transformation matrix,
14900 // then redo the scroll translate to get the correct result.
14901 canvas.translate(-transX, -transY);
14902 canvas.concat(transformToApply.getMatrix());
14903 canvas.translate(transX, transY);
14905 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
14908 float transformAlpha = transformToApply.getAlpha();
14909 if (transformAlpha < 1) {
14910 alpha *= transformAlpha;
14911 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
14915 if (!childHasIdentityMatrix && !usingRenderNodeProperties) {
14916 canvas.translate(-transX, -transY);
14917 canvas.concat(getMatrix());
14918 canvas.translate(transX, transY);
14922 // Deal with alpha if it is or used to be <1
14924 (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
14926 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
14928 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
14930 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
14932 final int multipliedAlpha = (int) (255 * alpha);
14933 if (!onSetAlpha(multipliedAlpha)) {
14934 int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
14935 if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 ||
14936 layerType != LAYER_TYPE_NONE) {
14937 layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
14939 if (usingRenderNodeProperties) {
14940 renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
14941 } else if (layerType == LAYER_TYPE_NONE) {
14942 final int scrollX = hasDisplayList ? 0 : sx;
14943 final int scrollY = hasDisplayList ? 0 : sy;
14944 canvas.saveLayerAlpha(scrollX, scrollY,
14945 scrollX + (mRight - mLeft), scrollY + (mBottom - mTop),
14946 multipliedAlpha, layerFlags);
14949 // Alpha is handled by the child directly, clobber the layer's alpha
14950 mPrivateFlags |= PFLAG_ALPHA_SET;
14954 } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
14956 mPrivateFlags &= ~PFLAG_ALPHA_SET;
14959 if (!usingRenderNodeProperties) {
14960 // apply clips directly, since RenderNode won't do it for this draw
14961 if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) == ViewGroup.FLAG_CLIP_CHILDREN
14962 && cache == null) {
14963 if (offsetForScroll) {
14964 canvas.clipRect(sx, sy, sx + (mRight - mLeft), sy + (mBottom - mTop));
14966 if (!scalingRequired || cache == null) {
14967 canvas.clipRect(0, 0, mRight - mLeft, mBottom - mTop);
14969 canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
14974 if (mClipBounds != null) {
14975 // clip bounds ignore scroll
14976 canvas.clipRect(mClipBounds);
14982 if (!usingRenderNodeProperties && hasDisplayList) {
14983 renderNode = getDisplayList();
14984 if (!renderNode.isValid()) {
14985 // Uncommon, but possible. If a view is removed from the hierarchy during the call
14986 // to getDisplayList(), the display list will be marked invalid and we should not
14987 // try to use it again.
14989 hasDisplayList = false;
14994 boolean layerRendered = false;
14995 if (layerType == LAYER_TYPE_HARDWARE && !usingRenderNodeProperties) {
14996 final HardwareLayer layer = getHardwareLayer();
14997 if (layer != null && layer.isValid()) {
14998 int restoreAlpha = mLayerPaint.getAlpha();
14999 mLayerPaint.setAlpha((int) (alpha * 255));
15000 ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint);
15001 mLayerPaint.setAlpha(restoreAlpha);
15002 layerRendered = true;
15004 final int scrollX = hasDisplayList ? 0 : sx;
15005 final int scrollY = hasDisplayList ? 0 : sy;
15006 canvas.saveLayer(scrollX, scrollY,
15007 scrollX + mRight - mLeft, scrollY + mBottom - mTop, mLayerPaint,
15008 Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
15012 if (!layerRendered) {
15013 if (!hasDisplayList) {
15014 // Fast path for layouts with no backgrounds
15015 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15016 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15017 dispatchDraw(canvas);
15018 if (mOverlay != null && !mOverlay.isEmpty()) {
15019 mOverlay.getOverlayView().draw(canvas);
15024 drawAccessibilityFocus(canvas);
15026 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15027 ((HardwareCanvas) canvas).drawRenderNode(renderNode, null, flags);
15030 } else if (cache != null) {
15031 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15033 int restoreAlpha = 0;
15035 if (layerType == LAYER_TYPE_NONE) {
15036 cachePaint = parent.mCachePaint;
15037 if (cachePaint == null) {
15038 cachePaint = new Paint();
15039 cachePaint.setDither(false);
15040 parent.mCachePaint = cachePaint;
15043 cachePaint = mLayerPaint;
15044 restoreAlpha = mLayerPaint.getAlpha();
15046 cachePaint.setAlpha((int) (alpha * 255));
15047 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
15048 cachePaint.setAlpha(restoreAlpha);
15051 if (restoreTo >= 0) {
15052 canvas.restoreToCount(restoreTo);
15055 if (a != null && !more) {
15056 if (!hardwareAccelerated && !a.getFillAfter()) {
15059 parent.finishAnimatingView(this, a);
15062 if (more && hardwareAccelerated) {
15063 if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
15064 // alpha animations should cause the child to recreate its display list
15069 mRecreateDisplayList = false;
15075 * Manually render this view (and all of its children) to the given Canvas.
15076 * The view must have already done a full layout before this function is
15077 * called. When implementing a view, implement
15078 * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
15079 * If you do need to override this method, call the superclass version.
15081 * @param canvas The Canvas to which the View is rendered.
15083 public void draw(Canvas canvas) {
15084 final int privateFlags = mPrivateFlags;
15085 final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
15086 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
15087 mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
15090 * Draw traversal performs several drawing steps which must be executed
15091 * in the appropriate order:
15093 * 1. Draw the background
15094 * 2. If necessary, save the canvas' layers to prepare for fading
15095 * 3. Draw view's content
15097 * 5. If necessary, draw the fading edges and restore layers
15098 * 6. Draw decorations (scrollbars for instance)
15101 // Step 1, draw the background, if needed
15104 if (!dirtyOpaque) {
15105 drawBackground(canvas);
15108 // skip step 2 & 5 if possible (common case)
15109 final int viewFlags = mViewFlags;
15110 boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
15111 boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
15112 if (!verticalEdges && !horizontalEdges) {
15113 // Step 3, draw the content
15114 if (!dirtyOpaque) onDraw(canvas);
15116 // Step 4, draw the children
15117 dispatchDraw(canvas);
15119 // Step 6, draw decorations (scrollbars)
15120 onDrawScrollBars(canvas);
15122 if (mOverlay != null && !mOverlay.isEmpty()) {
15123 mOverlay.getOverlayView().dispatchDraw(canvas);
15131 * Here we do the full fledged routine...
15132 * (this is an uncommon case where speed matters less,
15133 * this is why we repeat some of the tests that have been
15137 boolean drawTop = false;
15138 boolean drawBottom = false;
15139 boolean drawLeft = false;
15140 boolean drawRight = false;
15142 float topFadeStrength = 0.0f;
15143 float bottomFadeStrength = 0.0f;
15144 float leftFadeStrength = 0.0f;
15145 float rightFadeStrength = 0.0f;
15147 // Step 2, save the canvas' layers
15148 int paddingLeft = mPaddingLeft;
15150 final boolean offsetRequired = isPaddingOffsetRequired();
15151 if (offsetRequired) {
15152 paddingLeft += getLeftPaddingOffset();
15155 int left = mScrollX + paddingLeft;
15156 int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
15157 int top = mScrollY + getFadeTop(offsetRequired);
15158 int bottom = top + getFadeHeight(offsetRequired);
15160 if (offsetRequired) {
15161 right += getRightPaddingOffset();
15162 bottom += getBottomPaddingOffset();
15165 final ScrollabilityCache scrollabilityCache = mScrollCache;
15166 final float fadeHeight = scrollabilityCache.fadingEdgeLength;
15167 int length = (int) fadeHeight;
15169 // clip the fade length if top and bottom fades overlap
15170 // overlapping fades produce odd-looking artifacts
15171 if (verticalEdges && (top + length > bottom - length)) {
15172 length = (bottom - top) / 2;
15175 // also clip horizontal fades if necessary
15176 if (horizontalEdges && (left + length > right - length)) {
15177 length = (right - left) / 2;
15180 if (verticalEdges) {
15181 topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
15182 drawTop = topFadeStrength * fadeHeight > 1.0f;
15183 bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
15184 drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
15187 if (horizontalEdges) {
15188 leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
15189 drawLeft = leftFadeStrength * fadeHeight > 1.0f;
15190 rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
15191 drawRight = rightFadeStrength * fadeHeight > 1.0f;
15194 saveCount = canvas.getSaveCount();
15196 int solidColor = getSolidColor();
15197 if (solidColor == 0) {
15198 final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
15201 canvas.saveLayer(left, top, right, top + length, null, flags);
15205 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
15209 canvas.saveLayer(left, top, left + length, bottom, null, flags);
15213 canvas.saveLayer(right - length, top, right, bottom, null, flags);
15216 scrollabilityCache.setFadeColor(solidColor);
15219 // Step 3, draw the content
15220 if (!dirtyOpaque) onDraw(canvas);
15222 // Step 4, draw the children
15223 dispatchDraw(canvas);
15225 // Step 5, draw the fade effect and restore layers
15226 final Paint p = scrollabilityCache.paint;
15227 final Matrix matrix = scrollabilityCache.matrix;
15228 final Shader fade = scrollabilityCache.shader;
15231 matrix.setScale(1, fadeHeight * topFadeStrength);
15232 matrix.postTranslate(left, top);
15233 fade.setLocalMatrix(matrix);
15235 canvas.drawRect(left, top, right, top + length, p);
15239 matrix.setScale(1, fadeHeight * bottomFadeStrength);
15240 matrix.postRotate(180);
15241 matrix.postTranslate(left, bottom);
15242 fade.setLocalMatrix(matrix);
15244 canvas.drawRect(left, bottom - length, right, bottom, p);
15248 matrix.setScale(1, fadeHeight * leftFadeStrength);
15249 matrix.postRotate(-90);
15250 matrix.postTranslate(left, top);
15251 fade.setLocalMatrix(matrix);
15253 canvas.drawRect(left, top, left + length, bottom, p);
15257 matrix.setScale(1, fadeHeight * rightFadeStrength);
15258 matrix.postRotate(90);
15259 matrix.postTranslate(right, top);
15260 fade.setLocalMatrix(matrix);
15262 canvas.drawRect(right - length, top, right, bottom, p);
15265 canvas.restoreToCount(saveCount);
15267 // Step 6, draw decorations (scrollbars)
15268 onDrawScrollBars(canvas);
15270 if (mOverlay != null && !mOverlay.isEmpty()) {
15271 mOverlay.getOverlayView().dispatchDraw(canvas);
15276 * Draws the accessibility focus rect onto the specified canvas.
15278 * @param canvas Canvas on which to draw the focus rect
15280 private void drawAccessibilityFocus(Canvas canvas) {
15281 if (mAttachInfo == null) {
15285 final Rect bounds = mAttachInfo.mTmpInvalRect;
15286 final ViewRootImpl viewRoot = getViewRootImpl();
15287 if (viewRoot == null || viewRoot.getAccessibilityFocusedHost() != this) {
15291 final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
15292 if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
15296 final Drawable drawable = viewRoot.getAccessibilityFocusedDrawable();
15297 if (drawable == null) {
15301 final AccessibilityNodeInfo virtualView = viewRoot.getAccessibilityFocusedVirtualView();
15302 if (virtualView != null) {
15303 virtualView.getBoundsInScreen(bounds);
15304 final int[] offset = mAttachInfo.mTmpLocation;
15305 getLocationOnScreen(offset);
15306 bounds.offset(-offset[0], -offset[1]);
15308 bounds.set(0, 0, mRight - mLeft, mBottom - mTop);
15312 canvas.translate(mScrollX, mScrollY);
15313 canvas.clipRect(bounds, Region.Op.REPLACE);
15314 drawable.setBounds(bounds);
15315 drawable.draw(canvas);
15320 * Draws the background onto the specified canvas.
15322 * @param canvas Canvas on which to draw the background
15324 private void drawBackground(Canvas canvas) {
15325 final Drawable background = mBackground;
15326 if (background == null) {
15330 if (mBackgroundSizeChanged) {
15331 background.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
15332 mBackgroundSizeChanged = false;
15333 mPrivateFlags3 |= PFLAG3_OUTLINE_INVALID;
15336 // Attempt to use a display list if requested.
15337 if (canvas.isHardwareAccelerated() && mAttachInfo != null
15338 && mAttachInfo.mHardwareRenderer != null) {
15339 mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
15341 final RenderNode displayList = mBackgroundRenderNode;
15342 if (displayList != null && displayList.isValid()) {
15343 setBackgroundDisplayListProperties(displayList);
15344 ((HardwareCanvas) canvas).drawRenderNode(displayList);
15349 final int scrollX = mScrollX;
15350 final int scrollY = mScrollY;
15351 if ((scrollX | scrollY) == 0) {
15352 background.draw(canvas);
15354 canvas.translate(scrollX, scrollY);
15355 background.draw(canvas);
15356 canvas.translate(-scrollX, -scrollY);
15361 * Set up background drawable display list properties.
15363 * @param displayList Valid display list for the background drawable
15365 private void setBackgroundDisplayListProperties(RenderNode displayList) {
15366 displayList.setTranslationX(mScrollX);
15367 displayList.setTranslationY(mScrollY);
15371 * Creates a new display list or updates the existing display list for the
15372 * specified Drawable.
15374 * @param drawable Drawable for which to create a display list
15375 * @param renderNode Existing RenderNode, or {@code null}
15376 * @return A valid display list for the specified drawable
15378 private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
15379 if (renderNode == null) {
15380 renderNode = RenderNode.create(drawable.getClass().getName(), this);
15383 final Rect bounds = drawable.getBounds();
15384 final int width = bounds.width();
15385 final int height = bounds.height();
15386 final HardwareCanvas canvas = renderNode.start(width, height);
15388 drawable.draw(canvas);
15390 renderNode.end(canvas);
15393 // Set up drawable properties that are view-independent.
15394 renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
15395 renderNode.setProjectBackwards(drawable.isProjected());
15396 renderNode.setProjectionReceiver(true);
15397 renderNode.setClipToBounds(false);
15402 * Returns the overlay for this view, creating it if it does not yet exist.
15403 * Adding drawables to the overlay will cause them to be displayed whenever
15404 * the view itself is redrawn. Objects in the overlay should be actively
15405 * managed: remove them when they should not be displayed anymore. The
15406 * overlay will always have the same size as its host view.
15408 * <p>Note: Overlays do not currently work correctly with {@link
15409 * SurfaceView} or {@link TextureView}; contents in overlays for these
15410 * types of views may not display correctly.</p>
15412 * @return The ViewOverlay object for this view.
15415 public ViewOverlay getOverlay() {
15416 if (mOverlay == null) {
15417 mOverlay = new ViewOverlay(mContext, this);
15423 * Override this if your view is known to always be drawn on top of a solid color background,
15424 * and needs to draw fading edges. Returning a non-zero color enables the view system to
15425 * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
15426 * should be set to 0xFF.
15428 * @see #setVerticalFadingEdgeEnabled(boolean)
15429 * @see #setHorizontalFadingEdgeEnabled(boolean)
15431 * @return The known solid color background for this view, or 0 if the color may vary
15433 @ViewDebug.ExportedProperty(category = "drawing")
15434 public int getSolidColor() {
15439 * Build a human readable string representation of the specified view flags.
15441 * @param flags the view flags to convert to a string
15442 * @return a String representing the supplied flags
15444 private static String printFlags(int flags) {
15445 String output = "";
15447 if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
15448 output += "TAKES_FOCUS";
15452 switch (flags & VISIBILITY_MASK) {
15454 if (numFlags > 0) {
15457 output += "INVISIBLE";
15458 // USELESS HERE numFlags++;
15461 if (numFlags > 0) {
15465 // USELESS HERE numFlags++;
15474 * Build a human readable string representation of the specified private
15477 * @param privateFlags the private view flags to convert to a string
15478 * @return a String representing the supplied flags
15480 private static String printPrivateFlags(int privateFlags) {
15481 String output = "";
15484 if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
15485 output += "WANTS_FOCUS";
15489 if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
15490 if (numFlags > 0) {
15493 output += "FOCUSED";
15497 if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
15498 if (numFlags > 0) {
15501 output += "SELECTED";
15505 if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
15506 if (numFlags > 0) {
15509 output += "IS_ROOT_NAMESPACE";
15513 if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
15514 if (numFlags > 0) {
15517 output += "HAS_BOUNDS";
15521 if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
15522 if (numFlags > 0) {
15526 // USELESS HERE numFlags++;
15532 * <p>Indicates whether or not this view's layout will be requested during
15533 * the next hierarchy layout pass.</p>
15535 * @return true if the layout will be forced during next layout pass
15537 public boolean isLayoutRequested() {
15538 return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
15542 * Return true if o is a ViewGroup that is laying out using optical bounds.
15545 public static boolean isLayoutModeOptical(Object o) {
15546 return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
15549 private boolean setOpticalFrame(int left, int top, int right, int bottom) {
15550 Insets parentInsets = mParent instanceof View ?
15551 ((View) mParent).getOpticalInsets() : Insets.NONE;
15552 Insets childInsets = getOpticalInsets();
15554 left + parentInsets.left - childInsets.left,
15555 top + parentInsets.top - childInsets.top,
15556 right + parentInsets.left + childInsets.right,
15557 bottom + parentInsets.top + childInsets.bottom);
15561 * Assign a size and position to a view and all of its
15564 * <p>This is the second phase of the layout mechanism.
15565 * (The first is measuring). In this phase, each parent calls
15566 * layout on all of its children to position them.
15567 * This is typically done using the child measurements
15568 * that were stored in the measure pass().</p>
15570 * <p>Derived classes should not override this method.
15571 * Derived classes with children should override
15572 * onLayout. In that method, they should
15573 * call layout on each of their children.</p>
15575 * @param l Left position, relative to parent
15576 * @param t Top position, relative to parent
15577 * @param r Right position, relative to parent
15578 * @param b Bottom position, relative to parent
15580 @SuppressWarnings({"unchecked"})
15581 public void layout(int l, int t, int r, int b) {
15582 if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
15583 onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
15584 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
15589 int oldB = mBottom;
15592 boolean changed = isLayoutModeOptical(mParent) ?
15593 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
15595 if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
15596 onLayout(changed, l, t, r, b);
15597 mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
15599 ListenerInfo li = mListenerInfo;
15600 if (li != null && li.mOnLayoutChangeListeners != null) {
15601 ArrayList<OnLayoutChangeListener> listenersCopy =
15602 (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
15603 int numListeners = listenersCopy.size();
15604 for (int i = 0; i < numListeners; ++i) {
15605 listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
15610 mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
15611 mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
15615 * Called from layout when this view should
15616 * assign a size and position to each of its children.
15618 * Derived classes with children should override
15619 * this method and call layout on each of
15621 * @param changed This is a new size or position for this view
15622 * @param left Left position, relative to parent
15623 * @param top Top position, relative to parent
15624 * @param right Right position, relative to parent
15625 * @param bottom Bottom position, relative to parent
15627 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
15631 * Assign a size and position to this view.
15633 * This is called from layout.
15635 * @param left Left position, relative to parent
15636 * @param top Top position, relative to parent
15637 * @param right Right position, relative to parent
15638 * @param bottom Bottom position, relative to parent
15639 * @return true if the new size and position are different than the
15643 protected boolean setFrame(int left, int top, int right, int bottom) {
15644 boolean changed = false;
15647 Log.d("View", this + " View.setFrame(" + left + "," + top + ","
15648 + right + "," + bottom + ")");
15651 if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
15654 // Remember our drawn bit
15655 int drawn = mPrivateFlags & PFLAG_DRAWN;
15657 int oldWidth = mRight - mLeft;
15658 int oldHeight = mBottom - mTop;
15659 int newWidth = right - left;
15660 int newHeight = bottom - top;
15661 boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
15663 // Invalidate our old position
15664 invalidate(sizeChanged);
15670 mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
15672 mPrivateFlags |= PFLAG_HAS_BOUNDS;
15676 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
15679 if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
15680 // If we are visible, force the DRAWN bit to on so that
15681 // this invalidate will go through (at least to our parent).
15682 // This is because someone may have invalidated this view
15683 // before this call to setFrame came in, thereby clearing
15685 mPrivateFlags |= PFLAG_DRAWN;
15686 invalidate(sizeChanged);
15687 // parent display list may need to be recreated based on a change in the bounds
15689 invalidateParentCaches();
15692 // Reset drawn bit to original value (invalidate turns it off)
15693 mPrivateFlags |= drawn;
15695 mBackgroundSizeChanged = true;
15697 notifySubtreeAccessibilityStateChangedIfNeeded();
15703 * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
15706 public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
15707 setFrame(left, top, right, bottom);
15710 private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
15711 onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
15712 if (mOverlay != null) {
15713 mOverlay.getOverlayView().setRight(newWidth);
15714 mOverlay.getOverlayView().setBottom(newHeight);
15716 mPrivateFlags3 |= PFLAG3_OUTLINE_INVALID;
15720 * Finalize inflating a view from XML. This is called as the last phase
15721 * of inflation, after all child views have been added.
15723 * <p>Even if the subclass overrides onFinishInflate, they should always be
15724 * sure to call the super method, so that we get called.
15726 protected void onFinishInflate() {
15730 * Returns the resources associated with this view.
15732 * @return Resources object.
15734 public Resources getResources() {
15739 * Invalidates the specified Drawable.
15741 * @param drawable the drawable to invalidate
15744 public void invalidateDrawable(@NonNull Drawable drawable) {
15745 if (verifyDrawable(drawable)) {
15746 final Rect dirty = drawable.getDirtyBounds();
15747 final int scrollX = mScrollX;
15748 final int scrollY = mScrollY;
15750 invalidate(dirty.left + scrollX, dirty.top + scrollY,
15751 dirty.right + scrollX, dirty.bottom + scrollY);
15753 mPrivateFlags3 |= PFLAG3_OUTLINE_INVALID;
15758 * Schedules an action on a drawable to occur at a specified time.
15760 * @param who the recipient of the action
15761 * @param what the action to run on the drawable
15762 * @param when the time at which the action must occur. Uses the
15763 * {@link SystemClock#uptimeMillis} timebase.
15766 public void scheduleDrawable(Drawable who, Runnable what, long when) {
15767 if (verifyDrawable(who) && what != null) {
15768 final long delay = when - SystemClock.uptimeMillis();
15769 if (mAttachInfo != null) {
15770 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
15771 Choreographer.CALLBACK_ANIMATION, what, who,
15772 Choreographer.subtractFrameDelay(delay));
15774 ViewRootImpl.getRunQueue().postDelayed(what, delay);
15780 * Cancels a scheduled action on a drawable.
15782 * @param who the recipient of the action
15783 * @param what the action to cancel
15786 public void unscheduleDrawable(Drawable who, Runnable what) {
15787 if (verifyDrawable(who) && what != null) {
15788 if (mAttachInfo != null) {
15789 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15790 Choreographer.CALLBACK_ANIMATION, what, who);
15792 ViewRootImpl.getRunQueue().removeCallbacks(what);
15797 * Unschedule any events associated with the given Drawable. This can be
15798 * used when selecting a new Drawable into a view, so that the previous
15799 * one is completely unscheduled.
15801 * @param who The Drawable to unschedule.
15803 * @see #drawableStateChanged
15805 public void unscheduleDrawable(Drawable who) {
15806 if (mAttachInfo != null && who != null) {
15807 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15808 Choreographer.CALLBACK_ANIMATION, null, who);
15813 * Resolve the Drawables depending on the layout direction. This is implicitly supposing
15814 * that the View directionality can and will be resolved before its Drawables.
15816 * Will call {@link View#onResolveDrawables} when resolution is done.
15820 protected void resolveDrawables() {
15821 // Drawables resolution may need to happen before resolving the layout direction (which is
15822 // done only during the measure() call).
15823 // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
15824 // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
15825 // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
15826 // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
15827 // direction to be resolved as its resolved value will be the same as its raw value.
15828 if (!isLayoutDirectionResolved() &&
15829 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
15833 final int layoutDirection = isLayoutDirectionResolved() ?
15834 getLayoutDirection() : getRawLayoutDirection();
15836 if (mBackground != null) {
15837 mBackground.setLayoutDirection(layoutDirection);
15839 mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
15840 onResolveDrawables(layoutDirection);
15844 * Called when layout direction has been resolved.
15846 * The default implementation does nothing.
15848 * @param layoutDirection The resolved layout direction.
15850 * @see #LAYOUT_DIRECTION_LTR
15851 * @see #LAYOUT_DIRECTION_RTL
15855 public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
15861 protected void resetResolvedDrawables() {
15862 mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
15865 private boolean isDrawablesResolved() {
15866 return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
15870 * If your view subclass is displaying its own Drawable objects, it should
15871 * override this function and return true for any Drawable it is
15872 * displaying. This allows animations for those drawables to be
15875 * <p>Be sure to call through to the super class when overriding this
15878 * @param who The Drawable to verify. Return true if it is one you are
15879 * displaying, else return the result of calling through to the
15882 * @return boolean If true than the Drawable is being displayed in the
15883 * view; else false and it is not allowed to animate.
15885 * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
15886 * @see #drawableStateChanged()
15888 protected boolean verifyDrawable(Drawable who) {
15889 return who == mBackground;
15893 * This function is called whenever the state of the view changes in such
15894 * a way that it impacts the state of drawables being shown.
15896 * If the View has a StateListAnimator, it will also be called to run necessary state
15897 * change animations.
15899 * Be sure to call through to the superclass when overriding this function.
15901 * @see Drawable#setState(int[])
15903 protected void drawableStateChanged() {
15904 final Drawable d = mBackground;
15905 if (d != null && d.isStateful()) {
15906 d.setState(getDrawableState());
15909 if (mStateListAnimator != null) {
15910 mStateListAnimator.setState(getDrawableState());
15915 * This function is called whenever the view hotspot changes and needs to
15916 * be propagated to drawables managed by the view.
15918 * Be sure to call through to the superclass when overriding this function.
15920 * @param x hotspot x coordinate
15921 * @param y hotspot y coordinate
15923 public void drawableHotspotChanged(float x, float y) {
15924 if (mBackground != null) {
15925 mBackground.setHotspot(x, y);
15930 * Call this to force a view to update its drawable state. This will cause
15931 * drawableStateChanged to be called on this view. Views that are interested
15932 * in the new state should call getDrawableState.
15934 * @see #drawableStateChanged
15935 * @see #getDrawableState
15937 public void refreshDrawableState() {
15938 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
15939 drawableStateChanged();
15941 ViewParent parent = mParent;
15942 if (parent != null) {
15943 parent.childDrawableStateChanged(this);
15948 * Return an array of resource IDs of the drawable states representing the
15949 * current state of the view.
15951 * @return The current drawable state
15953 * @see Drawable#setState(int[])
15954 * @see #drawableStateChanged()
15955 * @see #onCreateDrawableState(int)
15957 public final int[] getDrawableState() {
15958 if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
15959 return mDrawableState;
15961 mDrawableState = onCreateDrawableState(0);
15962 mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
15963 return mDrawableState;
15968 * Generate the new {@link android.graphics.drawable.Drawable} state for
15969 * this view. This is called by the view
15970 * system when the cached Drawable state is determined to be invalid. To
15971 * retrieve the current state, you should use {@link #getDrawableState}.
15973 * @param extraSpace if non-zero, this is the number of extra entries you
15974 * would like in the returned array in which you can place your own
15977 * @return Returns an array holding the current {@link Drawable} state of
15980 * @see #mergeDrawableStates(int[], int[])
15982 protected int[] onCreateDrawableState(int extraSpace) {
15983 if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
15984 mParent instanceof View) {
15985 return ((View) mParent).onCreateDrawableState(extraSpace);
15988 int[] drawableState;
15990 int privateFlags = mPrivateFlags;
15992 int viewStateIndex = 0;
15993 if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
15994 if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED;
15995 if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED;
15996 if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
15997 if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED;
15998 if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
15999 if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
16000 HardwareRenderer.isAvailable()) {
16001 // This is set if HW acceleration is requested, even if the current
16002 // process doesn't allow it. This is just to allow app preview
16003 // windows to better match their app.
16004 viewStateIndex |= VIEW_STATE_ACCELERATED;
16006 if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
16008 final int privateFlags2 = mPrivateFlags2;
16009 if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
16010 if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
16012 drawableState = VIEW_STATE_SETS[viewStateIndex];
16014 //noinspection ConstantIfStatement
16016 Log.i("View", "drawableStateIndex=" + viewStateIndex);
16017 Log.i("View", toString()
16018 + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
16019 + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
16020 + " fo=" + hasFocus()
16021 + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
16022 + " wf=" + hasWindowFocus()
16023 + ": " + Arrays.toString(drawableState));
16026 if (extraSpace == 0) {
16027 return drawableState;
16030 final int[] fullState;
16031 if (drawableState != null) {
16032 fullState = new int[drawableState.length + extraSpace];
16033 System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
16035 fullState = new int[extraSpace];
16042 * Merge your own state values in <var>additionalState</var> into the base
16043 * state values <var>baseState</var> that were returned by
16044 * {@link #onCreateDrawableState(int)}.
16046 * @param baseState The base state values returned by
16047 * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
16048 * own additional state values.
16050 * @param additionalState The additional state values you would like
16051 * added to <var>baseState</var>; this array is not modified.
16053 * @return As a convenience, the <var>baseState</var> array you originally
16054 * passed into the function is returned.
16056 * @see #onCreateDrawableState(int)
16058 protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
16059 final int N = baseState.length;
16061 while (i >= 0 && baseState[i] == 0) {
16064 System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
16069 * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
16070 * on all Drawable objects associated with this view.
16072 * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
16073 * attached to this view.
16075 public void jumpDrawablesToCurrentState() {
16076 if (mBackground != null) {
16077 mBackground.jumpToCurrentState();
16079 if (mStateListAnimator != null) {
16080 mStateListAnimator.jumpToCurrentState();
16085 * Sets the background color for this view.
16086 * @param color the color of the background
16088 @RemotableViewMethod
16089 public void setBackgroundColor(int color) {
16090 if (mBackground instanceof ColorDrawable) {
16091 ((ColorDrawable) mBackground.mutate()).setColor(color);
16092 computeOpaqueFlags();
16093 mBackgroundResource = 0;
16095 setBackground(new ColorDrawable(color));
16100 * Set the background to a given resource. The resource should refer to
16101 * a Drawable object or 0 to remove the background.
16102 * @param resid The identifier of the resource.
16104 * @attr ref android.R.styleable#View_background
16106 @RemotableViewMethod
16107 public void setBackgroundResource(int resid) {
16108 if (resid != 0 && resid == mBackgroundResource) {
16114 d = mContext.getDrawable(resid);
16118 mBackgroundResource = resid;
16122 * Set the background to a given Drawable, or remove the background. If the
16123 * background has padding, this View's padding is set to the background's
16124 * padding. However, when a background is removed, this View's padding isn't
16125 * touched. If setting the padding is desired, please use
16126 * {@link #setPadding(int, int, int, int)}.
16128 * @param background The Drawable to use as the background, or null to remove the
16131 public void setBackground(Drawable background) {
16132 //noinspection deprecation
16133 setBackgroundDrawable(background);
16137 * @deprecated use {@link #setBackground(Drawable)} instead
16140 public void setBackgroundDrawable(Drawable background) {
16141 computeOpaqueFlags();
16143 if (background == mBackground) {
16147 boolean requestLayout = false;
16149 mBackgroundResource = 0;
16152 * Regardless of whether we're setting a new background or not, we want
16153 * to clear the previous drawable.
16155 if (mBackground != null) {
16156 mBackground.setCallback(null);
16157 unscheduleDrawable(mBackground);
16160 if (background != null) {
16161 Rect padding = sThreadLocal.get();
16162 if (padding == null) {
16163 padding = new Rect();
16164 sThreadLocal.set(padding);
16166 resetResolvedDrawables();
16167 background.setLayoutDirection(getLayoutDirection());
16168 if (background.getPadding(padding)) {
16169 resetResolvedPadding();
16170 switch (background.getLayoutDirection()) {
16171 case LAYOUT_DIRECTION_RTL:
16172 mUserPaddingLeftInitial = padding.right;
16173 mUserPaddingRightInitial = padding.left;
16174 internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
16176 case LAYOUT_DIRECTION_LTR:
16178 mUserPaddingLeftInitial = padding.left;
16179 mUserPaddingRightInitial = padding.right;
16180 internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
16182 mLeftPaddingDefined = false;
16183 mRightPaddingDefined = false;
16186 // Compare the minimum sizes of the old Drawable and the new. If there isn't an old or
16187 // if it has a different minimum size, we should layout again
16188 if (mBackground == null
16189 || mBackground.getMinimumHeight() != background.getMinimumHeight()
16190 || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
16191 requestLayout = true;
16194 background.setCallback(this);
16195 if (background.isStateful()) {
16196 background.setState(getDrawableState());
16198 background.setVisible(getVisibility() == VISIBLE, false);
16199 mBackground = background;
16201 applyBackgroundTint();
16203 if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
16204 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
16205 mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
16206 requestLayout = true;
16209 /* Remove the background */
16210 mBackground = null;
16212 if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) {
16214 * This view ONLY drew the background before and we're removing
16215 * the background, so now it won't draw anything
16216 * (hence we SKIP_DRAW)
16218 mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND;
16219 mPrivateFlags |= PFLAG_SKIP_DRAW;
16223 * When the background is set, we try to apply its padding to this
16224 * View. When the background is removed, we don't touch this View's
16225 * padding. This is noted in the Javadocs. Hence, we don't need to
16226 * requestLayout(), the invalidate() below is sufficient.
16229 // The old background's minimum size could have affected this
16230 // View's layout, so let's requestLayout
16231 requestLayout = true;
16234 computeOpaqueFlags();
16236 if (requestLayout) {
16240 mBackgroundSizeChanged = true;
16245 * Gets the background drawable
16247 * @return The drawable used as the background for this view, if any.
16249 * @see #setBackground(Drawable)
16251 * @attr ref android.R.styleable#View_background
16253 public Drawable getBackground() {
16254 return mBackground;
16258 * Applies a tint to the background drawable. Does not modify the current tint
16259 * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
16261 * Subsequent calls to {@link #setBackground(Drawable)} will automatically
16262 * mutate the drawable and apply the specified tint and tint mode using
16263 * {@link Drawable#setTintList(ColorStateList)}.
16265 * @param tint the tint to apply, may be {@code null} to clear tint
16267 * @attr ref android.R.styleable#View_backgroundTint
16268 * @see #getBackgroundTintList()
16269 * @see Drawable#setTintList(ColorStateList)
16271 public void setBackgroundTintList(@Nullable ColorStateList tint) {
16272 if (mBackgroundTint == null) {
16273 mBackgroundTint = new TintInfo();
16275 mBackgroundTint.mTintList = tint;
16276 mBackgroundTint.mHasTintList = true;
16278 applyBackgroundTint();
16282 * Return the tint applied to the background drawable, if specified.
16284 * @return the tint applied to the background drawable
16285 * @attr ref android.R.styleable#View_backgroundTint
16286 * @see #setBackgroundTintList(ColorStateList)
16289 public ColorStateList getBackgroundTintList() {
16290 return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
16294 * Specifies the blending mode used to apply the tint specified by
16295 * {@link #setBackgroundTintList(ColorStateList)}} to the background
16296 * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
16298 * @param tintMode the blending mode used to apply the tint, may be
16299 * {@code null} to clear tint
16300 * @attr ref android.R.styleable#View_backgroundTintMode
16301 * @see #getBackgroundTintMode()
16302 * @see Drawable#setTintMode(PorterDuff.Mode)
16304 public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
16305 if (mBackgroundTint == null) {
16306 mBackgroundTint = new TintInfo();
16308 mBackgroundTint.mTintMode = tintMode;
16309 mBackgroundTint.mHasTintMode = true;
16311 applyBackgroundTint();
16315 * Return the blending mode used to apply the tint to the background
16316 * drawable, if specified.
16318 * @return the blending mode used to apply the tint to the background
16320 * @attr ref android.R.styleable#View_backgroundTintMode
16321 * @see #setBackgroundTintMode(PorterDuff.Mode)
16324 public PorterDuff.Mode getBackgroundTintMode() {
16325 return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
16328 private void applyBackgroundTint() {
16329 if (mBackground != null && mBackgroundTint != null) {
16330 final TintInfo tintInfo = mBackgroundTint;
16331 if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
16332 mBackground = mBackground.mutate();
16334 if (tintInfo.mHasTintList) {
16335 mBackground.setTintList(tintInfo.mTintList);
16338 if (tintInfo.mHasTintMode) {
16339 mBackground.setTintMode(tintInfo.mTintMode);
16346 * Sets the padding. The view may add on the space required to display
16347 * the scrollbars, depending on the style and visibility of the scrollbars.
16348 * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
16349 * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
16350 * from the values set in this call.
16352 * @attr ref android.R.styleable#View_padding
16353 * @attr ref android.R.styleable#View_paddingBottom
16354 * @attr ref android.R.styleable#View_paddingLeft
16355 * @attr ref android.R.styleable#View_paddingRight
16356 * @attr ref android.R.styleable#View_paddingTop
16357 * @param left the left padding in pixels
16358 * @param top the top padding in pixels
16359 * @param right the right padding in pixels
16360 * @param bottom the bottom padding in pixels
16362 public void setPadding(int left, int top, int right, int bottom) {
16363 resetResolvedPadding();
16365 mUserPaddingStart = UNDEFINED_PADDING;
16366 mUserPaddingEnd = UNDEFINED_PADDING;
16368 mUserPaddingLeftInitial = left;
16369 mUserPaddingRightInitial = right;
16371 mLeftPaddingDefined = true;
16372 mRightPaddingDefined = true;
16374 internalSetPadding(left, top, right, bottom);
16380 protected void internalSetPadding(int left, int top, int right, int bottom) {
16381 mUserPaddingLeft = left;
16382 mUserPaddingRight = right;
16383 mUserPaddingBottom = bottom;
16385 final int viewFlags = mViewFlags;
16386 boolean changed = false;
16388 // Common case is there are no scroll bars.
16389 if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
16390 if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
16391 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
16392 ? 0 : getVerticalScrollbarWidth();
16393 switch (mVerticalScrollbarPosition) {
16394 case SCROLLBAR_POSITION_DEFAULT:
16395 if (isLayoutRtl()) {
16401 case SCROLLBAR_POSITION_RIGHT:
16404 case SCROLLBAR_POSITION_LEFT:
16409 if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
16410 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
16411 ? 0 : getHorizontalScrollbarHeight();
16415 if (mPaddingLeft != left) {
16417 mPaddingLeft = left;
16419 if (mPaddingTop != top) {
16423 if (mPaddingRight != right) {
16425 mPaddingRight = right;
16427 if (mPaddingBottom != bottom) {
16429 mPaddingBottom = bottom;
16438 * Sets the relative padding. The view may add on the space required to display
16439 * the scrollbars, depending on the style and visibility of the scrollbars.
16440 * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
16441 * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
16442 * from the values set in this call.
16444 * @attr ref android.R.styleable#View_padding
16445 * @attr ref android.R.styleable#View_paddingBottom
16446 * @attr ref android.R.styleable#View_paddingStart
16447 * @attr ref android.R.styleable#View_paddingEnd
16448 * @attr ref android.R.styleable#View_paddingTop
16449 * @param start the start padding in pixels
16450 * @param top the top padding in pixels
16451 * @param end the end padding in pixels
16452 * @param bottom the bottom padding in pixels
16454 public void setPaddingRelative(int start, int top, int end, int bottom) {
16455 resetResolvedPadding();
16457 mUserPaddingStart = start;
16458 mUserPaddingEnd = end;
16459 mLeftPaddingDefined = true;
16460 mRightPaddingDefined = true;
16462 switch(getLayoutDirection()) {
16463 case LAYOUT_DIRECTION_RTL:
16464 mUserPaddingLeftInitial = end;
16465 mUserPaddingRightInitial = start;
16466 internalSetPadding(end, top, start, bottom);
16468 case LAYOUT_DIRECTION_LTR:
16470 mUserPaddingLeftInitial = start;
16471 mUserPaddingRightInitial = end;
16472 internalSetPadding(start, top, end, bottom);
16477 * Returns the top padding of this view.
16479 * @return the top padding in pixels
16481 public int getPaddingTop() {
16482 return mPaddingTop;
16486 * Returns the bottom padding of this view. If there are inset and enabled
16487 * scrollbars, this value may include the space required to display the
16488 * scrollbars as well.
16490 * @return the bottom padding in pixels
16492 public int getPaddingBottom() {
16493 return mPaddingBottom;
16497 * Returns the left padding of this view. If there are inset and enabled
16498 * scrollbars, this value may include the space required to display the
16499 * scrollbars as well.
16501 * @return the left padding in pixels
16503 public int getPaddingLeft() {
16504 if (!isPaddingResolved()) {
16507 return mPaddingLeft;
16511 * Returns the start padding of this view depending on its resolved layout direction.
16512 * If there are inset and enabled scrollbars, this value may include the space
16513 * required to display the scrollbars as well.
16515 * @return the start padding in pixels
16517 public int getPaddingStart() {
16518 if (!isPaddingResolved()) {
16521 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
16522 mPaddingRight : mPaddingLeft;
16526 * Returns the right padding of this view. If there are inset and enabled
16527 * scrollbars, this value may include the space required to display the
16528 * scrollbars as well.
16530 * @return the right padding in pixels
16532 public int getPaddingRight() {
16533 if (!isPaddingResolved()) {
16536 return mPaddingRight;
16540 * Returns the end padding of this view depending on its resolved layout direction.
16541 * If there are inset and enabled scrollbars, this value may include the space
16542 * required to display the scrollbars as well.
16544 * @return the end padding in pixels
16546 public int getPaddingEnd() {
16547 if (!isPaddingResolved()) {
16550 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
16551 mPaddingLeft : mPaddingRight;
16555 * Return if the padding as been set thru relative values
16556 * {@link #setPaddingRelative(int, int, int, int)} or thru
16557 * @attr ref android.R.styleable#View_paddingStart or
16558 * @attr ref android.R.styleable#View_paddingEnd
16560 * @return true if the padding is relative or false if it is not.
16562 public boolean isPaddingRelative() {
16563 return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
16566 Insets computeOpticalInsets() {
16567 return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
16573 public void resetPaddingToInitialValues() {
16574 if (isRtlCompatibilityMode()) {
16575 mPaddingLeft = mUserPaddingLeftInitial;
16576 mPaddingRight = mUserPaddingRightInitial;
16579 if (isLayoutRtl()) {
16580 mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
16581 mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
16583 mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
16584 mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
16591 public Insets getOpticalInsets() {
16592 if (mLayoutInsets == null) {
16593 mLayoutInsets = computeOpticalInsets();
16595 return mLayoutInsets;
16599 * Set this view's optical insets.
16601 * <p>This method should be treated similarly to setMeasuredDimension and not as a general
16602 * property. Views that compute their own optical insets should call it as part of measurement.
16603 * This method does not request layout. If you are setting optical insets outside of
16604 * measure/layout itself you will want to call requestLayout() yourself.
16608 public void setOpticalInsets(Insets insets) {
16609 mLayoutInsets = insets;
16613 * Changes the selection state of this view. A view can be selected or not.
16614 * Note that selection is not the same as focus. Views are typically
16615 * selected in the context of an AdapterView like ListView or GridView;
16616 * the selected view is the view that is highlighted.
16618 * @param selected true if the view must be selected, false otherwise
16620 public void setSelected(boolean selected) {
16621 //noinspection DoubleNegation
16622 if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
16623 mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
16624 if (!selected) resetPressedState();
16626 refreshDrawableState();
16627 dispatchSetSelected(selected);
16629 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
16631 notifyViewAccessibilityStateChangedIfNeeded(
16632 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
16638 * Dispatch setSelected to all of this View's children.
16640 * @see #setSelected(boolean)
16642 * @param selected The new selected state
16644 protected void dispatchSetSelected(boolean selected) {
16648 * Indicates the selection state of this view.
16650 * @return true if the view is selected, false otherwise
16652 @ViewDebug.ExportedProperty
16653 public boolean isSelected() {
16654 return (mPrivateFlags & PFLAG_SELECTED) != 0;
16658 * Changes the activated state of this view. A view can be activated or not.
16659 * Note that activation is not the same as selection. Selection is
16660 * a transient property, representing the view (hierarchy) the user is
16661 * currently interacting with. Activation is a longer-term state that the
16662 * user can move views in and out of. For example, in a list view with
16663 * single or multiple selection enabled, the views in the current selection
16664 * set are activated. (Um, yeah, we are deeply sorry about the terminology
16665 * here.) The activated state is propagated down to children of the view it
16668 * @param activated true if the view must be activated, false otherwise
16670 public void setActivated(boolean activated) {
16671 //noinspection DoubleNegation
16672 if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
16673 mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
16675 refreshDrawableState();
16676 dispatchSetActivated(activated);
16681 * Dispatch setActivated to all of this View's children.
16683 * @see #setActivated(boolean)
16685 * @param activated The new activated state
16687 protected void dispatchSetActivated(boolean activated) {
16691 * Indicates the activation state of this view.
16693 * @return true if the view is activated, false otherwise
16695 @ViewDebug.ExportedProperty
16696 public boolean isActivated() {
16697 return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
16701 * Returns the ViewTreeObserver for this view's hierarchy. The view tree
16702 * observer can be used to get notifications when global events, like
16705 * The returned ViewTreeObserver observer is not guaranteed to remain
16706 * valid for the lifetime of this View. If the caller of this method keeps
16707 * a long-lived reference to ViewTreeObserver, it should always check for
16708 * the return value of {@link ViewTreeObserver#isAlive()}.
16710 * @return The ViewTreeObserver for this view's hierarchy.
16712 public ViewTreeObserver getViewTreeObserver() {
16713 if (mAttachInfo != null) {
16714 return mAttachInfo.mTreeObserver;
16716 if (mFloatingTreeObserver == null) {
16717 mFloatingTreeObserver = new ViewTreeObserver();
16719 return mFloatingTreeObserver;
16723 * <p>Finds the topmost view in the current view hierarchy.</p>
16725 * @return the topmost view containing this view
16727 public View getRootView() {
16728 if (mAttachInfo != null) {
16729 final View v = mAttachInfo.mRootView;
16735 View parent = this;
16737 while (parent.mParent != null && parent.mParent instanceof View) {
16738 parent = (View) parent.mParent;
16745 * Transforms a motion event from view-local coordinates to on-screen
16748 * @param ev the view-local motion event
16749 * @return false if the transformation could not be applied
16752 public boolean toGlobalMotionEvent(MotionEvent ev) {
16753 final AttachInfo info = mAttachInfo;
16754 if (info == null) {
16758 final Matrix m = info.mTmpMatrix;
16759 m.set(Matrix.IDENTITY_MATRIX);
16760 transformMatrixToGlobal(m);
16766 * Transforms a motion event from on-screen coordinates to view-local
16769 * @param ev the on-screen motion event
16770 * @return false if the transformation could not be applied
16773 public boolean toLocalMotionEvent(MotionEvent ev) {
16774 final AttachInfo info = mAttachInfo;
16775 if (info == null) {
16779 final Matrix m = info.mTmpMatrix;
16780 m.set(Matrix.IDENTITY_MATRIX);
16781 transformMatrixToLocal(m);
16787 * Modifies the input matrix such that it maps view-local coordinates to
16788 * on-screen coordinates.
16790 * @param m input matrix to modify
16793 public void transformMatrixToGlobal(Matrix m) {
16794 final ViewParent parent = mParent;
16795 if (parent instanceof View) {
16796 final View vp = (View) parent;
16797 vp.transformMatrixToGlobal(m);
16798 m.preTranslate(-vp.mScrollX, -vp.mScrollY);
16799 } else if (parent instanceof ViewRootImpl) {
16800 final ViewRootImpl vr = (ViewRootImpl) parent;
16801 vr.transformMatrixToGlobal(m);
16802 m.preTranslate(0, -vr.mCurScrollY);
16805 m.preTranslate(mLeft, mTop);
16807 if (!hasIdentityMatrix()) {
16808 m.preConcat(getMatrix());
16813 * Modifies the input matrix such that it maps on-screen coordinates to
16814 * view-local coordinates.
16816 * @param m input matrix to modify
16819 public void transformMatrixToLocal(Matrix m) {
16820 final ViewParent parent = mParent;
16821 if (parent instanceof View) {
16822 final View vp = (View) parent;
16823 vp.transformMatrixToLocal(m);
16824 m.postTranslate(vp.mScrollX, vp.mScrollY);
16825 } else if (parent instanceof ViewRootImpl) {
16826 final ViewRootImpl vr = (ViewRootImpl) parent;
16827 vr.transformMatrixToLocal(m);
16828 m.postTranslate(0, vr.mCurScrollY);
16831 m.postTranslate(-mLeft, -mTop);
16833 if (!hasIdentityMatrix()) {
16834 m.postConcat(getInverseMatrix());
16841 @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
16842 @ViewDebug.IntToString(from = 0, to = "x"),
16843 @ViewDebug.IntToString(from = 1, to = "y")
16845 public int[] getLocationOnScreen() {
16846 int[] location = new int[2];
16847 getLocationOnScreen(location);
16852 * <p>Computes the coordinates of this view on the screen. The argument
16853 * must be an array of two integers. After the method returns, the array
16854 * contains the x and y location in that order.</p>
16856 * @param location an array of two integers in which to hold the coordinates
16858 public void getLocationOnScreen(int[] location) {
16859 getLocationInWindow(location);
16861 final AttachInfo info = mAttachInfo;
16862 if (info != null) {
16863 location[0] += info.mWindowLeft;
16864 location[1] += info.mWindowTop;
16869 * <p>Computes the coordinates of this view in its window. The argument
16870 * must be an array of two integers. After the method returns, the array
16871 * contains the x and y location in that order.</p>
16873 * @param location an array of two integers in which to hold the coordinates
16875 public void getLocationInWindow(int[] location) {
16876 if (location == null || location.length < 2) {
16877 throw new IllegalArgumentException("location must be an array of two integers");
16880 if (mAttachInfo == null) {
16881 // When the view is not attached to a window, this method does not make sense
16882 location[0] = location[1] = 0;
16886 float[] position = mAttachInfo.mTmpTransformLocation;
16887 position[0] = position[1] = 0.0f;
16889 if (!hasIdentityMatrix()) {
16890 getMatrix().mapPoints(position);
16893 position[0] += mLeft;
16894 position[1] += mTop;
16896 ViewParent viewParent = mParent;
16897 while (viewParent instanceof View) {
16898 final View view = (View) viewParent;
16900 position[0] -= view.mScrollX;
16901 position[1] -= view.mScrollY;
16903 if (!view.hasIdentityMatrix()) {
16904 view.getMatrix().mapPoints(position);
16907 position[0] += view.mLeft;
16908 position[1] += view.mTop;
16910 viewParent = view.mParent;
16913 if (viewParent instanceof ViewRootImpl) {
16915 final ViewRootImpl vr = (ViewRootImpl) viewParent;
16916 position[1] -= vr.mCurScrollY;
16919 location[0] = (int) (position[0] + 0.5f);
16920 location[1] = (int) (position[1] + 0.5f);
16925 * @param id the id of the view to be found
16926 * @return the view of the specified id, null if cannot be found
16928 protected View findViewTraversal(int id) {
16937 * @param tag the tag of the view to be found
16938 * @return the view of specified tag, null if cannot be found
16940 protected View findViewWithTagTraversal(Object tag) {
16941 if (tag != null && tag.equals(mTag)) {
16949 * @param predicate The predicate to evaluate.
16950 * @param childToSkip If not null, ignores this child during the recursive traversal.
16951 * @return The first view that matches the predicate or null.
16953 protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
16954 if (predicate.apply(this)) {
16961 * Look for a child view with the given id. If this view has the given
16962 * id, return this view.
16964 * @param id The id to search for.
16965 * @return The view that has the given id in the hierarchy or null
16967 public final View findViewById(int id) {
16971 return findViewTraversal(id);
16975 * Finds a view by its unuque and stable accessibility id.
16977 * @param accessibilityId The searched accessibility id.
16978 * @return The found view.
16980 final View findViewByAccessibilityId(int accessibilityId) {
16981 if (accessibilityId < 0) {
16984 return findViewByAccessibilityIdTraversal(accessibilityId);
16988 * Performs the traversal to find a view by its unuque and stable accessibility id.
16990 * <strong>Note:</strong>This method does not stop at the root namespace
16991 * boundary since the user can touch the screen at an arbitrary location
16992 * potentially crossing the root namespace bounday which will send an
16993 * accessibility event to accessibility services and they should be able
16994 * to obtain the event source. Also accessibility ids are guaranteed to be
16995 * unique in the window.
16997 * @param accessibilityId The accessibility id.
16998 * @return The found view.
17002 public View findViewByAccessibilityIdTraversal(int accessibilityId) {
17003 if (getAccessibilityViewId() == accessibilityId) {
17010 * Look for a child view with the given tag. If this view has the given
17011 * tag, return this view.
17013 * @param tag The tag to search for, using "tag.equals(getTag())".
17014 * @return The View that has the given tag in the hierarchy or null
17016 public final View findViewWithTag(Object tag) {
17020 return findViewWithTagTraversal(tag);
17025 * Look for a child view that matches the specified predicate.
17026 * If this view matches the predicate, return this view.
17028 * @param predicate The predicate to evaluate.
17029 * @return The first view that matches the predicate or null.
17031 public final View findViewByPredicate(Predicate<View> predicate) {
17032 return findViewByPredicateTraversal(predicate, null);
17037 * Look for a child view that matches the specified predicate,
17038 * starting with the specified view and its descendents and then
17039 * recusively searching the ancestors and siblings of that view
17040 * until this view is reached.
17042 * This method is useful in cases where the predicate does not match
17043 * a single unique view (perhaps multiple views use the same id)
17044 * and we are trying to find the view that is "closest" in scope to the
17047 * @param start The view to start from.
17048 * @param predicate The predicate to evaluate.
17049 * @return The first view that matches the predicate or null.
17051 public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
17052 View childToSkip = null;
17054 View view = start.findViewByPredicateTraversal(predicate, childToSkip);
17055 if (view != null || start == this) {
17059 ViewParent parent = start.getParent();
17060 if (parent == null || !(parent instanceof View)) {
17064 childToSkip = start;
17065 start = (View) parent;
17070 * Sets the identifier for this view. The identifier does not have to be
17071 * unique in this view's hierarchy. The identifier should be a positive
17076 * @see #findViewById(int)
17078 * @param id a number used to identify the view
17080 * @attr ref android.R.styleable#View_id
17082 public void setId(int id) {
17084 if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
17085 mID = generateViewId();
17092 * @param isRoot true if the view belongs to the root namespace, false
17095 public void setIsRootNamespace(boolean isRoot) {
17097 mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
17099 mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
17106 * @return true if the view belongs to the root namespace, false otherwise
17108 public boolean isRootNamespace() {
17109 return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
17113 * Returns this view's identifier.
17115 * @return a positive integer used to identify the view or {@link #NO_ID}
17116 * if the view has no ID
17119 * @see #findViewById(int)
17120 * @attr ref android.R.styleable#View_id
17122 @ViewDebug.CapturedViewProperty
17123 public int getId() {
17128 * Returns this view's tag.
17130 * @return the Object stored in this view as a tag, or {@code null} if not
17133 * @see #setTag(Object)
17134 * @see #getTag(int)
17136 @ViewDebug.ExportedProperty
17137 public Object getTag() {
17142 * Sets the tag associated with this view. A tag can be used to mark
17143 * a view in its hierarchy and does not have to be unique within the
17144 * hierarchy. Tags can also be used to store data within a view without
17145 * resorting to another data structure.
17147 * @param tag an Object to tag the view with
17150 * @see #setTag(int, Object)
17152 public void setTag(final Object tag) {
17157 * Returns the tag associated with this view and the specified key.
17159 * @param key The key identifying the tag
17161 * @return the Object stored in this view as a tag, or {@code null} if not
17164 * @see #setTag(int, Object)
17167 public Object getTag(int key) {
17168 if (mKeyedTags != null) return mKeyedTags.get(key);
17173 * Sets a tag associated with this view and a key. A tag can be used
17174 * to mark a view in its hierarchy and does not have to be unique within
17175 * the hierarchy. Tags can also be used to store data within a view
17176 * without resorting to another data structure.
17178 * The specified key should be an id declared in the resources of the
17179 * application to ensure it is unique (see the <a
17180 * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
17181 * Keys identified as belonging to
17182 * the Android framework or not associated with any package will cause
17183 * an {@link IllegalArgumentException} to be thrown.
17185 * @param key The key identifying the tag
17186 * @param tag An Object to tag the view with
17188 * @throws IllegalArgumentException If they specified key is not valid
17190 * @see #setTag(Object)
17191 * @see #getTag(int)
17193 public void setTag(int key, final Object tag) {
17194 // If the package id is 0x00 or 0x01, it's either an undefined package
17195 // or a framework id
17196 if ((key >>> 24) < 2) {
17197 throw new IllegalArgumentException("The key must be an application-specific "
17201 setKeyedTag(key, tag);
17205 * Variation of {@link #setTag(int, Object)} that enforces the key to be a
17210 public void setTagInternal(int key, Object tag) {
17211 if ((key >>> 24) != 0x1) {
17212 throw new IllegalArgumentException("The key must be a framework-specific "
17216 setKeyedTag(key, tag);
17219 private void setKeyedTag(int key, Object tag) {
17220 if (mKeyedTags == null) {
17221 mKeyedTags = new SparseArray<Object>(2);
17224 mKeyedTags.put(key, tag);
17228 * Prints information about this view in the log output, with the tag
17229 * {@link #VIEW_LOG_TAG}.
17233 public void debug() {
17238 * Prints information about this view in the log output, with the tag
17239 * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
17240 * indentation defined by the <code>depth</code>.
17242 * @param depth the indentation level
17246 protected void debug(int depth) {
17247 String output = debugIndent(depth - 1);
17249 output += "+ " + this;
17252 output += " (id=" + id + ")";
17254 Object tag = getTag();
17256 output += " (tag=" + tag + ")";
17258 Log.d(VIEW_LOG_TAG, output);
17260 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
17261 output = debugIndent(depth) + " FOCUSED";
17262 Log.d(VIEW_LOG_TAG, output);
17265 output = debugIndent(depth);
17266 output += "frame={" + mLeft + ", " + mTop + ", " + mRight
17267 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
17269 Log.d(VIEW_LOG_TAG, output);
17271 if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
17272 || mPaddingBottom != 0) {
17273 output = debugIndent(depth);
17274 output += "padding={" + mPaddingLeft + ", " + mPaddingTop
17275 + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
17276 Log.d(VIEW_LOG_TAG, output);
17279 output = debugIndent(depth);
17280 output += "mMeasureWidth=" + mMeasuredWidth +
17281 " mMeasureHeight=" + mMeasuredHeight;
17282 Log.d(VIEW_LOG_TAG, output);
17284 output = debugIndent(depth);
17285 if (mLayoutParams == null) {
17286 output += "BAD! no layout params";
17288 output = mLayoutParams.debug(output);
17290 Log.d(VIEW_LOG_TAG, output);
17292 output = debugIndent(depth);
17293 output += "flags={";
17294 output += View.printFlags(mViewFlags);
17296 Log.d(VIEW_LOG_TAG, output);
17298 output = debugIndent(depth);
17299 output += "privateFlags={";
17300 output += View.printPrivateFlags(mPrivateFlags);
17302 Log.d(VIEW_LOG_TAG, output);
17306 * Creates a string of whitespaces used for indentation.
17308 * @param depth the indentation level
17309 * @return a String containing (depth * 2 + 3) * 2 white spaces
17313 protected static String debugIndent(int depth) {
17314 StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
17315 for (int i = 0; i < (depth * 2) + 3; i++) {
17316 spaces.append(' ').append(' ');
17318 return spaces.toString();
17322 * <p>Return the offset of the widget's text baseline from the widget's top
17323 * boundary. If this widget does not support baseline alignment, this
17324 * method returns -1. </p>
17326 * @return the offset of the baseline within the widget's bounds or -1
17327 * if baseline alignment is not supported
17329 @ViewDebug.ExportedProperty(category = "layout")
17330 public int getBaseline() {
17335 * Returns whether the view hierarchy is currently undergoing a layout pass. This
17336 * information is useful to avoid situations such as calling {@link #requestLayout()} during
17339 * @return whether the view hierarchy is currently undergoing a layout pass
17341 public boolean isInLayout() {
17342 ViewRootImpl viewRoot = getViewRootImpl();
17343 return (viewRoot != null && viewRoot.isInLayout());
17347 * Call this when something has changed which has invalidated the
17348 * layout of this view. This will schedule a layout pass of the view
17349 * tree. This should not be called while the view hierarchy is currently in a layout
17350 * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
17351 * end of the current layout pass (and then layout will run again) or after the current
17352 * frame is drawn and the next layout occurs.
17354 * <p>Subclasses which override this method should call the superclass method to
17355 * handle possible request-during-layout errors correctly.</p>
17357 public void requestLayout() {
17358 if (mMeasureCache != null) mMeasureCache.clear();
17360 if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
17361 // Only trigger request-during-layout logic if this is the view requesting it,
17362 // not the views in its parent hierarchy
17363 ViewRootImpl viewRoot = getViewRootImpl();
17364 if (viewRoot != null && viewRoot.isInLayout()) {
17365 if (!viewRoot.requestLayoutDuringLayout(this)) {
17369 mAttachInfo.mViewRequestingLayout = this;
17372 mPrivateFlags |= PFLAG_FORCE_LAYOUT;
17373 mPrivateFlags |= PFLAG_INVALIDATED;
17375 if (mParent != null && !mParent.isLayoutRequested()) {
17376 mParent.requestLayout();
17378 if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
17379 mAttachInfo.mViewRequestingLayout = null;
17384 * Forces this view to be laid out during the next layout pass.
17385 * This method does not call requestLayout() or forceLayout()
17388 public void forceLayout() {
17389 if (mMeasureCache != null) mMeasureCache.clear();
17391 mPrivateFlags |= PFLAG_FORCE_LAYOUT;
17392 mPrivateFlags |= PFLAG_INVALIDATED;
17397 * This is called to find out how big a view should be. The parent
17398 * supplies constraint information in the width and height parameters.
17402 * The actual measurement work of a view is performed in
17403 * {@link #onMeasure(int, int)}, called by this method. Therefore, only
17404 * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
17408 * @param widthMeasureSpec Horizontal space requirements as imposed by the
17410 * @param heightMeasureSpec Vertical space requirements as imposed by the
17413 * @see #onMeasure(int, int)
17415 public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
17416 boolean optical = isLayoutModeOptical(this);
17417 if (optical != isLayoutModeOptical(mParent)) {
17418 Insets insets = getOpticalInsets();
17419 int oWidth = insets.left + insets.right;
17420 int oHeight = insets.top + insets.bottom;
17421 widthMeasureSpec = MeasureSpec.adjust(widthMeasureSpec, optical ? -oWidth : oWidth);
17422 heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
17425 // Suppress sign extension for the low bytes
17426 long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
17427 if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
17429 final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
17430 final boolean isExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY &&
17431 MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
17432 final boolean matchingSize = isExactly &&
17433 getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec) &&
17434 getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
17435 if (forceLayout || !matchingSize &&
17436 (widthMeasureSpec != mOldWidthMeasureSpec ||
17437 heightMeasureSpec != mOldHeightMeasureSpec)) {
17439 // first clears the measured dimension flag
17440 mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
17442 resolveRtlPropertiesIfNeeded();
17444 int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
17445 if (cacheIndex < 0 || sIgnoreMeasureCache) {
17446 // measure ourselves, this should set the measured dimension flag back
17447 onMeasure(widthMeasureSpec, heightMeasureSpec);
17448 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
17450 long value = mMeasureCache.valueAt(cacheIndex);
17451 // Casting a long to int drops the high 32 bits, no mask needed
17452 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
17453 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
17456 // flag not set, setMeasuredDimension() was not invoked, we raise
17457 // an exception to warn the developer
17458 if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
17459 throw new IllegalStateException("onMeasure() did not set the"
17460 + " measured dimension by calling"
17461 + " setMeasuredDimension()");
17464 mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
17467 mOldWidthMeasureSpec = widthMeasureSpec;
17468 mOldHeightMeasureSpec = heightMeasureSpec;
17470 mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
17471 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
17476 * Measure the view and its content to determine the measured width and the
17477 * measured height. This method is invoked by {@link #measure(int, int)} and
17478 * should be overriden by subclasses to provide accurate and efficient
17479 * measurement of their contents.
17483 * <strong>CONTRACT:</strong> When overriding this method, you
17484 * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
17485 * measured width and height of this view. Failure to do so will trigger an
17486 * <code>IllegalStateException</code>, thrown by
17487 * {@link #measure(int, int)}. Calling the superclass'
17488 * {@link #onMeasure(int, int)} is a valid use.
17492 * The base class implementation of measure defaults to the background size,
17493 * unless a larger size is allowed by the MeasureSpec. Subclasses should
17494 * override {@link #onMeasure(int, int)} to provide better measurements of
17499 * If this method is overridden, it is the subclass's responsibility to make
17500 * sure the measured height and width are at least the view's minimum height
17501 * and width ({@link #getSuggestedMinimumHeight()} and
17502 * {@link #getSuggestedMinimumWidth()}).
17505 * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
17506 * The requirements are encoded with
17507 * {@link android.view.View.MeasureSpec}.
17508 * @param heightMeasureSpec vertical space requirements as imposed by the parent.
17509 * The requirements are encoded with
17510 * {@link android.view.View.MeasureSpec}.
17512 * @see #getMeasuredWidth()
17513 * @see #getMeasuredHeight()
17514 * @see #setMeasuredDimension(int, int)
17515 * @see #getSuggestedMinimumHeight()
17516 * @see #getSuggestedMinimumWidth()
17517 * @see android.view.View.MeasureSpec#getMode(int)
17518 * @see android.view.View.MeasureSpec#getSize(int)
17520 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
17521 setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
17522 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
17526 * <p>This method must be called by {@link #onMeasure(int, int)} to store the
17527 * measured width and measured height. Failing to do so will trigger an
17528 * exception at measurement time.</p>
17530 * @param measuredWidth The measured width of this view. May be a complex
17531 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17532 * {@link #MEASURED_STATE_TOO_SMALL}.
17533 * @param measuredHeight The measured height of this view. May be a complex
17534 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17535 * {@link #MEASURED_STATE_TOO_SMALL}.
17537 protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
17538 boolean optical = isLayoutModeOptical(this);
17539 if (optical != isLayoutModeOptical(mParent)) {
17540 Insets insets = getOpticalInsets();
17541 int opticalWidth = insets.left + insets.right;
17542 int opticalHeight = insets.top + insets.bottom;
17544 measuredWidth += optical ? opticalWidth : -opticalWidth;
17545 measuredHeight += optical ? opticalHeight : -opticalHeight;
17547 setMeasuredDimensionRaw(measuredWidth, measuredHeight);
17551 * Sets the measured dimension without extra processing for things like optical bounds.
17552 * Useful for reapplying consistent values that have already been cooked with adjustments
17553 * for optical bounds, etc. such as those from the measurement cache.
17555 * @param measuredWidth The measured width of this view. May be a complex
17556 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17557 * {@link #MEASURED_STATE_TOO_SMALL}.
17558 * @param measuredHeight The measured height of this view. May be a complex
17559 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17560 * {@link #MEASURED_STATE_TOO_SMALL}.
17562 private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
17563 mMeasuredWidth = measuredWidth;
17564 mMeasuredHeight = measuredHeight;
17566 mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
17570 * Merge two states as returned by {@link #getMeasuredState()}.
17571 * @param curState The current state as returned from a view or the result
17572 * of combining multiple views.
17573 * @param newState The new view state to combine.
17574 * @return Returns a new integer reflecting the combination of the two
17577 public static int combineMeasuredStates(int curState, int newState) {
17578 return curState | newState;
17582 * Version of {@link #resolveSizeAndState(int, int, int)}
17583 * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
17585 public static int resolveSize(int size, int measureSpec) {
17586 return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
17590 * Utility to reconcile a desired size and state, with constraints imposed
17591 * by a MeasureSpec. Will take the desired size, unless a different size
17592 * is imposed by the constraints. The returned value is a compound integer,
17593 * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
17594 * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting
17595 * size is smaller than the size the view wants to be.
17597 * @param size How big the view wants to be
17598 * @param measureSpec Constraints imposed by the parent
17599 * @return Size information bit mask as defined by
17600 * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
17602 public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
17604 int specMode = MeasureSpec.getMode(measureSpec);
17605 int specSize = MeasureSpec.getSize(measureSpec);
17606 switch (specMode) {
17607 case MeasureSpec.UNSPECIFIED:
17610 case MeasureSpec.AT_MOST:
17611 if (specSize < size) {
17612 result = specSize | MEASURED_STATE_TOO_SMALL;
17617 case MeasureSpec.EXACTLY:
17621 return result | (childMeasuredState&MEASURED_STATE_MASK);
17625 * Utility to return a default size. Uses the supplied size if the
17626 * MeasureSpec imposed no constraints. Will get larger if allowed
17627 * by the MeasureSpec.
17629 * @param size Default size for this view
17630 * @param measureSpec Constraints imposed by the parent
17631 * @return The size this view should be.
17633 public static int getDefaultSize(int size, int measureSpec) {
17635 int specMode = MeasureSpec.getMode(measureSpec);
17636 int specSize = MeasureSpec.getSize(measureSpec);
17638 switch (specMode) {
17639 case MeasureSpec.UNSPECIFIED:
17642 case MeasureSpec.AT_MOST:
17643 case MeasureSpec.EXACTLY:
17651 * Returns the suggested minimum height that the view should use. This
17652 * returns the maximum of the view's minimum height
17653 * and the background's minimum height
17654 * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
17656 * When being used in {@link #onMeasure(int, int)}, the caller should still
17657 * ensure the returned height is within the requirements of the parent.
17659 * @return The suggested minimum height of the view.
17661 protected int getSuggestedMinimumHeight() {
17662 return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
17667 * Returns the suggested minimum width that the view should use. This
17668 * returns the maximum of the view's minimum width)
17669 * and the background's minimum width
17670 * ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
17672 * When being used in {@link #onMeasure(int, int)}, the caller should still
17673 * ensure the returned width is within the requirements of the parent.
17675 * @return The suggested minimum width of the view.
17677 protected int getSuggestedMinimumWidth() {
17678 return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
17682 * Returns the minimum height of the view.
17684 * @return the minimum height the view will try to be.
17686 * @see #setMinimumHeight(int)
17688 * @attr ref android.R.styleable#View_minHeight
17690 public int getMinimumHeight() {
17695 * Sets the minimum height of the view. It is not guaranteed the view will
17696 * be able to achieve this minimum height (for example, if its parent layout
17697 * constrains it with less available height).
17699 * @param minHeight The minimum height the view will try to be.
17701 * @see #getMinimumHeight()
17703 * @attr ref android.R.styleable#View_minHeight
17705 public void setMinimumHeight(int minHeight) {
17706 mMinHeight = minHeight;
17711 * Returns the minimum width of the view.
17713 * @return the minimum width the view will try to be.
17715 * @see #setMinimumWidth(int)
17717 * @attr ref android.R.styleable#View_minWidth
17719 public int getMinimumWidth() {
17724 * Sets the minimum width of the view. It is not guaranteed the view will
17725 * be able to achieve this minimum width (for example, if its parent layout
17726 * constrains it with less available width).
17728 * @param minWidth The minimum width the view will try to be.
17730 * @see #getMinimumWidth()
17732 * @attr ref android.R.styleable#View_minWidth
17734 public void setMinimumWidth(int minWidth) {
17735 mMinWidth = minWidth;
17741 * Get the animation currently associated with this view.
17743 * @return The animation that is currently playing or
17744 * scheduled to play for this view.
17746 public Animation getAnimation() {
17747 return mCurrentAnimation;
17751 * Start the specified animation now.
17753 * @param animation the animation to start now
17755 public void startAnimation(Animation animation) {
17756 animation.setStartTime(Animation.START_ON_FIRST_FRAME);
17757 setAnimation(animation);
17758 invalidateParentCaches();
17763 * Cancels any animations for this view.
17765 public void clearAnimation() {
17766 if (mCurrentAnimation != null) {
17767 mCurrentAnimation.detach();
17769 mCurrentAnimation = null;
17770 invalidateParentIfNeeded();
17774 * Sets the next animation to play for this view.
17775 * If you want the animation to play immediately, use
17776 * {@link #startAnimation(android.view.animation.Animation)} instead.
17777 * This method provides allows fine-grained
17778 * control over the start time and invalidation, but you
17779 * must make sure that 1) the animation has a start time set, and
17780 * 2) the view's parent (which controls animations on its children)
17781 * will be invalidated when the animation is supposed to
17784 * @param animation The next animation, or null.
17786 public void setAnimation(Animation animation) {
17787 mCurrentAnimation = animation;
17789 if (animation != null) {
17790 // If the screen is off assume the animation start time is now instead of
17791 // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
17792 // would cause the animation to start when the screen turns back on
17793 if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
17794 && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
17795 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
17802 * Invoked by a parent ViewGroup to notify the start of the animation
17803 * currently associated with this view. If you override this method,
17804 * always call super.onAnimationStart();
17806 * @see #setAnimation(android.view.animation.Animation)
17807 * @see #getAnimation()
17809 protected void onAnimationStart() {
17810 mPrivateFlags |= PFLAG_ANIMATION_STARTED;
17814 * Invoked by a parent ViewGroup to notify the end of the animation
17815 * currently associated with this view. If you override this method,
17816 * always call super.onAnimationEnd();
17818 * @see #setAnimation(android.view.animation.Animation)
17819 * @see #getAnimation()
17821 protected void onAnimationEnd() {
17822 mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
17826 * Invoked if there is a Transform that involves alpha. Subclass that can
17827 * draw themselves with the specified alpha should return true, and then
17828 * respect that alpha when their onDraw() is called. If this returns false
17829 * then the view may be redirected to draw into an offscreen buffer to
17830 * fulfill the request, which will look fine, but may be slower than if the
17831 * subclass handles it internally. The default implementation returns false.
17833 * @param alpha The alpha (0..255) to apply to the view's drawing
17834 * @return true if the view can draw with the specified alpha.
17836 protected boolean onSetAlpha(int alpha) {
17841 * This is used by the RootView to perform an optimization when
17842 * the view hierarchy contains one or several SurfaceView.
17843 * SurfaceView is always considered transparent, but its children are not,
17844 * therefore all View objects remove themselves from the global transparent
17845 * region (passed as a parameter to this function).
17847 * @param region The transparent region for this ViewAncestor (window).
17849 * @return Returns true if the effective visibility of the view at this
17850 * point is opaque, regardless of the transparent region; returns false
17851 * if it is possible for underlying windows to be seen behind the view.
17855 public boolean gatherTransparentRegion(Region region) {
17856 final AttachInfo attachInfo = mAttachInfo;
17857 if (region != null && attachInfo != null) {
17858 final int pflags = mPrivateFlags;
17859 if ((pflags & PFLAG_SKIP_DRAW) == 0) {
17860 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
17861 // remove it from the transparent region.
17862 final int[] location = attachInfo.mTransparentLocation;
17863 getLocationInWindow(location);
17864 region.op(location[0], location[1], location[0] + mRight - mLeft,
17865 location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
17866 } else if ((pflags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null &&
17867 mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
17868 // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
17869 // exists, so we remove the background drawable's non-transparent
17870 // parts from this transparent region.
17871 applyDrawableToTransparentRegion(mBackground, region);
17878 * Play a sound effect for this view.
17880 * <p>The framework will play sound effects for some built in actions, such as
17881 * clicking, but you may wish to play these effects in your widget,
17882 * for instance, for internal navigation.
17884 * <p>The sound effect will only be played if sound effects are enabled by the user, and
17885 * {@link #isSoundEffectsEnabled()} is true.
17887 * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
17889 public void playSoundEffect(int soundConstant) {
17890 if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
17893 mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
17899 * <p>Provide haptic feedback to the user for this view.
17901 * <p>The framework will provide haptic feedback for some built in actions,
17902 * such as long presses, but you may wish to provide feedback for your
17905 * <p>The feedback will only be performed if
17906 * {@link #isHapticFeedbackEnabled()} is true.
17908 * @param feedbackConstant One of the constants defined in
17909 * {@link HapticFeedbackConstants}
17911 public boolean performHapticFeedback(int feedbackConstant) {
17912 return performHapticFeedback(feedbackConstant, 0);
17918 * <p>Like {@link #performHapticFeedback(int)}, with additional options.
17920 * @param feedbackConstant One of the constants defined in
17921 * {@link HapticFeedbackConstants}
17922 * @param flags Additional flags as per {@link HapticFeedbackConstants}.
17924 public boolean performHapticFeedback(int feedbackConstant, int flags) {
17925 if (mAttachInfo == null) {
17928 //noinspection SimplifiableIfStatement
17929 if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
17930 && !isHapticFeedbackEnabled()) {
17933 return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
17934 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
17938 * Request that the visibility of the status bar or other screen/window
17939 * decorations be changed.
17941 * <p>This method is used to put the over device UI into temporary modes
17942 * where the user's attention is focused more on the application content,
17943 * by dimming or hiding surrounding system affordances. This is typically
17944 * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
17945 * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
17946 * to be placed behind the action bar (and with these flags other system
17947 * affordances) so that smooth transitions between hiding and showing them
17950 * <p>Two representative examples of the use of system UI visibility is
17951 * implementing a content browsing application (like a magazine reader)
17952 * and a video playing application.
17954 * <p>The first code shows a typical implementation of a View in a content
17955 * browsing application. In this implementation, the application goes
17956 * into a content-oriented mode by hiding the status bar and action bar,
17957 * and putting the navigation elements into lights out mode. The user can
17958 * then interact with content while in this mode. Such an application should
17959 * provide an easy way for the user to toggle out of the mode (such as to
17960 * check information in the status bar or access notifications). In the
17961 * implementation here, this is done simply by tapping on the content.
17963 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
17966 * <p>This second code sample shows a typical implementation of a View
17967 * in a video playing application. In this situation, while the video is
17968 * playing the application would like to go into a complete full-screen mode,
17969 * to use as much of the display as possible for the video. When in this state
17970 * the user can not interact with the application; the system intercepts
17971 * touching on the screen to pop the UI out of full screen mode. See
17972 * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
17974 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
17977 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
17978 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
17979 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
17980 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
17981 * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
17983 public void setSystemUiVisibility(int visibility) {
17984 if (visibility != mSystemUiVisibility) {
17985 mSystemUiVisibility = visibility;
17986 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
17987 mParent.recomputeViewAttributes(this);
17993 * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
17994 * @return Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
17995 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
17996 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
17997 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
17998 * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
18000 public int getSystemUiVisibility() {
18001 return mSystemUiVisibility;
18005 * Returns the current system UI visibility that is currently set for
18006 * the entire window. This is the combination of the
18007 * {@link #setSystemUiVisibility(int)} values supplied by all of the
18008 * views in the window.
18010 public int getWindowSystemUiVisibility() {
18011 return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
18015 * Override to find out when the window's requested system UI visibility
18016 * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
18017 * This is different from the callbacks received through
18018 * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
18019 * in that this is only telling you about the local request of the window,
18020 * not the actual values applied by the system.
18022 public void onWindowSystemUiVisibilityChanged(int visible) {
18026 * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
18027 * the view hierarchy.
18029 public void dispatchWindowSystemUiVisiblityChanged(int visible) {
18030 onWindowSystemUiVisibilityChanged(visible);
18034 * Set a listener to receive callbacks when the visibility of the system bar changes.
18035 * @param l The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
18037 public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
18038 getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
18039 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
18040 mParent.recomputeViewAttributes(this);
18045 * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
18046 * the view hierarchy.
18048 public void dispatchSystemUiVisibilityChanged(int visibility) {
18049 ListenerInfo li = mListenerInfo;
18050 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
18051 li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
18052 visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
18056 boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
18057 int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
18058 if (val != mSystemUiVisibility) {
18059 setSystemUiVisibility(val);
18066 public void setDisabledSystemUiVisibility(int flags) {
18067 if (mAttachInfo != null) {
18068 if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
18069 mAttachInfo.mDisabledSystemUiVisibility = flags;
18070 if (mParent != null) {
18071 mParent.recomputeViewAttributes(this);
18078 * Creates an image that the system displays during the drag and drop
18079 * operation. This is called a "drag shadow". The default implementation
18080 * for a DragShadowBuilder based on a View returns an image that has exactly the same
18081 * appearance as the given View. The default also positions the center of the drag shadow
18082 * directly under the touch point. If no View is provided (the constructor with no parameters
18083 * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
18084 * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overriden, then the
18085 * default is an invisible drag shadow.
18087 * You are not required to use the View you provide to the constructor as the basis of the
18088 * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
18089 * anything you want as the drag shadow.
18092 * You pass a DragShadowBuilder object to the system when you start the drag. The system
18093 * calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
18094 * size and position of the drag shadow. It uses this data to construct a
18095 * {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
18096 * so that your application can draw the shadow image in the Canvas.
18099 * <div class="special reference">
18100 * <h3>Developer Guides</h3>
18101 * <p>For a guide to implementing drag and drop features, read the
18102 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
18105 public static class DragShadowBuilder {
18106 private final WeakReference<View> mView;
18109 * Constructs a shadow image builder based on a View. By default, the resulting drag
18110 * shadow will have the same appearance and dimensions as the View, with the touch point
18111 * over the center of the View.
18112 * @param view A View. Any View in scope can be used.
18114 public DragShadowBuilder(View view) {
18115 mView = new WeakReference<View>(view);
18119 * Construct a shadow builder object with no associated View. This
18120 * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
18121 * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
18122 * to supply the drag shadow's dimensions and appearance without
18123 * reference to any View object. If they are not overridden, then the result is an
18124 * invisible drag shadow.
18126 public DragShadowBuilder() {
18127 mView = new WeakReference<View>(null);
18131 * Returns the View object that had been passed to the
18132 * {@link #View.DragShadowBuilder(View)}
18133 * constructor. If that View parameter was {@code null} or if the
18134 * {@link #View.DragShadowBuilder()}
18135 * constructor was used to instantiate the builder object, this method will return
18138 * @return The View object associate with this builder object.
18140 @SuppressWarnings({"JavadocReference"})
18141 final public View getView() {
18142 return mView.get();
18146 * Provides the metrics for the shadow image. These include the dimensions of
18147 * the shadow image, and the point within that shadow that should
18148 * be centered under the touch location while dragging.
18150 * The default implementation sets the dimensions of the shadow to be the
18151 * same as the dimensions of the View itself and centers the shadow under
18155 * @param shadowSize A {@link android.graphics.Point} containing the width and height
18156 * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
18157 * desired width and must set {@link android.graphics.Point#y} to the desired height of the
18160 * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
18161 * shadow image that should be underneath the touch point during the drag and drop
18162 * operation. Your application must set {@link android.graphics.Point#x} to the
18163 * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
18165 public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
18166 final View view = mView.get();
18167 if (view != null) {
18168 shadowSize.set(view.getWidth(), view.getHeight());
18169 shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
18171 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
18176 * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
18177 * based on the dimensions it received from the
18178 * {@link #onProvideShadowMetrics(Point, Point)} callback.
18180 * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
18182 public void onDrawShadow(Canvas canvas) {
18183 final View view = mView.get();
18184 if (view != null) {
18187 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
18193 * Starts a drag and drop operation. When your application calls this method, it passes a
18194 * {@link android.view.View.DragShadowBuilder} object to the system. The
18195 * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
18196 * to get metrics for the drag shadow, and then calls the object's
18197 * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
18199 * Once the system has the drag shadow, it begins the drag and drop operation by sending
18200 * drag events to all the View objects in your application that are currently visible. It does
18201 * this either by calling the View object's drag listener (an implementation of
18202 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
18203 * View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
18204 * Both are passed a {@link android.view.DragEvent} object that has a
18205 * {@link android.view.DragEvent#getAction()} value of
18206 * {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
18209 * Your application can invoke startDrag() on any attached View object. The View object does not
18210 * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
18211 * be related to the View the user selected for dragging.
18213 * @param data A {@link android.content.ClipData} object pointing to the data to be
18214 * transferred by the drag and drop operation.
18215 * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
18217 * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
18218 * drop operation. This Object is put into every DragEvent object sent by the system during the
18221 * myLocalState is a lightweight mechanism for the sending information from the dragged View
18222 * to the target Views. For example, it can contain flags that differentiate between a
18223 * a copy operation and a move operation.
18225 * @param flags Flags that control the drag and drop operation. No flags are currently defined,
18226 * so the parameter should be set to 0.
18227 * @return {@code true} if the method completes successfully, or
18228 * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
18229 * do a drag, and so no drag operation is in progress.
18231 public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
18232 Object myLocalState, int flags) {
18233 if (ViewDebug.DEBUG_DRAG) {
18234 Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
18236 boolean okay = false;
18238 Point shadowSize = new Point();
18239 Point shadowTouchPoint = new Point();
18240 shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
18242 if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
18243 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
18244 throw new IllegalStateException("Drag shadow dimensions must not be negative");
18247 if (ViewDebug.DEBUG_DRAG) {
18248 Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
18249 + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
18251 Surface surface = new Surface();
18253 IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
18254 flags, shadowSize.x, shadowSize.y, surface);
18255 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
18256 + " surface=" + surface);
18257 if (token != null) {
18258 Canvas canvas = surface.lockCanvas(null);
18260 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
18261 shadowBuilder.onDrawShadow(canvas);
18263 surface.unlockCanvasAndPost(canvas);
18266 final ViewRootImpl root = getViewRootImpl();
18268 // Cache the local state object for delivery with DragEvents
18269 root.setLocalDragState(myLocalState);
18271 // repurpose 'shadowSize' for the last touch point
18272 root.getLastTouchPoint(shadowSize);
18274 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
18275 shadowSize.x, shadowSize.y,
18276 shadowTouchPoint.x, shadowTouchPoint.y, data);
18277 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
18279 // Off and running! Release our local surface instance; the drag
18280 // shadow surface is now managed by the system process.
18283 } catch (Exception e) {
18284 Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
18292 * Handles drag events sent by the system following a call to
18293 * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
18295 * When the system calls this method, it passes a
18296 * {@link android.view.DragEvent} object. A call to
18297 * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
18298 * in DragEvent. The method uses these to determine what is happening in the drag and drop
18300 * @param event The {@link android.view.DragEvent} sent by the system.
18301 * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
18302 * in DragEvent, indicating the type of drag event represented by this object.
18303 * @return {@code true} if the method was successful, otherwise {@code false}.
18305 * The method should return {@code true} in response to an action type of
18306 * {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
18310 * The method should also return {@code true} in response to an action type of
18311 * {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
18312 * {@code false} if it didn't.
18315 public boolean onDragEvent(DragEvent event) {
18320 * Detects if this View is enabled and has a drag event listener.
18321 * If both are true, then it calls the drag event listener with the
18322 * {@link android.view.DragEvent} it received. If the drag event listener returns
18323 * {@code true}, then dispatchDragEvent() returns {@code true}.
18325 * For all other cases, the method calls the
18326 * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
18327 * method and returns its result.
18330 * This ensures that a drag event is always consumed, even if the View does not have a drag
18331 * event listener. However, if the View has a listener and the listener returns true, then
18332 * onDragEvent() is not called.
18335 public boolean dispatchDragEvent(DragEvent event) {
18336 ListenerInfo li = mListenerInfo;
18337 //noinspection SimplifiableIfStatement
18338 if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
18339 && li.mOnDragListener.onDrag(this, event)) {
18342 return onDragEvent(event);
18345 boolean canAcceptDrag() {
18346 return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
18350 * This needs to be a better API (NOT ON VIEW) before it is exposed. If
18351 * it is ever exposed at all.
18354 public void onCloseSystemDialogs(String reason) {
18358 * Given a Drawable whose bounds have been set to draw into this view,
18359 * update a Region being computed for
18360 * {@link #gatherTransparentRegion(android.graphics.Region)} so
18361 * that any non-transparent parts of the Drawable are removed from the
18362 * given transparent region.
18364 * @param dr The Drawable whose transparency is to be applied to the region.
18365 * @param region A Region holding the current transparency information,
18366 * where any parts of the region that are set are considered to be
18367 * transparent. On return, this region will be modified to have the
18368 * transparency information reduced by the corresponding parts of the
18369 * Drawable that are not transparent.
18372 public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
18374 Log.i("View", "Getting transparent region for: " + this);
18376 final Region r = dr.getTransparentRegion();
18377 final Rect db = dr.getBounds();
18378 final AttachInfo attachInfo = mAttachInfo;
18379 if (r != null && attachInfo != null) {
18380 final int w = getRight()-getLeft();
18381 final int h = getBottom()-getTop();
18383 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
18384 r.op(0, 0, db.left, h, Region.Op.UNION);
18386 if (db.right < w) {
18387 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
18388 r.op(db.right, 0, w, h, Region.Op.UNION);
18391 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
18392 r.op(0, 0, w, db.top, Region.Op.UNION);
18394 if (db.bottom < h) {
18395 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
18396 r.op(0, db.bottom, w, h, Region.Op.UNION);
18398 final int[] location = attachInfo.mTransparentLocation;
18399 getLocationInWindow(location);
18400 r.translate(location[0], location[1]);
18401 region.op(r, Region.Op.INTERSECT);
18403 region.op(db, Region.Op.DIFFERENCE);
18407 private void checkForLongClick(int delayOffset) {
18408 if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
18409 mHasPerformedLongPress = false;
18411 if (mPendingCheckForLongPress == null) {
18412 mPendingCheckForLongPress = new CheckForLongPress();
18414 mPendingCheckForLongPress.rememberWindowAttachCount();
18415 postDelayed(mPendingCheckForLongPress,
18416 ViewConfiguration.getLongPressTimeout() - delayOffset);
18421 * Inflate a view from an XML resource. This convenience method wraps the {@link
18422 * LayoutInflater} class, which provides a full range of options for view inflation.
18424 * @param context The Context object for your activity or application.
18425 * @param resource The resource ID to inflate
18426 * @param root A view group that will be the parent. Used to properly inflate the
18427 * layout_* parameters.
18428 * @see LayoutInflater
18430 public static View inflate(Context context, int resource, ViewGroup root) {
18431 LayoutInflater factory = LayoutInflater.from(context);
18432 return factory.inflate(resource, root);
18436 * Scroll the view with standard behavior for scrolling beyond the normal
18437 * content boundaries. Views that call this method should override
18438 * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
18439 * results of an over-scroll operation.
18441 * Views can use this method to handle any touch or fling-based scrolling.
18443 * @param deltaX Change in X in pixels
18444 * @param deltaY Change in Y in pixels
18445 * @param scrollX Current X scroll value in pixels before applying deltaX
18446 * @param scrollY Current Y scroll value in pixels before applying deltaY
18447 * @param scrollRangeX Maximum content scroll range along the X axis
18448 * @param scrollRangeY Maximum content scroll range along the Y axis
18449 * @param maxOverScrollX Number of pixels to overscroll by in either direction
18450 * along the X axis.
18451 * @param maxOverScrollY Number of pixels to overscroll by in either direction
18452 * along the Y axis.
18453 * @param isTouchEvent true if this scroll operation is the result of a touch event.
18454 * @return true if scrolling was clamped to an over-scroll boundary along either
18455 * axis, false otherwise.
18457 @SuppressWarnings({"UnusedParameters"})
18458 protected boolean overScrollBy(int deltaX, int deltaY,
18459 int scrollX, int scrollY,
18460 int scrollRangeX, int scrollRangeY,
18461 int maxOverScrollX, int maxOverScrollY,
18462 boolean isTouchEvent) {
18463 final int overScrollMode = mOverScrollMode;
18464 final boolean canScrollHorizontal =
18465 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
18466 final boolean canScrollVertical =
18467 computeVerticalScrollRange() > computeVerticalScrollExtent();
18468 final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
18469 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
18470 final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
18471 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
18473 int newScrollX = scrollX + deltaX;
18474 if (!overScrollHorizontal) {
18475 maxOverScrollX = 0;
18478 int newScrollY = scrollY + deltaY;
18479 if (!overScrollVertical) {
18480 maxOverScrollY = 0;
18483 // Clamp values if at the limits and record
18484 final int left = -maxOverScrollX;
18485 final int right = maxOverScrollX + scrollRangeX;
18486 final int top = -maxOverScrollY;
18487 final int bottom = maxOverScrollY + scrollRangeY;
18489 boolean clampedX = false;
18490 if (newScrollX > right) {
18491 newScrollX = right;
18493 } else if (newScrollX < left) {
18498 boolean clampedY = false;
18499 if (newScrollY > bottom) {
18500 newScrollY = bottom;
18502 } else if (newScrollY < top) {
18507 onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
18509 return clampedX || clampedY;
18513 * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
18514 * respond to the results of an over-scroll operation.
18516 * @param scrollX New X scroll value in pixels
18517 * @param scrollY New Y scroll value in pixels
18518 * @param clampedX True if scrollX was clamped to an over-scroll boundary
18519 * @param clampedY True if scrollY was clamped to an over-scroll boundary
18521 protected void onOverScrolled(int scrollX, int scrollY,
18522 boolean clampedX, boolean clampedY) {
18523 // Intentionally empty.
18527 * Returns the over-scroll mode for this view. The result will be
18528 * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
18529 * (allow over-scrolling only if the view content is larger than the container),
18530 * or {@link #OVER_SCROLL_NEVER}.
18532 * @return This view's over-scroll mode.
18534 public int getOverScrollMode() {
18535 return mOverScrollMode;
18539 * Set the over-scroll mode for this view. Valid over-scroll modes are
18540 * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
18541 * (allow over-scrolling only if the view content is larger than the container),
18542 * or {@link #OVER_SCROLL_NEVER}.
18544 * Setting the over-scroll mode of a view will have an effect only if the
18545 * view is capable of scrolling.
18547 * @param overScrollMode The new over-scroll mode for this view.
18549 public void setOverScrollMode(int overScrollMode) {
18550 if (overScrollMode != OVER_SCROLL_ALWAYS &&
18551 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
18552 overScrollMode != OVER_SCROLL_NEVER) {
18553 throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
18555 mOverScrollMode = overScrollMode;
18559 * Enable or disable nested scrolling for this view.
18561 * <p>If this property is set to true the view will be permitted to initiate nested
18562 * scrolling operations with a compatible parent view in the current hierarchy. If this
18563 * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
18564 * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
18565 * the nested scroll.</p>
18567 * @param enabled true to enable nested scrolling, false to disable
18569 * @see #isNestedScrollingEnabled()
18571 public void setNestedScrollingEnabled(boolean enabled) {
18573 mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
18575 stopNestedScroll();
18576 mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
18581 * Returns true if nested scrolling is enabled for this view.
18583 * <p>If nested scrolling is enabled and this View class implementation supports it,
18584 * this view will act as a nested scrolling child view when applicable, forwarding data
18585 * about the scroll operation in progress to a compatible and cooperating nested scrolling
18588 * @return true if nested scrolling is enabled
18590 * @see #setNestedScrollingEnabled(boolean)
18592 public boolean isNestedScrollingEnabled() {
18593 return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
18594 PFLAG3_NESTED_SCROLLING_ENABLED;
18598 * Begin a nestable scroll operation along the given axes.
18600 * <p>A view starting a nested scroll promises to abide by the following contract:</p>
18602 * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
18603 * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
18604 * In the case of touch scrolling the nested scroll will be terminated automatically in
18605 * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
18606 * In the event of programmatic scrolling the caller must explicitly call
18607 * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
18609 * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
18610 * If it returns false the caller may ignore the rest of this contract until the next scroll.
18611 * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
18613 * <p>At each incremental step of the scroll the caller should invoke
18614 * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
18615 * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
18616 * parent at least partially consumed the scroll and the caller should adjust the amount it
18619 * <p>After applying the remainder of the scroll delta the caller should invoke
18620 * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
18621 * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
18622 * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
18625 * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
18626 * {@link #SCROLL_AXIS_VERTICAL}.
18627 * @return true if a cooperative parent was found and nested scrolling has been enabled for
18628 * the current gesture.
18630 * @see #stopNestedScroll()
18631 * @see #dispatchNestedPreScroll(int, int, int[], int[])
18632 * @see #dispatchNestedScroll(int, int, int, int, int[])
18634 public boolean startNestedScroll(int axes) {
18635 if (hasNestedScrollingParent()) {
18636 // Already in progress
18639 if (isNestedScrollingEnabled()) {
18640 ViewParent p = getParent();
18642 while (p != null) {
18644 if (p.onStartNestedScroll(child, this, axes)) {
18645 mNestedScrollingParent = p;
18646 p.onNestedScrollAccepted(child, this, axes);
18649 } catch (AbstractMethodError e) {
18650 Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
18651 "method onStartNestedScroll", e);
18652 // Allow the search upward to continue
18654 if (p instanceof View) {
18664 * Stop a nested scroll in progress.
18666 * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
18668 * @see #startNestedScroll(int)
18670 public void stopNestedScroll() {
18671 if (mNestedScrollingParent != null) {
18672 mNestedScrollingParent.onStopNestedScroll(this);
18673 mNestedScrollingParent = null;
18678 * Returns true if this view has a nested scrolling parent.
18680 * <p>The presence of a nested scrolling parent indicates that this view has initiated
18681 * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
18683 * @return whether this view has a nested scrolling parent
18685 public boolean hasNestedScrollingParent() {
18686 return mNestedScrollingParent != null;
18690 * Dispatch one step of a nested scroll in progress.
18692 * <p>Implementations of views that support nested scrolling should call this to report
18693 * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
18694 * is not currently in progress or nested scrolling is not
18695 * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
18697 * <p>Compatible View implementations should also call
18698 * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
18699 * consuming a component of the scroll event themselves.</p>
18701 * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
18702 * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
18703 * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
18704 * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
18705 * @param offsetInWindow Optional. If not null, on return this will contain the offset
18706 * in local view coordinates of this view from before this operation
18707 * to after it completes. View implementations may use this to adjust
18708 * expected input coordinate tracking.
18709 * @return true if the event was dispatched, false if it could not be dispatched.
18710 * @see #dispatchNestedPreScroll(int, int, int[], int[])
18712 public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
18713 int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
18714 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18715 if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
18718 if (offsetInWindow != null) {
18719 getLocationInWindow(offsetInWindow);
18720 startX = offsetInWindow[0];
18721 startY = offsetInWindow[1];
18724 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
18725 dxUnconsumed, dyUnconsumed);
18727 if (offsetInWindow != null) {
18728 getLocationInWindow(offsetInWindow);
18729 offsetInWindow[0] -= startX;
18730 offsetInWindow[1] -= startY;
18733 } else if (offsetInWindow != null) {
18734 // No motion, no dispatch. Keep offsetInWindow up to date.
18735 offsetInWindow[0] = 0;
18736 offsetInWindow[1] = 0;
18743 * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
18745 * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
18746 * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
18747 * scrolling operation to consume some or all of the scroll operation before the child view
18750 * @param dx Horizontal scroll distance in pixels
18751 * @param dy Vertical scroll distance in pixels
18752 * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
18753 * and consumed[1] the consumed dy.
18754 * @param offsetInWindow Optional. If not null, on return this will contain the offset
18755 * in local view coordinates of this view from before this operation
18756 * to after it completes. View implementations may use this to adjust
18757 * expected input coordinate tracking.
18758 * @return true if the parent consumed some or all of the scroll delta
18759 * @see #dispatchNestedScroll(int, int, int, int, int[])
18761 public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
18762 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18763 if (dx != 0 || dy != 0) {
18766 if (offsetInWindow != null) {
18767 getLocationInWindow(offsetInWindow);
18768 startX = offsetInWindow[0];
18769 startY = offsetInWindow[1];
18772 if (consumed == null) {
18773 if (mTempNestedScrollConsumed == null) {
18774 mTempNestedScrollConsumed = new int[2];
18776 consumed = mTempNestedScrollConsumed;
18780 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
18782 if (offsetInWindow != null) {
18783 getLocationInWindow(offsetInWindow);
18784 offsetInWindow[0] -= startX;
18785 offsetInWindow[1] -= startY;
18787 return consumed[0] != 0 || consumed[1] != 0;
18788 } else if (offsetInWindow != null) {
18789 offsetInWindow[0] = 0;
18790 offsetInWindow[1] = 0;
18797 * Dispatch a fling to a nested scrolling parent.
18799 * <p>This method should be used to indicate that a nested scrolling child has detected
18800 * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
18801 * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
18802 * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
18803 * along a scrollable axis.</p>
18805 * <p>If a nested scrolling child view would normally fling but it is at the edge of
18806 * its own content, it can use this method to delegate the fling to its nested scrolling
18807 * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
18809 * @param velocityX Horizontal fling velocity in pixels per second
18810 * @param velocityY Vertical fling velocity in pixels per second
18811 * @param consumed true if the child consumed the fling, false otherwise
18812 * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
18814 public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
18815 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18816 return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
18822 * Dispatch a fling to a nested scrolling parent before it is processed by this view.
18824 * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
18825 * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
18826 * offsets an opportunity for the parent view in a nested fling to fully consume the fling
18827 * before the child view consumes it. If this method returns <code>true</code>, a nested
18828 * parent view consumed the fling and this view should not scroll as a result.</p>
18830 * <p>For a better user experience, only one view in a nested scrolling chain should consume
18831 * the fling at a time. If a parent view consumed the fling this method will return false.
18832 * Custom view implementations should account for this in two ways:</p>
18835 * <li>If a custom view is paged and needs to settle to a fixed page-point, do not
18836 * call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
18837 * position regardless.</li>
18838 * <li>If a nested parent does consume the fling, this view should not scroll at all,
18839 * even to settle back to a valid idle position.</li>
18842 * <p>Views should also not offer fling velocities to nested parent views along an axis
18843 * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
18844 * should not offer a horizontal fling velocity to its parents since scrolling along that
18845 * axis is not permitted and carrying velocity along that motion does not make sense.</p>
18847 * @param velocityX Horizontal fling velocity in pixels per second
18848 * @param velocityY Vertical fling velocity in pixels per second
18849 * @return true if a nested scrolling parent consumed the fling
18851 public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
18852 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18853 return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
18859 * Gets a scale factor that determines the distance the view should scroll
18860 * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
18861 * @return The vertical scroll scale factor.
18864 protected float getVerticalScrollFactor() {
18865 if (mVerticalScrollFactor == 0) {
18866 TypedValue outValue = new TypedValue();
18867 if (!mContext.getTheme().resolveAttribute(
18868 com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
18869 throw new IllegalStateException(
18870 "Expected theme to define listPreferredItemHeight.");
18872 mVerticalScrollFactor = outValue.getDimension(
18873 mContext.getResources().getDisplayMetrics());
18875 return mVerticalScrollFactor;
18879 * Gets a scale factor that determines the distance the view should scroll
18880 * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
18881 * @return The horizontal scroll scale factor.
18884 protected float getHorizontalScrollFactor() {
18885 // TODO: Should use something else.
18886 return getVerticalScrollFactor();
18890 * Return the value specifying the text direction or policy that was set with
18891 * {@link #setTextDirection(int)}.
18893 * @return the defined text direction. It can be one of:
18895 * {@link #TEXT_DIRECTION_INHERIT},
18896 * {@link #TEXT_DIRECTION_FIRST_STRONG}
18897 * {@link #TEXT_DIRECTION_ANY_RTL},
18898 * {@link #TEXT_DIRECTION_LTR},
18899 * {@link #TEXT_DIRECTION_RTL},
18900 * {@link #TEXT_DIRECTION_LOCALE}
18902 * @attr ref android.R.styleable#View_textDirection
18906 @ViewDebug.ExportedProperty(category = "text", mapping = {
18907 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
18908 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
18909 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
18910 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
18911 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
18912 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
18914 public int getRawTextDirection() {
18915 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
18919 * Set the text direction.
18921 * @param textDirection the direction to set. Should be one of:
18923 * {@link #TEXT_DIRECTION_INHERIT},
18924 * {@link #TEXT_DIRECTION_FIRST_STRONG}
18925 * {@link #TEXT_DIRECTION_ANY_RTL},
18926 * {@link #TEXT_DIRECTION_LTR},
18927 * {@link #TEXT_DIRECTION_RTL},
18928 * {@link #TEXT_DIRECTION_LOCALE}
18930 * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
18931 * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
18932 * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
18934 * @attr ref android.R.styleable#View_textDirection
18936 public void setTextDirection(int textDirection) {
18937 if (getRawTextDirection() != textDirection) {
18938 // Reset the current text direction and the resolved one
18939 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
18940 resetResolvedTextDirection();
18941 // Set the new text direction
18942 mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
18944 resolveTextDirection();
18946 onRtlPropertiesChanged(getLayoutDirection());
18954 * Return the resolved text direction.
18956 * @return the resolved text direction. Returns one of:
18958 * {@link #TEXT_DIRECTION_FIRST_STRONG}
18959 * {@link #TEXT_DIRECTION_ANY_RTL},
18960 * {@link #TEXT_DIRECTION_LTR},
18961 * {@link #TEXT_DIRECTION_RTL},
18962 * {@link #TEXT_DIRECTION_LOCALE}
18964 * @attr ref android.R.styleable#View_textDirection
18966 @ViewDebug.ExportedProperty(category = "text", mapping = {
18967 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
18968 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
18969 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
18970 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
18971 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
18972 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
18974 public int getTextDirection() {
18975 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
18979 * Resolve the text direction.
18981 * @return true if resolution has been done, false otherwise.
18985 public boolean resolveTextDirection() {
18986 // Reset any previous text direction resolution
18987 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
18989 if (hasRtlSupport()) {
18990 // Set resolved text direction flag depending on text direction flag
18991 final int textDirection = getRawTextDirection();
18992 switch(textDirection) {
18993 case TEXT_DIRECTION_INHERIT:
18994 if (!canResolveTextDirection()) {
18995 // We cannot do the resolution if there is no parent, so use the default one
18996 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
18997 // Resolution will need to happen again later
19001 // Parent has not yet resolved, so we still return the default
19003 if (!mParent.isTextDirectionResolved()) {
19004 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19005 // Resolution will need to happen again later
19008 } catch (AbstractMethodError e) {
19009 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19010 " does not fully implement ViewParent", e);
19011 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
19012 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19016 // Set current resolved direction to the same value as the parent's one
19017 int parentResolvedDirection;
19019 parentResolvedDirection = mParent.getTextDirection();
19020 } catch (AbstractMethodError e) {
19021 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19022 " does not fully implement ViewParent", e);
19023 parentResolvedDirection = TEXT_DIRECTION_LTR;
19025 switch (parentResolvedDirection) {
19026 case TEXT_DIRECTION_FIRST_STRONG:
19027 case TEXT_DIRECTION_ANY_RTL:
19028 case TEXT_DIRECTION_LTR:
19029 case TEXT_DIRECTION_RTL:
19030 case TEXT_DIRECTION_LOCALE:
19032 (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
19035 // Default resolved direction is "first strong" heuristic
19036 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19039 case TEXT_DIRECTION_FIRST_STRONG:
19040 case TEXT_DIRECTION_ANY_RTL:
19041 case TEXT_DIRECTION_LTR:
19042 case TEXT_DIRECTION_RTL:
19043 case TEXT_DIRECTION_LOCALE:
19044 // Resolved direction is the same as text direction
19045 mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
19048 // Default resolved direction is "first strong" heuristic
19049 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19052 // Default resolved direction is "first strong" heuristic
19053 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19057 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
19062 * Check if text direction resolution can be done.
19064 * @return true if text direction resolution can be done otherwise return false.
19066 public boolean canResolveTextDirection() {
19067 switch (getRawTextDirection()) {
19068 case TEXT_DIRECTION_INHERIT:
19069 if (mParent != null) {
19071 return mParent.canResolveTextDirection();
19072 } catch (AbstractMethodError e) {
19073 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19074 " does not fully implement ViewParent", e);
19085 * Reset resolved text direction. Text direction will be resolved during a call to
19086 * {@link #onMeasure(int, int)}.
19090 public void resetResolvedTextDirection() {
19091 // Reset any previous text direction resolution
19092 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
19093 // Set to default value
19094 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19098 * @return true if text direction is inherited.
19102 public boolean isTextDirectionInherited() {
19103 return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
19107 * @return true if text direction is resolved.
19109 public boolean isTextDirectionResolved() {
19110 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
19114 * Return the value specifying the text alignment or policy that was set with
19115 * {@link #setTextAlignment(int)}.
19117 * @return the defined text alignment. It can be one of:
19119 * {@link #TEXT_ALIGNMENT_INHERIT},
19120 * {@link #TEXT_ALIGNMENT_GRAVITY},
19121 * {@link #TEXT_ALIGNMENT_CENTER},
19122 * {@link #TEXT_ALIGNMENT_TEXT_START},
19123 * {@link #TEXT_ALIGNMENT_TEXT_END},
19124 * {@link #TEXT_ALIGNMENT_VIEW_START},
19125 * {@link #TEXT_ALIGNMENT_VIEW_END}
19127 * @attr ref android.R.styleable#View_textAlignment
19131 @ViewDebug.ExportedProperty(category = "text", mapping = {
19132 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
19133 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
19134 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
19135 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
19136 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
19137 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
19138 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
19141 public int getRawTextAlignment() {
19142 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
19146 * Set the text alignment.
19148 * @param textAlignment The text alignment to set. Should be one of
19150 * {@link #TEXT_ALIGNMENT_INHERIT},
19151 * {@link #TEXT_ALIGNMENT_GRAVITY},
19152 * {@link #TEXT_ALIGNMENT_CENTER},
19153 * {@link #TEXT_ALIGNMENT_TEXT_START},
19154 * {@link #TEXT_ALIGNMENT_TEXT_END},
19155 * {@link #TEXT_ALIGNMENT_VIEW_START},
19156 * {@link #TEXT_ALIGNMENT_VIEW_END}
19158 * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
19159 * proceeds up the parent chain of the view to get the value. If there is no parent, then it
19160 * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
19162 * @attr ref android.R.styleable#View_textAlignment
19164 public void setTextAlignment(@TextAlignment int textAlignment) {
19165 if (textAlignment != getRawTextAlignment()) {
19166 // Reset the current and resolved text alignment
19167 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
19168 resetResolvedTextAlignment();
19169 // Set the new text alignment
19171 ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
19173 resolveTextAlignment();
19175 onRtlPropertiesChanged(getLayoutDirection());
19183 * Return the resolved text alignment.
19185 * @return the resolved text alignment. Returns one of:
19187 * {@link #TEXT_ALIGNMENT_GRAVITY},
19188 * {@link #TEXT_ALIGNMENT_CENTER},
19189 * {@link #TEXT_ALIGNMENT_TEXT_START},
19190 * {@link #TEXT_ALIGNMENT_TEXT_END},
19191 * {@link #TEXT_ALIGNMENT_VIEW_START},
19192 * {@link #TEXT_ALIGNMENT_VIEW_END}
19194 * @attr ref android.R.styleable#View_textAlignment
19196 @ViewDebug.ExportedProperty(category = "text", mapping = {
19197 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
19198 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
19199 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
19200 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
19201 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
19202 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
19203 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
19206 public int getTextAlignment() {
19207 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
19208 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
19212 * Resolve the text alignment.
19214 * @return true if resolution has been done, false otherwise.
19218 public boolean resolveTextAlignment() {
19219 // Reset any previous text alignment resolution
19220 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
19222 if (hasRtlSupport()) {
19223 // Set resolved text alignment flag depending on text alignment flag
19224 final int textAlignment = getRawTextAlignment();
19225 switch (textAlignment) {
19226 case TEXT_ALIGNMENT_INHERIT:
19227 // Check if we can resolve the text alignment
19228 if (!canResolveTextAlignment()) {
19229 // We cannot do the resolution if there is no parent so use the default
19230 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19231 // Resolution will need to happen again later
19235 // Parent has not yet resolved, so we still return the default
19237 if (!mParent.isTextAlignmentResolved()) {
19238 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19239 // Resolution will need to happen again later
19242 } catch (AbstractMethodError e) {
19243 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19244 " does not fully implement ViewParent", e);
19245 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
19246 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19250 int parentResolvedTextAlignment;
19252 parentResolvedTextAlignment = mParent.getTextAlignment();
19253 } catch (AbstractMethodError e) {
19254 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19255 " does not fully implement ViewParent", e);
19256 parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
19258 switch (parentResolvedTextAlignment) {
19259 case TEXT_ALIGNMENT_GRAVITY:
19260 case TEXT_ALIGNMENT_TEXT_START:
19261 case TEXT_ALIGNMENT_TEXT_END:
19262 case TEXT_ALIGNMENT_CENTER:
19263 case TEXT_ALIGNMENT_VIEW_START:
19264 case TEXT_ALIGNMENT_VIEW_END:
19265 // Resolved text alignment is the same as the parent resolved
19268 (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
19271 // Use default resolved text alignment
19272 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19275 case TEXT_ALIGNMENT_GRAVITY:
19276 case TEXT_ALIGNMENT_TEXT_START:
19277 case TEXT_ALIGNMENT_TEXT_END:
19278 case TEXT_ALIGNMENT_CENTER:
19279 case TEXT_ALIGNMENT_VIEW_START:
19280 case TEXT_ALIGNMENT_VIEW_END:
19281 // Resolved text alignment is the same as text alignment
19282 mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
19285 // Use default resolved text alignment
19286 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19289 // Use default resolved text alignment
19290 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19293 // Set the resolved
19294 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
19299 * Check if text alignment resolution can be done.
19301 * @return true if text alignment resolution can be done otherwise return false.
19303 public boolean canResolveTextAlignment() {
19304 switch (getRawTextAlignment()) {
19305 case TEXT_DIRECTION_INHERIT:
19306 if (mParent != null) {
19308 return mParent.canResolveTextAlignment();
19309 } catch (AbstractMethodError e) {
19310 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19311 " does not fully implement ViewParent", e);
19322 * Reset resolved text alignment. Text alignment will be resolved during a call to
19323 * {@link #onMeasure(int, int)}.
19327 public void resetResolvedTextAlignment() {
19328 // Reset any previous text alignment resolution
19329 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
19331 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19335 * @return true if text alignment is inherited.
19339 public boolean isTextAlignmentInherited() {
19340 return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
19344 * @return true if text alignment is resolved.
19346 public boolean isTextAlignmentResolved() {
19347 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
19351 * Generate a value suitable for use in {@link #setId(int)}.
19352 * This value will not collide with ID values generated at build time by aapt for R.id.
19354 * @return a generated ID value
19356 public static int generateViewId() {
19358 final int result = sNextGeneratedId.get();
19359 // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
19360 int newValue = result + 1;
19361 if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
19362 if (sNextGeneratedId.compareAndSet(result, newValue)) {
19369 * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
19370 * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
19371 * a normal View or a ViewGroup with
19372 * {@link android.view.ViewGroup#isTransitionGroup()} true.
19375 public void captureTransitioningViews(List<View> transitioningViews) {
19376 if (getVisibility() == View.VISIBLE) {
19377 transitioningViews.add(this);
19382 * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
19383 * @param namedElements Will contain all Views in the hierarchy having a transitionName.
19386 public void findNamedViews(Map<String, View> namedElements) {
19387 if (getVisibility() == VISIBLE || mGhostView != null) {
19388 String transitionName = getTransitionName();
19389 if (transitionName != null) {
19390 namedElements.put(transitionName, this);
19399 * A Property wrapper around the <code>alpha</code> functionality handled by the
19400 * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
19402 public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
19404 public void setValue(View object, float value) {
19405 object.setAlpha(value);
19409 public Float get(View object) {
19410 return object.getAlpha();
19415 * A Property wrapper around the <code>translationX</code> functionality handled by the
19416 * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
19418 public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
19420 public void setValue(View object, float value) {
19421 object.setTranslationX(value);
19425 public Float get(View object) {
19426 return object.getTranslationX();
19431 * A Property wrapper around the <code>translationY</code> functionality handled by the
19432 * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
19434 public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
19436 public void setValue(View object, float value) {
19437 object.setTranslationY(value);
19441 public Float get(View object) {
19442 return object.getTranslationY();
19447 * A Property wrapper around the <code>translationZ</code> functionality handled by the
19448 * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
19450 public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
19452 public void setValue(View object, float value) {
19453 object.setTranslationZ(value);
19457 public Float get(View object) {
19458 return object.getTranslationZ();
19463 * A Property wrapper around the <code>x</code> functionality handled by the
19464 * {@link View#setX(float)} and {@link View#getX()} methods.
19466 public static final Property<View, Float> X = new FloatProperty<View>("x") {
19468 public void setValue(View object, float value) {
19469 object.setX(value);
19473 public Float get(View object) {
19474 return object.getX();
19479 * A Property wrapper around the <code>y</code> functionality handled by the
19480 * {@link View#setY(float)} and {@link View#getY()} methods.
19482 public static final Property<View, Float> Y = new FloatProperty<View>("y") {
19484 public void setValue(View object, float value) {
19485 object.setY(value);
19489 public Float get(View object) {
19490 return object.getY();
19495 * A Property wrapper around the <code>z</code> functionality handled by the
19496 * {@link View#setZ(float)} and {@link View#getZ()} methods.
19498 public static final Property<View, Float> Z = new FloatProperty<View>("z") {
19500 public void setValue(View object, float value) {
19501 object.setZ(value);
19505 public Float get(View object) {
19506 return object.getZ();
19511 * A Property wrapper around the <code>rotation</code> functionality handled by the
19512 * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
19514 public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
19516 public void setValue(View object, float value) {
19517 object.setRotation(value);
19521 public Float get(View object) {
19522 return object.getRotation();
19527 * A Property wrapper around the <code>rotationX</code> functionality handled by the
19528 * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
19530 public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
19532 public void setValue(View object, float value) {
19533 object.setRotationX(value);
19537 public Float get(View object) {
19538 return object.getRotationX();
19543 * A Property wrapper around the <code>rotationY</code> functionality handled by the
19544 * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
19546 public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
19548 public void setValue(View object, float value) {
19549 object.setRotationY(value);
19553 public Float get(View object) {
19554 return object.getRotationY();
19559 * A Property wrapper around the <code>scaleX</code> functionality handled by the
19560 * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
19562 public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
19564 public void setValue(View object, float value) {
19565 object.setScaleX(value);
19569 public Float get(View object) {
19570 return object.getScaleX();
19575 * A Property wrapper around the <code>scaleY</code> functionality handled by the
19576 * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
19578 public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
19580 public void setValue(View object, float value) {
19581 object.setScaleY(value);
19585 public Float get(View object) {
19586 return object.getScaleY();
19591 * A MeasureSpec encapsulates the layout requirements passed from parent to child.
19592 * Each MeasureSpec represents a requirement for either the width or the height.
19593 * A MeasureSpec is comprised of a size and a mode. There are three possible
19596 * <dt>UNSPECIFIED</dt>
19598 * The parent has not imposed any constraint on the child. It can be whatever size
19604 * The parent has determined an exact size for the child. The child is going to be
19605 * given those bounds regardless of how big it wants to be.
19610 * The child can be as large as it wants up to the specified size.
19614 * MeasureSpecs are implemented as ints to reduce object allocation. This class
19615 * is provided to pack and unpack the <size, mode> tuple into the int.
19617 public static class MeasureSpec {
19618 private static final int MODE_SHIFT = 30;
19619 private static final int MODE_MASK = 0x3 << MODE_SHIFT;
19622 * Measure specification mode: The parent has not imposed any constraint
19623 * on the child. It can be whatever size it wants.
19625 public static final int UNSPECIFIED = 0 << MODE_SHIFT;
19628 * Measure specification mode: The parent has determined an exact size
19629 * for the child. The child is going to be given those bounds regardless
19630 * of how big it wants to be.
19632 public static final int EXACTLY = 1 << MODE_SHIFT;
19635 * Measure specification mode: The child can be as large as it wants up
19636 * to the specified size.
19638 public static final int AT_MOST = 2 << MODE_SHIFT;
19641 * Creates a measure specification based on the supplied size and mode.
19643 * The mode must always be one of the following:
19645 * <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
19646 * <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
19647 * <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
19650 * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
19651 * implementation was such that the order of arguments did not matter
19652 * and overflow in either value could impact the resulting MeasureSpec.
19653 * {@link android.widget.RelativeLayout} was affected by this bug.
19654 * Apps targeting API levels greater than 17 will get the fixed, more strict
19657 * @param size the size of the measure specification
19658 * @param mode the mode of the measure specification
19659 * @return the measure specification based on size and mode
19661 public static int makeMeasureSpec(int size, int mode) {
19662 if (sUseBrokenMakeMeasureSpec) {
19663 return size + mode;
19665 return (size & ~MODE_MASK) | (mode & MODE_MASK);
19670 * Extracts the mode from the supplied measure specification.
19672 * @param measureSpec the measure specification to extract the mode from
19673 * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
19674 * {@link android.view.View.MeasureSpec#AT_MOST} or
19675 * {@link android.view.View.MeasureSpec#EXACTLY}
19677 public static int getMode(int measureSpec) {
19678 return (measureSpec & MODE_MASK);
19682 * Extracts the size from the supplied measure specification.
19684 * @param measureSpec the measure specification to extract the size from
19685 * @return the size in pixels defined in the supplied measure specification
19687 public static int getSize(int measureSpec) {
19688 return (measureSpec & ~MODE_MASK);
19691 static int adjust(int measureSpec, int delta) {
19692 final int mode = getMode(measureSpec);
19693 if (mode == UNSPECIFIED) {
19694 // No need to adjust size for UNSPECIFIED mode.
19695 return makeMeasureSpec(0, UNSPECIFIED);
19697 int size = getSize(measureSpec) + delta;
19699 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
19700 ") spec: " + toString(measureSpec) + " delta: " + delta);
19703 return makeMeasureSpec(size, mode);
19707 * Returns a String representation of the specified measure
19710 * @param measureSpec the measure specification to convert to a String
19711 * @return a String with the following format: "MeasureSpec: MODE SIZE"
19713 public static String toString(int measureSpec) {
19714 int mode = getMode(measureSpec);
19715 int size = getSize(measureSpec);
19717 StringBuilder sb = new StringBuilder("MeasureSpec: ");
19719 if (mode == UNSPECIFIED)
19720 sb.append("UNSPECIFIED ");
19721 else if (mode == EXACTLY)
19722 sb.append("EXACTLY ");
19723 else if (mode == AT_MOST)
19724 sb.append("AT_MOST ");
19726 sb.append(mode).append(" ");
19729 return sb.toString();
19733 private final class CheckForLongPress implements Runnable {
19734 private int mOriginalWindowAttachCount;
19737 public void run() {
19738 if (isPressed() && (mParent != null)
19739 && mOriginalWindowAttachCount == mWindowAttachCount) {
19740 if (performLongClick()) {
19741 mHasPerformedLongPress = true;
19746 public void rememberWindowAttachCount() {
19747 mOriginalWindowAttachCount = mWindowAttachCount;
19751 private final class CheckForTap implements Runnable {
19756 public void run() {
19757 mPrivateFlags &= ~PFLAG_PREPRESSED;
19758 setPressed(true, x, y);
19759 checkForLongClick(ViewConfiguration.getTapTimeout());
19763 private final class PerformClick implements Runnable {
19765 public void run() {
19771 public void hackTurnOffWindowResizeAnim(boolean off) {
19772 mAttachInfo.mTurnOffWindowResizeAnim = off;
19776 * This method returns a ViewPropertyAnimator object, which can be used to animate
19777 * specific properties on this View.
19779 * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
19781 public ViewPropertyAnimator animate() {
19782 if (mAnimator == null) {
19783 mAnimator = new ViewPropertyAnimator(this);
19789 * Sets the name of the View to be used to identify Views in Transitions.
19790 * Names should be unique in the View hierarchy.
19792 * @param transitionName The name of the View to uniquely identify it for Transitions.
19794 public final void setTransitionName(String transitionName) {
19795 mTransitionName = transitionName;
19799 * Returns the name of the View to be used to identify Views in Transitions.
19800 * Names should be unique in the View hierarchy.
19802 * <p>This returns null if the View has not been given a name.</p>
19804 * @return The name used of the View to be used to identify Views in Transitions or null
19805 * if no name has been given.
19807 @ViewDebug.ExportedProperty
19808 public String getTransitionName() {
19809 return mTransitionName;
19813 * Interface definition for a callback to be invoked when a hardware key event is
19814 * dispatched to this view. The callback will be invoked before the key event is
19815 * given to the view. This is only useful for hardware keyboards; a software input
19816 * method has no obligation to trigger this listener.
19818 public interface OnKeyListener {
19820 * Called when a hardware key is dispatched to a view. This allows listeners to
19821 * get a chance to respond before the target view.
19822 * <p>Key presses in software keyboards will generally NOT trigger this method,
19823 * although some may elect to do so in some situations. Do not assume a
19824 * software input method has to be key-based; even if it is, it may use key presses
19825 * in a different way than you expect, so there is no way to reliably catch soft
19826 * input key presses.
19828 * @param v The view the key has been dispatched to.
19829 * @param keyCode The code for the physical key that was pressed
19830 * @param event The KeyEvent object containing full information about
19832 * @return True if the listener has consumed the event, false otherwise.
19834 boolean onKey(View v, int keyCode, KeyEvent event);
19838 * Interface definition for a callback to be invoked when a touch event is
19839 * dispatched to this view. The callback will be invoked before the touch
19840 * event is given to the view.
19842 public interface OnTouchListener {
19844 * Called when a touch event is dispatched to a view. This allows listeners to
19845 * get a chance to respond before the target view.
19847 * @param v The view the touch event has been dispatched to.
19848 * @param event The MotionEvent object containing full information about
19850 * @return True if the listener has consumed the event, false otherwise.
19852 boolean onTouch(View v, MotionEvent event);
19856 * Interface definition for a callback to be invoked when a hover event is
19857 * dispatched to this view. The callback will be invoked before the hover
19858 * event is given to the view.
19860 public interface OnHoverListener {
19862 * Called when a hover event is dispatched to a view. This allows listeners to
19863 * get a chance to respond before the target view.
19865 * @param v The view the hover event has been dispatched to.
19866 * @param event The MotionEvent object containing full information about
19868 * @return True if the listener has consumed the event, false otherwise.
19870 boolean onHover(View v, MotionEvent event);
19874 * Interface definition for a callback to be invoked when a generic motion event is
19875 * dispatched to this view. The callback will be invoked before the generic motion
19876 * event is given to the view.
19878 public interface OnGenericMotionListener {
19880 * Called when a generic motion event is dispatched to a view. This allows listeners to
19881 * get a chance to respond before the target view.
19883 * @param v The view the generic motion event has been dispatched to.
19884 * @param event The MotionEvent object containing full information about
19886 * @return True if the listener has consumed the event, false otherwise.
19888 boolean onGenericMotion(View v, MotionEvent event);
19892 * Interface definition for a callback to be invoked when a view has been clicked and held.
19894 public interface OnLongClickListener {
19896 * Called when a view has been clicked and held.
19898 * @param v The view that was clicked and held.
19900 * @return true if the callback consumed the long click, false otherwise.
19902 boolean onLongClick(View v);
19906 * Interface definition for a callback to be invoked when a drag is being dispatched
19907 * to this view. The callback will be invoked before the hosting view's own
19908 * onDrag(event) method. If the listener wants to fall back to the hosting view's
19909 * onDrag(event) behavior, it should return 'false' from this callback.
19911 * <div class="special reference">
19912 * <h3>Developer Guides</h3>
19913 * <p>For a guide to implementing drag and drop features, read the
19914 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
19917 public interface OnDragListener {
19919 * Called when a drag event is dispatched to a view. This allows listeners
19920 * to get a chance to override base View behavior.
19922 * @param v The View that received the drag event.
19923 * @param event The {@link android.view.DragEvent} object for the drag event.
19924 * @return {@code true} if the drag event was handled successfully, or {@code false}
19925 * if the drag event was not handled. Note that {@code false} will trigger the View
19926 * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
19928 boolean onDrag(View v, DragEvent event);
19932 * Interface definition for a callback to be invoked when the focus state of
19935 public interface OnFocusChangeListener {
19937 * Called when the focus state of a view has changed.
19939 * @param v The view whose state has changed.
19940 * @param hasFocus The new focus state of v.
19942 void onFocusChange(View v, boolean hasFocus);
19946 * Interface definition for a callback to be invoked when a view is clicked.
19948 public interface OnClickListener {
19950 * Called when a view has been clicked.
19952 * @param v The view that was clicked.
19954 void onClick(View v);
19958 * Interface definition for a callback to be invoked when the context menu
19959 * for this view is being built.
19961 public interface OnCreateContextMenuListener {
19963 * Called when the context menu for this view is being built. It is not
19964 * safe to hold onto the menu after this method returns.
19966 * @param menu The context menu that is being built
19967 * @param v The view for which the context menu is being built
19968 * @param menuInfo Extra information about the item for which the
19969 * context menu should be shown. This information will vary
19970 * depending on the class of v.
19972 void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
19976 * Interface definition for a callback to be invoked when the status bar changes
19977 * visibility. This reports <strong>global</strong> changes to the system UI
19978 * state, not what the application is requesting.
19980 * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
19982 public interface OnSystemUiVisibilityChangeListener {
19984 * Called when the status bar changes visibility because of a call to
19985 * {@link View#setSystemUiVisibility(int)}.
19987 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19988 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
19989 * This tells you the <strong>global</strong> state of these UI visibility
19990 * flags, not what your app is currently applying.
19992 public void onSystemUiVisibilityChange(int visibility);
19996 * Interface definition for a callback to be invoked when this view is attached
19997 * or detached from its window.
19999 public interface OnAttachStateChangeListener {
20001 * Called when the view is attached to a window.
20002 * @param v The view that was attached
20004 public void onViewAttachedToWindow(View v);
20006 * Called when the view is detached from a window.
20007 * @param v The view that was detached
20009 public void onViewDetachedFromWindow(View v);
20013 * Listener for applying window insets on a view in a custom way.
20015 * <p>Apps may choose to implement this interface if they want to apply custom policy
20016 * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
20018 * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
20019 * method will be called instead of the View's own
20020 * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
20021 * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
20022 * the View's normal behavior as part of its own.</p>
20024 public interface OnApplyWindowInsetsListener {
20026 * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
20027 * on a View, this listener method will be called instead of the view's own
20028 * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
20030 * @param v The view applying window insets
20031 * @param insets The insets to apply
20032 * @return The insets supplied, minus any insets that were consumed
20034 public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
20037 private final class UnsetPressedState implements Runnable {
20039 public void run() {
20045 * Base class for derived classes that want to save and restore their own
20046 * state in {@link android.view.View#onSaveInstanceState()}.
20048 public static class BaseSavedState extends AbsSavedState {
20050 * Constructor used when reading from a parcel. Reads the state of the superclass.
20054 public BaseSavedState(Parcel source) {
20059 * Constructor called by derived classes when creating their SavedState objects
20061 * @param superState The state of the superclass of this view
20063 public BaseSavedState(Parcelable superState) {
20067 public static final Parcelable.Creator<BaseSavedState> CREATOR =
20068 new Parcelable.Creator<BaseSavedState>() {
20069 public BaseSavedState createFromParcel(Parcel in) {
20070 return new BaseSavedState(in);
20073 public BaseSavedState[] newArray(int size) {
20074 return new BaseSavedState[size];
20080 * A set of information given to a view when it is attached to its parent
20083 final static class AttachInfo {
20084 interface Callbacks {
20085 void playSoundEffect(int effectId);
20086 boolean performHapticFeedback(int effectId, boolean always);
20090 * InvalidateInfo is used to post invalidate(int, int, int, int) messages
20091 * to a Handler. This class contains the target (View) to invalidate and
20092 * the coordinates of the dirty rectangle.
20094 * For performance purposes, this class also implements a pool of up to
20095 * POOL_LIMIT objects that get reused. This reduces memory allocations
20096 * whenever possible.
20098 static class InvalidateInfo {
20099 private static final int POOL_LIMIT = 10;
20101 private static final SynchronizedPool<InvalidateInfo> sPool =
20102 new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
20111 public static InvalidateInfo obtain() {
20112 InvalidateInfo instance = sPool.acquire();
20113 return (instance != null) ? instance : new InvalidateInfo();
20116 public void recycle() {
20118 sPool.release(this);
20122 final IWindowSession mSession;
20124 final IWindow mWindow;
20126 final IBinder mWindowToken;
20128 final Display mDisplay;
20130 final Callbacks mRootCallbacks;
20132 IWindowId mIWindowId;
20133 WindowId mWindowId;
20136 * The top view of the hierarchy.
20140 IBinder mPanelParentWindowToken;
20142 boolean mHardwareAccelerated;
20143 boolean mHardwareAccelerationRequested;
20144 HardwareRenderer mHardwareRenderer;
20145 List<RenderNode> mPendingAnimatingRenderNodes;
20148 * The state of the display to which the window is attached, as reported
20149 * by {@link Display#getState()}. Note that the display state constants
20150 * declared by {@link Display} do not exactly line up with the screen state
20151 * constants declared by {@link View} (there are more display states than
20154 int mDisplayState = Display.STATE_UNKNOWN;
20157 * Scale factor used by the compatibility mode
20159 float mApplicationScale;
20162 * Indicates whether the application is in compatibility mode
20164 boolean mScalingRequired;
20167 * If set, ViewRootImpl doesn't use its lame animation for when the window resizes.
20169 boolean mTurnOffWindowResizeAnim;
20172 * Left position of this view's window
20177 * Top position of this view's window
20182 * Indicates whether views need to use 32-bit drawing caches
20184 boolean mUse32BitDrawingCache;
20187 * For windows that are full-screen but using insets to layout inside
20188 * of the screen areas, these are the current insets to appear inside
20189 * the overscan area of the display.
20191 final Rect mOverscanInsets = new Rect();
20194 * For windows that are full-screen but using insets to layout inside
20195 * of the screen decorations, these are the current insets for the
20196 * content of the window.
20198 final Rect mContentInsets = new Rect();
20201 * For windows that are full-screen but using insets to layout inside
20202 * of the screen decorations, these are the current insets for the
20203 * actual visible parts of the window.
20205 final Rect mVisibleInsets = new Rect();
20208 * For windows that are full-screen but using insets to layout inside
20209 * of the screen decorations, these are the current insets for the
20210 * stable system windows.
20212 final Rect mStableInsets = new Rect();
20215 * The internal insets given by this window. This value is
20216 * supplied by the client (through
20217 * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
20218 * be given to the window manager when changed to be used in laying
20219 * out windows behind it.
20221 final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
20222 = new ViewTreeObserver.InternalInsetsInfo();
20225 * Set to true when mGivenInternalInsets is non-empty.
20227 boolean mHasNonEmptyGivenInternalInsets;
20230 * All views in the window's hierarchy that serve as scroll containers,
20231 * used to determine if the window can be resized or must be panned
20232 * to adjust for a soft input area.
20234 final ArrayList<View> mScrollContainers = new ArrayList<View>();
20236 final KeyEvent.DispatcherState mKeyDispatchState
20237 = new KeyEvent.DispatcherState();
20240 * Indicates whether the view's window currently has the focus.
20242 boolean mHasWindowFocus;
20245 * The current visibility of the window.
20247 int mWindowVisibility;
20250 * Indicates the time at which drawing started to occur.
20255 * Indicates whether or not ignoring the DIRTY_MASK flags.
20257 boolean mIgnoreDirtyState;
20260 * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
20261 * to avoid clearing that flag prematurely.
20263 boolean mSetIgnoreDirtyState = false;
20266 * Indicates whether the view's window is currently in touch mode.
20268 boolean mInTouchMode;
20271 * Indicates whether the view has requested unbuffered input dispatching for the current
20274 boolean mUnbufferedDispatchRequested;
20277 * Indicates that ViewAncestor should trigger a global layout change
20278 * the next time it performs a traversal
20280 boolean mRecomputeGlobalAttributes;
20283 * Always report new attributes at next traversal.
20285 boolean mForceReportNewAttributes;
20288 * Set during a traveral if any views want to keep the screen on.
20290 boolean mKeepScreenOn;
20293 * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
20295 int mSystemUiVisibility;
20298 * Hack to force certain system UI visibility flags to be cleared.
20300 int mDisabledSystemUiVisibility;
20303 * Last global system UI visibility reported by the window manager.
20305 int mGlobalSystemUiVisibility;
20308 * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
20311 boolean mHasSystemUiListeners;
20314 * Set if the window has requested to extend into the overscan region
20315 * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
20317 boolean mOverscanRequested;
20320 * Set if the visibility of any views has changed.
20322 boolean mViewVisibilityChanged;
20325 * Set to true if a view has been scrolled.
20327 boolean mViewScrollChanged;
20330 * Set to true if high contrast mode enabled
20332 boolean mHighContrastText;
20335 * Global to the view hierarchy used as a temporary for dealing with
20336 * x/y points in the transparent region computations.
20338 final int[] mTransparentLocation = new int[2];
20341 * Global to the view hierarchy used as a temporary for dealing with
20342 * x/y points in the ViewGroup.invalidateChild implementation.
20344 final int[] mInvalidateChildLocation = new int[2];
20347 * Global to the view hierarchy used as a temporary for dealng with
20348 * computing absolute on-screen location.
20350 final int[] mTmpLocation = new int[2];
20353 * Global to the view hierarchy used as a temporary for dealing with
20354 * x/y location when view is transformed.
20356 final float[] mTmpTransformLocation = new float[2];
20359 * The view tree observer used to dispatch global events like
20360 * layout, pre-draw, touch mode change, etc.
20362 final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
20365 * A Canvas used by the view hierarchy to perform bitmap caching.
20370 * The view root impl.
20372 final ViewRootImpl mViewRootImpl;
20375 * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
20376 * handler can be used to pump events in the UI events queue.
20378 final Handler mHandler;
20381 * Temporary for use in computing invalidate rectangles while
20382 * calling up the hierarchy.
20384 final Rect mTmpInvalRect = new Rect();
20387 * Temporary for use in computing hit areas with transformed views
20389 final RectF mTmpTransformRect = new RectF();
20392 * Temporary for use in computing hit areas with transformed views
20394 final RectF mTmpTransformRect1 = new RectF();
20397 * Temporary list of rectanges.
20399 final List<RectF> mTmpRectList = new ArrayList<>();
20402 * Temporary for use in transforming invalidation rect
20404 final Matrix mTmpMatrix = new Matrix();
20407 * Temporary for use in transforming invalidation rect
20409 final Transformation mTmpTransformation = new Transformation();
20412 * Temporary for use in querying outlines from OutlineProviders
20414 final Outline mTmpOutline = new Outline();
20417 * Temporary list for use in collecting focusable descendents of a view.
20419 final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
20422 * The id of the window for accessibility purposes.
20424 int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
20427 * Flags related to accessibility processing.
20429 * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
20430 * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
20432 int mAccessibilityFetchFlags;
20435 * The drawable for highlighting accessibility focus.
20437 Drawable mAccessibilityFocusDrawable;
20440 * Show where the margins, bounds and layout bounds are for each view.
20442 boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
20445 * Point used to compute visible regions.
20447 final Point mPoint = new Point();
20450 * Used to track which View originated a requestLayout() call, used when
20451 * requestLayout() is called during layout.
20453 View mViewRequestingLayout;
20456 * Creates a new set of attachment information with the specified
20457 * events handler and thread.
20459 * @param handler the events handler the view must use
20461 AttachInfo(IWindowSession session, IWindow window, Display display,
20462 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
20463 mSession = session;
20465 mWindowToken = window.asBinder();
20466 mDisplay = display;
20467 mViewRootImpl = viewRootImpl;
20468 mHandler = handler;
20469 mRootCallbacks = effectPlayer;
20474 * <p>ScrollabilityCache holds various fields used by a View when scrolling
20475 * is supported. This avoids keeping too many unused fields in most
20476 * instances of View.</p>
20478 private static class ScrollabilityCache implements Runnable {
20481 * Scrollbars are not visible
20483 public static final int OFF = 0;
20486 * Scrollbars are visible
20488 public static final int ON = 1;
20491 * Scrollbars are fading away
20493 public static final int FADING = 2;
20495 public boolean fadeScrollBars;
20497 public int fadingEdgeLength;
20498 public int scrollBarDefaultDelayBeforeFade;
20499 public int scrollBarFadeDuration;
20501 public int scrollBarSize;
20502 public ScrollBarDrawable scrollBar;
20503 public float[] interpolatorValues;
20506 public final Paint paint;
20507 public final Matrix matrix;
20508 public Shader shader;
20510 public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
20512 private static final float[] OPAQUE = { 255 };
20513 private static final float[] TRANSPARENT = { 0.0f };
20516 * When fading should start. This time moves into the future every time
20517 * a new scroll happens. Measured based on SystemClock.uptimeMillis()
20519 public long fadeStartTime;
20523 * The current state of the scrollbars: ON, OFF, or FADING
20525 public int state = OFF;
20527 private int mLastColor;
20529 public ScrollabilityCache(ViewConfiguration configuration, View host) {
20530 fadingEdgeLength = configuration.getScaledFadingEdgeLength();
20531 scrollBarSize = configuration.getScaledScrollBarSize();
20532 scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
20533 scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
20535 paint = new Paint();
20536 matrix = new Matrix();
20537 // use use a height of 1, and then wack the matrix each time we
20538 // actually use it.
20539 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
20540 paint.setShader(shader);
20541 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
20546 public void setFadeColor(int color) {
20547 if (color != mLastColor) {
20548 mLastColor = color;
20551 shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
20552 color & 0x00FFFFFF, Shader.TileMode.CLAMP);
20553 paint.setShader(shader);
20554 // Restore the default transfer mode (src_over)
20555 paint.setXfermode(null);
20557 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
20558 paint.setShader(shader);
20559 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
20564 public void run() {
20565 long now = AnimationUtils.currentAnimationTimeMillis();
20566 if (now >= fadeStartTime) {
20568 // the animation fades the scrollbars out by changing
20569 // the opacity (alpha) from fully opaque to fully
20571 int nextFrame = (int) now;
20572 int framesCount = 0;
20574 Interpolator interpolator = scrollBarInterpolator;
20577 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
20580 nextFrame += scrollBarFadeDuration;
20581 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
20585 // Kick off the fade animation
20586 host.invalidate(true);
20592 * Resuable callback for sending
20593 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
20595 private class SendViewScrolledAccessibilityEvent implements Runnable {
20596 public volatile boolean mIsPending;
20598 public void run() {
20599 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
20600 mIsPending = false;
20606 * This class represents a delegate that can be registered in a {@link View}
20607 * to enhance accessibility support via composition rather via inheritance.
20608 * It is specifically targeted to widget developers that extend basic View
20609 * classes i.e. classes in package android.view, that would like their
20610 * applications to be backwards compatible.
20612 * <div class="special reference">
20613 * <h3>Developer Guides</h3>
20614 * <p>For more information about making applications accessible, read the
20615 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
20616 * developer guide.</p>
20619 * A scenario in which a developer would like to use an accessibility delegate
20620 * is overriding a method introduced in a later API version then the minimal API
20621 * version supported by the application. For example, the method
20622 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
20623 * in API version 4 when the accessibility APIs were first introduced. If a
20624 * developer would like his application to run on API version 4 devices (assuming
20625 * all other APIs used by the application are version 4 or lower) and take advantage
20626 * of this method, instead of overriding the method which would break the application's
20627 * backwards compatibility, he can override the corresponding method in this
20628 * delegate and register the delegate in the target View if the API version of
20629 * the system is high enough i.e. the API version is same or higher to the API
20630 * version that introduced
20631 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
20634 * Here is an example implementation:
20637 * if (Build.VERSION.SDK_INT >= 14) {
20638 * // If the API version is equal of higher than the version in
20639 * // which onInitializeAccessibilityNodeInfo was introduced we
20640 * // register a delegate with a customized implementation.
20641 * View view = findViewById(R.id.view_id);
20642 * view.setAccessibilityDelegate(new AccessibilityDelegate() {
20643 * public void onInitializeAccessibilityNodeInfo(View host,
20644 * AccessibilityNodeInfo info) {
20645 * // Let the default implementation populate the info.
20646 * super.onInitializeAccessibilityNodeInfo(host, info);
20647 * // Set some other information.
20648 * info.setEnabled(host.isEnabled());
20652 * </code></pre></p>
20654 * This delegate contains methods that correspond to the accessibility methods
20655 * in View. If a delegate has been specified the implementation in View hands
20656 * off handling to the corresponding method in this delegate. The default
20657 * implementation the delegate methods behaves exactly as the corresponding
20658 * method in View for the case of no accessibility delegate been set. Hence,
20659 * to customize the behavior of a View method, clients can override only the
20660 * corresponding delegate method without altering the behavior of the rest
20661 * accessibility related methods of the host view.
20664 public static class AccessibilityDelegate {
20667 * Sends an accessibility event of the given type. If accessibility is not
20668 * enabled this method has no effect.
20670 * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
20671 * View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
20675 * @param host The View hosting the delegate.
20676 * @param eventType The type of the event to send.
20678 * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
20680 public void sendAccessibilityEvent(View host, int eventType) {
20681 host.sendAccessibilityEventInternal(eventType);
20685 * Performs the specified accessibility action on the view. For
20686 * possible accessibility actions look at {@link AccessibilityNodeInfo}.
20688 * The default implementation behaves as
20689 * {@link View#performAccessibilityAction(int, Bundle)
20690 * View#performAccessibilityAction(int, Bundle)} for the case of
20691 * no accessibility delegate been set.
20694 * @param action The action to perform.
20695 * @return Whether the action was performed.
20697 * @see View#performAccessibilityAction(int, Bundle)
20698 * View#performAccessibilityAction(int, Bundle)
20700 public boolean performAccessibilityAction(View host, int action, Bundle args) {
20701 return host.performAccessibilityActionInternal(action, args);
20705 * Sends an accessibility event. This method behaves exactly as
20706 * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
20707 * empty {@link AccessibilityEvent} and does not perform a check whether
20708 * accessibility is enabled.
20710 * The default implementation behaves as
20711 * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
20712 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
20713 * the case of no accessibility delegate been set.
20716 * @param host The View hosting the delegate.
20717 * @param event The event to send.
20719 * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
20720 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)
20722 public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
20723 host.sendAccessibilityEventUncheckedInternal(event);
20727 * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
20728 * to its children for adding their text content to the event.
20730 * The default implementation behaves as
20731 * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
20732 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
20733 * the case of no accessibility delegate been set.
20736 * @param host The View hosting the delegate.
20737 * @param event The event.
20738 * @return True if the event population was completed.
20740 * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
20741 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
20743 public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
20744 return host.dispatchPopulateAccessibilityEventInternal(event);
20748 * Gives a chance to the host View to populate the accessibility event with its
20751 * The default implementation behaves as
20752 * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
20753 * View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
20754 * the case of no accessibility delegate been set.
20757 * @param host The View hosting the delegate.
20758 * @param event The accessibility event which to populate.
20760 * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
20761 * View#onPopulateAccessibilityEvent(AccessibilityEvent)
20763 public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
20764 host.onPopulateAccessibilityEventInternal(event);
20768 * Initializes an {@link AccessibilityEvent} with information about the
20769 * the host View which is the event source.
20771 * The default implementation behaves as
20772 * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
20773 * View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
20774 * the case of no accessibility delegate been set.
20777 * @param host The View hosting the delegate.
20778 * @param event The event to initialize.
20780 * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
20781 * View#onInitializeAccessibilityEvent(AccessibilityEvent)
20783 public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
20784 host.onInitializeAccessibilityEventInternal(event);
20788 * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
20790 * The default implementation behaves as
20791 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
20792 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
20793 * the case of no accessibility delegate been set.
20796 * @param host The View hosting the delegate.
20797 * @param info The instance to initialize.
20799 * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
20800 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
20802 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
20803 host.onInitializeAccessibilityNodeInfoInternal(info);
20807 * Called when a child of the host View has requested sending an
20808 * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
20809 * to augment the event.
20811 * The default implementation behaves as
20812 * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
20813 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
20814 * the case of no accessibility delegate been set.
20817 * @param host The View hosting the delegate.
20818 * @param child The child which requests sending the event.
20819 * @param event The event to be sent.
20820 * @return True if the event should be sent
20822 * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
20823 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
20825 public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
20826 AccessibilityEvent event) {
20827 return host.onRequestSendAccessibilityEventInternal(child, event);
20831 * Gets the provider for managing a virtual view hierarchy rooted at this View
20832 * and reported to {@link android.accessibilityservice.AccessibilityService}s
20833 * that explore the window content.
20835 * The default implementation behaves as
20836 * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
20837 * the case of no accessibility delegate been set.
20840 * @return The provider.
20842 * @see AccessibilityNodeProvider
20844 public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
20849 * Returns an {@link AccessibilityNodeInfo} representing the host view from the
20850 * point of view of an {@link android.accessibilityservice.AccessibilityService}.
20851 * This method is responsible for obtaining an accessibility node info from a
20852 * pool of reusable instances and calling
20853 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
20854 * view to initialize the former.
20856 * <strong>Note:</strong> The client is responsible for recycling the obtained
20857 * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
20861 * The default implementation behaves as
20862 * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
20863 * the case of no accessibility delegate been set.
20865 * @return A populated {@link AccessibilityNodeInfo}.
20867 * @see AccessibilityNodeInfo
20871 public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
20872 return host.createAccessibilityNodeInfoInternal();
20876 private class MatchIdPredicate implements Predicate<View> {
20880 public boolean apply(View view) {
20881 return (view.mID == mId);
20885 private class MatchLabelForPredicate implements Predicate<View> {
20886 private int mLabeledId;
20889 public boolean apply(View view) {
20890 return (view.mLabelForId == mLabeledId);
20894 private class SendViewStateChangedAccessibilityEvent implements Runnable {
20895 private int mChangeTypes = 0;
20896 private boolean mPosted;
20897 private boolean mPostedWithDelay;
20898 private long mLastEventTimeMillis;
20901 public void run() {
20903 mPostedWithDelay = false;
20904 mLastEventTimeMillis = SystemClock.uptimeMillis();
20905 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
20906 final AccessibilityEvent event = AccessibilityEvent.obtain();
20907 event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
20908 event.setContentChangeTypes(mChangeTypes);
20909 sendAccessibilityEventUnchecked(event);
20914 public void runOrPost(int changeType) {
20915 mChangeTypes |= changeType;
20917 // If this is a live region or the child of a live region, collect
20918 // all events from this frame and send them on the next frame.
20919 if (inLiveRegion()) {
20920 // If we're already posted with a delay, remove that.
20921 if (mPostedWithDelay) {
20922 removeCallbacks(this);
20923 mPostedWithDelay = false;
20925 // Only post if we're not already posted.
20937 final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
20938 final long minEventIntevalMillis =
20939 ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
20940 if (timeSinceLastMillis >= minEventIntevalMillis) {
20941 removeCallbacks(this);
20944 postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
20945 mPostedWithDelay = true;
20950 private boolean inLiveRegion() {
20951 if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
20955 ViewParent parent = getParent();
20956 while (parent instanceof View) {
20957 if (((View) parent).getAccessibilityLiveRegion()
20958 != View.ACCESSIBILITY_LIVE_REGION_NONE) {
20961 parent = parent.getParent();
20968 * Dump all private flags in readable format, useful for documentation and
20971 private static void dumpFlags() {
20972 final HashMap<String, String> found = Maps.newHashMap();
20974 for (Field field : View.class.getDeclaredFields()) {
20975 final int modifiers = field.getModifiers();
20976 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
20977 if (field.getType().equals(int.class)) {
20978 final int value = field.getInt(null);
20979 dumpFlag(found, field.getName(), value);
20980 } else if (field.getType().equals(int[].class)) {
20981 final int[] values = (int[]) field.get(null);
20982 for (int i = 0; i < values.length; i++) {
20983 dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
20988 } catch (IllegalAccessException e) {
20989 throw new RuntimeException(e);
20992 final ArrayList<String> keys = Lists.newArrayList();
20993 keys.addAll(found.keySet());
20994 Collections.sort(keys);
20995 for (String key : keys) {
20996 Log.d(VIEW_LOG_TAG, found.get(key));
21000 private static void dumpFlag(HashMap<String, String> found, String name, int value) {
21001 // Sort flags by prefix, then by bits, always keeping unique keys
21002 final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
21003 final int prefix = name.indexOf('_');
21004 final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
21005 final String output = bits + " " + name;
21006 found.put(key, output);