1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.view; 18 19 import android.animation.AnimatorInflater; 20 import android.animation.StateListAnimator; 21 import android.annotation.CallSuper; 22 import android.annotation.ColorInt; 23 import android.annotation.DrawableRes; 24 import android.annotation.FloatRange; 25 import android.annotation.IdRes; 26 import android.annotation.IntDef; 27 import android.annotation.IntRange; 28 import android.annotation.LayoutRes; 29 import android.annotation.NonNull; 30 import android.annotation.Nullable; 31 import android.annotation.Size; 32 import android.annotation.UiThread; 33 import android.content.ClipData; 34 import android.content.Context; 35 import android.content.ContextWrapper; 36 import android.content.Intent; 37 import android.content.res.ColorStateList; 38 import android.content.res.Configuration; 39 import android.content.res.Resources; 40 import android.content.res.TypedArray; 41 import android.graphics.Bitmap; 42 import android.graphics.Canvas; 43 import android.graphics.Insets; 44 import android.graphics.Interpolator; 45 import android.graphics.LinearGradient; 46 import android.graphics.Matrix; 47 import android.graphics.Outline; 48 import android.graphics.Paint; 49 import android.graphics.PixelFormat; 50 import android.graphics.Point; 51 import android.graphics.PorterDuff; 52 import android.graphics.PorterDuffXfermode; 53 import android.graphics.Rect; 54 import android.graphics.RectF; 55 import android.graphics.Region; 56 import android.graphics.Shader; 57 import android.graphics.drawable.ColorDrawable; 58 import android.graphics.drawable.Drawable; 59 import android.hardware.display.DisplayManagerGlobal; 60 import android.os.Build.VERSION_CODES; 61 import android.os.Bundle; 62 import android.os.Handler; 63 import android.os.IBinder; 64 import android.os.Parcel; 65 import android.os.Parcelable; 66 import android.os.RemoteException; 67 import android.os.SystemClock; 68 import android.os.SystemProperties; 69 import android.os.Trace; 70 import android.text.TextUtils; 71 import android.util.AttributeSet; 72 import android.util.FloatProperty; 73 import android.util.LayoutDirection; 74 import android.util.Log; 75 import android.util.LongSparseLongArray; 76 import android.util.Pools.SynchronizedPool; 77 import android.util.Property; 78 import android.util.SparseArray; 79 import android.util.StateSet; 80 import android.util.SuperNotCalledException; 81 import android.util.TypedValue; 82 import android.view.ContextMenu.ContextMenuInfo; 83 import android.view.AccessibilityIterators.CharacterTextSegmentIterator; 84 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator; 85 import android.view.AccessibilityIterators.TextSegmentIterator; 86 import android.view.AccessibilityIterators.WordTextSegmentIterator; 87 import android.view.accessibility.AccessibilityEvent; 88 import android.view.accessibility.AccessibilityEventSource; 89 import android.view.accessibility.AccessibilityManager; 90 import android.view.accessibility.AccessibilityNodeInfo; 91 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; 92 import android.view.accessibility.AccessibilityNodeProvider; 93 import android.view.animation.Animation; 94 import android.view.animation.AnimationUtils; 95 import android.view.animation.Transformation; 96 import android.view.inputmethod.EditorInfo; 97 import android.view.inputmethod.InputConnection; 98 import android.view.inputmethod.InputMethodManager; 99 import android.widget.Checkable; 100 import android.widget.FrameLayout; 101 import android.widget.ScrollBarDrawable; 102 import static android.os.Build.VERSION_CODES.*; 103 import static java.lang.Math.max; 104 105 import com.android.internal.R; 106 import com.android.internal.util.Predicate; 107 import com.android.internal.view.menu.MenuBuilder; 108 import com.android.internal.widget.ScrollBarUtils; 109 import com.google.android.collect.Lists; 110 import com.google.android.collect.Maps; 111 112 import java.lang.NullPointerException; 113 import java.lang.annotation.Retention; 114 import java.lang.annotation.RetentionPolicy; 115 import java.lang.ref.WeakReference; 116 import java.lang.reflect.Field; 117 import java.lang.reflect.InvocationTargetException; 118 import java.lang.reflect.Method; 119 import java.lang.reflect.Modifier; 120 import java.util.ArrayList; 121 import java.util.Arrays; 122 import java.util.Collections; 123 import java.util.HashMap; 124 import java.util.List; 125 import java.util.Locale; 126 import java.util.Map; 127 import java.util.concurrent.CopyOnWriteArrayList; 128 import java.util.concurrent.atomic.AtomicInteger; 129 130 /** 131 * <p> 132 * This class represents the basic building block for user interface components. A View 133 * occupies a rectangular area on the screen and is responsible for drawing and 134 * event handling. View is the base class for <em>widgets</em>, which are 135 * used to create interactive UI components (buttons, text fields, etc.). The 136 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which 137 * are invisible containers that hold other Views (or other ViewGroups) and define 138 * their layout properties. 139 * </p> 140 * 141 * <div class="special reference"> 142 * <h3>Developer Guides</h3> 143 * <p>For information about using this class to develop your application's user interface, 144 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide. 145 * </div> 146 * 147 * <a name="Using"></a> 148 * <h3>Using Views</h3> 149 * <p> 150 * All of the views in a window are arranged in a single tree. You can add views 151 * either from code or by specifying a tree of views in one or more XML layout 152 * files. There are many specialized subclasses of views that act as controls or 153 * are capable of displaying text, images, or other content. 154 * </p> 155 * <p> 156 * Once you have created a tree of views, there are typically a few types of 157 * common operations you may wish to perform: 158 * <ul> 159 * <li><strong>Set properties:</strong> for example setting the text of a 160 * {@link android.widget.TextView}. The available properties and the methods 161 * that set them will vary among the different subclasses of views. Note that 162 * properties that are known at build time can be set in the XML layout 163 * files.</li> 164 * <li><strong>Set focus:</strong> The framework will handle moving focus in 165 * response to user input. To force focus to a specific view, call 166 * {@link #requestFocus}.</li> 167 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners 168 * that will be notified when something interesting happens to the view. For 169 * example, all views will let you set a listener to be notified when the view 170 * gains or loses focus. You can register such a listener using 171 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}. 172 * Other view subclasses offer more specialized listeners. For example, a Button 173 * exposes a listener to notify clients when the button is clicked.</li> 174 * <li><strong>Set visibility:</strong> You can hide or show views using 175 * {@link #setVisibility(int)}.</li> 176 * </ul> 177 * </p> 178 * <p><em> 179 * Note: The Android framework is responsible for measuring, laying out and 180 * drawing views. You should not call methods that perform these actions on 181 * views yourself unless you are actually implementing a 182 * {@link android.view.ViewGroup}. 183 * </em></p> 184 * 185 * <a name="Lifecycle"></a> 186 * <h3>Implementing a Custom View</h3> 187 * 188 * <p> 189 * To implement a custom view, you will usually begin by providing overrides for 190 * some of the standard methods that the framework calls on all views. You do 191 * not need to override all of these methods. In fact, you can start by just 192 * overriding {@link #onDraw(android.graphics.Canvas)}. 193 * <table border="2" width="85%" align="center" cellpadding="5"> 194 * <thead> 195 * <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr> 196 * </thead> 197 * 198 * <tbody> 199 * <tr> 200 * <td rowspan="2">Creation</td> 201 * <td>Constructors</td> 202 * <td>There is a form of the constructor that are called when the view 203 * is created from code and a form that is called when the view is 204 * inflated from a layout file. The second form should parse and apply 205 * any attributes defined in the layout file. 206 * </td> 207 * </tr> 208 * <tr> 209 * <td><code>{@link #onFinishInflate()}</code></td> 210 * <td>Called after a view and all of its children has been inflated 211 * from XML.</td> 212 * </tr> 213 * 214 * <tr> 215 * <td rowspan="3">Layout</td> 216 * <td><code>{@link #onMeasure(int, int)}</code></td> 217 * <td>Called to determine the size requirements for this view and all 218 * of its children. 219 * </td> 220 * </tr> 221 * <tr> 222 * <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td> 223 * <td>Called when this view should assign a size and position to all 224 * of its children. 225 * </td> 226 * </tr> 227 * <tr> 228 * <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td> 229 * <td>Called when the size of this view has changed. 230 * </td> 231 * </tr> 232 * 233 * <tr> 234 * <td>Drawing</td> 235 * <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td> 236 * <td>Called when the view should render its content. 237 * </td> 238 * </tr> 239 * 240 * <tr> 241 * <td rowspan="4">Event processing</td> 242 * <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td> 243 * <td>Called when a new hardware key event occurs. 244 * </td> 245 * </tr> 246 * <tr> 247 * <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td> 248 * <td>Called when a hardware key up event occurs. 249 * </td> 250 * </tr> 251 * <tr> 252 * <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td> 253 * <td>Called when a trackball motion event occurs. 254 * </td> 255 * </tr> 256 * <tr> 257 * <td><code>{@link #onTouchEvent(MotionEvent)}</code></td> 258 * <td>Called when a touch screen motion event occurs. 259 * </td> 260 * </tr> 261 * 262 * <tr> 263 * <td rowspan="2">Focus</td> 264 * <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td> 265 * <td>Called when the view gains or loses focus. 266 * </td> 267 * </tr> 268 * 269 * <tr> 270 * <td><code>{@link #onWindowFocusChanged(boolean)}</code></td> 271 * <td>Called when the window containing the view gains or loses focus. 272 * </td> 273 * </tr> 274 * 275 * <tr> 276 * <td rowspan="3">Attaching</td> 277 * <td><code>{@link #onAttachedToWindow()}</code></td> 278 * <td>Called when the view is attached to a window. 279 * </td> 280 * </tr> 281 * 282 * <tr> 283 * <td><code>{@link #onDetachedFromWindow}</code></td> 284 * <td>Called when the view is detached from its window. 285 * </td> 286 * </tr> 287 * 288 * <tr> 289 * <td><code>{@link #onWindowVisibilityChanged(int)}</code></td> 290 * <td>Called when the visibility of the window containing the view 291 * has changed. 292 * </td> 293 * </tr> 294 * </tbody> 295 * 296 * </table> 297 * </p> 298 * 299 * <a name="IDs"></a> 300 * <h3>IDs</h3> 301 * Views may have an integer id associated with them. These ids are typically 302 * assigned in the layout XML files, and are used to find specific views within 303 * the view tree. A common pattern is to: 304 * <ul> 305 * <li>Define a Button in the layout file and assign it a unique ID. 306 * <pre> 307 * <Button 308 * android:id="@+id/my_button" 309 * android:layout_width="wrap_content" 310 * android:layout_height="wrap_content" 311 * android:text="@string/my_button_text"/> 312 * </pre></li> 313 * <li>From the onCreate method of an Activity, find the Button 314 * <pre class="prettyprint"> 315 * Button myButton = (Button) findViewById(R.id.my_button); 316 * </pre></li> 317 * </ul> 318 * <p> 319 * View IDs need not be unique throughout the tree, but it is good practice to 320 * ensure that they are at least unique within the part of the tree you are 321 * searching. 322 * </p> 323 * 324 * <a name="Position"></a> 325 * <h3>Position</h3> 326 * <p> 327 * The geometry of a view is that of a rectangle. A view has a location, 328 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and 329 * two dimensions, expressed as a width and a height. The unit for location 330 * and dimensions is the pixel. 331 * </p> 332 * 333 * <p> 334 * It is possible to retrieve the location of a view by invoking the methods 335 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X, 336 * coordinate of the rectangle representing the view. The latter returns the 337 * top, or Y, coordinate of the rectangle representing the view. These methods 338 * both return the location of the view relative to its parent. For instance, 339 * when getLeft() returns 20, that means the view is located 20 pixels to the 340 * right of the left edge of its direct parent. 341 * </p> 342 * 343 * <p> 344 * In addition, several convenience methods are offered to avoid unnecessary 345 * computations, namely {@link #getRight()} and {@link #getBottom()}. 346 * These methods return the coordinates of the right and bottom edges of the 347 * rectangle representing the view. For instance, calling {@link #getRight()} 348 * is similar to the following computation: <code>getLeft() + getWidth()</code> 349 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.) 350 * </p> 351 * 352 * <a name="SizePaddingMargins"></a> 353 * <h3>Size, padding and margins</h3> 354 * <p> 355 * The size of a view is expressed with a width and a height. A view actually 356 * possess two pairs of width and height values. 357 * </p> 358 * 359 * <p> 360 * The first pair is known as <em>measured width</em> and 361 * <em>measured height</em>. These dimensions define how big a view wants to be 362 * within its parent (see <a href="#Layout">Layout</a> for more details.) The 363 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()} 364 * and {@link #getMeasuredHeight()}. 365 * </p> 366 * 367 * <p> 368 * The second pair is simply known as <em>width</em> and <em>height</em>, or 369 * sometimes <em>drawing width</em> and <em>drawing height</em>. These 370 * dimensions define the actual size of the view on screen, at drawing time and 371 * after layout. These values may, but do not have to, be different from the 372 * measured width and height. The width and height can be obtained by calling 373 * {@link #getWidth()} and {@link #getHeight()}. 374 * </p> 375 * 376 * <p> 377 * To measure its dimensions, a view takes into account its padding. The padding 378 * is expressed in pixels for the left, top, right and bottom parts of the view. 379 * Padding can be used to offset the content of the view by a specific amount of 380 * pixels. For instance, a left padding of 2 will push the view's content by 381 * 2 pixels to the right of the left edge. Padding can be set using the 382 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)} 383 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()}, 384 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()}, 385 * {@link #getPaddingEnd()}. 386 * </p> 387 * 388 * <p> 389 * Even though a view can define a padding, it does not provide any support for 390 * margins. However, view groups provide such a support. Refer to 391 * {@link android.view.ViewGroup} and 392 * {@link android.view.ViewGroup.MarginLayoutParams} for further information. 393 * </p> 394 * 395 * <a name="Layout"></a> 396 * <h3>Layout</h3> 397 * <p> 398 * Layout is a two pass process: a measure pass and a layout pass. The measuring 399 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal 400 * of the view tree. Each view pushes dimension specifications down the tree 401 * during the recursion. At the end of the measure pass, every view has stored 402 * its measurements. The second pass happens in 403 * {@link #layout(int,int,int,int)} and is also top-down. During 404 * this pass each parent is responsible for positioning all of its children 405 * using the sizes computed in the measure pass. 406 * </p> 407 * 408 * <p> 409 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and 410 * {@link #getMeasuredHeight()} values must be set, along with those for all of 411 * that view's descendants. A view's measured width and measured height values 412 * must respect the constraints imposed by the view's parents. This guarantees 413 * that at the end of the measure pass, all parents accept all of their 414 * children's measurements. A parent view may call measure() more than once on 415 * its children. For example, the parent may measure each child once with 416 * unspecified dimensions to find out how big they want to be, then call 417 * measure() on them again with actual numbers if the sum of all the children's 418 * unconstrained sizes is too big or too small. 419 * </p> 420 * 421 * <p> 422 * The measure pass uses two classes to communicate dimensions. The 423 * {@link MeasureSpec} class is used by views to tell their parents how they 424 * want to be measured and positioned. The base LayoutParams class just 425 * describes how big the view wants to be for both width and height. For each 426 * dimension, it can specify one of: 427 * <ul> 428 * <li> an exact number 429 * <li>MATCH_PARENT, which means the view wants to be as big as its parent 430 * (minus padding) 431 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to 432 * enclose its content (plus padding). 433 * </ul> 434 * There are subclasses of LayoutParams for different subclasses of ViewGroup. 435 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds 436 * an X and Y value. 437 * </p> 438 * 439 * <p> 440 * MeasureSpecs are used to push requirements down the tree from parent to 441 * child. A MeasureSpec can be in one of three modes: 442 * <ul> 443 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension 444 * of a child view. For example, a LinearLayout may call measure() on its child 445 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how 446 * tall the child view wants to be given a width of 240 pixels. 447 * <li>EXACTLY: This is used by the parent to impose an exact size on the 448 * child. The child must use this size, and guarantee that all of its 449 * descendants will fit within this size. 450 * <li>AT_MOST: This is used by the parent to impose a maximum size on the 451 * child. The child must guarantee that it and all of its descendants will fit 452 * within this size. 453 * </ul> 454 * </p> 455 * 456 * <p> 457 * To initiate a layout, call {@link #requestLayout}. This method is typically 458 * called by a view on itself when it believes that is can no longer fit within 459 * its current bounds. 460 * </p> 461 * 462 * <a name="Drawing"></a> 463 * <h3>Drawing</h3> 464 * <p> 465 * Drawing is handled by walking the tree and recording the drawing commands of 466 * any View that needs to update. After this, the drawing commands of the 467 * entire tree are issued to screen, clipped to the newly damaged area. 468 * </p> 469 * 470 * <p> 471 * The tree is largely recorded and drawn in order, with parents drawn before 472 * (i.e., behind) their children, with siblings drawn in the order they appear 473 * in the tree. If you set a background drawable for a View, then the View will 474 * draw it before calling back to its <code>onDraw()</code> method. The child 475 * drawing order can be overridden with 476 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order} 477 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views. 478 * </p> 479 * 480 * <p> 481 * To force a view to draw, call {@link #invalidate()}. 482 * </p> 483 * 484 * <a name="EventHandlingThreading"></a> 485 * <h3>Event Handling and Threading</h3> 486 * <p> 487 * The basic cycle of a view is as follows: 488 * <ol> 489 * <li>An event comes in and is dispatched to the appropriate view. The view 490 * handles the event and notifies any listeners.</li> 491 * <li>If in the course of processing the event, the view's bounds may need 492 * to be changed, the view will call {@link #requestLayout()}.</li> 493 * <li>Similarly, if in the course of processing the event the view's appearance 494 * may need to be changed, the view will call {@link #invalidate()}.</li> 495 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called, 496 * the framework will take care of measuring, laying out, and drawing the tree 497 * as appropriate.</li> 498 * </ol> 499 * </p> 500 * 501 * <p><em>Note: The entire view tree is single threaded. You must always be on 502 * the UI thread when calling any method on any view.</em> 503 * If you are doing work on other threads and want to update the state of a view 504 * from that thread, you should use a {@link Handler}. 505 * </p> 506 * 507 * <a name="FocusHandling"></a> 508 * <h3>Focus Handling</h3> 509 * <p> 510 * The framework will handle routine focus movement in response to user input. 511 * This includes changing the focus as views are removed or hidden, or as new 512 * views become available. Views indicate their willingness to take focus 513 * through the {@link #isFocusable} method. To change whether a view can take 514 * focus, call {@link #setFocusable(boolean)}. When in touch mode (see notes below) 515 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode} 516 * and can change this via {@link #setFocusableInTouchMode(boolean)}. 517 * </p> 518 * <p> 519 * Focus movement is based on an algorithm which finds the nearest neighbor in a 520 * given direction. In rare cases, the default algorithm may not match the 521 * intended behavior of the developer. In these situations, you can provide 522 * explicit overrides by using these XML attributes in the layout file: 523 * <pre> 524 * nextFocusDown 525 * nextFocusLeft 526 * nextFocusRight 527 * nextFocusUp 528 * </pre> 529 * </p> 530 * 531 * 532 * <p> 533 * To get a particular view to take focus, call {@link #requestFocus()}. 534 * </p> 535 * 536 * <a name="TouchMode"></a> 537 * <h3>Touch Mode</h3> 538 * <p> 539 * When a user is navigating a user interface via directional keys such as a D-pad, it is 540 * necessary to give focus to actionable items such as buttons so the user can see 541 * what will take input. If the device has touch capabilities, however, and the user 542 * begins interacting with the interface by touching it, it is no longer necessary to 543 * always highlight, or give focus to, a particular view. This motivates a mode 544 * for interaction named 'touch mode'. 545 * </p> 546 * <p> 547 * For a touch capable device, once the user touches the screen, the device 548 * will enter touch mode. From this point onward, only views for which 549 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets. 550 * Other views that are touchable, like buttons, will not take focus when touched; they will 551 * only fire the on click listeners. 552 * </p> 553 * <p> 554 * Any time a user hits a directional key, such as a D-pad direction, the view device will 555 * exit touch mode, and find a view to take focus, so that the user may resume interacting 556 * with the user interface without touching the screen again. 557 * </p> 558 * <p> 559 * The touch mode state is maintained across {@link android.app.Activity}s. Call 560 * {@link #isInTouchMode} to see whether the device is currently in touch mode. 561 * </p> 562 * 563 * <a name="Scrolling"></a> 564 * <h3>Scrolling</h3> 565 * <p> 566 * The framework provides basic support for views that wish to internally 567 * scroll their content. This includes keeping track of the X and Y scroll 568 * offset as well as mechanisms for drawing scrollbars. See 569 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and 570 * {@link #awakenScrollBars()} for more details. 571 * </p> 572 * 573 * <a name="Tags"></a> 574 * <h3>Tags</h3> 575 * <p> 576 * Unlike IDs, tags are not used to identify views. Tags are essentially an 577 * extra piece of information that can be associated with a view. They are most 578 * often used as a convenience to store data related to views in the views 579 * themselves rather than by putting them in a separate structure. 580 * </p> 581 * <p> 582 * Tags may be specified with character sequence values in layout XML as either 583 * a single tag using the {@link android.R.styleable#View_tag android:tag} 584 * attribute or multiple tags using the {@code <tag>} child element: 585 * <pre> 586 * <View ... 587 * android:tag="@string/mytag_value" /> 588 * <View ...> 589 * <tag android:id="@+id/mytag" 590 * android:value="@string/mytag_value" /> 591 * </View> 592 * </pre> 593 * </p> 594 * <p> 595 * Tags may also be specified with arbitrary objects from code using 596 * {@link #setTag(Object)} or {@link #setTag(int, Object)}. 597 * </p> 598 * 599 * <a name="Themes"></a> 600 * <h3>Themes</h3> 601 * <p> 602 * By default, Views are created using the theme of the Context object supplied 603 * to their constructor; however, a different theme may be specified by using 604 * the {@link android.R.styleable#View_theme android:theme} attribute in layout 605 * XML or by passing a {@link ContextThemeWrapper} to the constructor from 606 * code. 607 * </p> 608 * <p> 609 * When the {@link android.R.styleable#View_theme android:theme} attribute is 610 * used in XML, the specified theme is applied on top of the inflation 611 * context's theme (see {@link LayoutInflater}) and used for the view itself as 612 * well as any child elements. 613 * </p> 614 * <p> 615 * In the following example, both views will be created using the Material dark 616 * color scheme; however, because an overlay theme is used which only defines a 617 * subset of attributes, the value of 618 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on 619 * the inflation context's theme (e.g. the Activity theme) will be preserved. 620 * <pre> 621 * <LinearLayout 622 * ... 623 * android:theme="@android:theme/ThemeOverlay.Material.Dark"> 624 * <View ...> 625 * </LinearLayout> 626 * </pre> 627 * </p> 628 * 629 * <a name="Properties"></a> 630 * <h3>Properties</h3> 631 * <p> 632 * The View class exposes an {@link #ALPHA} property, as well as several transform-related 633 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are 634 * available both in the {@link Property} form as well as in similarly-named setter/getter 635 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can 636 * be used to set persistent state associated with these rendering-related properties on the view. 637 * The properties and methods can also be used in conjunction with 638 * {@link android.animation.Animator Animator}-based animations, described more in the 639 * <a href="#Animation">Animation</a> section. 640 * </p> 641 * 642 * <a name="Animation"></a> 643 * <h3>Animation</h3> 644 * <p> 645 * Starting with Android 3.0, the preferred way of animating views is to use the 646 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based 647 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and 648 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0 649 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only 650 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class 651 * makes animating these View properties particularly easy and efficient. 652 * </p> 653 * <p> 654 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered. 655 * You can attach an {@link Animation} object to a view using 656 * {@link #setAnimation(Animation)} or 657 * {@link #startAnimation(Animation)}. The animation can alter the scale, 658 * rotation, translation and alpha of a view over time. If the animation is 659 * attached to a view that has children, the animation will affect the entire 660 * subtree rooted by that node. When an animation is started, the framework will 661 * take care of redrawing the appropriate views until the animation completes. 662 * </p> 663 * 664 * <a name="Security"></a> 665 * <h3>Security</h3> 666 * <p> 667 * Sometimes it is essential that an application be able to verify that an action 668 * is being performed with the full knowledge and consent of the user, such as 669 * granting a permission request, making a purchase or clicking on an advertisement. 670 * Unfortunately, a malicious application could try to spoof the user into 671 * performing these actions, unaware, by concealing the intended purpose of the view. 672 * As a remedy, the framework offers a touch filtering mechanism that can be used to 673 * improve the security of views that provide access to sensitive functionality. 674 * </p><p> 675 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the 676 * android:filterTouchesWhenObscured layout attribute to true. When enabled, the framework 677 * will discard touches that are received whenever the view's window is obscured by 678 * another visible window. As a result, the view will not receive touches whenever a 679 * toast, dialog or other window appears above the view's window. 680 * </p><p> 681 * For more fine-grained control over security, consider overriding the 682 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own 683 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}. 684 * </p> 685 * 686 * @attr ref android.R.styleable#View_alpha 687 * @attr ref android.R.styleable#View_background 688 * @attr ref android.R.styleable#View_clickable 689 * @attr ref android.R.styleable#View_contentDescription 690 * @attr ref android.R.styleable#View_drawingCacheQuality 691 * @attr ref android.R.styleable#View_duplicateParentState 692 * @attr ref android.R.styleable#View_id 693 * @attr ref android.R.styleable#View_requiresFadingEdge 694 * @attr ref android.R.styleable#View_fadeScrollbars 695 * @attr ref android.R.styleable#View_fadingEdgeLength 696 * @attr ref android.R.styleable#View_filterTouchesWhenObscured 697 * @attr ref android.R.styleable#View_fitsSystemWindows 698 * @attr ref android.R.styleable#View_isScrollContainer 699 * @attr ref android.R.styleable#View_focusable 700 * @attr ref android.R.styleable#View_focusableInTouchMode 701 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 702 * @attr ref android.R.styleable#View_keepScreenOn 703 * @attr ref android.R.styleable#View_layerType 704 * @attr ref android.R.styleable#View_layoutDirection 705 * @attr ref android.R.styleable#View_longClickable 706 * @attr ref android.R.styleable#View_minHeight 707 * @attr ref android.R.styleable#View_minWidth 708 * @attr ref android.R.styleable#View_nextFocusDown 709 * @attr ref android.R.styleable#View_nextFocusLeft 710 * @attr ref android.R.styleable#View_nextFocusRight 711 * @attr ref android.R.styleable#View_nextFocusUp 712 * @attr ref android.R.styleable#View_onClick 713 * @attr ref android.R.styleable#View_padding 714 * @attr ref android.R.styleable#View_paddingBottom 715 * @attr ref android.R.styleable#View_paddingLeft 716 * @attr ref android.R.styleable#View_paddingRight 717 * @attr ref android.R.styleable#View_paddingTop 718 * @attr ref android.R.styleable#View_paddingStart 719 * @attr ref android.R.styleable#View_paddingEnd 720 * @attr ref android.R.styleable#View_saveEnabled 721 * @attr ref android.R.styleable#View_rotation 722 * @attr ref android.R.styleable#View_rotationX 723 * @attr ref android.R.styleable#View_rotationY 724 * @attr ref android.R.styleable#View_scaleX 725 * @attr ref android.R.styleable#View_scaleY 726 * @attr ref android.R.styleable#View_scrollX 727 * @attr ref android.R.styleable#View_scrollY 728 * @attr ref android.R.styleable#View_scrollbarSize 729 * @attr ref android.R.styleable#View_scrollbarStyle 730 * @attr ref android.R.styleable#View_scrollbars 731 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade 732 * @attr ref android.R.styleable#View_scrollbarFadeDuration 733 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal 734 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal 735 * @attr ref android.R.styleable#View_scrollbarThumbVertical 736 * @attr ref android.R.styleable#View_scrollbarTrackVertical 737 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack 738 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack 739 * @attr ref android.R.styleable#View_stateListAnimator 740 * @attr ref android.R.styleable#View_transitionName 741 * @attr ref android.R.styleable#View_soundEffectsEnabled 742 * @attr ref android.R.styleable#View_tag 743 * @attr ref android.R.styleable#View_textAlignment 744 * @attr ref android.R.styleable#View_textDirection 745 * @attr ref android.R.styleable#View_transformPivotX 746 * @attr ref android.R.styleable#View_transformPivotY 747 * @attr ref android.R.styleable#View_translationX 748 * @attr ref android.R.styleable#View_translationY 749 * @attr ref android.R.styleable#View_translationZ 750 * @attr ref android.R.styleable#View_visibility 751 * @attr ref android.R.styleable#View_theme 752 * 753 * @see android.view.ViewGroup 754 */ 755 @UiThread 756 public class View implements Drawable.Callback, KeyEvent.Callback, 757 AccessibilityEventSource { 758 private static final boolean DBG = false; 759 760 /** 761 * The logging tag used by this class with android.util.Log. 762 */ 763 protected static final String VIEW_LOG_TAG = "View"; 764 765 /** 766 * When set to true, apps will draw debugging information about their layouts. 767 * 768 * @hide 769 */ 770 public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout"; 771 772 /** 773 * When set to true, this view will save its attribute data. 774 * 775 * @hide 776 */ 777 public static boolean mDebugViewAttributes = false; 778 779 /** 780 * Used to mark a View that has no ID. 781 */ 782 public static final int NO_ID = -1; 783 784 /** 785 * Signals that compatibility booleans have been initialized according to 786 * target SDK versions. 787 */ 788 private static boolean sCompatibilityDone = false; 789 790 /** 791 * Use the old (broken) way of building MeasureSpecs. 792 */ 793 private static boolean sUseBrokenMakeMeasureSpec = false; 794 795 /** 796 * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED 797 */ 798 static boolean sUseZeroUnspecifiedMeasureSpec = false; 799 800 /** 801 * Ignore any optimizations using the measure cache. 802 */ 803 private static boolean sIgnoreMeasureCache = false; 804 805 /** 806 * Ignore an optimization that skips unnecessary EXACTLY layout passes. 807 */ 808 private static boolean sAlwaysRemeasureExactly = false; 809 810 /** 811 * Relax constraints around whether setLayoutParams() must be called after 812 * modifying the layout params. 813 */ 814 private static boolean sLayoutParamsAlwaysChanged = false; 815 816 /** 817 * Allow setForeground/setBackground to be called (and ignored) on a textureview, 818 * without throwing 819 */ 820 static boolean sTextureViewIgnoresDrawableSetters = false; 821 822 /** 823 * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when 824 * calling setFlags. 825 */ 826 private static final int NOT_FOCUSABLE = 0x00000000; 827 828 /** 829 * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling 830 * setFlags. 831 */ 832 private static final int FOCUSABLE = 0x00000001; 833 834 /** 835 * Mask for use with setFlags indicating bits used for focus. 836 */ 837 private static final int FOCUSABLE_MASK = 0x00000001; 838 839 /** 840 * This view will adjust its padding to fit sytem windows (e.g. status bar) 841 */ 842 private static final int FITS_SYSTEM_WINDOWS = 0x00000002; 843 844 /** @hide */ 845 @IntDef({VISIBLE, INVISIBLE, GONE}) 846 @Retention(RetentionPolicy.SOURCE) 847 public @interface Visibility {} 848 849 /** 850 * This view is visible. 851 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code 852 * android:visibility}. 853 */ 854 public static final int VISIBLE = 0x00000000; 855 856 /** 857 * This view is invisible, but it still takes up space for layout purposes. 858 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code 859 * android:visibility}. 860 */ 861 public static final int INVISIBLE = 0x00000004; 862 863 /** 864 * This view is invisible, and it doesn't take any space for layout 865 * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code 866 * android:visibility}. 867 */ 868 public static final int GONE = 0x00000008; 869 870 /** 871 * Mask for use with setFlags indicating bits used for visibility. 872 * {@hide} 873 */ 874 static final int VISIBILITY_MASK = 0x0000000C; 875 876 private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE}; 877 878 /** 879 * This view is enabled. Interpretation varies by subclass. 880 * Use with ENABLED_MASK when calling setFlags. 881 * {@hide} 882 */ 883 static final int ENABLED = 0x00000000; 884 885 /** 886 * This view is disabled. Interpretation varies by subclass. 887 * Use with ENABLED_MASK when calling setFlags. 888 * {@hide} 889 */ 890 static final int DISABLED = 0x00000020; 891 892 /** 893 * Mask for use with setFlags indicating bits used for indicating whether 894 * this view is enabled 895 * {@hide} 896 */ 897 static final int ENABLED_MASK = 0x00000020; 898 899 /** 900 * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be 901 * called and further optimizations will be performed. It is okay to have 902 * this flag set and a background. Use with DRAW_MASK when calling setFlags. 903 * {@hide} 904 */ 905 static final int WILL_NOT_DRAW = 0x00000080; 906 907 /** 908 * Mask for use with setFlags indicating bits used for indicating whether 909 * this view is will draw 910 * {@hide} 911 */ 912 static final int DRAW_MASK = 0x00000080; 913 914 /** 915 * <p>This view doesn't show scrollbars.</p> 916 * {@hide} 917 */ 918 static final int SCROLLBARS_NONE = 0x00000000; 919 920 /** 921 * <p>This view shows horizontal scrollbars.</p> 922 * {@hide} 923 */ 924 static final int SCROLLBARS_HORIZONTAL = 0x00000100; 925 926 /** 927 * <p>This view shows vertical scrollbars.</p> 928 * {@hide} 929 */ 930 static final int SCROLLBARS_VERTICAL = 0x00000200; 931 932 /** 933 * <p>Mask for use with setFlags indicating bits used for indicating which 934 * scrollbars are enabled.</p> 935 * {@hide} 936 */ 937 static final int SCROLLBARS_MASK = 0x00000300; 938 939 /** 940 * Indicates that the view should filter touches when its window is obscured. 941 * Refer to the class comments for more information about this security feature. 942 * {@hide} 943 */ 944 static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400; 945 946 /** 947 * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate 948 * that they are optional and should be skipped if the window has 949 * requested system UI flags that ignore those insets for layout. 950 */ 951 static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800; 952 953 /** 954 * <p>This view doesn't show fading edges.</p> 955 * {@hide} 956 */ 957 static final int FADING_EDGE_NONE = 0x00000000; 958 959 /** 960 * <p>This view shows horizontal fading edges.</p> 961 * {@hide} 962 */ 963 static final int FADING_EDGE_HORIZONTAL = 0x00001000; 964 965 /** 966 * <p>This view shows vertical fading edges.</p> 967 * {@hide} 968 */ 969 static final int FADING_EDGE_VERTICAL = 0x00002000; 970 971 /** 972 * <p>Mask for use with setFlags indicating bits used for indicating which 973 * fading edges are enabled.</p> 974 * {@hide} 975 */ 976 static final int FADING_EDGE_MASK = 0x00003000; 977 978 /** 979 * <p>Indicates this view can be clicked. When clickable, a View reacts 980 * to clicks by notifying the OnClickListener.<p> 981 * {@hide} 982 */ 983 static final int CLICKABLE = 0x00004000; 984 985 /** 986 * <p>Indicates this view is caching its drawing into a bitmap.</p> 987 * {@hide} 988 */ 989 static final int DRAWING_CACHE_ENABLED = 0x00008000; 990 991 /** 992 * <p>Indicates that no icicle should be saved for this view.<p> 993 * {@hide} 994 */ 995 static final int SAVE_DISABLED = 0x000010000; 996 997 /** 998 * <p>Mask for use with setFlags indicating bits used for the saveEnabled 999 * property.</p> 1000 * {@hide} 1001 */ 1002 static final int SAVE_DISABLED_MASK = 0x000010000; 1003 1004 /** 1005 * <p>Indicates that no drawing cache should ever be created for this view.<p> 1006 * {@hide} 1007 */ 1008 static final int WILL_NOT_CACHE_DRAWING = 0x000020000; 1009 1010 /** 1011 * <p>Indicates this view can take / keep focus when int touch mode.</p> 1012 * {@hide} 1013 */ 1014 static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000; 1015 1016 /** @hide */ 1017 @Retention(RetentionPolicy.SOURCE) 1018 @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO}) 1019 public @interface DrawingCacheQuality {} 1020 1021 /** 1022 * <p>Enables low quality mode for the drawing cache.</p> 1023 */ 1024 public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000; 1025 1026 /** 1027 * <p>Enables high quality mode for the drawing cache.</p> 1028 */ 1029 public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000; 1030 1031 /** 1032 * <p>Enables automatic quality mode for the drawing cache.</p> 1033 */ 1034 public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000; 1035 1036 private static final int[] DRAWING_CACHE_QUALITY_FLAGS = { 1037 DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH 1038 }; 1039 1040 /** 1041 * <p>Mask for use with setFlags indicating bits used for the cache 1042 * quality property.</p> 1043 * {@hide} 1044 */ 1045 static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000; 1046 1047 /** 1048 * <p> 1049 * Indicates this view can be long clicked. When long clickable, a View 1050 * reacts to long clicks by notifying the OnLongClickListener or showing a 1051 * context menu. 1052 * </p> 1053 * {@hide} 1054 */ 1055 static final int LONG_CLICKABLE = 0x00200000; 1056 1057 /** 1058 * <p>Indicates that this view gets its drawable states from its direct parent 1059 * and ignores its original internal states.</p> 1060 * 1061 * @hide 1062 */ 1063 static final int DUPLICATE_PARENT_STATE = 0x00400000; 1064 1065 /** 1066 * <p> 1067 * Indicates this view can be context clicked. When context clickable, a View reacts to a 1068 * context click (e.g. a primary stylus button press or right mouse click) by notifying the 1069 * OnContextClickListener. 1070 * </p> 1071 * {@hide} 1072 */ 1073 static final int CONTEXT_CLICKABLE = 0x00800000; 1074 1075 1076 /** @hide */ 1077 @IntDef({ 1078 SCROLLBARS_INSIDE_OVERLAY, 1079 SCROLLBARS_INSIDE_INSET, 1080 SCROLLBARS_OUTSIDE_OVERLAY, 1081 SCROLLBARS_OUTSIDE_INSET 1082 }) 1083 @Retention(RetentionPolicy.SOURCE) 1084 public @interface ScrollBarStyle {} 1085 1086 /** 1087 * The scrollbar style to display the scrollbars inside the content area, 1088 * without increasing the padding. The scrollbars will be overlaid with 1089 * translucency on the view's content. 1090 */ 1091 public static final int SCROLLBARS_INSIDE_OVERLAY = 0; 1092 1093 /** 1094 * The scrollbar style to display the scrollbars inside the padded area, 1095 * increasing the padding of the view. The scrollbars will not overlap the 1096 * content area of the view. 1097 */ 1098 public static final int SCROLLBARS_INSIDE_INSET = 0x01000000; 1099 1100 /** 1101 * The scrollbar style to display the scrollbars at the edge of the view, 1102 * without increasing the padding. The scrollbars will be overlaid with 1103 * translucency. 1104 */ 1105 public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000; 1106 1107 /** 1108 * The scrollbar style to display the scrollbars at the edge of the view, 1109 * increasing the padding of the view. The scrollbars will only overlap the 1110 * background, if any. 1111 */ 1112 public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000; 1113 1114 /** 1115 * Mask to check if the scrollbar style is overlay or inset. 1116 * {@hide} 1117 */ 1118 static final int SCROLLBARS_INSET_MASK = 0x01000000; 1119 1120 /** 1121 * Mask to check if the scrollbar style is inside or outside. 1122 * {@hide} 1123 */ 1124 static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000; 1125 1126 /** 1127 * Mask for scrollbar style. 1128 * {@hide} 1129 */ 1130 static final int SCROLLBARS_STYLE_MASK = 0x03000000; 1131 1132 /** 1133 * View flag indicating that the screen should remain on while the 1134 * window containing this view is visible to the user. This effectively 1135 * takes care of automatically setting the WindowManager's 1136 * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}. 1137 */ 1138 public static final int KEEP_SCREEN_ON = 0x04000000; 1139 1140 /** 1141 * View flag indicating whether this view should have sound effects enabled 1142 * for events such as clicking and touching. 1143 */ 1144 public static final int SOUND_EFFECTS_ENABLED = 0x08000000; 1145 1146 /** 1147 * View flag indicating whether this view should have haptic feedback 1148 * enabled for events such as long presses. 1149 */ 1150 public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000; 1151 1152 /** 1153 * <p>Indicates that the view hierarchy should stop saving state when 1154 * it reaches this view. If state saving is initiated immediately at 1155 * the view, it will be allowed. 1156 * {@hide} 1157 */ 1158 static final int PARENT_SAVE_DISABLED = 0x20000000; 1159 1160 /** 1161 * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p> 1162 * {@hide} 1163 */ 1164 static final int PARENT_SAVE_DISABLED_MASK = 0x20000000; 1165 1166 /** @hide */ 1167 @IntDef(flag = true, 1168 value = { 1169 FOCUSABLES_ALL, 1170 FOCUSABLES_TOUCH_MODE 1171 }) 1172 @Retention(RetentionPolicy.SOURCE) 1173 public @interface FocusableMode {} 1174 1175 /** 1176 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)} 1177 * should add all focusable Views regardless if they are focusable in touch mode. 1178 */ 1179 public static final int FOCUSABLES_ALL = 0x00000000; 1180 1181 /** 1182 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)} 1183 * should add only Views focusable in touch mode. 1184 */ 1185 public static final int FOCUSABLES_TOUCH_MODE = 0x00000001; 1186 1187 /** @hide */ 1188 @IntDef({ 1189 FOCUS_BACKWARD, 1190 FOCUS_FORWARD, 1191 FOCUS_LEFT, 1192 FOCUS_UP, 1193 FOCUS_RIGHT, 1194 FOCUS_DOWN 1195 }) 1196 @Retention(RetentionPolicy.SOURCE) 1197 public @interface FocusDirection {} 1198 1199 /** @hide */ 1200 @IntDef({ 1201 FOCUS_LEFT, 1202 FOCUS_UP, 1203 FOCUS_RIGHT, 1204 FOCUS_DOWN 1205 }) 1206 @Retention(RetentionPolicy.SOURCE) 1207 public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward 1208 1209 /** 1210 * Use with {@link #focusSearch(int)}. Move focus to the previous selectable 1211 * item. 1212 */ 1213 public static final int FOCUS_BACKWARD = 0x00000001; 1214 1215 /** 1216 * Use with {@link #focusSearch(int)}. Move focus to the next selectable 1217 * item. 1218 */ 1219 public static final int FOCUS_FORWARD = 0x00000002; 1220 1221 /** 1222 * Use with {@link #focusSearch(int)}. Move focus to the left. 1223 */ 1224 public static final int FOCUS_LEFT = 0x00000011; 1225 1226 /** 1227 * Use with {@link #focusSearch(int)}. Move focus up. 1228 */ 1229 public static final int FOCUS_UP = 0x00000021; 1230 1231 /** 1232 * Use with {@link #focusSearch(int)}. Move focus to the right. 1233 */ 1234 public static final int FOCUS_RIGHT = 0x00000042; 1235 1236 /** 1237 * Use with {@link #focusSearch(int)}. Move focus down. 1238 */ 1239 public static final int FOCUS_DOWN = 0x00000082; 1240 1241 /** 1242 * Bits of {@link #getMeasuredWidthAndState()} and 1243 * {@link #getMeasuredWidthAndState()} that provide the actual measured size. 1244 */ 1245 public static final int MEASURED_SIZE_MASK = 0x00ffffff; 1246 1247 /** 1248 * Bits of {@link #getMeasuredWidthAndState()} and 1249 * {@link #getMeasuredWidthAndState()} that provide the additional state bits. 1250 */ 1251 public static final int MEASURED_STATE_MASK = 0xff000000; 1252 1253 /** 1254 * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits 1255 * for functions that combine both width and height into a single int, 1256 * such as {@link #getMeasuredState()} and the childState argument of 1257 * {@link #resolveSizeAndState(int, int, int)}. 1258 */ 1259 public static final int MEASURED_HEIGHT_STATE_SHIFT = 16; 1260 1261 /** 1262 * Bit of {@link #getMeasuredWidthAndState()} and 1263 * {@link #getMeasuredWidthAndState()} that indicates the measured size 1264 * is smaller that the space the view would like to have. 1265 */ 1266 public static final int MEASURED_STATE_TOO_SMALL = 0x01000000; 1267 1268 /** 1269 * Base View state sets 1270 */ 1271 // Singles 1272 /** 1273 * Indicates the view has no states set. States are used with 1274 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1275 * view depending on its state. 1276 * 1277 * @see android.graphics.drawable.Drawable 1278 * @see #getDrawableState() 1279 */ 1280 protected static final int[] EMPTY_STATE_SET; 1281 /** 1282 * Indicates the view is enabled. States are used with 1283 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1284 * view depending on its state. 1285 * 1286 * @see android.graphics.drawable.Drawable 1287 * @see #getDrawableState() 1288 */ 1289 protected static final int[] ENABLED_STATE_SET; 1290 /** 1291 * Indicates the view is focused. States are used with 1292 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1293 * view depending on its state. 1294 * 1295 * @see android.graphics.drawable.Drawable 1296 * @see #getDrawableState() 1297 */ 1298 protected static final int[] FOCUSED_STATE_SET; 1299 /** 1300 * Indicates the view is selected. States are used with 1301 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1302 * view depending on its state. 1303 * 1304 * @see android.graphics.drawable.Drawable 1305 * @see #getDrawableState() 1306 */ 1307 protected static final int[] SELECTED_STATE_SET; 1308 /** 1309 * Indicates the view is pressed. States are used with 1310 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1311 * view depending on its state. 1312 * 1313 * @see android.graphics.drawable.Drawable 1314 * @see #getDrawableState() 1315 */ 1316 protected static final int[] PRESSED_STATE_SET; 1317 /** 1318 * Indicates the view's window has focus. States are used with 1319 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1320 * view depending on its state. 1321 * 1322 * @see android.graphics.drawable.Drawable 1323 * @see #getDrawableState() 1324 */ 1325 protected static final int[] WINDOW_FOCUSED_STATE_SET; 1326 // Doubles 1327 /** 1328 * Indicates the view is enabled and has the focus. 1329 * 1330 * @see #ENABLED_STATE_SET 1331 * @see #FOCUSED_STATE_SET 1332 */ 1333 protected static final int[] ENABLED_FOCUSED_STATE_SET; 1334 /** 1335 * Indicates the view is enabled and selected. 1336 * 1337 * @see #ENABLED_STATE_SET 1338 * @see #SELECTED_STATE_SET 1339 */ 1340 protected static final int[] ENABLED_SELECTED_STATE_SET; 1341 /** 1342 * Indicates the view is enabled and that its window has focus. 1343 * 1344 * @see #ENABLED_STATE_SET 1345 * @see #WINDOW_FOCUSED_STATE_SET 1346 */ 1347 protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET; 1348 /** 1349 * Indicates the view is focused and selected. 1350 * 1351 * @see #FOCUSED_STATE_SET 1352 * @see #SELECTED_STATE_SET 1353 */ 1354 protected static final int[] FOCUSED_SELECTED_STATE_SET; 1355 /** 1356 * Indicates the view has the focus and that its window has the focus. 1357 * 1358 * @see #FOCUSED_STATE_SET 1359 * @see #WINDOW_FOCUSED_STATE_SET 1360 */ 1361 protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET; 1362 /** 1363 * Indicates the view is selected and that its window has the focus. 1364 * 1365 * @see #SELECTED_STATE_SET 1366 * @see #WINDOW_FOCUSED_STATE_SET 1367 */ 1368 protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET; 1369 // Triples 1370 /** 1371 * Indicates the view is enabled, focused and selected. 1372 * 1373 * @see #ENABLED_STATE_SET 1374 * @see #FOCUSED_STATE_SET 1375 * @see #SELECTED_STATE_SET 1376 */ 1377 protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET; 1378 /** 1379 * Indicates the view is enabled, focused and its window has the focus. 1380 * 1381 * @see #ENABLED_STATE_SET 1382 * @see #FOCUSED_STATE_SET 1383 * @see #WINDOW_FOCUSED_STATE_SET 1384 */ 1385 protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET; 1386 /** 1387 * Indicates the view is enabled, selected and its window has the focus. 1388 * 1389 * @see #ENABLED_STATE_SET 1390 * @see #SELECTED_STATE_SET 1391 * @see #WINDOW_FOCUSED_STATE_SET 1392 */ 1393 protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1394 /** 1395 * Indicates the view is focused, selected and its window has the focus. 1396 * 1397 * @see #FOCUSED_STATE_SET 1398 * @see #SELECTED_STATE_SET 1399 * @see #WINDOW_FOCUSED_STATE_SET 1400 */ 1401 protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1402 /** 1403 * Indicates the view is enabled, focused, selected and its window 1404 * has the focus. 1405 * 1406 * @see #ENABLED_STATE_SET 1407 * @see #FOCUSED_STATE_SET 1408 * @see #SELECTED_STATE_SET 1409 * @see #WINDOW_FOCUSED_STATE_SET 1410 */ 1411 protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1412 /** 1413 * Indicates the view is pressed and its window has the focus. 1414 * 1415 * @see #PRESSED_STATE_SET 1416 * @see #WINDOW_FOCUSED_STATE_SET 1417 */ 1418 protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET; 1419 /** 1420 * Indicates the view is pressed and selected. 1421 * 1422 * @see #PRESSED_STATE_SET 1423 * @see #SELECTED_STATE_SET 1424 */ 1425 protected static final int[] PRESSED_SELECTED_STATE_SET; 1426 /** 1427 * Indicates the view is pressed, selected and its window has the focus. 1428 * 1429 * @see #PRESSED_STATE_SET 1430 * @see #SELECTED_STATE_SET 1431 * @see #WINDOW_FOCUSED_STATE_SET 1432 */ 1433 protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1434 /** 1435 * Indicates the view is pressed and focused. 1436 * 1437 * @see #PRESSED_STATE_SET 1438 * @see #FOCUSED_STATE_SET 1439 */ 1440 protected static final int[] PRESSED_FOCUSED_STATE_SET; 1441 /** 1442 * Indicates the view is pressed, focused and its window has the focus. 1443 * 1444 * @see #PRESSED_STATE_SET 1445 * @see #FOCUSED_STATE_SET 1446 * @see #WINDOW_FOCUSED_STATE_SET 1447 */ 1448 protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET; 1449 /** 1450 * Indicates the view is pressed, focused and selected. 1451 * 1452 * @see #PRESSED_STATE_SET 1453 * @see #SELECTED_STATE_SET 1454 * @see #FOCUSED_STATE_SET 1455 */ 1456 protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET; 1457 /** 1458 * Indicates the view is pressed, focused, selected and its window has the focus. 1459 * 1460 * @see #PRESSED_STATE_SET 1461 * @see #FOCUSED_STATE_SET 1462 * @see #SELECTED_STATE_SET 1463 * @see #WINDOW_FOCUSED_STATE_SET 1464 */ 1465 protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1466 /** 1467 * Indicates the view is pressed and enabled. 1468 * 1469 * @see #PRESSED_STATE_SET 1470 * @see #ENABLED_STATE_SET 1471 */ 1472 protected static final int[] PRESSED_ENABLED_STATE_SET; 1473 /** 1474 * Indicates the view is pressed, enabled and its window has the focus. 1475 * 1476 * @see #PRESSED_STATE_SET 1477 * @see #ENABLED_STATE_SET 1478 * @see #WINDOW_FOCUSED_STATE_SET 1479 */ 1480 protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET; 1481 /** 1482 * Indicates the view is pressed, enabled and selected. 1483 * 1484 * @see #PRESSED_STATE_SET 1485 * @see #ENABLED_STATE_SET 1486 * @see #SELECTED_STATE_SET 1487 */ 1488 protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET; 1489 /** 1490 * Indicates the view is pressed, enabled, selected and its window has the 1491 * focus. 1492 * 1493 * @see #PRESSED_STATE_SET 1494 * @see #ENABLED_STATE_SET 1495 * @see #SELECTED_STATE_SET 1496 * @see #WINDOW_FOCUSED_STATE_SET 1497 */ 1498 protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1499 /** 1500 * Indicates the view is pressed, enabled and focused. 1501 * 1502 * @see #PRESSED_STATE_SET 1503 * @see #ENABLED_STATE_SET 1504 * @see #FOCUSED_STATE_SET 1505 */ 1506 protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET; 1507 /** 1508 * Indicates the view is pressed, enabled, focused and its window has the 1509 * focus. 1510 * 1511 * @see #PRESSED_STATE_SET 1512 * @see #ENABLED_STATE_SET 1513 * @see #FOCUSED_STATE_SET 1514 * @see #WINDOW_FOCUSED_STATE_SET 1515 */ 1516 protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET; 1517 /** 1518 * Indicates the view is pressed, enabled, focused and selected. 1519 * 1520 * @see #PRESSED_STATE_SET 1521 * @see #ENABLED_STATE_SET 1522 * @see #SELECTED_STATE_SET 1523 * @see #FOCUSED_STATE_SET 1524 */ 1525 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET; 1526 /** 1527 * Indicates the view is pressed, enabled, focused, selected and its window 1528 * has the focus. 1529 * 1530 * @see #PRESSED_STATE_SET 1531 * @see #ENABLED_STATE_SET 1532 * @see #SELECTED_STATE_SET 1533 * @see #FOCUSED_STATE_SET 1534 * @see #WINDOW_FOCUSED_STATE_SET 1535 */ 1536 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1537 1538 static { 1539 EMPTY_STATE_SET = StateSet.get(0); 1540 1541 WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED); 1542 1543 SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED); 1544 SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1545 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED); 1546 1547 FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED); 1548 FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1549 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED); 1550 FOCUSED_SELECTED_STATE_SET = StateSet.get( 1551 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED); 1552 FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1553 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 1554 | StateSet.VIEW_STATE_FOCUSED); 1555 1556 ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED); 1557 ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1558 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED); 1559 ENABLED_SELECTED_STATE_SET = StateSet.get( 1560 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED); 1561 ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1562 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 1563 | StateSet.VIEW_STATE_ENABLED); 1564 ENABLED_FOCUSED_STATE_SET = StateSet.get( 1565 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED); 1566 ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1567 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED 1568 | StateSet.VIEW_STATE_ENABLED); 1569 ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get( 1570 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED 1571 | StateSet.VIEW_STATE_ENABLED); 1572 ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1573 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 1574 | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED); 1575 1576 PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED); 1577 PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1578 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED); 1579 PRESSED_SELECTED_STATE_SET = StateSet.get( 1580 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED); 1581 PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1582 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 1583 | StateSet.VIEW_STATE_PRESSED); 1584 PRESSED_FOCUSED_STATE_SET = StateSet.get( 1585 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED); 1586 PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1587 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED 1588 | StateSet.VIEW_STATE_PRESSED); 1589 PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get( 1590 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED 1591 | StateSet.VIEW_STATE_PRESSED); 1592 PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1593 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 1594 | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED); 1595 PRESSED_ENABLED_STATE_SET = StateSet.get( 1596 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED); 1597 PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1598 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED 1599 | StateSet.VIEW_STATE_PRESSED); 1600 PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get( 1601 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED 1602 | StateSet.VIEW_STATE_PRESSED); 1603 PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1604 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 1605 | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED); 1606 PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get( 1607 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED 1608 | StateSet.VIEW_STATE_PRESSED); 1609 PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1610 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED 1611 | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED); 1612 PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get( 1613 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED 1614 | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED); 1615 PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1616 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 1617 | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED 1618 | StateSet.VIEW_STATE_PRESSED); 1619 } 1620 1621 /** 1622 * Accessibility event types that are dispatched for text population. 1623 */ 1624 private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES = 1625 AccessibilityEvent.TYPE_VIEW_CLICKED 1626 | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED 1627 | AccessibilityEvent.TYPE_VIEW_SELECTED 1628 | AccessibilityEvent.TYPE_VIEW_FOCUSED 1629 | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED 1630 | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER 1631 | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT 1632 | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED 1633 | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED 1634 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED 1635 | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY; 1636 1637 /** 1638 * Temporary Rect currently for use in setBackground(). This will probably 1639 * be extended in the future to hold our own class with more than just 1640 * a Rect. :) 1641 */ 1642 static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>(); 1643 1644 /** 1645 * Map used to store views' tags. 1646 */ 1647 private SparseArray<Object> mKeyedTags; 1648 1649 /** 1650 * The next available accessibility id. 1651 */ 1652 private static int sNextAccessibilityViewId; 1653 1654 /** 1655 * The animation currently associated with this view. 1656 * @hide 1657 */ 1658 protected Animation mCurrentAnimation = null; 1659 1660 /** 1661 * Width as measured during measure pass. 1662 * {@hide} 1663 */ 1664 @ViewDebug.ExportedProperty(category = "measurement") 1665 int mMeasuredWidth; 1666 1667 /** 1668 * Height as measured during measure pass. 1669 * {@hide} 1670 */ 1671 @ViewDebug.ExportedProperty(category = "measurement") 1672 int mMeasuredHeight; 1673 1674 /** 1675 * Flag to indicate that this view was marked INVALIDATED, or had its display list 1676 * invalidated, prior to the current drawing iteration. If true, the view must re-draw 1677 * its display list. This flag, used only when hw accelerated, allows us to clear the 1678 * flag while retaining this information until it's needed (at getDisplayList() time and 1679 * in drawChild(), when we decide to draw a view's children's display lists into our own). 1680 * 1681 * {@hide} 1682 */ 1683 boolean mRecreateDisplayList = false; 1684 1685 /** 1686 * The view's identifier. 1687 * {@hide} 1688 * 1689 * @see #setId(int) 1690 * @see #getId() 1691 */ 1692 @IdRes 1693 @ViewDebug.ExportedProperty(resolveId = true) 1694 int mID = NO_ID; 1695 1696 /** 1697 * The stable ID of this view for accessibility purposes. 1698 */ 1699 int mAccessibilityViewId = NO_ID; 1700 1701 private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED; 1702 1703 SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent; 1704 1705 /** 1706 * The view's tag. 1707 * {@hide} 1708 * 1709 * @see #setTag(Object) 1710 * @see #getTag() 1711 */ 1712 protected Object mTag = null; 1713 1714 // for mPrivateFlags: 1715 /** {@hide} */ 1716 static final int PFLAG_WANTS_FOCUS = 0x00000001; 1717 /** {@hide} */ 1718 static final int PFLAG_FOCUSED = 0x00000002; 1719 /** {@hide} */ 1720 static final int PFLAG_SELECTED = 0x00000004; 1721 /** {@hide} */ 1722 static final int PFLAG_IS_ROOT_NAMESPACE = 0x00000008; 1723 /** {@hide} */ 1724 static final int PFLAG_HAS_BOUNDS = 0x00000010; 1725 /** {@hide} */ 1726 static final int PFLAG_DRAWN = 0x00000020; 1727 /** 1728 * When this flag is set, this view is running an animation on behalf of its 1729 * children and should therefore not cancel invalidate requests, even if they 1730 * lie outside of this view's bounds. 1731 * 1732 * {@hide} 1733 */ 1734 static final int PFLAG_DRAW_ANIMATION = 0x00000040; 1735 /** {@hide} */ 1736 static final int PFLAG_SKIP_DRAW = 0x00000080; 1737 /** {@hide} */ 1738 static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200; 1739 /** {@hide} */ 1740 static final int PFLAG_DRAWABLE_STATE_DIRTY = 0x00000400; 1741 /** {@hide} */ 1742 static final int PFLAG_MEASURED_DIMENSION_SET = 0x00000800; 1743 /** {@hide} */ 1744 static final int PFLAG_FORCE_LAYOUT = 0x00001000; 1745 /** {@hide} */ 1746 static final int PFLAG_LAYOUT_REQUIRED = 0x00002000; 1747 1748 private static final int PFLAG_PRESSED = 0x00004000; 1749 1750 /** {@hide} */ 1751 static final int PFLAG_DRAWING_CACHE_VALID = 0x00008000; 1752 /** 1753 * Flag used to indicate that this view should be drawn once more (and only once 1754 * more) after its animation has completed. 1755 * {@hide} 1756 */ 1757 static final int PFLAG_ANIMATION_STARTED = 0x00010000; 1758 1759 private static final int PFLAG_SAVE_STATE_CALLED = 0x00020000; 1760 1761 /** 1762 * Indicates that the View returned true when onSetAlpha() was called and that 1763 * the alpha must be restored. 1764 * {@hide} 1765 */ 1766 static final int PFLAG_ALPHA_SET = 0x00040000; 1767 1768 /** 1769 * Set by {@link #setScrollContainer(boolean)}. 1770 */ 1771 static final int PFLAG_SCROLL_CONTAINER = 0x00080000; 1772 1773 /** 1774 * Set by {@link #setScrollContainer(boolean)}. 1775 */ 1776 static final int PFLAG_SCROLL_CONTAINER_ADDED = 0x00100000; 1777 1778 /** 1779 * View flag indicating whether this view was invalidated (fully or partially.) 1780 * 1781 * @hide 1782 */ 1783 static final int PFLAG_DIRTY = 0x00200000; 1784 1785 /** 1786 * View flag indicating whether this view was invalidated by an opaque 1787 * invalidate request. 1788 * 1789 * @hide 1790 */ 1791 static final int PFLAG_DIRTY_OPAQUE = 0x00400000; 1792 1793 /** 1794 * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}. 1795 * 1796 * @hide 1797 */ 1798 static final int PFLAG_DIRTY_MASK = 0x00600000; 1799 1800 /** 1801 * Indicates whether the background is opaque. 1802 * 1803 * @hide 1804 */ 1805 static final int PFLAG_OPAQUE_BACKGROUND = 0x00800000; 1806 1807 /** 1808 * Indicates whether the scrollbars are opaque. 1809 * 1810 * @hide 1811 */ 1812 static final int PFLAG_OPAQUE_SCROLLBARS = 0x01000000; 1813 1814 /** 1815 * Indicates whether the view is opaque. 1816 * 1817 * @hide 1818 */ 1819 static final int PFLAG_OPAQUE_MASK = 0x01800000; 1820 1821 /** 1822 * Indicates a prepressed state; 1823 * the short time between ACTION_DOWN and recognizing 1824 * a 'real' press. Prepressed is used to recognize quick taps 1825 * even when they are shorter than ViewConfiguration.getTapTimeout(). 1826 * 1827 * @hide 1828 */ 1829 private static final int PFLAG_PREPRESSED = 0x02000000; 1830 1831 /** 1832 * Indicates whether the view is temporarily detached. 1833 * 1834 * @hide 1835 */ 1836 static final int PFLAG_CANCEL_NEXT_UP_EVENT = 0x04000000; 1837 1838 /** 1839 * Indicates that we should awaken scroll bars once attached 1840 * 1841 * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged 1842 * during window attachment and it is no longer needed. Feel free to repurpose it. 1843 * 1844 * @hide 1845 */ 1846 private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000; 1847 1848 /** 1849 * Indicates that the view has received HOVER_ENTER. Cleared on HOVER_EXIT. 1850 * @hide 1851 */ 1852 private static final int PFLAG_HOVERED = 0x10000000; 1853 1854 /** 1855 * no longer needed, should be reused 1856 */ 1857 private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000; 1858 1859 /** {@hide} */ 1860 static final int PFLAG_ACTIVATED = 0x40000000; 1861 1862 /** 1863 * Indicates that this view was specifically invalidated, not just dirtied because some 1864 * child view was invalidated. The flag is used to determine when we need to recreate 1865 * a view's display list (as opposed to just returning a reference to its existing 1866 * display list). 1867 * 1868 * @hide 1869 */ 1870 static final int PFLAG_INVALIDATED = 0x80000000; 1871 1872 /** 1873 * Masks for mPrivateFlags2, as generated by dumpFlags(): 1874 * 1875 * |-------|-------|-------|-------| 1876 * 1 PFLAG2_DRAG_CAN_ACCEPT 1877 * 1 PFLAG2_DRAG_HOVERED 1878 * 11 PFLAG2_LAYOUT_DIRECTION_MASK 1879 * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL 1880 * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED 1881 * 11 PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK 1882 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[1] 1883 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[2] 1884 * 11 PFLAG2_TEXT_DIRECTION_FLAGS[3] 1885 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[4] 1886 * 1 1 PFLAG2_TEXT_DIRECTION_FLAGS[5] 1887 * 11 PFLAG2_TEXT_DIRECTION_FLAGS[6] 1888 * 111 PFLAG2_TEXT_DIRECTION_FLAGS[7] 1889 * 111 PFLAG2_TEXT_DIRECTION_MASK 1890 * 1 PFLAG2_TEXT_DIRECTION_RESOLVED 1891 * 1 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT 1892 * 111 PFLAG2_TEXT_DIRECTION_RESOLVED_MASK 1893 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[1] 1894 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[2] 1895 * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[3] 1896 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[4] 1897 * 1 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[5] 1898 * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[6] 1899 * 111 PFLAG2_TEXT_ALIGNMENT_MASK 1900 * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED 1901 * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT 1902 * 111 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK 1903 * 111 PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK 1904 * 11 PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK 1905 * 1 PFLAG2_ACCESSIBILITY_FOCUSED 1906 * 1 PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED 1907 * 1 PFLAG2_VIEW_QUICK_REJECTED 1908 * 1 PFLAG2_PADDING_RESOLVED 1909 * 1 PFLAG2_DRAWABLE_RESOLVED 1910 * 1 PFLAG2_HAS_TRANSIENT_STATE 1911 * |-------|-------|-------|-------| 1912 */ 1913 1914 /** 1915 * Indicates that this view has reported that it can accept the current drag's content. 1916 * Cleared when the drag operation concludes. 1917 * @hide 1918 */ 1919 static final int PFLAG2_DRAG_CAN_ACCEPT = 0x00000001; 1920 1921 /** 1922 * Indicates that this view is currently directly under the drag location in a 1923 * drag-and-drop operation involving content that it can accept. Cleared when 1924 * the drag exits the view, or when the drag operation concludes. 1925 * @hide 1926 */ 1927 static final int PFLAG2_DRAG_HOVERED = 0x00000002; 1928 1929 /** @hide */ 1930 @IntDef({ 1931 LAYOUT_DIRECTION_LTR, 1932 LAYOUT_DIRECTION_RTL, 1933 LAYOUT_DIRECTION_INHERIT, 1934 LAYOUT_DIRECTION_LOCALE 1935 }) 1936 @Retention(RetentionPolicy.SOURCE) 1937 // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection 1938 public @interface LayoutDir {} 1939 1940 /** @hide */ 1941 @IntDef({ 1942 LAYOUT_DIRECTION_LTR, 1943 LAYOUT_DIRECTION_RTL 1944 }) 1945 @Retention(RetentionPolicy.SOURCE) 1946 public @interface ResolvedLayoutDir {} 1947 1948 /** 1949 * A flag to indicate that the layout direction of this view has not been defined yet. 1950 * @hide 1951 */ 1952 public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED; 1953 1954 /** 1955 * Horizontal layout direction of this view is from Left to Right. 1956 * Use with {@link #setLayoutDirection}. 1957 */ 1958 public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR; 1959 1960 /** 1961 * Horizontal layout direction of this view is from Right to Left. 1962 * Use with {@link #setLayoutDirection}. 1963 */ 1964 public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL; 1965 1966 /** 1967 * Horizontal layout direction of this view is inherited from its parent. 1968 * Use with {@link #setLayoutDirection}. 1969 */ 1970 public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT; 1971 1972 /** 1973 * Horizontal layout direction of this view is from deduced from the default language 1974 * script for the locale. Use with {@link #setLayoutDirection}. 1975 */ 1976 public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE; 1977 1978 /** 1979 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED) 1980 * @hide 1981 */ 1982 static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2; 1983 1984 /** 1985 * Mask for use with private flags indicating bits used for horizontal layout direction. 1986 * @hide 1987 */ 1988 static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 1989 1990 /** 1991 * Indicates whether the view horizontal layout direction has been resolved and drawn to the 1992 * right-to-left direction. 1993 * @hide 1994 */ 1995 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 1996 1997 /** 1998 * Indicates whether the view horizontal layout direction has been resolved. 1999 * @hide 2000 */ 2001 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 2002 2003 /** 2004 * Mask for use with private flags indicating bits used for resolved horizontal layout direction. 2005 * @hide 2006 */ 2007 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C 2008 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 2009 2010 /* 2011 * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct 2012 * flag value. 2013 * @hide 2014 */ 2015 private static final int[] LAYOUT_DIRECTION_FLAGS = { 2016 LAYOUT_DIRECTION_LTR, 2017 LAYOUT_DIRECTION_RTL, 2018 LAYOUT_DIRECTION_INHERIT, 2019 LAYOUT_DIRECTION_LOCALE 2020 }; 2021 2022 /** 2023 * Default horizontal layout direction. 2024 */ 2025 private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT; 2026 2027 /** 2028 * Default horizontal layout direction. 2029 * @hide 2030 */ 2031 static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR; 2032 2033 /** 2034 * Text direction is inherited through {@link ViewGroup} 2035 */ 2036 public static final int TEXT_DIRECTION_INHERIT = 0; 2037 2038 /** 2039 * Text direction is using "first strong algorithm". The first strong directional character 2040 * determines the paragraph direction. If there is no strong directional character, the 2041 * paragraph direction is the view's resolved layout direction. 2042 */ 2043 public static final int TEXT_DIRECTION_FIRST_STRONG = 1; 2044 2045 /** 2046 * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains 2047 * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters. 2048 * If there are neither, the paragraph direction is the view's resolved layout direction. 2049 */ 2050 public static final int TEXT_DIRECTION_ANY_RTL = 2; 2051 2052 /** 2053 * Text direction is forced to LTR. 2054 */ 2055 public static final int TEXT_DIRECTION_LTR = 3; 2056 2057 /** 2058 * Text direction is forced to RTL. 2059 */ 2060 public static final int TEXT_DIRECTION_RTL = 4; 2061 2062 /** 2063 * Text direction is coming from the system Locale. 2064 */ 2065 public static final int TEXT_DIRECTION_LOCALE = 5; 2066 2067 /** 2068 * Text direction is using "first strong algorithm". The first strong directional character 2069 * determines the paragraph direction. If there is no strong directional character, the 2070 * paragraph direction is LTR. 2071 */ 2072 public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6; 2073 2074 /** 2075 * Text direction is using "first strong algorithm". The first strong directional character 2076 * determines the paragraph direction. If there is no strong directional character, the 2077 * paragraph direction is RTL. 2078 */ 2079 public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7; 2080 2081 /** 2082 * Default text direction is inherited 2083 */ 2084 private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT; 2085 2086 /** 2087 * Default resolved text direction 2088 * @hide 2089 */ 2090 static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG; 2091 2092 /** 2093 * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED) 2094 * @hide 2095 */ 2096 static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6; 2097 2098 /** 2099 * Mask for use with private flags indicating bits used for text direction. 2100 * @hide 2101 */ 2102 static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007 2103 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT; 2104 2105 /** 2106 * Array of text direction flags for mapping attribute "textDirection" to correct 2107 * flag value. 2108 * @hide 2109 */ 2110 private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = { 2111 TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2112 TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2113 TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2114 TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2115 TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2116 TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2117 TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2118 TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT 2119 }; 2120 2121 /** 2122 * Indicates whether the view text direction has been resolved. 2123 * @hide 2124 */ 2125 static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008 2126 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT; 2127 2128 /** 2129 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED) 2130 * @hide 2131 */ 2132 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10; 2133 2134 /** 2135 * Mask for use with private flags indicating bits used for resolved text direction. 2136 * @hide 2137 */ 2138 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007 2139 << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT; 2140 2141 /** 2142 * Indicates whether the view text direction has been resolved to the "first strong" heuristic. 2143 * @hide 2144 */ 2145 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT = 2146 TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT; 2147 2148 /** @hide */ 2149 @IntDef({ 2150 TEXT_ALIGNMENT_INHERIT, 2151 TEXT_ALIGNMENT_GRAVITY, 2152 TEXT_ALIGNMENT_CENTER, 2153 TEXT_ALIGNMENT_TEXT_START, 2154 TEXT_ALIGNMENT_TEXT_END, 2155 TEXT_ALIGNMENT_VIEW_START, 2156 TEXT_ALIGNMENT_VIEW_END 2157 }) 2158 @Retention(RetentionPolicy.SOURCE) 2159 public @interface TextAlignment {} 2160 2161 /** 2162 * Default text alignment. The text alignment of this View is inherited from its parent. 2163 * Use with {@link #setTextAlignment(int)} 2164 */ 2165 public static final int TEXT_ALIGNMENT_INHERIT = 0; 2166 2167 /** 2168 * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL, 2169 * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction. 2170 * 2171 * Use with {@link #setTextAlignment(int)} 2172 */ 2173 public static final int TEXT_ALIGNMENT_GRAVITY = 1; 2174 2175 /** 2176 * Align to the start of the paragraph, e.g. ALIGN_NORMAL. 2177 * 2178 * Use with {@link #setTextAlignment(int)} 2179 */ 2180 public static final int TEXT_ALIGNMENT_TEXT_START = 2; 2181 2182 /** 2183 * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE. 2184 * 2185 * Use with {@link #setTextAlignment(int)} 2186 */ 2187 public static final int TEXT_ALIGNMENT_TEXT_END = 3; 2188 2189 /** 2190 * Center the paragraph, e.g. ALIGN_CENTER. 2191 * 2192 * Use with {@link #setTextAlignment(int)} 2193 */ 2194 public static final int TEXT_ALIGNMENT_CENTER = 4; 2195 2196 /** 2197 * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved 2198 * layoutDirection is LTR, and ALIGN_RIGHT otherwise. 2199 * 2200 * Use with {@link #setTextAlignment(int)} 2201 */ 2202 public static final int TEXT_ALIGNMENT_VIEW_START = 5; 2203 2204 /** 2205 * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved 2206 * layoutDirection is LTR, and ALIGN_LEFT otherwise. 2207 * 2208 * Use with {@link #setTextAlignment(int)} 2209 */ 2210 public static final int TEXT_ALIGNMENT_VIEW_END = 6; 2211 2212 /** 2213 * Default text alignment is inherited 2214 */ 2215 private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY; 2216 2217 /** 2218 * Default resolved text alignment 2219 * @hide 2220 */ 2221 static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY; 2222 2223 /** 2224 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED) 2225 * @hide 2226 */ 2227 static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13; 2228 2229 /** 2230 * Mask for use with private flags indicating bits used for text alignment. 2231 * @hide 2232 */ 2233 static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT; 2234 2235 /** 2236 * Array of text direction flags for mapping attribute "textAlignment" to correct 2237 * flag value. 2238 * @hide 2239 */ 2240 private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = { 2241 TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2242 TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2243 TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2244 TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2245 TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2246 TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2247 TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT 2248 }; 2249 2250 /** 2251 * Indicates whether the view text alignment has been resolved. 2252 * @hide 2253 */ 2254 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT; 2255 2256 /** 2257 * Bit shift to get the resolved text alignment. 2258 * @hide 2259 */ 2260 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17; 2261 2262 /** 2263 * Mask for use with private flags indicating bits used for text alignment. 2264 * @hide 2265 */ 2266 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007 2267 << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT; 2268 2269 /** 2270 * Indicates whether if the view text alignment has been resolved to gravity 2271 */ 2272 private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT = 2273 TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT; 2274 2275 // Accessiblity constants for mPrivateFlags2 2276 2277 /** 2278 * Shift for the bits in {@link #mPrivateFlags2} related to the 2279 * "importantForAccessibility" attribute. 2280 */ 2281 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20; 2282 2283 /** 2284 * Automatically determine whether a view is important for accessibility. 2285 */ 2286 public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000; 2287 2288 /** 2289 * The view is important for accessibility. 2290 */ 2291 public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001; 2292 2293 /** 2294 * The view is not important for accessibility. 2295 */ 2296 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002; 2297 2298 /** 2299 * The view is not important for accessibility, nor are any of its 2300 * descendant views. 2301 */ 2302 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004; 2303 2304 /** 2305 * The default whether the view is important for accessibility. 2306 */ 2307 static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO; 2308 2309 /** 2310 * Mask for obtainig the bits which specify how to determine 2311 * whether a view is important for accessibility. 2312 */ 2313 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO 2314 | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO 2315 | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) 2316 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT; 2317 2318 /** 2319 * Shift for the bits in {@link #mPrivateFlags2} related to the 2320 * "accessibilityLiveRegion" attribute. 2321 */ 2322 static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23; 2323 2324 /** 2325 * Live region mode specifying that accessibility services should not 2326 * automatically announce changes to this view. This is the default live 2327 * region mode for most views. 2328 * <p> 2329 * Use with {@link #setAccessibilityLiveRegion(int)}. 2330 */ 2331 public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000; 2332 2333 /** 2334 * Live region mode specifying that accessibility services should announce 2335 * changes to this view. 2336 * <p> 2337 * Use with {@link #setAccessibilityLiveRegion(int)}. 2338 */ 2339 public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001; 2340 2341 /** 2342 * Live region mode specifying that accessibility services should interrupt 2343 * ongoing speech to immediately announce changes to this view. 2344 * <p> 2345 * Use with {@link #setAccessibilityLiveRegion(int)}. 2346 */ 2347 public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002; 2348 2349 /** 2350 * The default whether the view is important for accessibility. 2351 */ 2352 static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE; 2353 2354 /** 2355 * Mask for obtaining the bits which specify a view's accessibility live 2356 * region mode. 2357 */ 2358 static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE 2359 | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE) 2360 << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT; 2361 2362 /** 2363 * Flag indicating whether a view has accessibility focus. 2364 */ 2365 static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000; 2366 2367 /** 2368 * Flag whether the accessibility state of the subtree rooted at this view changed. 2369 */ 2370 static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000; 2371 2372 /** 2373 * Flag indicating whether a view failed the quickReject() check in draw(). This condition 2374 * is used to check whether later changes to the view's transform should invalidate the 2375 * view to force the quickReject test to run again. 2376 */ 2377 static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000; 2378 2379 /** 2380 * Flag indicating that start/end padding has been resolved into left/right padding 2381 * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()} 2382 * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved 2383 * during measurement. In some special cases this is required such as when an adapter-based 2384 * view measures prospective children without attaching them to a window. 2385 */ 2386 static final int PFLAG2_PADDING_RESOLVED = 0x20000000; 2387 2388 /** 2389 * Flag indicating that the start/end drawables has been resolved into left/right ones. 2390 */ 2391 static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000; 2392 2393 /** 2394 * Indicates that the view is tracking some sort of transient state 2395 * that the app should not need to be aware of, but that the framework 2396 * should take special care to preserve. 2397 */ 2398 static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000; 2399 2400 /** 2401 * Group of bits indicating that RTL properties resolution is done. 2402 */ 2403 static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED | 2404 PFLAG2_TEXT_DIRECTION_RESOLVED | 2405 PFLAG2_TEXT_ALIGNMENT_RESOLVED | 2406 PFLAG2_PADDING_RESOLVED | 2407 PFLAG2_DRAWABLE_RESOLVED; 2408 2409 // There are a couple of flags left in mPrivateFlags2 2410 2411 /* End of masks for mPrivateFlags2 */ 2412 2413 /** 2414 * Masks for mPrivateFlags3, as generated by dumpFlags(): 2415 * 2416 * |-------|-------|-------|-------| 2417 * 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM 2418 * 1 PFLAG3_VIEW_IS_ANIMATING_ALPHA 2419 * 1 PFLAG3_IS_LAID_OUT 2420 * 1 PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT 2421 * 1 PFLAG3_CALLED_SUPER 2422 * 1 PFLAG3_APPLYING_INSETS 2423 * 1 PFLAG3_FITTING_SYSTEM_WINDOWS 2424 * 1 PFLAG3_NESTED_SCROLLING_ENABLED 2425 * 1 PFLAG3_SCROLL_INDICATOR_TOP 2426 * 1 PFLAG3_SCROLL_INDICATOR_BOTTOM 2427 * 1 PFLAG3_SCROLL_INDICATOR_LEFT 2428 * 1 PFLAG3_SCROLL_INDICATOR_RIGHT 2429 * 1 PFLAG3_SCROLL_INDICATOR_START 2430 * 1 PFLAG3_SCROLL_INDICATOR_END 2431 * 1 PFLAG3_ASSIST_BLOCKED 2432 * 1 PFLAG3_POINTER_ICON_NULL 2433 * 1 PFLAG3_POINTER_ICON_VALUE_START 2434 * 11111111 PFLAG3_POINTER_ICON_MASK 2435 * 1 PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE 2436 * 1 PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED 2437 * 1 PFLAG3_TEMPORARY_DETACH 2438 * |-------|-------|-------|-------| 2439 */ 2440 2441 /** 2442 * Flag indicating that view has a transform animation set on it. This is used to track whether 2443 * an animation is cleared between successive frames, in order to tell the associated 2444 * DisplayList to clear its animation matrix. 2445 */ 2446 static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1; 2447 2448 /** 2449 * Flag indicating that view has an alpha animation set on it. This is used to track whether an 2450 * animation is cleared between successive frames, in order to tell the associated 2451 * DisplayList to restore its alpha value. 2452 */ 2453 static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2; 2454 2455 /** 2456 * Flag indicating that the view has been through at least one layout since it 2457 * was last attached to a window. 2458 */ 2459 static final int PFLAG3_IS_LAID_OUT = 0x4; 2460 2461 /** 2462 * Flag indicating that a call to measure() was skipped and should be done 2463 * instead when layout() is invoked. 2464 */ 2465 static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8; 2466 2467 /** 2468 * Flag indicating that an overridden method correctly called down to 2469 * the superclass implementation as required by the API spec. 2470 */ 2471 static final int PFLAG3_CALLED_SUPER = 0x10; 2472 2473 /** 2474 * Flag indicating that we're in the process of applying window insets. 2475 */ 2476 static final int PFLAG3_APPLYING_INSETS = 0x20; 2477 2478 /** 2479 * Flag indicating that we're in the process of fitting system windows using the old method. 2480 */ 2481 static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40; 2482 2483 /** 2484 * Flag indicating that nested scrolling is enabled for this view. 2485 * The view will optionally cooperate with views up its parent chain to allow for 2486 * integrated nested scrolling along the same axis. 2487 */ 2488 static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80; 2489 2490 /** 2491 * Flag indicating that the bottom scroll indicator should be displayed 2492 * when this view can scroll up. 2493 */ 2494 static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100; 2495 2496 /** 2497 * Flag indicating that the bottom scroll indicator should be displayed 2498 * when this view can scroll down. 2499 */ 2500 static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200; 2501 2502 /** 2503 * Flag indicating that the left scroll indicator should be displayed 2504 * when this view can scroll left. 2505 */ 2506 static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400; 2507 2508 /** 2509 * Flag indicating that the right scroll indicator should be displayed 2510 * when this view can scroll right. 2511 */ 2512 static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800; 2513 2514 /** 2515 * Flag indicating that the start scroll indicator should be displayed 2516 * when this view can scroll in the start direction. 2517 */ 2518 static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000; 2519 2520 /** 2521 * Flag indicating that the end scroll indicator should be displayed 2522 * when this view can scroll in the end direction. 2523 */ 2524 static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000; 2525 2526 static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED; 2527 2528 static final int SCROLL_INDICATORS_NONE = 0x0000; 2529 2530 /** 2531 * Mask for use with setFlags indicating bits used for indicating which 2532 * scroll indicators are enabled. 2533 */ 2534 static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP 2535 | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT 2536 | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START 2537 | PFLAG3_SCROLL_INDICATOR_END; 2538 2539 /** 2540 * Left-shift required to translate between public scroll indicator flags 2541 * and internal PFLAGS3 flags. When used as a right-shift, translates 2542 * PFLAGS3 flags to public flags. 2543 */ 2544 static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8; 2545 2546 /** @hide */ 2547 @Retention(RetentionPolicy.SOURCE) 2548 @IntDef(flag = true, 2549 value = { 2550 SCROLL_INDICATOR_TOP, 2551 SCROLL_INDICATOR_BOTTOM, 2552 SCROLL_INDICATOR_LEFT, 2553 SCROLL_INDICATOR_RIGHT, 2554 SCROLL_INDICATOR_START, 2555 SCROLL_INDICATOR_END, 2556 }) 2557 public @interface ScrollIndicators {} 2558 2559 /** 2560 * Scroll indicator direction for the top edge of the view. 2561 * 2562 * @see #setScrollIndicators(int) 2563 * @see #setScrollIndicators(int, int) 2564 * @see #getScrollIndicators() 2565 */ 2566 public static final int SCROLL_INDICATOR_TOP = 2567 PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 2568 2569 /** 2570 * Scroll indicator direction for the bottom edge of the view. 2571 * 2572 * @see #setScrollIndicators(int) 2573 * @see #setScrollIndicators(int, int) 2574 * @see #getScrollIndicators() 2575 */ 2576 public static final int SCROLL_INDICATOR_BOTTOM = 2577 PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 2578 2579 /** 2580 * Scroll indicator direction for the left edge of the view. 2581 * 2582 * @see #setScrollIndicators(int) 2583 * @see #setScrollIndicators(int, int) 2584 * @see #getScrollIndicators() 2585 */ 2586 public static final int SCROLL_INDICATOR_LEFT = 2587 PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 2588 2589 /** 2590 * Scroll indicator direction for the right edge of the view. 2591 * 2592 * @see #setScrollIndicators(int) 2593 * @see #setScrollIndicators(int, int) 2594 * @see #getScrollIndicators() 2595 */ 2596 public static final int SCROLL_INDICATOR_RIGHT = 2597 PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 2598 2599 /** 2600 * Scroll indicator direction for the starting edge of the view. 2601 * <p> 2602 * Resolved according to the view's layout direction, see 2603 * {@link #getLayoutDirection()} for more information. 2604 * 2605 * @see #setScrollIndicators(int) 2606 * @see #setScrollIndicators(int, int) 2607 * @see #getScrollIndicators() 2608 */ 2609 public static final int SCROLL_INDICATOR_START = 2610 PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 2611 2612 /** 2613 * Scroll indicator direction for the ending edge of the view. 2614 * <p> 2615 * Resolved according to the view's layout direction, see 2616 * {@link #getLayoutDirection()} for more information. 2617 * 2618 * @see #setScrollIndicators(int) 2619 * @see #setScrollIndicators(int, int) 2620 * @see #getScrollIndicators() 2621 */ 2622 public static final int SCROLL_INDICATOR_END = 2623 PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 2624 2625 /** 2626 * <p>Indicates that we are allowing {@link ViewStructure} to traverse 2627 * into this view.<p> 2628 */ 2629 static final int PFLAG3_ASSIST_BLOCKED = 0x4000; 2630 2631 /** 2632 * The mask for use with private flags indicating bits used for pointer icon shapes. 2633 */ 2634 static final int PFLAG3_POINTER_ICON_MASK = 0x7f8000; 2635 2636 /** 2637 * Left-shift used for pointer icon shape values in private flags. 2638 */ 2639 static final int PFLAG3_POINTER_ICON_LSHIFT = 15; 2640 2641 /** 2642 * Value indicating no specific pointer icons. 2643 */ 2644 private static final int PFLAG3_POINTER_ICON_NOT_SPECIFIED = 0 << PFLAG3_POINTER_ICON_LSHIFT; 2645 2646 /** 2647 * Value indicating {@link PointerIcon.TYPE_NULL}. 2648 */ 2649 private static final int PFLAG3_POINTER_ICON_NULL = 1 << PFLAG3_POINTER_ICON_LSHIFT; 2650 2651 /** 2652 * The base value for other pointer icon shapes. 2653 */ 2654 private static final int PFLAG3_POINTER_ICON_VALUE_START = 2 << PFLAG3_POINTER_ICON_LSHIFT; 2655 2656 /** 2657 * Whether this view has rendered elements that overlap (see {@link 2658 * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and 2659 * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when 2660 * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is 2661 * determined by whatever {@link #hasOverlappingRendering()} returns. 2662 */ 2663 private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000; 2664 2665 /** 2666 * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value 2667 * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid. 2668 */ 2669 private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000; 2670 2671 /** 2672 * Flag indicating that the view is temporarily detached from the parent view. 2673 * 2674 * @see #onStartTemporaryDetach() 2675 * @see #onFinishTemporaryDetach() 2676 */ 2677 static final int PFLAG3_TEMPORARY_DETACH = 0x2000000; 2678 2679 /* End of masks for mPrivateFlags3 */ 2680 2681 /** 2682 * Always allow a user to over-scroll this view, provided it is a 2683 * view that can scroll. 2684 * 2685 * @see #getOverScrollMode() 2686 * @see #setOverScrollMode(int) 2687 */ 2688 public static final int OVER_SCROLL_ALWAYS = 0; 2689 2690 /** 2691 * Allow a user to over-scroll this view only if the content is large 2692 * enough to meaningfully scroll, provided it is a view that can scroll. 2693 * 2694 * @see #getOverScrollMode() 2695 * @see #setOverScrollMode(int) 2696 */ 2697 public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1; 2698 2699 /** 2700 * Never allow a user to over-scroll this view. 2701 * 2702 * @see #getOverScrollMode() 2703 * @see #setOverScrollMode(int) 2704 */ 2705 public static final int OVER_SCROLL_NEVER = 2; 2706 2707 /** 2708 * Special constant for {@link #setSystemUiVisibility(int)}: View has 2709 * requested the system UI (status bar) to be visible (the default). 2710 * 2711 * @see #setSystemUiVisibility(int) 2712 */ 2713 public static final int SYSTEM_UI_FLAG_VISIBLE = 0; 2714 2715 /** 2716 * Flag for {@link #setSystemUiVisibility(int)}: View has requested the 2717 * system UI to enter an unobtrusive "low profile" mode. 2718 * 2719 * <p>This is for use in games, book readers, video players, or any other 2720 * "immersive" application where the usual system chrome is deemed too distracting. 2721 * 2722 * <p>In low profile mode, the status bar and/or navigation icons may dim. 2723 * 2724 * @see #setSystemUiVisibility(int) 2725 */ 2726 public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001; 2727 2728 /** 2729 * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the 2730 * system navigation be temporarily hidden. 2731 * 2732 * <p>This is an even less obtrusive state than that called for by 2733 * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls 2734 * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause 2735 * those to disappear. This is useful (in conjunction with the 2736 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and 2737 * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN} 2738 * window flags) for displaying content using every last pixel on the display. 2739 * 2740 * <p>There is a limitation: because navigation controls are so important, the least user 2741 * interaction will cause them to reappear immediately. When this happens, both 2742 * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically, 2743 * so that both elements reappear at the same time. 2744 * 2745 * @see #setSystemUiVisibility(int) 2746 */ 2747 public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002; 2748 2749 /** 2750 * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go 2751 * into the normal fullscreen mode so that its content can take over the screen 2752 * while still allowing the user to interact with the application. 2753 * 2754 * <p>This has the same visual effect as 2755 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN 2756 * WindowManager.LayoutParams.FLAG_FULLSCREEN}, 2757 * meaning that non-critical screen decorations (such as the status bar) will be 2758 * hidden while the user is in the View's window, focusing the experience on 2759 * that content. Unlike the window flag, if you are using ActionBar in 2760 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY 2761 * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also 2762 * hide the action bar. 2763 * 2764 * <p>This approach to going fullscreen is best used over the window flag when 2765 * it is a transient state -- that is, the application does this at certain 2766 * points in its user interaction where it wants to allow the user to focus 2767 * on content, but not as a continuous state. For situations where the application 2768 * would like to simply stay full screen the entire time (such as a game that 2769 * wants to take over the screen), the 2770 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag} 2771 * is usually a better approach. The state set here will be removed by the system 2772 * in various situations (such as the user moving to another application) like 2773 * the other system UI states. 2774 * 2775 * <p>When using this flag, the application should provide some easy facility 2776 * for the user to go out of it. A common example would be in an e-book 2777 * reader, where tapping on the screen brings back whatever screen and UI 2778 * decorations that had been hidden while the user was immersed in reading 2779 * the book. 2780 * 2781 * @see #setSystemUiVisibility(int) 2782 */ 2783 public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004; 2784 2785 /** 2786 * Flag for {@link #setSystemUiVisibility(int)}: When using other layout 2787 * flags, we would like a stable view of the content insets given to 2788 * {@link #fitSystemWindows(Rect)}. This means that the insets seen there 2789 * will always represent the worst case that the application can expect 2790 * as a continuous state. In the stock Android UI this is the space for 2791 * the system bar, nav bar, and status bar, but not more transient elements 2792 * such as an input method. 2793 * 2794 * The stable layout your UI sees is based on the system UI modes you can 2795 * switch to. That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} 2796 * then you will get a stable layout for changes of the 2797 * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify 2798 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and 2799 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition 2800 * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} 2801 * with a stable layout. (Note that you should avoid using 2802 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.) 2803 * 2804 * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN} 2805 * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}), 2806 * then a hidden status bar will be considered a "stable" state for purposes 2807 * here. This allows your UI to continually hide the status bar, while still 2808 * using the system UI flags to hide the action bar while still retaining 2809 * a stable layout. Note that changing the window fullscreen flag will never 2810 * provide a stable layout for a clean transition. 2811 * 2812 * <p>If you are using ActionBar in 2813 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY 2814 * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the 2815 * insets it adds to those given to the application. 2816 */ 2817 public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100; 2818 2819 /** 2820 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window 2821 * to be laid out as if it has requested 2822 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't. This 2823 * allows it to avoid artifacts when switching in and out of that mode, at 2824 * the expense that some of its user interface may be covered by screen 2825 * decorations when they are shown. You can perform layout of your inner 2826 * UI elements to account for the navigation system UI through the 2827 * {@link #fitSystemWindows(Rect)} method. 2828 */ 2829 public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200; 2830 2831 /** 2832 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window 2833 * to be laid out as if it has requested 2834 * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't. This 2835 * allows it to avoid artifacts when switching in and out of that mode, at 2836 * the expense that some of its user interface may be covered by screen 2837 * decorations when they are shown. You can perform layout of your inner 2838 * UI elements to account for non-fullscreen system UI through the 2839 * {@link #fitSystemWindows(Rect)} method. 2840 */ 2841 public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400; 2842 2843 /** 2844 * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when 2845 * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. If this flag is 2846 * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any 2847 * user interaction. 2848 * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only 2849 * has an effect when used in combination with that flag.</p> 2850 */ 2851 public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800; 2852 2853 /** 2854 * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when 2855 * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation 2856 * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. Use this flag to create an immersive 2857 * experience while also hiding the system bars. If this flag is not set, 2858 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user 2859 * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system 2860 * if the user swipes from the top of the screen. 2861 * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with 2862 * system gestures, such as swiping from the top of the screen. These transient system bars 2863 * will overlay app’s content, may have some degree of transparency, and will automatically 2864 * hide after a short timeout. 2865 * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and 2866 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination 2867 * with one or both of those flags.</p> 2868 */ 2869 public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000; 2870 2871 /** 2872 * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that 2873 * is compatible with light status bar backgrounds. 2874 * 2875 * <p>For this to take effect, the window must request 2876 * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS 2877 * FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not 2878 * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS 2879 * FLAG_TRANSLUCENT_STATUS}. 2880 * 2881 * @see android.R.attr#windowLightStatusBar 2882 */ 2883 public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000; 2884 2885 /** 2886 * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead. 2887 */ 2888 public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE; 2889 2890 /** 2891 * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead. 2892 */ 2893 public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE; 2894 2895 /** 2896 * @hide 2897 * 2898 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2899 * out of the public fields to keep the undefined bits out of the developer's way. 2900 * 2901 * Flag to make the status bar not expandable. Unless you also 2902 * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show. 2903 */ 2904 public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000; 2905 2906 /** 2907 * @hide 2908 * 2909 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2910 * out of the public fields to keep the undefined bits out of the developer's way. 2911 * 2912 * Flag to hide notification icons and scrolling ticker text. 2913 */ 2914 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000; 2915 2916 /** 2917 * @hide 2918 * 2919 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2920 * out of the public fields to keep the undefined bits out of the developer's way. 2921 * 2922 * Flag to disable incoming notification alerts. This will not block 2923 * icons, but it will block sound, vibrating and other visual or aural notifications. 2924 */ 2925 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000; 2926 2927 /** 2928 * @hide 2929 * 2930 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2931 * out of the public fields to keep the undefined bits out of the developer's way. 2932 * 2933 * Flag to hide only the scrolling ticker. Note that 2934 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies 2935 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}. 2936 */ 2937 public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000; 2938 2939 /** 2940 * @hide 2941 * 2942 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2943 * out of the public fields to keep the undefined bits out of the developer's way. 2944 * 2945 * Flag to hide the center system info area. 2946 */ 2947 public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000; 2948 2949 /** 2950 * @hide 2951 * 2952 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2953 * out of the public fields to keep the undefined bits out of the developer's way. 2954 * 2955 * Flag to hide only the home button. Don't use this 2956 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 2957 */ 2958 public static final int STATUS_BAR_DISABLE_HOME = 0x00200000; 2959 2960 /** 2961 * @hide 2962 * 2963 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2964 * out of the public fields to keep the undefined bits out of the developer's way. 2965 * 2966 * Flag to hide only the back button. Don't use this 2967 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 2968 */ 2969 public static final int STATUS_BAR_DISABLE_BACK = 0x00400000; 2970 2971 /** 2972 * @hide 2973 * 2974 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2975 * out of the public fields to keep the undefined bits out of the developer's way. 2976 * 2977 * Flag to hide only the clock. You might use this if your activity has 2978 * its own clock making the status bar's clock redundant. 2979 */ 2980 public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000; 2981 2982 /** 2983 * @hide 2984 * 2985 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2986 * out of the public fields to keep the undefined bits out of the developer's way. 2987 * 2988 * Flag to hide only the recent apps button. Don't use this 2989 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 2990 */ 2991 public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000; 2992 2993 /** 2994 * @hide 2995 * 2996 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2997 * out of the public fields to keep the undefined bits out of the developer's way. 2998 * 2999 * Flag to disable the global search gesture. Don't use this 3000 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 3001 */ 3002 public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000; 3003 3004 /** 3005 * @hide 3006 * 3007 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3008 * out of the public fields to keep the undefined bits out of the developer's way. 3009 * 3010 * Flag to specify that the status bar is displayed in transient mode. 3011 */ 3012 public static final int STATUS_BAR_TRANSIENT = 0x04000000; 3013 3014 /** 3015 * @hide 3016 * 3017 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3018 * out of the public fields to keep the undefined bits out of the developer's way. 3019 * 3020 * Flag to specify that the navigation bar is displayed in transient mode. 3021 */ 3022 public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000; 3023 3024 /** 3025 * @hide 3026 * 3027 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3028 * out of the public fields to keep the undefined bits out of the developer's way. 3029 * 3030 * Flag to specify that the hidden status bar would like to be shown. 3031 */ 3032 public static final int STATUS_BAR_UNHIDE = 0x10000000; 3033 3034 /** 3035 * @hide 3036 * 3037 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3038 * out of the public fields to keep the undefined bits out of the developer's way. 3039 * 3040 * Flag to specify that the hidden navigation bar would like to be shown. 3041 */ 3042 public static final int NAVIGATION_BAR_UNHIDE = 0x20000000; 3043 3044 /** 3045 * @hide 3046 * 3047 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3048 * out of the public fields to keep the undefined bits out of the developer's way. 3049 * 3050 * Flag to specify that the status bar is displayed in translucent mode. 3051 */ 3052 public static final int STATUS_BAR_TRANSLUCENT = 0x40000000; 3053 3054 /** 3055 * @hide 3056 * 3057 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3058 * out of the public fields to keep the undefined bits out of the developer's way. 3059 * 3060 * Flag to specify that the navigation bar is displayed in translucent mode. 3061 */ 3062 public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000; 3063 3064 /** 3065 * @hide 3066 * 3067 * Whether Recents is visible or not. 3068 */ 3069 public static final int RECENT_APPS_VISIBLE = 0x00004000; 3070 3071 /** 3072 * @hide 3073 * 3074 * Whether the TV's picture-in-picture is visible or not. 3075 */ 3076 public static final int TV_PICTURE_IN_PICTURE_VISIBLE = 0x00010000; 3077 3078 /** 3079 * @hide 3080 * 3081 * Makes navigation bar transparent (but not the status bar). 3082 */ 3083 public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000; 3084 3085 /** 3086 * @hide 3087 * 3088 * Makes status bar transparent (but not the navigation bar). 3089 */ 3090 public static final int STATUS_BAR_TRANSPARENT = 0x0000008; 3091 3092 /** 3093 * @hide 3094 * 3095 * Makes both status bar and navigation bar transparent. 3096 */ 3097 public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT 3098 | STATUS_BAR_TRANSPARENT; 3099 3100 /** 3101 * @hide 3102 */ 3103 public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7; 3104 3105 /** 3106 * These are the system UI flags that can be cleared by events outside 3107 * of an application. Currently this is just the ability to tap on the 3108 * screen while hiding the navigation bar to have it return. 3109 * @hide 3110 */ 3111 public static final int SYSTEM_UI_CLEARABLE_FLAGS = 3112 SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION 3113 | SYSTEM_UI_FLAG_FULLSCREEN; 3114 3115 /** 3116 * Flags that can impact the layout in relation to system UI. 3117 */ 3118 public static final int SYSTEM_UI_LAYOUT_FLAGS = 3119 SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 3120 | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 3121 3122 /** @hide */ 3123 @IntDef(flag = true, 3124 value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION }) 3125 @Retention(RetentionPolicy.SOURCE) 3126 public @interface FindViewFlags {} 3127 3128 /** 3129 * Find views that render the specified text. 3130 * 3131 * @see #findViewsWithText(ArrayList, CharSequence, int) 3132 */ 3133 public static final int FIND_VIEWS_WITH_TEXT = 0x00000001; 3134 3135 /** 3136 * Find find views that contain the specified content description. 3137 * 3138 * @see #findViewsWithText(ArrayList, CharSequence, int) 3139 */ 3140 public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002; 3141 3142 /** 3143 * Find views that contain {@link AccessibilityNodeProvider}. Such 3144 * a View is a root of virtual view hierarchy and may contain the searched 3145 * text. If this flag is set Views with providers are automatically 3146 * added and it is a responsibility of the client to call the APIs of 3147 * the provider to determine whether the virtual tree rooted at this View 3148 * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s 3149 * representing the virtual views with this text. 3150 * 3151 * @see #findViewsWithText(ArrayList, CharSequence, int) 3152 * 3153 * @hide 3154 */ 3155 public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004; 3156 3157 /** 3158 * The undefined cursor position. 3159 * 3160 * @hide 3161 */ 3162 public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1; 3163 3164 /** 3165 * Indicates that the screen has changed state and is now off. 3166 * 3167 * @see #onScreenStateChanged(int) 3168 */ 3169 public static final int SCREEN_STATE_OFF = 0x0; 3170 3171 /** 3172 * Indicates that the screen has changed state and is now on. 3173 * 3174 * @see #onScreenStateChanged(int) 3175 */ 3176 public static final int SCREEN_STATE_ON = 0x1; 3177 3178 /** 3179 * Indicates no axis of view scrolling. 3180 */ 3181 public static final int SCROLL_AXIS_NONE = 0; 3182 3183 /** 3184 * Indicates scrolling along the horizontal axis. 3185 */ 3186 public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0; 3187 3188 /** 3189 * Indicates scrolling along the vertical axis. 3190 */ 3191 public static final int SCROLL_AXIS_VERTICAL = 1 << 1; 3192 3193 /** 3194 * Controls the over-scroll mode for this view. 3195 * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)}, 3196 * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}, 3197 * and {@link #OVER_SCROLL_NEVER}. 3198 */ 3199 private int mOverScrollMode; 3200 3201 /** 3202 * The parent this view is attached to. 3203 * {@hide} 3204 * 3205 * @see #getParent() 3206 */ 3207 protected ViewParent mParent; 3208 3209 /** 3210 * {@hide} 3211 */ 3212 AttachInfo mAttachInfo; 3213 3214 /** 3215 * {@hide} 3216 */ 3217 @ViewDebug.ExportedProperty(flagMapping = { 3218 @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT, 3219 name = "FORCE_LAYOUT"), 3220 @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED, 3221 name = "LAYOUT_REQUIRED"), 3222 @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID, 3223 name = "DRAWING_CACHE_INVALID", outputIf = false), 3224 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true), 3225 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false), 3226 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"), 3227 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY") 3228 }, formatToHexString = true) 3229 int mPrivateFlags; 3230 int mPrivateFlags2; 3231 int mPrivateFlags3; 3232 3233 /** 3234 * This view's request for the visibility of the status bar. 3235 * @hide 3236 */ 3237 @ViewDebug.ExportedProperty(flagMapping = { 3238 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE, 3239 equals = SYSTEM_UI_FLAG_LOW_PROFILE, 3240 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true), 3241 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION, 3242 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION, 3243 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true), 3244 @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK, 3245 equals = SYSTEM_UI_FLAG_VISIBLE, 3246 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true) 3247 }, formatToHexString = true) 3248 int mSystemUiVisibility; 3249 3250 /** 3251 * Reference count for transient state. 3252 * @see #setHasTransientState(boolean) 3253 */ 3254 int mTransientStateCount = 0; 3255 3256 /** 3257 * Count of how many windows this view has been attached to. 3258 */ 3259 int mWindowAttachCount; 3260 3261 /** 3262 * The layout parameters associated with this view and used by the parent 3263 * {@link android.view.ViewGroup} to determine how this view should be 3264 * laid out. 3265 * {@hide} 3266 */ 3267 protected ViewGroup.LayoutParams mLayoutParams; 3268 3269 /** 3270 * The view flags hold various views states. 3271 * {@hide} 3272 */ 3273 @ViewDebug.ExportedProperty(formatToHexString = true) 3274 int mViewFlags; 3275 3276 static class TransformationInfo { 3277 /** 3278 * The transform matrix for the View. This transform is calculated internally 3279 * based on the translation, rotation, and scale properties. 3280 * 3281 * Do *not* use this variable directly; instead call getMatrix(), which will 3282 * load the value from the View's RenderNode. 3283 */ 3284 private final Matrix mMatrix = new Matrix(); 3285 3286 /** 3287 * The inverse transform matrix for the View. This transform is calculated 3288 * internally based on the translation, rotation, and scale properties. 3289 * 3290 * Do *not* use this variable directly; instead call getInverseMatrix(), 3291 * which will load the value from the View's RenderNode. 3292 */ 3293 private Matrix mInverseMatrix; 3294 3295 /** 3296 * The opacity of the View. This is a value from 0 to 1, where 0 means 3297 * completely transparent and 1 means completely opaque. 3298 */ 3299 @ViewDebug.ExportedProperty 3300 float mAlpha = 1f; 3301 3302 /** 3303 * The opacity of the view as manipulated by the Fade transition. This is a hidden 3304 * property only used by transitions, which is composited with the other alpha 3305 * values to calculate the final visual alpha value. 3306 */ 3307 float mTransitionAlpha = 1f; 3308 } 3309 3310 TransformationInfo mTransformationInfo; 3311 3312 /** 3313 * Current clip bounds. to which all drawing of this view are constrained. 3314 */ 3315 Rect mClipBounds = null; 3316 3317 private boolean mLastIsOpaque; 3318 3319 /** 3320 * The distance in pixels from the left edge of this view's parent 3321 * to the left edge of this view. 3322 * {@hide} 3323 */ 3324 @ViewDebug.ExportedProperty(category = "layout") 3325 protected int mLeft; 3326 /** 3327 * The distance in pixels from the left edge of this view's parent 3328 * to the right edge of this view. 3329 * {@hide} 3330 */ 3331 @ViewDebug.ExportedProperty(category = "layout") 3332 protected int mRight; 3333 /** 3334 * The distance in pixels from the top edge of this view's parent 3335 * to the top edge of this view. 3336 * {@hide} 3337 */ 3338 @ViewDebug.ExportedProperty(category = "layout") 3339 protected int mTop; 3340 /** 3341 * The distance in pixels from the top edge of this view's parent 3342 * to the bottom edge of this view. 3343 * {@hide} 3344 */ 3345 @ViewDebug.ExportedProperty(category = "layout") 3346 protected int mBottom; 3347 3348 /** 3349 * The offset, in pixels, by which the content of this view is scrolled 3350 * horizontally. 3351 * {@hide} 3352 */ 3353 @ViewDebug.ExportedProperty(category = "scrolling") 3354 protected int mScrollX; 3355 /** 3356 * The offset, in pixels, by which the content of this view is scrolled 3357 * vertically. 3358 * {@hide} 3359 */ 3360 @ViewDebug.ExportedProperty(category = "scrolling") 3361 protected int mScrollY; 3362 3363 /** 3364 * The left padding in pixels, that is the distance in pixels between the 3365 * left edge of this view and the left edge of its content. 3366 * {@hide} 3367 */ 3368 @ViewDebug.ExportedProperty(category = "padding") 3369 protected int mPaddingLeft = 0; 3370 /** 3371 * The right padding in pixels, that is the distance in pixels between the 3372 * right edge of this view and the right edge of its content. 3373 * {@hide} 3374 */ 3375 @ViewDebug.ExportedProperty(category = "padding") 3376 protected int mPaddingRight = 0; 3377 /** 3378 * The top padding in pixels, that is the distance in pixels between the 3379 * top edge of this view and the top edge of its content. 3380 * {@hide} 3381 */ 3382 @ViewDebug.ExportedProperty(category = "padding") 3383 protected int mPaddingTop; 3384 /** 3385 * The bottom padding in pixels, that is the distance in pixels between the 3386 * bottom edge of this view and the bottom edge of its content. 3387 * {@hide} 3388 */ 3389 @ViewDebug.ExportedProperty(category = "padding") 3390 protected int mPaddingBottom; 3391 3392 /** 3393 * The layout insets in pixels, that is the distance in pixels between the 3394 * visible edges of this view its bounds. 3395 */ 3396 private Insets mLayoutInsets; 3397 3398 /** 3399 * Briefly describes the view and is primarily used for accessibility support. 3400 */ 3401 private CharSequence mContentDescription; 3402 3403 /** 3404 * Specifies the id of a view for which this view serves as a label for 3405 * accessibility purposes. 3406 */ 3407 private int mLabelForId = View.NO_ID; 3408 3409 /** 3410 * Predicate for matching labeled view id with its label for 3411 * accessibility purposes. 3412 */ 3413 private MatchLabelForPredicate mMatchLabelForPredicate; 3414 3415 /** 3416 * Specifies a view before which this one is visited in accessibility traversal. 3417 */ 3418 private int mAccessibilityTraversalBeforeId = NO_ID; 3419 3420 /** 3421 * Specifies a view after which this one is visited in accessibility traversal. 3422 */ 3423 private int mAccessibilityTraversalAfterId = NO_ID; 3424 3425 /** 3426 * Predicate for matching a view by its id. 3427 */ 3428 private MatchIdPredicate mMatchIdPredicate; 3429 3430 /** 3431 * Cache the paddingRight set by the user to append to the scrollbar's size. 3432 * 3433 * @hide 3434 */ 3435 @ViewDebug.ExportedProperty(category = "padding") 3436 protected int mUserPaddingRight; 3437 3438 /** 3439 * Cache the paddingBottom set by the user to append to the scrollbar's size. 3440 * 3441 * @hide 3442 */ 3443 @ViewDebug.ExportedProperty(category = "padding") 3444 protected int mUserPaddingBottom; 3445 3446 /** 3447 * Cache the paddingLeft set by the user to append to the scrollbar's size. 3448 * 3449 * @hide 3450 */ 3451 @ViewDebug.ExportedProperty(category = "padding") 3452 protected int mUserPaddingLeft; 3453 3454 /** 3455 * Cache the paddingStart set by the user to append to the scrollbar's size. 3456 * 3457 */ 3458 @ViewDebug.ExportedProperty(category = "padding") 3459 int mUserPaddingStart; 3460 3461 /** 3462 * Cache the paddingEnd set by the user to append to the scrollbar's size. 3463 * 3464 */ 3465 @ViewDebug.ExportedProperty(category = "padding") 3466 int mUserPaddingEnd; 3467 3468 /** 3469 * Cache initial left padding. 3470 * 3471 * @hide 3472 */ 3473 int mUserPaddingLeftInitial; 3474 3475 /** 3476 * Cache initial right padding. 3477 * 3478 * @hide 3479 */ 3480 int mUserPaddingRightInitial; 3481 3482 /** 3483 * Default undefined padding 3484 */ 3485 private static final int UNDEFINED_PADDING = Integer.MIN_VALUE; 3486 3487 /** 3488 * Cache if a left padding has been defined 3489 */ 3490 private boolean mLeftPaddingDefined = false; 3491 3492 /** 3493 * Cache if a right padding has been defined 3494 */ 3495 private boolean mRightPaddingDefined = false; 3496 3497 /** 3498 * @hide 3499 */ 3500 int mOldWidthMeasureSpec = Integer.MIN_VALUE; 3501 /** 3502 * @hide 3503 */ 3504 int mOldHeightMeasureSpec = Integer.MIN_VALUE; 3505 3506 private LongSparseLongArray mMeasureCache; 3507 3508 @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_") 3509 private Drawable mBackground; 3510 private TintInfo mBackgroundTint; 3511 3512 @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_") 3513 private ForegroundInfo mForegroundInfo; 3514 3515 private Drawable mScrollIndicatorDrawable; 3516 3517 /** 3518 * RenderNode used for backgrounds. 3519 * <p> 3520 * When non-null and valid, this is expected to contain an up-to-date copy 3521 * of the background drawable. It is cleared on temporary detach, and reset 3522 * on cleanup. 3523 */ 3524 private RenderNode mBackgroundRenderNode; 3525 3526 private int mBackgroundResource; 3527 private boolean mBackgroundSizeChanged; 3528 3529 private String mTransitionName; 3530 3531 static class TintInfo { 3532 ColorStateList mTintList; 3533 PorterDuff.Mode mTintMode; 3534 boolean mHasTintMode; 3535 boolean mHasTintList; 3536 } 3537 3538 private static class ForegroundInfo { 3539 private Drawable mDrawable; 3540 private TintInfo mTintInfo; 3541 private int mGravity = Gravity.FILL; 3542 private boolean mInsidePadding = true; 3543 private boolean mBoundsChanged = true; 3544 private final Rect mSelfBounds = new Rect(); 3545 private final Rect mOverlayBounds = new Rect(); 3546 } 3547 3548 static class ListenerInfo { 3549 /** 3550 * Listener used to dispatch focus change events. 3551 * This field should be made private, so it is hidden from the SDK. 3552 * {@hide} 3553 */ 3554 protected OnFocusChangeListener mOnFocusChangeListener; 3555 3556 /** 3557 * Listeners for layout change events. 3558 */ 3559 private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners; 3560 3561 protected OnScrollChangeListener mOnScrollChangeListener; 3562 3563 /** 3564 * Listeners for attach events. 3565 */ 3566 private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners; 3567 3568 /** 3569 * Listener used to dispatch click events. 3570 * This field should be made private, so it is hidden from the SDK. 3571 * {@hide} 3572 */ 3573 public OnClickListener mOnClickListener; 3574 3575 /** 3576 * Listener used to dispatch long click events. 3577 * This field should be made private, so it is hidden from the SDK. 3578 * {@hide} 3579 */ 3580 protected OnLongClickListener mOnLongClickListener; 3581 3582 /** 3583 * Listener used to dispatch context click events. This field should be made private, so it 3584 * is hidden from the SDK. 3585 * {@hide} 3586 */ 3587 protected OnContextClickListener mOnContextClickListener; 3588 3589 /** 3590 * Listener used to build the context menu. 3591 * This field should be made private, so it is hidden from the SDK. 3592 * {@hide} 3593 */ 3594 protected OnCreateContextMenuListener mOnCreateContextMenuListener; 3595 3596 private OnKeyListener mOnKeyListener; 3597 3598 private OnTouchListener mOnTouchListener; 3599 3600 private OnHoverListener mOnHoverListener; 3601 3602 private OnGenericMotionListener mOnGenericMotionListener; 3603 3604 private OnDragListener mOnDragListener; 3605 3606 private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener; 3607 3608 OnApplyWindowInsetsListener mOnApplyWindowInsetsListener; 3609 } 3610 3611 ListenerInfo mListenerInfo; 3612 3613 // Temporary values used to hold (x,y) coordinates when delegating from the 3614 // two-arg performLongClick() method to the legacy no-arg version. 3615 private float mLongClickX = Float.NaN; 3616 private float mLongClickY = Float.NaN; 3617 3618 /** 3619 * The application environment this view lives in. 3620 * This field should be made private, so it is hidden from the SDK. 3621 * {@hide} 3622 */ 3623 @ViewDebug.ExportedProperty(deepExport = true) 3624 protected Context mContext; 3625 3626 private final Resources mResources; 3627 3628 private ScrollabilityCache mScrollCache; 3629 3630 private int[] mDrawableState = null; 3631 3632 ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND; 3633 3634 /** 3635 * Animator that automatically runs based on state changes. 3636 */ 3637 private StateListAnimator mStateListAnimator; 3638 3639 /** 3640 * When this view has focus and the next focus is {@link #FOCUS_LEFT}, 3641 * the user may specify which view to go to next. 3642 */ 3643 private int mNextFocusLeftId = View.NO_ID; 3644 3645 /** 3646 * When this view has focus and the next focus is {@link #FOCUS_RIGHT}, 3647 * the user may specify which view to go to next. 3648 */ 3649 private int mNextFocusRightId = View.NO_ID; 3650 3651 /** 3652 * When this view has focus and the next focus is {@link #FOCUS_UP}, 3653 * the user may specify which view to go to next. 3654 */ 3655 private int mNextFocusUpId = View.NO_ID; 3656 3657 /** 3658 * When this view has focus and the next focus is {@link #FOCUS_DOWN}, 3659 * the user may specify which view to go to next. 3660 */ 3661 private int mNextFocusDownId = View.NO_ID; 3662 3663 /** 3664 * When this view has focus and the next focus is {@link #FOCUS_FORWARD}, 3665 * the user may specify which view to go to next. 3666 */ 3667 int mNextFocusForwardId = View.NO_ID; 3668 3669 private CheckForLongPress mPendingCheckForLongPress; 3670 private CheckForTap mPendingCheckForTap = null; 3671 private PerformClick mPerformClick; 3672 private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent; 3673 3674 private UnsetPressedState mUnsetPressedState; 3675 3676 /** 3677 * Whether the long press's action has been invoked. The tap's action is invoked on the 3678 * up event while a long press is invoked as soon as the long press duration is reached, so 3679 * a long press could be performed before the tap is checked, in which case the tap's action 3680 * should not be invoked. 3681 */ 3682 private boolean mHasPerformedLongPress; 3683 3684 /** 3685 * Whether a context click button is currently pressed down. This is true when the stylus is 3686 * touching the screen and the primary button has been pressed, or if a mouse's right button is 3687 * pressed. This is false once the button is released or if the stylus has been lifted. 3688 */ 3689 private boolean mInContextButtonPress; 3690 3691 /** 3692 * Whether the next up event should be ignored for the purposes of gesture recognition. This is 3693 * true after a stylus button press has occured, when the next up event should not be recognized 3694 * as a tap. 3695 */ 3696 private boolean mIgnoreNextUpEvent; 3697 3698 /** 3699 * The minimum height of the view. We'll try our best to have the height 3700 * of this view to at least this amount. 3701 */ 3702 @ViewDebug.ExportedProperty(category = "measurement") 3703 private int mMinHeight; 3704 3705 /** 3706 * The minimum width of the view. We'll try our best to have the width 3707 * of this view to at least this amount. 3708 */ 3709 @ViewDebug.ExportedProperty(category = "measurement") 3710 private int mMinWidth; 3711 3712 /** 3713 * The delegate to handle touch events that are physically in this view 3714 * but should be handled by another view. 3715 */ 3716 private TouchDelegate mTouchDelegate = null; 3717 3718 /** 3719 * Solid color to use as a background when creating the drawing cache. Enables 3720 * the cache to use 16 bit bitmaps instead of 32 bit. 3721 */ 3722 private int mDrawingCacheBackgroundColor = 0; 3723 3724 /** 3725 * Special tree observer used when mAttachInfo is null. 3726 */ 3727 private ViewTreeObserver mFloatingTreeObserver; 3728 3729 /** 3730 * Cache the touch slop from the context that created the view. 3731 */ 3732 private int mTouchSlop; 3733 3734 /** 3735 * Object that handles automatic animation of view properties. 3736 */ 3737 private ViewPropertyAnimator mAnimator = null; 3738 3739 /** 3740 * List of registered FrameMetricsObservers. 3741 */ 3742 private ArrayList<FrameMetricsObserver> mFrameMetricsObservers; 3743 3744 /** 3745 * Flag indicating that a drag can cross window boundaries. When 3746 * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called 3747 * with this flag set, all visible applications will be able to participate 3748 * in the drag operation and receive the dragged content. 3749 * 3750 * If this is the only flag set, then the drag recipient will only have access to text data 3751 * and intents contained in the {@link ClipData} object. Access to URIs contained in the 3752 * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags. 3753 */ 3754 public static final int DRAG_FLAG_GLOBAL = 1 << 8; // 256 3755 3756 /** 3757 * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to 3758 * request read access to the content URI(s) contained in the {@link ClipData} object. 3759 * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION 3760 */ 3761 public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION; 3762 3763 /** 3764 * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to 3765 * request write access to the content URI(s) contained in the {@link ClipData} object. 3766 * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION 3767 */ 3768 public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION; 3769 3770 /** 3771 * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link 3772 * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device 3773 * reboots until explicitly revoked with 3774 * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}. 3775 * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION 3776 */ 3777 public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION = 3778 Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION; 3779 3780 /** 3781 * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link 3782 * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix 3783 * match against the original granted URI. 3784 * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION 3785 */ 3786 public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION = 3787 Intent.FLAG_GRANT_PREFIX_URI_PERMISSION; 3788 3789 /** 3790 * Flag indicating that the drag shadow will be opaque. When 3791 * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called 3792 * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent. 3793 */ 3794 public static final int DRAG_FLAG_OPAQUE = 1 << 9; 3795 3796 /** 3797 * Vertical scroll factor cached by {@link #getVerticalScrollFactor}. 3798 */ 3799 private float mVerticalScrollFactor; 3800 3801 /** 3802 * Position of the vertical scroll bar. 3803 */ 3804 private int mVerticalScrollbarPosition; 3805 3806 /** 3807 * Position the scroll bar at the default position as determined by the system. 3808 */ 3809 public static final int SCROLLBAR_POSITION_DEFAULT = 0; 3810 3811 /** 3812 * Position the scroll bar along the left edge. 3813 */ 3814 public static final int SCROLLBAR_POSITION_LEFT = 1; 3815 3816 /** 3817 * Position the scroll bar along the right edge. 3818 */ 3819 public static final int SCROLLBAR_POSITION_RIGHT = 2; 3820 3821 /** 3822 * Indicates that the view does not have a layer. 3823 * 3824 * @see #getLayerType() 3825 * @see #setLayerType(int, android.graphics.Paint) 3826 * @see #LAYER_TYPE_SOFTWARE 3827 * @see #LAYER_TYPE_HARDWARE 3828 */ 3829 public static final int LAYER_TYPE_NONE = 0; 3830 3831 /** 3832 * <p>Indicates that the view has a software layer. A software layer is backed 3833 * by a bitmap and causes the view to be rendered using Android's software 3834 * rendering pipeline, even if hardware acceleration is enabled.</p> 3835 * 3836 * <p>Software layers have various usages:</p> 3837 * <p>When the application is not using hardware acceleration, a software layer 3838 * is useful to apply a specific color filter and/or blending mode and/or 3839 * translucency to a view and all its children.</p> 3840 * <p>When the application is using hardware acceleration, a software layer 3841 * is useful to render drawing primitives not supported by the hardware 3842 * accelerated pipeline. It can also be used to cache a complex view tree 3843 * into a texture and reduce the complexity of drawing operations. For instance, 3844 * when animating a complex view tree with a translation, a software layer can 3845 * be used to render the view tree only once.</p> 3846 * <p>Software layers should be avoided when the affected view tree updates 3847 * often. Every update will require to re-render the software layer, which can 3848 * potentially be slow (particularly when hardware acceleration is turned on 3849 * since the layer will have to be uploaded into a hardware texture after every 3850 * update.)</p> 3851 * 3852 * @see #getLayerType() 3853 * @see #setLayerType(int, android.graphics.Paint) 3854 * @see #LAYER_TYPE_NONE 3855 * @see #LAYER_TYPE_HARDWARE 3856 */ 3857 public static final int LAYER_TYPE_SOFTWARE = 1; 3858 3859 /** 3860 * <p>Indicates that the view has a hardware layer. A hardware layer is backed 3861 * by a hardware specific texture (generally Frame Buffer Objects or FBO on 3862 * OpenGL hardware) and causes the view to be rendered using Android's hardware 3863 * rendering pipeline, but only if hardware acceleration is turned on for the 3864 * view hierarchy. When hardware acceleration is turned off, hardware layers 3865 * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p> 3866 * 3867 * <p>A hardware layer is useful to apply a specific color filter and/or 3868 * blending mode and/or translucency to a view and all its children.</p> 3869 * <p>A hardware layer can be used to cache a complex view tree into a 3870 * texture and reduce the complexity of drawing operations. For instance, 3871 * when animating a complex view tree with a translation, a hardware layer can 3872 * be used to render the view tree only once.</p> 3873 * <p>A hardware layer can also be used to increase the rendering quality when 3874 * rotation transformations are applied on a view. It can also be used to 3875 * prevent potential clipping issues when applying 3D transforms on a view.</p> 3876 * 3877 * @see #getLayerType() 3878 * @see #setLayerType(int, android.graphics.Paint) 3879 * @see #LAYER_TYPE_NONE 3880 * @see #LAYER_TYPE_SOFTWARE 3881 */ 3882 public static final int LAYER_TYPE_HARDWARE = 2; 3883 3884 @ViewDebug.ExportedProperty(category = "drawing", mapping = { 3885 @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"), 3886 @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"), 3887 @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE") 3888 }) 3889 int mLayerType = LAYER_TYPE_NONE; 3890 Paint mLayerPaint; 3891 3892 /** 3893 * Set to true when drawing cache is enabled and cannot be created. 3894 * 3895 * @hide 3896 */ 3897 public boolean mCachingFailed; 3898 private Bitmap mDrawingCache; 3899 private Bitmap mUnscaledDrawingCache; 3900 3901 /** 3902 * RenderNode holding View properties, potentially holding a DisplayList of View content. 3903 * <p> 3904 * When non-null and valid, this is expected to contain an up-to-date copy 3905 * of the View content. Its DisplayList content is cleared on temporary detach and reset on 3906 * cleanup. 3907 */ 3908 final RenderNode mRenderNode; 3909 3910 /** 3911 * Set to true when the view is sending hover accessibility events because it 3912 * is the innermost hovered view. 3913 */ 3914 private boolean mSendingHoverAccessibilityEvents; 3915 3916 /** 3917 * Delegate for injecting accessibility functionality. 3918 */ 3919 AccessibilityDelegate mAccessibilityDelegate; 3920 3921 /** 3922 * The view's overlay layer. Developers get a reference to the overlay via getOverlay() 3923 * and add/remove objects to/from the overlay directly through the Overlay methods. 3924 */ 3925 ViewOverlay mOverlay; 3926 3927 /** 3928 * The currently active parent view for receiving delegated nested scrolling events. 3929 * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared 3930 * by {@link #stopNestedScroll()} at the same point where we clear 3931 * requestDisallowInterceptTouchEvent. 3932 */ 3933 private ViewParent mNestedScrollingParent; 3934 3935 /** 3936 * Consistency verifier for debugging purposes. 3937 * @hide 3938 */ 3939 protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier = 3940 InputEventConsistencyVerifier.isInstrumentationEnabled() ? 3941 new InputEventConsistencyVerifier(this, 0) : null; 3942 3943 private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1); 3944 3945 private int[] mTempNestedScrollConsumed; 3946 3947 /** 3948 * An overlay is going to draw this View instead of being drawn as part of this 3949 * View's parent. mGhostView is the View in the Overlay that must be invalidated 3950 * when this view is invalidated. 3951 */ 3952 GhostView mGhostView; 3953 3954 /** 3955 * Holds pairs of adjacent attribute data: attribute name followed by its value. 3956 * @hide 3957 */ 3958 @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true) 3959 public String[] mAttributes; 3960 3961 /** 3962 * Maps a Resource id to its name. 3963 */ 3964 private static SparseArray<String> mAttributeMap; 3965 3966 /** 3967 * Queue of pending runnables. Used to postpone calls to post() until this 3968 * view is attached and has a handler. 3969 */ 3970 private HandlerActionQueue mRunQueue; 3971 3972 /** 3973 * The pointer icon when the mouse hovers on this view. The default is null. 3974 */ 3975 private PointerIcon mPointerIcon; 3976 3977 /** 3978 * @hide 3979 */ 3980 String mStartActivityRequestWho; 3981 3982 /** 3983 * Simple constructor to use when creating a view from code. 3984 * 3985 * @param context The Context the view is running in, through which it can 3986 * access the current theme, resources, etc. 3987 */ View(Context context)3988 public View(Context context) { 3989 mContext = context; 3990 mResources = context != null ? context.getResources() : null; 3991 mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED; 3992 // Set some flags defaults 3993 mPrivateFlags2 = 3994 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) | 3995 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) | 3996 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) | 3997 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) | 3998 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) | 3999 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT); 4000 mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); 4001 setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS); 4002 mUserPaddingStart = UNDEFINED_PADDING; 4003 mUserPaddingEnd = UNDEFINED_PADDING; 4004 mRenderNode = RenderNode.create(getClass().getName(), this); 4005 4006 if (!sCompatibilityDone && context != null) { 4007 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion; 4008 4009 // Older apps may need this compatibility hack for measurement. 4010 sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1; 4011 4012 // Older apps expect onMeasure() to always be called on a layout pass, regardless 4013 // of whether a layout was requested on that View. 4014 sIgnoreMeasureCache = targetSdkVersion < KITKAT; 4015 4016 Canvas.sCompatibilityRestore = targetSdkVersion < M; 4017 4018 // In M and newer, our widgets can pass a "hint" value in the size 4019 // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers 4020 // know what the expected parent size is going to be, so e.g. list items can size 4021 // themselves at 1/3 the size of their container. It breaks older apps though, 4022 // specifically apps that use some popular open source libraries. 4023 sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M; 4024 4025 // Old versions of the platform would give different results from 4026 // LinearLayout measurement passes using EXACTLY and non-EXACTLY 4027 // modes, so we always need to run an additional EXACTLY pass. 4028 sAlwaysRemeasureExactly = targetSdkVersion <= M; 4029 4030 // Prior to N, layout params could change without requiring a 4031 // subsequent call to setLayoutParams() and they would usually 4032 // work. Partial layout breaks this assumption. 4033 sLayoutParamsAlwaysChanged = targetSdkVersion <= M; 4034 4035 // Prior to N, TextureView would silently ignore calls to setBackground/setForeground. 4036 // On N+, we throw, but that breaks compatibility with apps that use these methods. 4037 sTextureViewIgnoresDrawableSetters = targetSdkVersion <= M; 4038 4039 sCompatibilityDone = true; 4040 } 4041 } 4042 4043 /** 4044 * Constructor that is called when inflating a view from XML. This is called 4045 * when a view is being constructed from an XML file, supplying attributes 4046 * that were specified in the XML file. This version uses a default style of 4047 * 0, so the only attribute values applied are those in the Context's Theme 4048 * and the given AttributeSet. 4049 * 4050 * <p> 4051 * The method onFinishInflate() will be called after all children have been 4052 * added. 4053 * 4054 * @param context The Context the view is running in, through which it can 4055 * access the current theme, resources, etc. 4056 * @param attrs The attributes of the XML tag that is inflating the view. 4057 * @see #View(Context, AttributeSet, int) 4058 */ 4059 public View(Context context, @Nullable AttributeSet attrs) { 4060 this(context, attrs, 0); 4061 } 4062 4063 /** 4064 * Perform inflation from XML and apply a class-specific base style from a 4065 * theme attribute. This constructor of View allows subclasses to use their 4066 * own base style when they are inflating. For example, a Button class's 4067 * constructor would call this version of the super class constructor and 4068 * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this 4069 * allows the theme's button style to modify all of the base view attributes 4070 * (in particular its background) as well as the Button class's attributes. 4071 * 4072 * @param context The Context the view is running in, through which it can 4073 * access the current theme, resources, etc. 4074 * @param attrs The attributes of the XML tag that is inflating the view. 4075 * @param defStyleAttr An attribute in the current theme that contains a 4076 * reference to a style resource that supplies default values for 4077 * the view. Can be 0 to not look for defaults. 4078 * @see #View(Context, AttributeSet) 4079 */ 4080 public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 4081 this(context, attrs, defStyleAttr, 0); 4082 } 4083 4084 /** 4085 * Perform inflation from XML and apply a class-specific base style from a 4086 * theme attribute or style resource. This constructor of View allows 4087 * subclasses to use their own base style when they are inflating. 4088 * <p> 4089 * When determining the final value of a particular attribute, there are 4090 * four inputs that come into play: 4091 * <ol> 4092 * <li>Any attribute values in the given AttributeSet. 4093 * <li>The style resource specified in the AttributeSet (named "style"). 4094 * <li>The default style specified by <var>defStyleAttr</var>. 4095 * <li>The default style specified by <var>defStyleRes</var>. 4096 * <li>The base values in this theme. 4097 * </ol> 4098 * <p> 4099 * Each of these inputs is considered in-order, with the first listed taking 4100 * precedence over the following ones. In other words, if in the 4101 * AttributeSet you have supplied <code><Button * textColor="#ff000000"></code> 4102 * , then the button's text will <em>always</em> be black, regardless of 4103 * what is specified in any of the styles. 4104 * 4105 * @param context The Context the view is running in, through which it can 4106 * access the current theme, resources, etc. 4107 * @param attrs The attributes of the XML tag that is inflating the view. 4108 * @param defStyleAttr An attribute in the current theme that contains a 4109 * reference to a style resource that supplies default values for 4110 * the view. Can be 0 to not look for defaults. 4111 * @param defStyleRes A resource identifier of a style resource that 4112 * supplies default values for the view, used only if 4113 * defStyleAttr is 0 or can not be found in the theme. Can be 0 4114 * to not look for defaults. 4115 * @see #View(Context, AttributeSet, int) 4116 */ 4117 public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { 4118 this(context); 4119 4120 final TypedArray a = context.obtainStyledAttributes( 4121 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes); 4122 4123 if (mDebugViewAttributes) { 4124 saveAttributeData(attrs, a); 4125 } 4126 4127 Drawable background = null; 4128 4129 int leftPadding = -1; 4130 int topPadding = -1; 4131 int rightPadding = -1; 4132 int bottomPadding = -1; 4133 int startPadding = UNDEFINED_PADDING; 4134 int endPadding = UNDEFINED_PADDING; 4135 4136 int padding = -1; 4137 4138 int viewFlagValues = 0; 4139 int viewFlagMasks = 0; 4140 4141 boolean setScrollContainer = false; 4142 4143 int x = 0; 4144 int y = 0; 4145 4146 float tx = 0; 4147 float ty = 0; 4148 float tz = 0; 4149 float elevation = 0; 4150 float rotation = 0; 4151 float rotationX = 0; 4152 float rotationY = 0; 4153 float sx = 1f; 4154 float sy = 1f; 4155 boolean transformSet = false; 4156 4157 int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY; 4158 int overScrollMode = mOverScrollMode; 4159 boolean initializeScrollbars = false; 4160 boolean initializeScrollIndicators = false; 4161 4162 boolean startPaddingDefined = false; 4163 boolean endPaddingDefined = false; 4164 boolean leftPaddingDefined = false; 4165 boolean rightPaddingDefined = false; 4166 4167 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion; 4168 4169 final int N = a.getIndexCount(); 4170 for (int i = 0; i < N; i++) { 4171 int attr = a.getIndex(i); 4172 switch (attr) { 4173 case com.android.internal.R.styleable.View_background: 4174 background = a.getDrawable(attr); 4175 break; 4176 case com.android.internal.R.styleable.View_padding: 4177 padding = a.getDimensionPixelSize(attr, -1); 4178 mUserPaddingLeftInitial = padding; 4179 mUserPaddingRightInitial = padding; 4180 leftPaddingDefined = true; 4181 rightPaddingDefined = true; 4182 break; 4183 case com.android.internal.R.styleable.View_paddingLeft: 4184 leftPadding = a.getDimensionPixelSize(attr, -1); 4185 mUserPaddingLeftInitial = leftPadding; 4186 leftPaddingDefined = true; 4187 break; 4188 case com.android.internal.R.styleable.View_paddingTop: 4189 topPadding = a.getDimensionPixelSize(attr, -1); 4190 break; 4191 case com.android.internal.R.styleable.View_paddingRight: 4192 rightPadding = a.getDimensionPixelSize(attr, -1); 4193 mUserPaddingRightInitial = rightPadding; 4194 rightPaddingDefined = true; 4195 break; 4196 case com.android.internal.R.styleable.View_paddingBottom: 4197 bottomPadding = a.getDimensionPixelSize(attr, -1); 4198 break; 4199 case com.android.internal.R.styleable.View_paddingStart: 4200 startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING); 4201 startPaddingDefined = (startPadding != UNDEFINED_PADDING); 4202 break; 4203 case com.android.internal.R.styleable.View_paddingEnd: 4204 endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING); 4205 endPaddingDefined = (endPadding != UNDEFINED_PADDING); 4206 break; 4207 case com.android.internal.R.styleable.View_scrollX: 4208 x = a.getDimensionPixelOffset(attr, 0); 4209 break; 4210 case com.android.internal.R.styleable.View_scrollY: 4211 y = a.getDimensionPixelOffset(attr, 0); 4212 break; 4213 case com.android.internal.R.styleable.View_alpha: 4214 setAlpha(a.getFloat(attr, 1f)); 4215 break; 4216 case com.android.internal.R.styleable.View_transformPivotX: 4217 setPivotX(a.getDimensionPixelOffset(attr, 0)); 4218 break; 4219 case com.android.internal.R.styleable.View_transformPivotY: 4220 setPivotY(a.getDimensionPixelOffset(attr, 0)); 4221 break; 4222 case com.android.internal.R.styleable.View_translationX: 4223 tx = a.getDimensionPixelOffset(attr, 0); 4224 transformSet = true; 4225 break; 4226 case com.android.internal.R.styleable.View_translationY: 4227 ty = a.getDimensionPixelOffset(attr, 0); 4228 transformSet = true; 4229 break; 4230 case com.android.internal.R.styleable.View_translationZ: 4231 tz = a.getDimensionPixelOffset(attr, 0); 4232 transformSet = true; 4233 break; 4234 case com.android.internal.R.styleable.View_elevation: 4235 elevation = a.getDimensionPixelOffset(attr, 0); 4236 transformSet = true; 4237 break; 4238 case com.android.internal.R.styleable.View_rotation: 4239 rotation = a.getFloat(attr, 0); 4240 transformSet = true; 4241 break; 4242 case com.android.internal.R.styleable.View_rotationX: 4243 rotationX = a.getFloat(attr, 0); 4244 transformSet = true; 4245 break; 4246 case com.android.internal.R.styleable.View_rotationY: 4247 rotationY = a.getFloat(attr, 0); 4248 transformSet = true; 4249 break; 4250 case com.android.internal.R.styleable.View_scaleX: 4251 sx = a.getFloat(attr, 1f); 4252 transformSet = true; 4253 break; 4254 case com.android.internal.R.styleable.View_scaleY: 4255 sy = a.getFloat(attr, 1f); 4256 transformSet = true; 4257 break; 4258 case com.android.internal.R.styleable.View_id: 4259 mID = a.getResourceId(attr, NO_ID); 4260 break; 4261 case com.android.internal.R.styleable.View_tag: 4262 mTag = a.getText(attr); 4263 break; 4264 case com.android.internal.R.styleable.View_fitsSystemWindows: 4265 if (a.getBoolean(attr, false)) { 4266 viewFlagValues |= FITS_SYSTEM_WINDOWS; 4267 viewFlagMasks |= FITS_SYSTEM_WINDOWS; 4268 } 4269 break; 4270 case com.android.internal.R.styleable.View_focusable: 4271 if (a.getBoolean(attr, false)) { 4272 viewFlagValues |= FOCUSABLE; 4273 viewFlagMasks |= FOCUSABLE_MASK; 4274 } 4275 break; 4276 case com.android.internal.R.styleable.View_focusableInTouchMode: 4277 if (a.getBoolean(attr, false)) { 4278 viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE; 4279 viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK; 4280 } 4281 break; 4282 case com.android.internal.R.styleable.View_clickable: 4283 if (a.getBoolean(attr, false)) { 4284 viewFlagValues |= CLICKABLE; 4285 viewFlagMasks |= CLICKABLE; 4286 } 4287 break; 4288 case com.android.internal.R.styleable.View_longClickable: 4289 if (a.getBoolean(attr, false)) { 4290 viewFlagValues |= LONG_CLICKABLE; 4291 viewFlagMasks |= LONG_CLICKABLE; 4292 } 4293 break; 4294 case com.android.internal.R.styleable.View_contextClickable: 4295 if (a.getBoolean(attr, false)) { 4296 viewFlagValues |= CONTEXT_CLICKABLE; 4297 viewFlagMasks |= CONTEXT_CLICKABLE; 4298 } 4299 break; 4300 case com.android.internal.R.styleable.View_saveEnabled: 4301 if (!a.getBoolean(attr, true)) { 4302 viewFlagValues |= SAVE_DISABLED; 4303 viewFlagMasks |= SAVE_DISABLED_MASK; 4304 } 4305 break; 4306 case com.android.internal.R.styleable.View_duplicateParentState: 4307 if (a.getBoolean(attr, false)) { 4308 viewFlagValues |= DUPLICATE_PARENT_STATE; 4309 viewFlagMasks |= DUPLICATE_PARENT_STATE; 4310 } 4311 break; 4312 case com.android.internal.R.styleable.View_visibility: 4313 final int visibility = a.getInt(attr, 0); 4314 if (visibility != 0) { 4315 viewFlagValues |= VISIBILITY_FLAGS[visibility]; 4316 viewFlagMasks |= VISIBILITY_MASK; 4317 } 4318 break; 4319 case com.android.internal.R.styleable.View_layoutDirection: 4320 // Clear any layout direction flags (included resolved bits) already set 4321 mPrivateFlags2 &= 4322 ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK); 4323 // Set the layout direction flags depending on the value of the attribute 4324 final int layoutDirection = a.getInt(attr, -1); 4325 final int value = (layoutDirection != -1) ? 4326 LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT; 4327 mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT); 4328 break; 4329 case com.android.internal.R.styleable.View_drawingCacheQuality: 4330 final int cacheQuality = a.getInt(attr, 0); 4331 if (cacheQuality != 0) { 4332 viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality]; 4333 viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK; 4334 } 4335 break; 4336 case com.android.internal.R.styleable.View_contentDescription: 4337 setContentDescription(a.getString(attr)); 4338 break; 4339 case com.android.internal.R.styleable.View_accessibilityTraversalBefore: 4340 setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID)); 4341 break; 4342 case com.android.internal.R.styleable.View_accessibilityTraversalAfter: 4343 setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID)); 4344 break; 4345 case com.android.internal.R.styleable.View_labelFor: 4346 setLabelFor(a.getResourceId(attr, NO_ID)); 4347 break; 4348 case com.android.internal.R.styleable.View_soundEffectsEnabled: 4349 if (!a.getBoolean(attr, true)) { 4350 viewFlagValues &= ~SOUND_EFFECTS_ENABLED; 4351 viewFlagMasks |= SOUND_EFFECTS_ENABLED; 4352 } 4353 break; 4354 case com.android.internal.R.styleable.View_hapticFeedbackEnabled: 4355 if (!a.getBoolean(attr, true)) { 4356 viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED; 4357 viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED; 4358 } 4359 break; 4360 case R.styleable.View_scrollbars: 4361 final int scrollbars = a.getInt(attr, SCROLLBARS_NONE); 4362 if (scrollbars != SCROLLBARS_NONE) { 4363 viewFlagValues |= scrollbars; 4364 viewFlagMasks |= SCROLLBARS_MASK; 4365 initializeScrollbars = true; 4366 } 4367 break; 4368 //noinspection deprecation 4369 case R.styleable.View_fadingEdge: 4370 if (targetSdkVersion >= ICE_CREAM_SANDWICH) { 4371 // Ignore the attribute starting with ICS 4372 break; 4373 } 4374 // With builds < ICS, fall through and apply fading edges 4375 case R.styleable.View_requiresFadingEdge: 4376 final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE); 4377 if (fadingEdge != FADING_EDGE_NONE) { 4378 viewFlagValues |= fadingEdge; 4379 viewFlagMasks |= FADING_EDGE_MASK; 4380 initializeFadingEdgeInternal(a); 4381 } 4382 break; 4383 case R.styleable.View_scrollbarStyle: 4384 scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY); 4385 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) { 4386 viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK; 4387 viewFlagMasks |= SCROLLBARS_STYLE_MASK; 4388 } 4389 break; 4390 case R.styleable.View_isScrollContainer: 4391 setScrollContainer = true; 4392 if (a.getBoolean(attr, false)) { 4393 setScrollContainer(true); 4394 } 4395 break; 4396 case com.android.internal.R.styleable.View_keepScreenOn: 4397 if (a.getBoolean(attr, false)) { 4398 viewFlagValues |= KEEP_SCREEN_ON; 4399 viewFlagMasks |= KEEP_SCREEN_ON; 4400 } 4401 break; 4402 case R.styleable.View_filterTouchesWhenObscured: 4403 if (a.getBoolean(attr, false)) { 4404 viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED; 4405 viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED; 4406 } 4407 break; 4408 case R.styleable.View_nextFocusLeft: 4409 mNextFocusLeftId = a.getResourceId(attr, View.NO_ID); 4410 break; 4411 case R.styleable.View_nextFocusRight: 4412 mNextFocusRightId = a.getResourceId(attr, View.NO_ID); 4413 break; 4414 case R.styleable.View_nextFocusUp: 4415 mNextFocusUpId = a.getResourceId(attr, View.NO_ID); 4416 break; 4417 case R.styleable.View_nextFocusDown: 4418 mNextFocusDownId = a.getResourceId(attr, View.NO_ID); 4419 break; 4420 case R.styleable.View_nextFocusForward: 4421 mNextFocusForwardId = a.getResourceId(attr, View.NO_ID); 4422 break; 4423 case R.styleable.View_minWidth: 4424 mMinWidth = a.getDimensionPixelSize(attr, 0); 4425 break; 4426 case R.styleable.View_minHeight: 4427 mMinHeight = a.getDimensionPixelSize(attr, 0); 4428 break; 4429 case R.styleable.View_onClick: 4430 if (context.isRestricted()) { 4431 throw new IllegalStateException("The android:onClick attribute cannot " 4432 + "be used within a restricted context"); 4433 } 4434 4435 final String handlerName = a.getString(attr); 4436 if (handlerName != null) { 4437 setOnClickListener(new DeclaredOnClickListener(this, handlerName)); 4438 } 4439 break; 4440 case R.styleable.View_overScrollMode: 4441 overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS); 4442 break; 4443 case R.styleable.View_verticalScrollbarPosition: 4444 mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT); 4445 break; 4446 case R.styleable.View_layerType: 4447 setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null); 4448 break; 4449 case R.styleable.View_textDirection: 4450 // Clear any text direction flag already set 4451 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK; 4452 // Set the text direction flags depending on the value of the attribute 4453 final int textDirection = a.getInt(attr, -1); 4454 if (textDirection != -1) { 4455 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection]; 4456 } 4457 break; 4458 case R.styleable.View_textAlignment: 4459 // Clear any text alignment flag already set 4460 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK; 4461 // Set the text alignment flag depending on the value of the attribute 4462 final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT); 4463 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment]; 4464 break; 4465 case R.styleable.View_importantForAccessibility: 4466 setImportantForAccessibility(a.getInt(attr, 4467 IMPORTANT_FOR_ACCESSIBILITY_DEFAULT)); 4468 break; 4469 case R.styleable.View_accessibilityLiveRegion: 4470 setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT)); 4471 break; 4472 case R.styleable.View_transitionName: 4473 setTransitionName(a.getString(attr)); 4474 break; 4475 case R.styleable.View_nestedScrollingEnabled: 4476 setNestedScrollingEnabled(a.getBoolean(attr, false)); 4477 break; 4478 case R.styleable.View_stateListAnimator: 4479 setStateListAnimator(AnimatorInflater.loadStateListAnimator(context, 4480 a.getResourceId(attr, 0))); 4481 break; 4482 case R.styleable.View_backgroundTint: 4483 // This will get applied later during setBackground(). 4484 if (mBackgroundTint == null) { 4485 mBackgroundTint = new TintInfo(); 4486 } 4487 mBackgroundTint.mTintList = a.getColorStateList( 4488 R.styleable.View_backgroundTint); 4489 mBackgroundTint.mHasTintList = true; 4490 break; 4491 case R.styleable.View_backgroundTintMode: 4492 // This will get applied later during setBackground(). 4493 if (mBackgroundTint == null) { 4494 mBackgroundTint = new TintInfo(); 4495 } 4496 mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt( 4497 R.styleable.View_backgroundTintMode, -1), null); 4498 mBackgroundTint.mHasTintMode = true; 4499 break; 4500 case R.styleable.View_outlineProvider: 4501 setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider, 4502 PROVIDER_BACKGROUND)); 4503 break; 4504 case R.styleable.View_foreground: 4505 if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) { 4506 setForeground(a.getDrawable(attr)); 4507 } 4508 break; 4509 case R.styleable.View_foregroundGravity: 4510 if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) { 4511 setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY)); 4512 } 4513 break; 4514 case R.styleable.View_foregroundTintMode: 4515 if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) { 4516 setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null)); 4517 } 4518 break; 4519 case R.styleable.View_foregroundTint: 4520 if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) { 4521 setForegroundTintList(a.getColorStateList(attr)); 4522 } 4523 break; 4524 case R.styleable.View_foregroundInsidePadding: 4525 if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) { 4526 if (mForegroundInfo == null) { 4527 mForegroundInfo = new ForegroundInfo(); 4528 } 4529 mForegroundInfo.mInsidePadding = a.getBoolean(attr, 4530 mForegroundInfo.mInsidePadding); 4531 } 4532 break; 4533 case R.styleable.View_scrollIndicators: 4534 final int scrollIndicators = 4535 (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT) 4536 & SCROLL_INDICATORS_PFLAG3_MASK; 4537 if (scrollIndicators != 0) { 4538 mPrivateFlags3 |= scrollIndicators; 4539 initializeScrollIndicators = true; 4540 } 4541 break; 4542 case R.styleable.View_pointerIcon: 4543 final int resourceId = a.getResourceId(attr, 0); 4544 if (resourceId != 0) { 4545 setPointerIcon(PointerIcon.load( 4546 context.getResources(), resourceId)); 4547 } else { 4548 final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED); 4549 if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) { 4550 setPointerIcon(PointerIcon.getSystemIcon(context, pointerType)); 4551 } 4552 } 4553 break; 4554 case R.styleable.View_forceHasOverlappingRendering: 4555 if (a.peekValue(attr) != null) { 4556 forceHasOverlappingRendering(a.getBoolean(attr, true)); 4557 } 4558 break; 4559 4560 } 4561 } 4562 4563 setOverScrollMode(overScrollMode); 4564 4565 // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet 4566 // the resolved layout direction). Those cached values will be used later during padding 4567 // resolution. 4568 mUserPaddingStart = startPadding; 4569 mUserPaddingEnd = endPadding; 4570 4571 if (background != null) { 4572 setBackground(background); 4573 } 4574 4575 // setBackground above will record that padding is currently provided by the background. 4576 // If we have padding specified via xml, record that here instead and use it. 4577 mLeftPaddingDefined = leftPaddingDefined; 4578 mRightPaddingDefined = rightPaddingDefined; 4579 4580 if (padding >= 0) { 4581 leftPadding = padding; 4582 topPadding = padding; 4583 rightPadding = padding; 4584 bottomPadding = padding; 4585 mUserPaddingLeftInitial = padding; 4586 mUserPaddingRightInitial = padding; 4587 } 4588 4589 if (isRtlCompatibilityMode()) { 4590 // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case. 4591 // left / right padding are used if defined (meaning here nothing to do). If they are not 4592 // defined and start / end padding are defined (e.g. in Frameworks resources), then we use 4593 // start / end and resolve them as left / right (layout direction is not taken into account). 4594 // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial 4595 // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if 4596 // defined. 4597 if (!mLeftPaddingDefined && startPaddingDefined) { 4598 leftPadding = startPadding; 4599 } 4600 mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial; 4601 if (!mRightPaddingDefined && endPaddingDefined) { 4602 rightPadding = endPadding; 4603 } 4604 mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial; 4605 } else { 4606 // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right 4607 // values defined. Otherwise, left /right values are used. 4608 // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial 4609 // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if 4610 // defined. 4611 final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined; 4612 4613 if (mLeftPaddingDefined && !hasRelativePadding) { 4614 mUserPaddingLeftInitial = leftPadding; 4615 } 4616 if (mRightPaddingDefined && !hasRelativePadding) { 4617 mUserPaddingRightInitial = rightPadding; 4618 } 4619 } 4620 4621 internalSetPadding( 4622 mUserPaddingLeftInitial, 4623 topPadding >= 0 ? topPadding : mPaddingTop, 4624 mUserPaddingRightInitial, 4625 bottomPadding >= 0 ? bottomPadding : mPaddingBottom); 4626 4627 if (viewFlagMasks != 0) { 4628 setFlags(viewFlagValues, viewFlagMasks); 4629 } 4630 4631 if (initializeScrollbars) { 4632 initializeScrollbarsInternal(a); 4633 } 4634 4635 if (initializeScrollIndicators) { 4636 initializeScrollIndicatorsInternal(); 4637 } 4638 4639 a.recycle(); 4640 4641 // Needs to be called after mViewFlags is set 4642 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) { 4643 recomputePadding(); 4644 } 4645 4646 if (x != 0 || y != 0) { 4647 scrollTo(x, y); 4648 } 4649 4650 if (transformSet) { 4651 setTranslationX(tx); 4652 setTranslationY(ty); 4653 setTranslationZ(tz); 4654 setElevation(elevation); 4655 setRotation(rotation); 4656 setRotationX(rotationX); 4657 setRotationY(rotationY); 4658 setScaleX(sx); 4659 setScaleY(sy); 4660 } 4661 4662 if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) { 4663 setScrollContainer(true); 4664 } 4665 4666 computeOpaqueFlags(); 4667 } 4668 4669 /** 4670 * An implementation of OnClickListener that attempts to lazily load a 4671 * named click handling method from a parent or ancestor context. 4672 */ 4673 private static class DeclaredOnClickListener implements OnClickListener { 4674 private final View mHostView; 4675 private final String mMethodName; 4676 4677 private Method mResolvedMethod; 4678 private Context mResolvedContext; 4679 DeclaredOnClickListener(@onNull View hostView, @NonNull String methodName)4680 public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) { 4681 mHostView = hostView; 4682 mMethodName = methodName; 4683 } 4684 4685 @Override onClick(@onNull View v)4686 public void onClick(@NonNull View v) { 4687 if (mResolvedMethod == null) { 4688 resolveMethod(mHostView.getContext(), mMethodName); 4689 } 4690 4691 try { 4692 mResolvedMethod.invoke(mResolvedContext, v); 4693 } catch (IllegalAccessException e) { 4694 throw new IllegalStateException( 4695 "Could not execute non-public method for android:onClick", e); 4696 } catch (InvocationTargetException e) { 4697 throw new IllegalStateException( 4698 "Could not execute method for android:onClick", e); 4699 } 4700 } 4701 4702 @NonNull resolveMethod(@ullable Context context, @NonNull String name)4703 private void resolveMethod(@Nullable Context context, @NonNull String name) { 4704 while (context != null) { 4705 try { 4706 if (!context.isRestricted()) { 4707 final Method method = context.getClass().getMethod(mMethodName, View.class); 4708 if (method != null) { 4709 mResolvedMethod = method; 4710 mResolvedContext = context; 4711 return; 4712 } 4713 } 4714 } catch (NoSuchMethodException e) { 4715 // Failed to find method, keep searching up the hierarchy. 4716 } 4717 4718 if (context instanceof ContextWrapper) { 4719 context = ((ContextWrapper) context).getBaseContext(); 4720 } else { 4721 // Can't search up the hierarchy, null out and fail. 4722 context = null; 4723 } 4724 } 4725 4726 final int id = mHostView.getId(); 4727 final String idText = id == NO_ID ? "" : " with id '" 4728 + mHostView.getContext().getResources().getResourceEntryName(id) + "'"; 4729 throw new IllegalStateException("Could not find method " + mMethodName 4730 + "(View) in a parent or ancestor Context for android:onClick " 4731 + "attribute defined on view " + mHostView.getClass() + idText); 4732 } 4733 } 4734 4735 /** 4736 * Non-public constructor for use in testing 4737 */ View()4738 View() { 4739 mResources = null; 4740 mRenderNode = RenderNode.create(getClass().getName(), this); 4741 } 4742 getAttributeMap()4743 private static SparseArray<String> getAttributeMap() { 4744 if (mAttributeMap == null) { 4745 mAttributeMap = new SparseArray<>(); 4746 } 4747 return mAttributeMap; 4748 } 4749 saveAttributeData(@ullable AttributeSet attrs, @NonNull TypedArray t)4750 private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) { 4751 final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount(); 4752 final int indexCount = t.getIndexCount(); 4753 final String[] attributes = new String[(attrsCount + indexCount) * 2]; 4754 4755 int i = 0; 4756 4757 // Store raw XML attributes. 4758 for (int j = 0; j < attrsCount; ++j) { 4759 attributes[i] = attrs.getAttributeName(j); 4760 attributes[i + 1] = attrs.getAttributeValue(j); 4761 i += 2; 4762 } 4763 4764 // Store resolved styleable attributes. 4765 final Resources res = t.getResources(); 4766 final SparseArray<String> attributeMap = getAttributeMap(); 4767 for (int j = 0; j < indexCount; ++j) { 4768 final int index = t.getIndex(j); 4769 if (!t.hasValueOrEmpty(index)) { 4770 // Value is undefined. Skip it. 4771 continue; 4772 } 4773 4774 final int resourceId = t.getResourceId(index, 0); 4775 if (resourceId == 0) { 4776 // Value is not a reference. Skip it. 4777 continue; 4778 } 4779 4780 String resourceName = attributeMap.get(resourceId); 4781 if (resourceName == null) { 4782 try { 4783 resourceName = res.getResourceName(resourceId); 4784 } catch (Resources.NotFoundException e) { 4785 resourceName = "0x" + Integer.toHexString(resourceId); 4786 } 4787 attributeMap.put(resourceId, resourceName); 4788 } 4789 4790 attributes[i] = resourceName; 4791 attributes[i + 1] = t.getString(index); 4792 i += 2; 4793 } 4794 4795 // Trim to fit contents. 4796 final String[] trimmed = new String[i]; 4797 System.arraycopy(attributes, 0, trimmed, 0, i); 4798 mAttributes = trimmed; 4799 } 4800 toString()4801 public String toString() { 4802 StringBuilder out = new StringBuilder(128); 4803 out.append(getClass().getName()); 4804 out.append('{'); 4805 out.append(Integer.toHexString(System.identityHashCode(this))); 4806 out.append(' '); 4807 switch (mViewFlags&VISIBILITY_MASK) { 4808 case VISIBLE: out.append('V'); break; 4809 case INVISIBLE: out.append('I'); break; 4810 case GONE: out.append('G'); break; 4811 default: out.append('.'); break; 4812 } 4813 out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.'); 4814 out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.'); 4815 out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D'); 4816 out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.'); 4817 out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.'); 4818 out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.'); 4819 out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.'); 4820 out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.'); 4821 out.append(' '); 4822 out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.'); 4823 out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.'); 4824 out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.'); 4825 if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) { 4826 out.append('p'); 4827 } else { 4828 out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.'); 4829 } 4830 out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.'); 4831 out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.'); 4832 out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.'); 4833 out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.'); 4834 out.append(' '); 4835 out.append(mLeft); 4836 out.append(','); 4837 out.append(mTop); 4838 out.append('-'); 4839 out.append(mRight); 4840 out.append(','); 4841 out.append(mBottom); 4842 final int id = getId(); 4843 if (id != NO_ID) { 4844 out.append(" #"); 4845 out.append(Integer.toHexString(id)); 4846 final Resources r = mResources; 4847 if (id > 0 && Resources.resourceHasPackage(id) && r != null) { 4848 try { 4849 String pkgname; 4850 switch (id&0xff000000) { 4851 case 0x7f000000: 4852 pkgname="app"; 4853 break; 4854 case 0x01000000: 4855 pkgname="android"; 4856 break; 4857 default: 4858 pkgname = r.getResourcePackageName(id); 4859 break; 4860 } 4861 String typename = r.getResourceTypeName(id); 4862 String entryname = r.getResourceEntryName(id); 4863 out.append(" "); 4864 out.append(pkgname); 4865 out.append(":"); 4866 out.append(typename); 4867 out.append("/"); 4868 out.append(entryname); 4869 } catch (Resources.NotFoundException e) { 4870 } 4871 } 4872 } 4873 out.append("}"); 4874 return out.toString(); 4875 } 4876 4877 /** 4878 * <p> 4879 * Initializes the fading edges from a given set of styled attributes. This 4880 * method should be called by subclasses that need fading edges and when an 4881 * instance of these subclasses is created programmatically rather than 4882 * being inflated from XML. This method is automatically called when the XML 4883 * is inflated. 4884 * </p> 4885 * 4886 * @param a the styled attributes set to initialize the fading edges from 4887 * 4888 * @removed 4889 */ initializeFadingEdge(TypedArray a)4890 protected void initializeFadingEdge(TypedArray a) { 4891 // This method probably shouldn't have been included in the SDK to begin with. 4892 // It relies on 'a' having been initialized using an attribute filter array that is 4893 // not publicly available to the SDK. The old method has been renamed 4894 // to initializeFadingEdgeInternal and hidden for framework use only; 4895 // this one initializes using defaults to make it safe to call for apps. 4896 4897 TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View); 4898 4899 initializeFadingEdgeInternal(arr); 4900 4901 arr.recycle(); 4902 } 4903 4904 /** 4905 * <p> 4906 * Initializes the fading edges from a given set of styled attributes. This 4907 * method should be called by subclasses that need fading edges and when an 4908 * instance of these subclasses is created programmatically rather than 4909 * being inflated from XML. This method is automatically called when the XML 4910 * is inflated. 4911 * </p> 4912 * 4913 * @param a the styled attributes set to initialize the fading edges from 4914 * @hide This is the real method; the public one is shimmed to be safe to call from apps. 4915 */ initializeFadingEdgeInternal(TypedArray a)4916 protected void initializeFadingEdgeInternal(TypedArray a) { 4917 initScrollCache(); 4918 4919 mScrollCache.fadingEdgeLength = a.getDimensionPixelSize( 4920 R.styleable.View_fadingEdgeLength, 4921 ViewConfiguration.get(mContext).getScaledFadingEdgeLength()); 4922 } 4923 4924 /** 4925 * Returns the size of the vertical faded edges used to indicate that more 4926 * content in this view is visible. 4927 * 4928 * @return The size in pixels of the vertical faded edge or 0 if vertical 4929 * faded edges are not enabled for this view. 4930 * @attr ref android.R.styleable#View_fadingEdgeLength 4931 */ getVerticalFadingEdgeLength()4932 public int getVerticalFadingEdgeLength() { 4933 if (isVerticalFadingEdgeEnabled()) { 4934 ScrollabilityCache cache = mScrollCache; 4935 if (cache != null) { 4936 return cache.fadingEdgeLength; 4937 } 4938 } 4939 return 0; 4940 } 4941 4942 /** 4943 * Set the size of the faded edge used to indicate that more content in this 4944 * view is available. Will not change whether the fading edge is enabled; use 4945 * {@link #setVerticalFadingEdgeEnabled(boolean)} or 4946 * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge 4947 * for the vertical or horizontal fading edges. 4948 * 4949 * @param length The size in pixels of the faded edge used to indicate that more 4950 * content in this view is visible. 4951 */ setFadingEdgeLength(int length)4952 public void setFadingEdgeLength(int length) { 4953 initScrollCache(); 4954 mScrollCache.fadingEdgeLength = length; 4955 } 4956 4957 /** 4958 * Returns the size of the horizontal faded edges used to indicate that more 4959 * content in this view is visible. 4960 * 4961 * @return The size in pixels of the horizontal faded edge or 0 if horizontal 4962 * faded edges are not enabled for this view. 4963 * @attr ref android.R.styleable#View_fadingEdgeLength 4964 */ getHorizontalFadingEdgeLength()4965 public int getHorizontalFadingEdgeLength() { 4966 if (isHorizontalFadingEdgeEnabled()) { 4967 ScrollabilityCache cache = mScrollCache; 4968 if (cache != null) { 4969 return cache.fadingEdgeLength; 4970 } 4971 } 4972 return 0; 4973 } 4974 4975 /** 4976 * Returns the width of the vertical scrollbar. 4977 * 4978 * @return The width in pixels of the vertical scrollbar or 0 if there 4979 * is no vertical scrollbar. 4980 */ getVerticalScrollbarWidth()4981 public int getVerticalScrollbarWidth() { 4982 ScrollabilityCache cache = mScrollCache; 4983 if (cache != null) { 4984 ScrollBarDrawable scrollBar = cache.scrollBar; 4985 if (scrollBar != null) { 4986 int size = scrollBar.getSize(true); 4987 if (size <= 0) { 4988 size = cache.scrollBarSize; 4989 } 4990 return size; 4991 } 4992 return 0; 4993 } 4994 return 0; 4995 } 4996 4997 /** 4998 * Returns the height of the horizontal scrollbar. 4999 * 5000 * @return The height in pixels of the horizontal scrollbar or 0 if 5001 * there is no horizontal scrollbar. 5002 */ getHorizontalScrollbarHeight()5003 protected int getHorizontalScrollbarHeight() { 5004 ScrollabilityCache cache = mScrollCache; 5005 if (cache != null) { 5006 ScrollBarDrawable scrollBar = cache.scrollBar; 5007 if (scrollBar != null) { 5008 int size = scrollBar.getSize(false); 5009 if (size <= 0) { 5010 size = cache.scrollBarSize; 5011 } 5012 return size; 5013 } 5014 return 0; 5015 } 5016 return 0; 5017 } 5018 5019 /** 5020 * <p> 5021 * Initializes the scrollbars from a given set of styled attributes. This 5022 * method should be called by subclasses that need scrollbars and when an 5023 * instance of these subclasses is created programmatically rather than 5024 * being inflated from XML. This method is automatically called when the XML 5025 * is inflated. 5026 * </p> 5027 * 5028 * @param a the styled attributes set to initialize the scrollbars from 5029 * 5030 * @removed 5031 */ initializeScrollbars(TypedArray a)5032 protected void initializeScrollbars(TypedArray a) { 5033 // It's not safe to use this method from apps. The parameter 'a' must have been obtained 5034 // using the View filter array which is not available to the SDK. As such, internal 5035 // framework usage now uses initializeScrollbarsInternal and we grab a default 5036 // TypedArray with the right filter instead here. 5037 TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View); 5038 5039 initializeScrollbarsInternal(arr); 5040 5041 // We ignored the method parameter. Recycle the one we actually did use. 5042 arr.recycle(); 5043 } 5044 5045 /** 5046 * <p> 5047 * Initializes the scrollbars from a given set of styled attributes. This 5048 * method should be called by subclasses that need scrollbars and when an 5049 * instance of these subclasses is created programmatically rather than 5050 * being inflated from XML. This method is automatically called when the XML 5051 * is inflated. 5052 * </p> 5053 * 5054 * @param a the styled attributes set to initialize the scrollbars from 5055 * @hide 5056 */ initializeScrollbarsInternal(TypedArray a)5057 protected void initializeScrollbarsInternal(TypedArray a) { 5058 initScrollCache(); 5059 5060 final ScrollabilityCache scrollabilityCache = mScrollCache; 5061 5062 if (scrollabilityCache.scrollBar == null) { 5063 scrollabilityCache.scrollBar = new ScrollBarDrawable(); 5064 scrollabilityCache.scrollBar.setState(getDrawableState()); 5065 scrollabilityCache.scrollBar.setCallback(this); 5066 } 5067 5068 final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true); 5069 5070 if (!fadeScrollbars) { 5071 scrollabilityCache.state = ScrollabilityCache.ON; 5072 } 5073 scrollabilityCache.fadeScrollBars = fadeScrollbars; 5074 5075 5076 scrollabilityCache.scrollBarFadeDuration = a.getInt( 5077 R.styleable.View_scrollbarFadeDuration, ViewConfiguration 5078 .getScrollBarFadeDuration()); 5079 scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt( 5080 R.styleable.View_scrollbarDefaultDelayBeforeFade, 5081 ViewConfiguration.getScrollDefaultDelay()); 5082 5083 5084 scrollabilityCache.scrollBarSize = a.getDimensionPixelSize( 5085 com.android.internal.R.styleable.View_scrollbarSize, 5086 ViewConfiguration.get(mContext).getScaledScrollBarSize()); 5087 5088 Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal); 5089 scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track); 5090 5091 Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal); 5092 if (thumb != null) { 5093 scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb); 5094 } 5095 5096 boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack, 5097 false); 5098 if (alwaysDraw) { 5099 scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true); 5100 } 5101 5102 track = a.getDrawable(R.styleable.View_scrollbarTrackVertical); 5103 scrollabilityCache.scrollBar.setVerticalTrackDrawable(track); 5104 5105 thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical); 5106 if (thumb != null) { 5107 scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb); 5108 } 5109 5110 alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack, 5111 false); 5112 if (alwaysDraw) { 5113 scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true); 5114 } 5115 5116 // Apply layout direction to the new Drawables if needed 5117 final int layoutDirection = getLayoutDirection(); 5118 if (track != null) { 5119 track.setLayoutDirection(layoutDirection); 5120 } 5121 if (thumb != null) { 5122 thumb.setLayoutDirection(layoutDirection); 5123 } 5124 5125 // Re-apply user/background padding so that scrollbar(s) get added 5126 resolvePadding(); 5127 } 5128 initializeScrollIndicatorsInternal()5129 private void initializeScrollIndicatorsInternal() { 5130 // Some day maybe we'll break this into top/left/start/etc. and let the 5131 // client control it. Until then, you can have any scroll indicator you 5132 // want as long as it's a 1dp foreground-colored rectangle. 5133 if (mScrollIndicatorDrawable == null) { 5134 mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material); 5135 } 5136 } 5137 5138 /** 5139 * <p> 5140 * Initalizes the scrollability cache if necessary. 5141 * </p> 5142 */ initScrollCache()5143 private void initScrollCache() { 5144 if (mScrollCache == null) { 5145 mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this); 5146 } 5147 } 5148 getScrollCache()5149 private ScrollabilityCache getScrollCache() { 5150 initScrollCache(); 5151 return mScrollCache; 5152 } 5153 5154 /** 5155 * Set the position of the vertical scroll bar. Should be one of 5156 * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or 5157 * {@link #SCROLLBAR_POSITION_RIGHT}. 5158 * 5159 * @param position Where the vertical scroll bar should be positioned. 5160 */ setVerticalScrollbarPosition(int position)5161 public void setVerticalScrollbarPosition(int position) { 5162 if (mVerticalScrollbarPosition != position) { 5163 mVerticalScrollbarPosition = position; 5164 computeOpaqueFlags(); 5165 resolvePadding(); 5166 } 5167 } 5168 5169 /** 5170 * @return The position where the vertical scroll bar will show, if applicable. 5171 * @see #setVerticalScrollbarPosition(int) 5172 */ getVerticalScrollbarPosition()5173 public int getVerticalScrollbarPosition() { 5174 return mVerticalScrollbarPosition; 5175 } 5176 isOnScrollbar(float x, float y)5177 boolean isOnScrollbar(float x, float y) { 5178 if (mScrollCache == null) { 5179 return false; 5180 } 5181 x += getScrollX(); 5182 y += getScrollY(); 5183 if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) { 5184 final Rect bounds = mScrollCache.mScrollBarBounds; 5185 getVerticalScrollBarBounds(bounds); 5186 if (bounds.contains((int)x, (int)y)) { 5187 return true; 5188 } 5189 } 5190 if (isHorizontalScrollBarEnabled()) { 5191 final Rect bounds = mScrollCache.mScrollBarBounds; 5192 getHorizontalScrollBarBounds(bounds); 5193 if (bounds.contains((int)x, (int)y)) { 5194 return true; 5195 } 5196 } 5197 return false; 5198 } 5199 isOnScrollbarThumb(float x, float y)5200 boolean isOnScrollbarThumb(float x, float y) { 5201 return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y); 5202 } 5203 isOnVerticalScrollbarThumb(float x, float y)5204 private boolean isOnVerticalScrollbarThumb(float x, float y) { 5205 if (mScrollCache == null) { 5206 return false; 5207 } 5208 if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) { 5209 x += getScrollX(); 5210 y += getScrollY(); 5211 final Rect bounds = mScrollCache.mScrollBarBounds; 5212 getVerticalScrollBarBounds(bounds); 5213 final int range = computeVerticalScrollRange(); 5214 final int offset = computeVerticalScrollOffset(); 5215 final int extent = computeVerticalScrollExtent(); 5216 final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(), 5217 extent, range); 5218 final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength, 5219 extent, range, offset); 5220 final int thumbTop = bounds.top + thumbOffset; 5221 if (x >= bounds.left && x <= bounds.right && y >= thumbTop 5222 && y <= thumbTop + thumbLength) { 5223 return true; 5224 } 5225 } 5226 return false; 5227 } 5228 isOnHorizontalScrollbarThumb(float x, float y)5229 private boolean isOnHorizontalScrollbarThumb(float x, float y) { 5230 if (mScrollCache == null) { 5231 return false; 5232 } 5233 if (isHorizontalScrollBarEnabled()) { 5234 x += getScrollX(); 5235 y += getScrollY(); 5236 final Rect bounds = mScrollCache.mScrollBarBounds; 5237 getHorizontalScrollBarBounds(bounds); 5238 final int range = computeHorizontalScrollRange(); 5239 final int offset = computeHorizontalScrollOffset(); 5240 final int extent = computeHorizontalScrollExtent(); 5241 final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(), 5242 extent, range); 5243 final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength, 5244 extent, range, offset); 5245 final int thumbLeft = bounds.left + thumbOffset; 5246 if (x >= thumbLeft && x <= thumbLeft + thumbLength && y >= bounds.top 5247 && y <= bounds.bottom) { 5248 return true; 5249 } 5250 } 5251 return false; 5252 } 5253 isDraggingScrollBar()5254 boolean isDraggingScrollBar() { 5255 return mScrollCache != null 5256 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING; 5257 } 5258 5259 /** 5260 * Sets the state of all scroll indicators. 5261 * <p> 5262 * See {@link #setScrollIndicators(int, int)} for usage information. 5263 * 5264 * @param indicators a bitmask of indicators that should be enabled, or 5265 * {@code 0} to disable all indicators 5266 * @see #setScrollIndicators(int, int) 5267 * @see #getScrollIndicators() 5268 * @attr ref android.R.styleable#View_scrollIndicators 5269 */ setScrollIndicators(@crollIndicators int indicators)5270 public void setScrollIndicators(@ScrollIndicators int indicators) { 5271 setScrollIndicators(indicators, 5272 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT); 5273 } 5274 5275 /** 5276 * Sets the state of the scroll indicators specified by the mask. To change 5277 * all scroll indicators at once, see {@link #setScrollIndicators(int)}. 5278 * <p> 5279 * When a scroll indicator is enabled, it will be displayed if the view 5280 * can scroll in the direction of the indicator. 5281 * <p> 5282 * Multiple indicator types may be enabled or disabled by passing the 5283 * logical OR of the desired types. If multiple types are specified, they 5284 * will all be set to the same enabled state. 5285 * <p> 5286 * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators 5287 * 5288 * @param indicators the indicator direction, or the logical OR of multiple 5289 * indicator directions. One or more of: 5290 * <ul> 5291 * <li>{@link #SCROLL_INDICATOR_TOP}</li> 5292 * <li>{@link #SCROLL_INDICATOR_BOTTOM}</li> 5293 * <li>{@link #SCROLL_INDICATOR_LEFT}</li> 5294 * <li>{@link #SCROLL_INDICATOR_RIGHT}</li> 5295 * <li>{@link #SCROLL_INDICATOR_START}</li> 5296 * <li>{@link #SCROLL_INDICATOR_END}</li> 5297 * </ul> 5298 * @see #setScrollIndicators(int) 5299 * @see #getScrollIndicators() 5300 * @attr ref android.R.styleable#View_scrollIndicators 5301 */ setScrollIndicators(@crollIndicators int indicators, @ScrollIndicators int mask)5302 public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) { 5303 // Shift and sanitize mask. 5304 mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 5305 mask &= SCROLL_INDICATORS_PFLAG3_MASK; 5306 5307 // Shift and mask indicators. 5308 indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 5309 indicators &= mask; 5310 5311 // Merge with non-masked flags. 5312 final int updatedFlags = indicators | (mPrivateFlags3 & ~mask); 5313 5314 if (mPrivateFlags3 != updatedFlags) { 5315 mPrivateFlags3 = updatedFlags; 5316 5317 if (indicators != 0) { 5318 initializeScrollIndicatorsInternal(); 5319 } 5320 invalidate(); 5321 } 5322 } 5323 5324 /** 5325 * Returns a bitmask representing the enabled scroll indicators. 5326 * <p> 5327 * For example, if the top and left scroll indicators are enabled and all 5328 * other indicators are disabled, the return value will be 5329 * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}. 5330 * <p> 5331 * To check whether the bottom scroll indicator is enabled, use the value 5332 * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}. 5333 * 5334 * @return a bitmask representing the enabled scroll indicators 5335 */ 5336 @ScrollIndicators getScrollIndicators()5337 public int getScrollIndicators() { 5338 return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) 5339 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 5340 } 5341 getListenerInfo()5342 ListenerInfo getListenerInfo() { 5343 if (mListenerInfo != null) { 5344 return mListenerInfo; 5345 } 5346 mListenerInfo = new ListenerInfo(); 5347 return mListenerInfo; 5348 } 5349 5350 /** 5351 * Register a callback to be invoked when the scroll X or Y positions of 5352 * this view change. 5353 * <p> 5354 * <b>Note:</b> Some views handle scrolling independently from View and may 5355 * have their own separate listeners for scroll-type events. For example, 5356 * {@link android.widget.ListView ListView} allows clients to register an 5357 * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener} 5358 * to listen for changes in list scroll position. 5359 * 5360 * @param l The listener to notify when the scroll X or Y position changes. 5361 * @see android.view.View#getScrollX() 5362 * @see android.view.View#getScrollY() 5363 */ setOnScrollChangeListener(OnScrollChangeListener l)5364 public void setOnScrollChangeListener(OnScrollChangeListener l) { 5365 getListenerInfo().mOnScrollChangeListener = l; 5366 } 5367 5368 /** 5369 * Register a callback to be invoked when focus of this view changed. 5370 * 5371 * @param l The callback that will run. 5372 */ setOnFocusChangeListener(OnFocusChangeListener l)5373 public void setOnFocusChangeListener(OnFocusChangeListener l) { 5374 getListenerInfo().mOnFocusChangeListener = l; 5375 } 5376 5377 /** 5378 * Add a listener that will be called when the bounds of the view change due to 5379 * layout processing. 5380 * 5381 * @param listener The listener that will be called when layout bounds change. 5382 */ addOnLayoutChangeListener(OnLayoutChangeListener listener)5383 public void addOnLayoutChangeListener(OnLayoutChangeListener listener) { 5384 ListenerInfo li = getListenerInfo(); 5385 if (li.mOnLayoutChangeListeners == null) { 5386 li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>(); 5387 } 5388 if (!li.mOnLayoutChangeListeners.contains(listener)) { 5389 li.mOnLayoutChangeListeners.add(listener); 5390 } 5391 } 5392 5393 /** 5394 * Remove a listener for layout changes. 5395 * 5396 * @param listener The listener for layout bounds change. 5397 */ removeOnLayoutChangeListener(OnLayoutChangeListener listener)5398 public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) { 5399 ListenerInfo li = mListenerInfo; 5400 if (li == null || li.mOnLayoutChangeListeners == null) { 5401 return; 5402 } 5403 li.mOnLayoutChangeListeners.remove(listener); 5404 } 5405 5406 /** 5407 * Add a listener for attach state changes. 5408 * 5409 * This listener will be called whenever this view is attached or detached 5410 * from a window. Remove the listener using 5411 * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}. 5412 * 5413 * @param listener Listener to attach 5414 * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener) 5415 */ addOnAttachStateChangeListener(OnAttachStateChangeListener listener)5416 public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) { 5417 ListenerInfo li = getListenerInfo(); 5418 if (li.mOnAttachStateChangeListeners == null) { 5419 li.mOnAttachStateChangeListeners 5420 = new CopyOnWriteArrayList<OnAttachStateChangeListener>(); 5421 } 5422 li.mOnAttachStateChangeListeners.add(listener); 5423 } 5424 5425 /** 5426 * Remove a listener for attach state changes. The listener will receive no further 5427 * notification of window attach/detach events. 5428 * 5429 * @param listener Listener to remove 5430 * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener) 5431 */ removeOnAttachStateChangeListener(OnAttachStateChangeListener listener)5432 public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) { 5433 ListenerInfo li = mListenerInfo; 5434 if (li == null || li.mOnAttachStateChangeListeners == null) { 5435 return; 5436 } 5437 li.mOnAttachStateChangeListeners.remove(listener); 5438 } 5439 5440 /** 5441 * Returns the focus-change callback registered for this view. 5442 * 5443 * @return The callback, or null if one is not registered. 5444 */ getOnFocusChangeListener()5445 public OnFocusChangeListener getOnFocusChangeListener() { 5446 ListenerInfo li = mListenerInfo; 5447 return li != null ? li.mOnFocusChangeListener : null; 5448 } 5449 5450 /** 5451 * Register a callback to be invoked when this view is clicked. If this view is not 5452 * clickable, it becomes clickable. 5453 * 5454 * @param l The callback that will run 5455 * 5456 * @see #setClickable(boolean) 5457 */ setOnClickListener(@ullable OnClickListener l)5458 public void setOnClickListener(@Nullable OnClickListener l) { 5459 if (!isClickable()) { 5460 setClickable(true); 5461 } 5462 getListenerInfo().mOnClickListener = l; 5463 } 5464 5465 /** 5466 * Return whether this view has an attached OnClickListener. Returns 5467 * true if there is a listener, false if there is none. 5468 */ hasOnClickListeners()5469 public boolean hasOnClickListeners() { 5470 ListenerInfo li = mListenerInfo; 5471 return (li != null && li.mOnClickListener != null); 5472 } 5473 5474 /** 5475 * Register a callback to be invoked when this view is clicked and held. If this view is not 5476 * long clickable, it becomes long clickable. 5477 * 5478 * @param l The callback that will run 5479 * 5480 * @see #setLongClickable(boolean) 5481 */ setOnLongClickListener(@ullable OnLongClickListener l)5482 public void setOnLongClickListener(@Nullable OnLongClickListener l) { 5483 if (!isLongClickable()) { 5484 setLongClickable(true); 5485 } 5486 getListenerInfo().mOnLongClickListener = l; 5487 } 5488 5489 /** 5490 * Register a callback to be invoked when this view is context clicked. If the view is not 5491 * context clickable, it becomes context clickable. 5492 * 5493 * @param l The callback that will run 5494 * @see #setContextClickable(boolean) 5495 */ setOnContextClickListener(@ullable OnContextClickListener l)5496 public void setOnContextClickListener(@Nullable OnContextClickListener l) { 5497 if (!isContextClickable()) { 5498 setContextClickable(true); 5499 } 5500 getListenerInfo().mOnContextClickListener = l; 5501 } 5502 5503 /** 5504 * Register a callback to be invoked when the context menu for this view is 5505 * being built. If this view is not long clickable, it becomes long clickable. 5506 * 5507 * @param l The callback that will run 5508 * 5509 */ setOnCreateContextMenuListener(OnCreateContextMenuListener l)5510 public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) { 5511 if (!isLongClickable()) { 5512 setLongClickable(true); 5513 } 5514 getListenerInfo().mOnCreateContextMenuListener = l; 5515 } 5516 5517 /** 5518 * Set an observer to collect stats for each frame rendered for this view. 5519 * 5520 * @hide 5521 */ addFrameMetricsListener(Window window, Window.OnFrameMetricsAvailableListener listener, Handler handler)5522 public void addFrameMetricsListener(Window window, 5523 Window.OnFrameMetricsAvailableListener listener, 5524 Handler handler) { 5525 if (mAttachInfo != null) { 5526 if (mAttachInfo.mHardwareRenderer != null) { 5527 if (mFrameMetricsObservers == null) { 5528 mFrameMetricsObservers = new ArrayList<>(); 5529 } 5530 5531 FrameMetricsObserver fmo = new FrameMetricsObserver(window, 5532 handler.getLooper(), listener); 5533 mFrameMetricsObservers.add(fmo); 5534 mAttachInfo.mHardwareRenderer.addFrameMetricsObserver(fmo); 5535 } else { 5536 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats"); 5537 } 5538 } else { 5539 if (mFrameMetricsObservers == null) { 5540 mFrameMetricsObservers = new ArrayList<>(); 5541 } 5542 5543 FrameMetricsObserver fmo = new FrameMetricsObserver(window, 5544 handler.getLooper(), listener); 5545 mFrameMetricsObservers.add(fmo); 5546 } 5547 } 5548 5549 /** 5550 * Remove observer configured to collect frame stats for this view. 5551 * 5552 * @hide 5553 */ removeFrameMetricsListener( Window.OnFrameMetricsAvailableListener listener)5554 public void removeFrameMetricsListener( 5555 Window.OnFrameMetricsAvailableListener listener) { 5556 ThreadedRenderer renderer = getHardwareRenderer(); 5557 FrameMetricsObserver fmo = findFrameMetricsObserver(listener); 5558 if (fmo == null) { 5559 throw new IllegalArgumentException( 5560 "attempt to remove OnFrameMetricsAvailableListener that was never added"); 5561 } 5562 5563 if (mFrameMetricsObservers != null) { 5564 mFrameMetricsObservers.remove(fmo); 5565 if (renderer != null) { 5566 renderer.removeFrameMetricsObserver(fmo); 5567 } 5568 } 5569 } 5570 registerPendingFrameMetricsObservers()5571 private void registerPendingFrameMetricsObservers() { 5572 if (mFrameMetricsObservers != null) { 5573 ThreadedRenderer renderer = getHardwareRenderer(); 5574 if (renderer != null) { 5575 for (FrameMetricsObserver fmo : mFrameMetricsObservers) { 5576 renderer.addFrameMetricsObserver(fmo); 5577 } 5578 } else { 5579 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats"); 5580 } 5581 } 5582 } 5583 findFrameMetricsObserver( Window.OnFrameMetricsAvailableListener listener)5584 private FrameMetricsObserver findFrameMetricsObserver( 5585 Window.OnFrameMetricsAvailableListener listener) { 5586 for (int i = 0; i < mFrameMetricsObservers.size(); i++) { 5587 FrameMetricsObserver observer = mFrameMetricsObservers.get(i); 5588 if (observer.mListener == listener) { 5589 return observer; 5590 } 5591 } 5592 5593 return null; 5594 } 5595 5596 /** 5597 * Call this view's OnClickListener, if it is defined. Performs all normal 5598 * actions associated with clicking: reporting accessibility event, playing 5599 * a sound, etc. 5600 * 5601 * @return True there was an assigned OnClickListener that was called, false 5602 * otherwise is returned. 5603 */ performClick()5604 public boolean performClick() { 5605 final boolean result; 5606 final ListenerInfo li = mListenerInfo; 5607 if (li != null && li.mOnClickListener != null) { 5608 playSoundEffect(SoundEffectConstants.CLICK); 5609 li.mOnClickListener.onClick(this); 5610 result = true; 5611 } else { 5612 result = false; 5613 } 5614 5615 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); 5616 return result; 5617 } 5618 5619 /** 5620 * Directly call any attached OnClickListener. Unlike {@link #performClick()}, 5621 * this only calls the listener, and does not do any associated clicking 5622 * actions like reporting an accessibility event. 5623 * 5624 * @return True there was an assigned OnClickListener that was called, false 5625 * otherwise is returned. 5626 */ callOnClick()5627 public boolean callOnClick() { 5628 ListenerInfo li = mListenerInfo; 5629 if (li != null && li.mOnClickListener != null) { 5630 li.mOnClickListener.onClick(this); 5631 return true; 5632 } 5633 return false; 5634 } 5635 5636 /** 5637 * Calls this view's OnLongClickListener, if it is defined. Invokes the 5638 * context menu if the OnLongClickListener did not consume the event. 5639 * 5640 * @return {@code true} if one of the above receivers consumed the event, 5641 * {@code false} otherwise 5642 */ performLongClick()5643 public boolean performLongClick() { 5644 return performLongClickInternal(mLongClickX, mLongClickY); 5645 } 5646 5647 /** 5648 * Calls this view's OnLongClickListener, if it is defined. Invokes the 5649 * context menu if the OnLongClickListener did not consume the event, 5650 * anchoring it to an (x,y) coordinate. 5651 * 5652 * @param x x coordinate of the anchoring touch event, or {@link Float#NaN} 5653 * to disable anchoring 5654 * @param y y coordinate of the anchoring touch event, or {@link Float#NaN} 5655 * to disable anchoring 5656 * @return {@code true} if one of the above receivers consumed the event, 5657 * {@code false} otherwise 5658 */ performLongClick(float x, float y)5659 public boolean performLongClick(float x, float y) { 5660 mLongClickX = x; 5661 mLongClickY = y; 5662 final boolean handled = performLongClick(); 5663 mLongClickX = Float.NaN; 5664 mLongClickY = Float.NaN; 5665 return handled; 5666 } 5667 5668 /** 5669 * Calls this view's OnLongClickListener, if it is defined. Invokes the 5670 * context menu if the OnLongClickListener did not consume the event, 5671 * optionally anchoring it to an (x,y) coordinate. 5672 * 5673 * @param x x coordinate of the anchoring touch event, or {@link Float#NaN} 5674 * to disable anchoring 5675 * @param y y coordinate of the anchoring touch event, or {@link Float#NaN} 5676 * to disable anchoring 5677 * @return {@code true} if one of the above receivers consumed the event, 5678 * {@code false} otherwise 5679 */ performLongClickInternal(float x, float y)5680 private boolean performLongClickInternal(float x, float y) { 5681 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED); 5682 5683 boolean handled = false; 5684 final ListenerInfo li = mListenerInfo; 5685 if (li != null && li.mOnLongClickListener != null) { 5686 handled = li.mOnLongClickListener.onLongClick(View.this); 5687 } 5688 if (!handled) { 5689 final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y); 5690 handled = isAnchored ? showContextMenu(x, y) : showContextMenu(); 5691 } 5692 if (handled) { 5693 performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); 5694 } 5695 return handled; 5696 } 5697 5698 /** 5699 * Call this view's OnContextClickListener, if it is defined. 5700 * 5701 * @param x the x coordinate of the context click 5702 * @param y the y coordinate of the context click 5703 * @return True if there was an assigned OnContextClickListener that consumed the event, false 5704 * otherwise. 5705 */ performContextClick(float x, float y)5706 public boolean performContextClick(float x, float y) { 5707 return performContextClick(); 5708 } 5709 5710 /** 5711 * Call this view's OnContextClickListener, if it is defined. 5712 * 5713 * @return True if there was an assigned OnContextClickListener that consumed the event, false 5714 * otherwise. 5715 */ performContextClick()5716 public boolean performContextClick() { 5717 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED); 5718 5719 boolean handled = false; 5720 ListenerInfo li = mListenerInfo; 5721 if (li != null && li.mOnContextClickListener != null) { 5722 handled = li.mOnContextClickListener.onContextClick(View.this); 5723 } 5724 if (handled) { 5725 performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK); 5726 } 5727 return handled; 5728 } 5729 5730 /** 5731 * Performs button-related actions during a touch down event. 5732 * 5733 * @param event The event. 5734 * @return True if the down was consumed. 5735 * 5736 * @hide 5737 */ performButtonActionOnTouchDown(MotionEvent event)5738 protected boolean performButtonActionOnTouchDown(MotionEvent event) { 5739 if (event.isFromSource(InputDevice.SOURCE_MOUSE) && 5740 (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) { 5741 showContextMenu(event.getX(), event.getY()); 5742 mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT; 5743 return true; 5744 } 5745 return false; 5746 } 5747 5748 /** 5749 * Shows the context menu for this view. 5750 * 5751 * @return {@code true} if the context menu was shown, {@code false} 5752 * otherwise 5753 * @see #showContextMenu(float, float) 5754 */ showContextMenu()5755 public boolean showContextMenu() { 5756 return getParent().showContextMenuForChild(this); 5757 } 5758 5759 /** 5760 * Shows the context menu for this view anchored to the specified 5761 * view-relative coordinate. 5762 * 5763 * @param x the X coordinate in pixels relative to the view to which the 5764 * menu should be anchored, or {@link Float#NaN} to disable anchoring 5765 * @param y the Y coordinate in pixels relative to the view to which the 5766 * menu should be anchored, or {@link Float#NaN} to disable anchoring 5767 * @return {@code true} if the context menu was shown, {@code false} 5768 * otherwise 5769 */ showContextMenu(float x, float y)5770 public boolean showContextMenu(float x, float y) { 5771 return getParent().showContextMenuForChild(this, x, y); 5772 } 5773 5774 /** 5775 * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}. 5776 * 5777 * @param callback Callback that will control the lifecycle of the action mode 5778 * @return The new action mode if it is started, null otherwise 5779 * 5780 * @see ActionMode 5781 * @see #startActionMode(android.view.ActionMode.Callback, int) 5782 */ startActionMode(ActionMode.Callback callback)5783 public ActionMode startActionMode(ActionMode.Callback callback) { 5784 return startActionMode(callback, ActionMode.TYPE_PRIMARY); 5785 } 5786 5787 /** 5788 * Start an action mode with the given type. 5789 * 5790 * @param callback Callback that will control the lifecycle of the action mode 5791 * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}. 5792 * @return The new action mode if it is started, null otherwise 5793 * 5794 * @see ActionMode 5795 */ startActionMode(ActionMode.Callback callback, int type)5796 public ActionMode startActionMode(ActionMode.Callback callback, int type) { 5797 ViewParent parent = getParent(); 5798 if (parent == null) return null; 5799 try { 5800 return parent.startActionModeForChild(this, callback, type); 5801 } catch (AbstractMethodError ame) { 5802 // Older implementations of custom views might not implement this. 5803 return parent.startActionModeForChild(this, callback); 5804 } 5805 } 5806 5807 /** 5808 * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's 5809 * Context, creating a unique View identifier to retrieve the result. 5810 * 5811 * @param intent The Intent to be started. 5812 * @param requestCode The request code to use. 5813 * @hide 5814 */ startActivityForResult(Intent intent, int requestCode)5815 public void startActivityForResult(Intent intent, int requestCode) { 5816 mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this); 5817 getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null); 5818 } 5819 5820 /** 5821 * If this View corresponds to the calling who, dispatches the activity result. 5822 * @param who The identifier for the targeted View to receive the result. 5823 * @param requestCode The integer request code originally supplied to 5824 * startActivityForResult(), allowing you to identify who this 5825 * result came from. 5826 * @param resultCode The integer result code returned by the child activity 5827 * through its setResult(). 5828 * @param data An Intent, which can return result data to the caller 5829 * (various data can be attached to Intent "extras"). 5830 * @return {@code true} if the activity result was dispatched. 5831 * @hide 5832 */ dispatchActivityResult( String who, int requestCode, int resultCode, Intent data)5833 public boolean dispatchActivityResult( 5834 String who, int requestCode, int resultCode, Intent data) { 5835 if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) { 5836 onActivityResult(requestCode, resultCode, data); 5837 mStartActivityRequestWho = null; 5838 return true; 5839 } 5840 return false; 5841 } 5842 5843 /** 5844 * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}. 5845 * 5846 * @param requestCode The integer request code originally supplied to 5847 * startActivityForResult(), allowing you to identify who this 5848 * result came from. 5849 * @param resultCode The integer result code returned by the child activity 5850 * through its setResult(). 5851 * @param data An Intent, which can return result data to the caller 5852 * (various data can be attached to Intent "extras"). 5853 * @hide 5854 */ onActivityResult(int requestCode, int resultCode, Intent data)5855 public void onActivityResult(int requestCode, int resultCode, Intent data) { 5856 // Do nothing. 5857 } 5858 5859 /** 5860 * Register a callback to be invoked when a hardware key is pressed in this view. 5861 * Key presses in software input methods will generally not trigger the methods of 5862 * this listener. 5863 * @param l the key listener to attach to this view 5864 */ setOnKeyListener(OnKeyListener l)5865 public void setOnKeyListener(OnKeyListener l) { 5866 getListenerInfo().mOnKeyListener = l; 5867 } 5868 5869 /** 5870 * Register a callback to be invoked when a touch event is sent to this view. 5871 * @param l the touch listener to attach to this view 5872 */ setOnTouchListener(OnTouchListener l)5873 public void setOnTouchListener(OnTouchListener l) { 5874 getListenerInfo().mOnTouchListener = l; 5875 } 5876 5877 /** 5878 * Register a callback to be invoked when a generic motion event is sent to this view. 5879 * @param l the generic motion listener to attach to this view 5880 */ setOnGenericMotionListener(OnGenericMotionListener l)5881 public void setOnGenericMotionListener(OnGenericMotionListener l) { 5882 getListenerInfo().mOnGenericMotionListener = l; 5883 } 5884 5885 /** 5886 * Register a callback to be invoked when a hover event is sent to this view. 5887 * @param l the hover listener to attach to this view 5888 */ setOnHoverListener(OnHoverListener l)5889 public void setOnHoverListener(OnHoverListener l) { 5890 getListenerInfo().mOnHoverListener = l; 5891 } 5892 5893 /** 5894 * Register a drag event listener callback object for this View. The parameter is 5895 * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a 5896 * View, the system calls the 5897 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method. 5898 * @param l An implementation of {@link android.view.View.OnDragListener}. 5899 */ setOnDragListener(OnDragListener l)5900 public void setOnDragListener(OnDragListener l) { 5901 getListenerInfo().mOnDragListener = l; 5902 } 5903 5904 /** 5905 * Give this view focus. This will cause 5906 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called. 5907 * 5908 * Note: this does not check whether this {@link View} should get focus, it just 5909 * gives it focus no matter what. It should only be called internally by framework 5910 * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}. 5911 * 5912 * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN}, 5913 * {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which 5914 * focus moved when requestFocus() is called. It may not always 5915 * apply, in which case use the default View.FOCUS_DOWN. 5916 * @param previouslyFocusedRect The rectangle of the view that had focus 5917 * prior in this View's coordinate system. 5918 */ handleFocusGainInternal(@ocusRealDirection int direction, Rect previouslyFocusedRect)5919 void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) { 5920 if (DBG) { 5921 System.out.println(this + " requestFocus()"); 5922 } 5923 5924 if ((mPrivateFlags & PFLAG_FOCUSED) == 0) { 5925 mPrivateFlags |= PFLAG_FOCUSED; 5926 5927 View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null; 5928 5929 if (mParent != null) { 5930 mParent.requestChildFocus(this, this); 5931 } 5932 5933 if (mAttachInfo != null) { 5934 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this); 5935 } 5936 5937 onFocusChanged(true, direction, previouslyFocusedRect); 5938 refreshDrawableState(); 5939 } 5940 } 5941 5942 /** 5943 * Populates <code>outRect</code> with the hotspot bounds. By default, 5944 * the hotspot bounds are identical to the screen bounds. 5945 * 5946 * @param outRect rect to populate with hotspot bounds 5947 * @hide Only for internal use by views and widgets. 5948 */ getHotspotBounds(Rect outRect)5949 public void getHotspotBounds(Rect outRect) { 5950 final Drawable background = getBackground(); 5951 if (background != null) { 5952 background.getHotspotBounds(outRect); 5953 } else { 5954 getBoundsOnScreen(outRect); 5955 } 5956 } 5957 5958 /** 5959 * Request that a rectangle of this view be visible on the screen, 5960 * scrolling if necessary just enough. 5961 * 5962 * <p>A View should call this if it maintains some notion of which part 5963 * of its content is interesting. For example, a text editing view 5964 * should call this when its cursor moves. 5965 * <p>The Rectangle passed into this method should be in the View's content coordinate space. 5966 * It should not be affected by which part of the View is currently visible or its scroll 5967 * position. 5968 * 5969 * @param rectangle The rectangle in the View's content coordinate space 5970 * @return Whether any parent scrolled. 5971 */ requestRectangleOnScreen(Rect rectangle)5972 public boolean requestRectangleOnScreen(Rect rectangle) { 5973 return requestRectangleOnScreen(rectangle, false); 5974 } 5975 5976 /** 5977 * Request that a rectangle of this view be visible on the screen, 5978 * scrolling if necessary just enough. 5979 * 5980 * <p>A View should call this if it maintains some notion of which part 5981 * of its content is interesting. For example, a text editing view 5982 * should call this when its cursor moves. 5983 * <p>The Rectangle passed into this method should be in the View's content coordinate space. 5984 * It should not be affected by which part of the View is currently visible or its scroll 5985 * position. 5986 * <p>When <code>immediate</code> is set to true, scrolling will not be 5987 * animated. 5988 * 5989 * @param rectangle The rectangle in the View's content coordinate space 5990 * @param immediate True to forbid animated scrolling, false otherwise 5991 * @return Whether any parent scrolled. 5992 */ requestRectangleOnScreen(Rect rectangle, boolean immediate)5993 public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) { 5994 if (mParent == null) { 5995 return false; 5996 } 5997 5998 View child = this; 5999 6000 RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF(); 6001 position.set(rectangle); 6002 6003 ViewParent parent = mParent; 6004 boolean scrolled = false; 6005 while (parent != null) { 6006 rectangle.set((int) position.left, (int) position.top, 6007 (int) position.right, (int) position.bottom); 6008 6009 scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate); 6010 6011 if (!(parent instanceof View)) { 6012 break; 6013 } 6014 6015 // move it from child's content coordinate space to parent's content coordinate space 6016 position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY()); 6017 6018 child = (View) parent; 6019 parent = child.getParent(); 6020 } 6021 6022 return scrolled; 6023 } 6024 6025 /** 6026 * Called when this view wants to give up focus. If focus is cleared 6027 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called. 6028 * <p> 6029 * <strong>Note:</strong> When a View clears focus the framework is trying 6030 * to give focus to the first focusable View from the top. Hence, if this 6031 * View is the first from the top that can take focus, then all callbacks 6032 * related to clearing focus will be invoked after which the framework will 6033 * give focus to this view. 6034 * </p> 6035 */ clearFocus()6036 public void clearFocus() { 6037 if (DBG) { 6038 System.out.println(this + " clearFocus()"); 6039 } 6040 6041 clearFocusInternal(null, true, true); 6042 } 6043 6044 /** 6045 * Clears focus from the view, optionally propagating the change up through 6046 * the parent hierarchy and requesting that the root view place new focus. 6047 * 6048 * @param propagate whether to propagate the change up through the parent 6049 * hierarchy 6050 * @param refocus when propagate is true, specifies whether to request the 6051 * root view place new focus 6052 */ clearFocusInternal(View focused, boolean propagate, boolean refocus)6053 void clearFocusInternal(View focused, boolean propagate, boolean refocus) { 6054 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) { 6055 mPrivateFlags &= ~PFLAG_FOCUSED; 6056 6057 if (propagate && mParent != null) { 6058 mParent.clearChildFocus(this); 6059 } 6060 6061 onFocusChanged(false, 0, null); 6062 refreshDrawableState(); 6063 6064 if (propagate && (!refocus || !rootViewRequestFocus())) { 6065 notifyGlobalFocusCleared(this); 6066 } 6067 } 6068 } 6069 notifyGlobalFocusCleared(View oldFocus)6070 void notifyGlobalFocusCleared(View oldFocus) { 6071 if (oldFocus != null && mAttachInfo != null) { 6072 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null); 6073 } 6074 } 6075 rootViewRequestFocus()6076 boolean rootViewRequestFocus() { 6077 final View root = getRootView(); 6078 return root != null && root.requestFocus(); 6079 } 6080 6081 /** 6082 * Called internally by the view system when a new view is getting focus. 6083 * This is what clears the old focus. 6084 * <p> 6085 * <b>NOTE:</b> The parent view's focused child must be updated manually 6086 * after calling this method. Otherwise, the view hierarchy may be left in 6087 * an inconstent state. 6088 */ unFocus(View focused)6089 void unFocus(View focused) { 6090 if (DBG) { 6091 System.out.println(this + " unFocus()"); 6092 } 6093 6094 clearFocusInternal(focused, false, false); 6095 } 6096 6097 /** 6098 * Returns true if this view has focus itself, or is the ancestor of the 6099 * view that has focus. 6100 * 6101 * @return True if this view has or contains focus, false otherwise. 6102 */ 6103 @ViewDebug.ExportedProperty(category = "focus") hasFocus()6104 public boolean hasFocus() { 6105 return (mPrivateFlags & PFLAG_FOCUSED) != 0; 6106 } 6107 6108 /** 6109 * Returns true if this view is focusable or if it contains a reachable View 6110 * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()" 6111 * is a View whose parents do not block descendants focus. 6112 * 6113 * Only {@link #VISIBLE} views are considered focusable. 6114 * 6115 * @return True if the view is focusable or if the view contains a focusable 6116 * View, false otherwise. 6117 * 6118 * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS 6119 * @see ViewGroup#getTouchscreenBlocksFocus() 6120 */ hasFocusable()6121 public boolean hasFocusable() { 6122 if (!isFocusableInTouchMode()) { 6123 for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) { 6124 final ViewGroup g = (ViewGroup) p; 6125 if (g.shouldBlockFocusForTouchscreen()) { 6126 return false; 6127 } 6128 } 6129 } 6130 return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable(); 6131 } 6132 6133 /** 6134 * Called by the view system when the focus state of this view changes. 6135 * When the focus change event is caused by directional navigation, direction 6136 * and previouslyFocusedRect provide insight into where the focus is coming from. 6137 * When overriding, be sure to call up through to the super class so that 6138 * the standard focus handling will occur. 6139 * 6140 * @param gainFocus True if the View has focus; false otherwise. 6141 * @param direction The direction focus has moved when requestFocus() 6142 * is called to give this view focus. Values are 6143 * {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT}, 6144 * {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}. 6145 * It may not always apply, in which case use the default. 6146 * @param previouslyFocusedRect The rectangle, in this view's coordinate 6147 * system, of the previously focused view. If applicable, this will be 6148 * passed in as finer grained information about where the focus is coming 6149 * from (in addition to direction). Will be <code>null</code> otherwise. 6150 */ 6151 @CallSuper onFocusChanged(boolean gainFocus, @FocusDirection int direction, @Nullable Rect previouslyFocusedRect)6152 protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction, 6153 @Nullable Rect previouslyFocusedRect) { 6154 if (gainFocus) { 6155 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); 6156 } else { 6157 notifyViewAccessibilityStateChangedIfNeeded( 6158 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 6159 } 6160 6161 InputMethodManager imm = InputMethodManager.peekInstance(); 6162 if (!gainFocus) { 6163 if (isPressed()) { 6164 setPressed(false); 6165 } 6166 if (imm != null && mAttachInfo != null 6167 && mAttachInfo.mHasWindowFocus) { 6168 imm.focusOut(this); 6169 } 6170 onFocusLost(); 6171 } else if (imm != null && mAttachInfo != null 6172 && mAttachInfo.mHasWindowFocus) { 6173 imm.focusIn(this); 6174 } 6175 6176 invalidate(true); 6177 ListenerInfo li = mListenerInfo; 6178 if (li != null && li.mOnFocusChangeListener != null) { 6179 li.mOnFocusChangeListener.onFocusChange(this, gainFocus); 6180 } 6181 6182 if (mAttachInfo != null) { 6183 mAttachInfo.mKeyDispatchState.reset(this); 6184 } 6185 } 6186 6187 /** 6188 * Sends an accessibility event of the given type. If accessibility is 6189 * not enabled this method has no effect. The default implementation calls 6190 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first 6191 * to populate information about the event source (this View), then calls 6192 * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to 6193 * populate the text content of the event source including its descendants, 6194 * and last calls 6195 * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)} 6196 * on its parent to request sending of the event to interested parties. 6197 * <p> 6198 * If an {@link AccessibilityDelegate} has been specified via calling 6199 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 6200 * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is 6201 * responsible for handling this call. 6202 * </p> 6203 * 6204 * @param eventType The type of the event to send, as defined by several types from 6205 * {@link android.view.accessibility.AccessibilityEvent}, such as 6206 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or 6207 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}. 6208 * 6209 * @see #onInitializeAccessibilityEvent(AccessibilityEvent) 6210 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 6211 * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent) 6212 * @see AccessibilityDelegate 6213 */ sendAccessibilityEvent(int eventType)6214 public void sendAccessibilityEvent(int eventType) { 6215 if (mAccessibilityDelegate != null) { 6216 mAccessibilityDelegate.sendAccessibilityEvent(this, eventType); 6217 } else { 6218 sendAccessibilityEventInternal(eventType); 6219 } 6220 } 6221 6222 /** 6223 * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT} 6224 * {@link AccessibilityEvent} to make an announcement which is related to some 6225 * sort of a context change for which none of the events representing UI transitions 6226 * is a good fit. For example, announcing a new page in a book. If accessibility 6227 * is not enabled this method does nothing. 6228 * 6229 * @param text The announcement text. 6230 */ announceForAccessibility(CharSequence text)6231 public void announceForAccessibility(CharSequence text) { 6232 if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) { 6233 AccessibilityEvent event = AccessibilityEvent.obtain( 6234 AccessibilityEvent.TYPE_ANNOUNCEMENT); 6235 onInitializeAccessibilityEvent(event); 6236 event.getText().add(text); 6237 event.setContentDescription(null); 6238 mParent.requestSendAccessibilityEvent(this, event); 6239 } 6240 } 6241 6242 /** 6243 * @see #sendAccessibilityEvent(int) 6244 * 6245 * Note: Called from the default {@link AccessibilityDelegate}. 6246 * 6247 * @hide 6248 */ sendAccessibilityEventInternal(int eventType)6249 public void sendAccessibilityEventInternal(int eventType) { 6250 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 6251 sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType)); 6252 } 6253 } 6254 6255 /** 6256 * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but 6257 * takes as an argument an empty {@link AccessibilityEvent} and does not 6258 * perform a check whether accessibility is enabled. 6259 * <p> 6260 * If an {@link AccessibilityDelegate} has been specified via calling 6261 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 6262 * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)} 6263 * is responsible for handling this call. 6264 * </p> 6265 * 6266 * @param event The event to send. 6267 * 6268 * @see #sendAccessibilityEvent(int) 6269 */ sendAccessibilityEventUnchecked(AccessibilityEvent event)6270 public void sendAccessibilityEventUnchecked(AccessibilityEvent event) { 6271 if (mAccessibilityDelegate != null) { 6272 mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event); 6273 } else { 6274 sendAccessibilityEventUncheckedInternal(event); 6275 } 6276 } 6277 6278 /** 6279 * @see #sendAccessibilityEventUnchecked(AccessibilityEvent) 6280 * 6281 * Note: Called from the default {@link AccessibilityDelegate}. 6282 * 6283 * @hide 6284 */ sendAccessibilityEventUncheckedInternal(AccessibilityEvent event)6285 public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) { 6286 if (!isShown()) { 6287 return; 6288 } 6289 onInitializeAccessibilityEvent(event); 6290 // Only a subset of accessibility events populates text content. 6291 if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) { 6292 dispatchPopulateAccessibilityEvent(event); 6293 } 6294 // In the beginning we called #isShown(), so we know that getParent() is not null. 6295 getParent().requestSendAccessibilityEvent(this, event); 6296 } 6297 6298 /** 6299 * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then 6300 * to its children for adding their text content to the event. Note that the 6301 * event text is populated in a separate dispatch path since we add to the 6302 * event not only the text of the source but also the text of all its descendants. 6303 * A typical implementation will call 6304 * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view 6305 * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} 6306 * on each child. Override this method if custom population of the event text 6307 * content is required. 6308 * <p> 6309 * If an {@link AccessibilityDelegate} has been specified via calling 6310 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 6311 * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)} 6312 * is responsible for handling this call. 6313 * </p> 6314 * <p> 6315 * <em>Note:</em> Accessibility events of certain types are not dispatched for 6316 * populating the event text via this method. For details refer to {@link AccessibilityEvent}. 6317 * </p> 6318 * 6319 * @param event The event. 6320 * 6321 * @return True if the event population was completed. 6322 */ dispatchPopulateAccessibilityEvent(AccessibilityEvent event)6323 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 6324 if (mAccessibilityDelegate != null) { 6325 return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event); 6326 } else { 6327 return dispatchPopulateAccessibilityEventInternal(event); 6328 } 6329 } 6330 6331 /** 6332 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 6333 * 6334 * Note: Called from the default {@link AccessibilityDelegate}. 6335 * 6336 * @hide 6337 */ dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event)6338 public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) { 6339 onPopulateAccessibilityEvent(event); 6340 return false; 6341 } 6342 6343 /** 6344 * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} 6345 * giving a chance to this View to populate the accessibility event with its 6346 * text content. While this method is free to modify event 6347 * attributes other than text content, doing so should normally be performed in 6348 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}. 6349 * <p> 6350 * Example: Adding formatted date string to an accessibility event in addition 6351 * to the text added by the super implementation: 6352 * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) { 6353 * super.onPopulateAccessibilityEvent(event); 6354 * final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY; 6355 * String selectedDateUtterance = DateUtils.formatDateTime(mContext, 6356 * mCurrentDate.getTimeInMillis(), flags); 6357 * event.getText().add(selectedDateUtterance); 6358 * }</pre> 6359 * <p> 6360 * If an {@link AccessibilityDelegate} has been specified via calling 6361 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 6362 * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)} 6363 * is responsible for handling this call. 6364 * </p> 6365 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding 6366 * information to the event, in case the default implementation has basic information to add. 6367 * </p> 6368 * 6369 * @param event The accessibility event which to populate. 6370 * 6371 * @see #sendAccessibilityEvent(int) 6372 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 6373 */ 6374 @CallSuper onPopulateAccessibilityEvent(AccessibilityEvent event)6375 public void onPopulateAccessibilityEvent(AccessibilityEvent event) { 6376 if (mAccessibilityDelegate != null) { 6377 mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event); 6378 } else { 6379 onPopulateAccessibilityEventInternal(event); 6380 } 6381 } 6382 6383 /** 6384 * @see #onPopulateAccessibilityEvent(AccessibilityEvent) 6385 * 6386 * Note: Called from the default {@link AccessibilityDelegate}. 6387 * 6388 * @hide 6389 */ onPopulateAccessibilityEventInternal(AccessibilityEvent event)6390 public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) { 6391 } 6392 6393 /** 6394 * Initializes an {@link AccessibilityEvent} with information about 6395 * this View which is the event source. In other words, the source of 6396 * an accessibility event is the view whose state change triggered firing 6397 * the event. 6398 * <p> 6399 * Example: Setting the password property of an event in addition 6400 * to properties set by the super implementation: 6401 * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 6402 * super.onInitializeAccessibilityEvent(event); 6403 * event.setPassword(true); 6404 * }</pre> 6405 * <p> 6406 * If an {@link AccessibilityDelegate} has been specified via calling 6407 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 6408 * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)} 6409 * is responsible for handling this call. 6410 * </p> 6411 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding 6412 * information to the event, in case the default implementation has basic information to add. 6413 * </p> 6414 * @param event The event to initialize. 6415 * 6416 * @see #sendAccessibilityEvent(int) 6417 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 6418 */ 6419 @CallSuper onInitializeAccessibilityEvent(AccessibilityEvent event)6420 public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 6421 if (mAccessibilityDelegate != null) { 6422 mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event); 6423 } else { 6424 onInitializeAccessibilityEventInternal(event); 6425 } 6426 } 6427 6428 /** 6429 * @see #onInitializeAccessibilityEvent(AccessibilityEvent) 6430 * 6431 * Note: Called from the default {@link AccessibilityDelegate}. 6432 * 6433 * @hide 6434 */ onInitializeAccessibilityEventInternal(AccessibilityEvent event)6435 public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) { 6436 event.setSource(this); 6437 event.setClassName(getAccessibilityClassName()); 6438 event.setPackageName(getContext().getPackageName()); 6439 event.setEnabled(isEnabled()); 6440 event.setContentDescription(mContentDescription); 6441 6442 switch (event.getEventType()) { 6443 case AccessibilityEvent.TYPE_VIEW_FOCUSED: { 6444 ArrayList<View> focusablesTempList = (mAttachInfo != null) 6445 ? mAttachInfo.mTempArrayList : new ArrayList<View>(); 6446 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL); 6447 event.setItemCount(focusablesTempList.size()); 6448 event.setCurrentItemIndex(focusablesTempList.indexOf(this)); 6449 if (mAttachInfo != null) { 6450 focusablesTempList.clear(); 6451 } 6452 } break; 6453 case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: { 6454 CharSequence text = getIterableTextForAccessibility(); 6455 if (text != null && text.length() > 0) { 6456 event.setFromIndex(getAccessibilitySelectionStart()); 6457 event.setToIndex(getAccessibilitySelectionEnd()); 6458 event.setItemCount(text.length()); 6459 } 6460 } break; 6461 } 6462 } 6463 6464 /** 6465 * Returns an {@link AccessibilityNodeInfo} representing this view from the 6466 * point of view of an {@link android.accessibilityservice.AccessibilityService}. 6467 * This method is responsible for obtaining an accessibility node info from a 6468 * pool of reusable instances and calling 6469 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to 6470 * initialize the former. 6471 * <p> 6472 * Note: The client is responsible for recycling the obtained instance by calling 6473 * {@link AccessibilityNodeInfo#recycle()} to minimize object creation. 6474 * </p> 6475 * 6476 * @return A populated {@link AccessibilityNodeInfo}. 6477 * 6478 * @see AccessibilityNodeInfo 6479 */ createAccessibilityNodeInfo()6480 public AccessibilityNodeInfo createAccessibilityNodeInfo() { 6481 if (mAccessibilityDelegate != null) { 6482 return mAccessibilityDelegate.createAccessibilityNodeInfo(this); 6483 } else { 6484 return createAccessibilityNodeInfoInternal(); 6485 } 6486 } 6487 6488 /** 6489 * @see #createAccessibilityNodeInfo() 6490 * 6491 * @hide 6492 */ createAccessibilityNodeInfoInternal()6493 public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() { 6494 AccessibilityNodeProvider provider = getAccessibilityNodeProvider(); 6495 if (provider != null) { 6496 return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID); 6497 } else { 6498 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this); 6499 onInitializeAccessibilityNodeInfo(info); 6500 return info; 6501 } 6502 } 6503 6504 /** 6505 * Initializes an {@link AccessibilityNodeInfo} with information about this view. 6506 * The base implementation sets: 6507 * <ul> 6508 * <li>{@link AccessibilityNodeInfo#setParent(View)},</li> 6509 * <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li> 6510 * <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li> 6511 * <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li> 6512 * <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li> 6513 * <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li> 6514 * <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li> 6515 * <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li> 6516 * <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li> 6517 * <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li> 6518 * <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li> 6519 * <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li> 6520 * <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li> 6521 * </ul> 6522 * <p> 6523 * Subclasses should override this method, call the super implementation, 6524 * and set additional attributes. 6525 * </p> 6526 * <p> 6527 * If an {@link AccessibilityDelegate} has been specified via calling 6528 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 6529 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)} 6530 * is responsible for handling this call. 6531 * </p> 6532 * 6533 * @param info The instance to initialize. 6534 */ 6535 @CallSuper onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info)6536 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 6537 if (mAccessibilityDelegate != null) { 6538 mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info); 6539 } else { 6540 onInitializeAccessibilityNodeInfoInternal(info); 6541 } 6542 } 6543 6544 /** 6545 * Gets the location of this view in screen coordinates. 6546 * 6547 * @param outRect The output location 6548 * @hide 6549 */ getBoundsOnScreen(Rect outRect)6550 public void getBoundsOnScreen(Rect outRect) { 6551 getBoundsOnScreen(outRect, false); 6552 } 6553 6554 /** 6555 * Gets the location of this view in screen coordinates. 6556 * 6557 * @param outRect The output location 6558 * @param clipToParent Whether to clip child bounds to the parent ones. 6559 * @hide 6560 */ getBoundsOnScreen(Rect outRect, boolean clipToParent)6561 public void getBoundsOnScreen(Rect outRect, boolean clipToParent) { 6562 if (mAttachInfo == null) { 6563 return; 6564 } 6565 6566 RectF position = mAttachInfo.mTmpTransformRect; 6567 position.set(0, 0, mRight - mLeft, mBottom - mTop); 6568 6569 if (!hasIdentityMatrix()) { 6570 getMatrix().mapRect(position); 6571 } 6572 6573 position.offset(mLeft, mTop); 6574 6575 ViewParent parent = mParent; 6576 while (parent instanceof View) { 6577 View parentView = (View) parent; 6578 6579 position.offset(-parentView.mScrollX, -parentView.mScrollY); 6580 6581 if (clipToParent) { 6582 position.left = Math.max(position.left, 0); 6583 position.top = Math.max(position.top, 0); 6584 position.right = Math.min(position.right, parentView.getWidth()); 6585 position.bottom = Math.min(position.bottom, parentView.getHeight()); 6586 } 6587 6588 if (!parentView.hasIdentityMatrix()) { 6589 parentView.getMatrix().mapRect(position); 6590 } 6591 6592 position.offset(parentView.mLeft, parentView.mTop); 6593 6594 parent = parentView.mParent; 6595 } 6596 6597 if (parent instanceof ViewRootImpl) { 6598 ViewRootImpl viewRootImpl = (ViewRootImpl) parent; 6599 position.offset(0, -viewRootImpl.mCurScrollY); 6600 } 6601 6602 position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop); 6603 6604 outRect.set(Math.round(position.left), Math.round(position.top), 6605 Math.round(position.right), Math.round(position.bottom)); 6606 } 6607 6608 /** 6609 * Return the class name of this object to be used for accessibility purposes. 6610 * Subclasses should only override this if they are implementing something that 6611 * should be seen as a completely new class of view when used by accessibility, 6612 * unrelated to the class it is deriving from. This is used to fill in 6613 * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}. 6614 */ getAccessibilityClassName()6615 public CharSequence getAccessibilityClassName() { 6616 return View.class.getName(); 6617 } 6618 6619 /** 6620 * Called when assist structure is being retrieved from a view as part of 6621 * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}. 6622 * @param structure Fill in with structured view data. The default implementation 6623 * fills in all data that can be inferred from the view itself. 6624 */ onProvideStructure(ViewStructure structure)6625 public void onProvideStructure(ViewStructure structure) { 6626 final int id = mID; 6627 if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0 6628 && (id&0x0000ffff) != 0) { 6629 String pkg, type, entry; 6630 try { 6631 final Resources res = getResources(); 6632 entry = res.getResourceEntryName(id); 6633 type = res.getResourceTypeName(id); 6634 pkg = res.getResourcePackageName(id); 6635 } catch (Resources.NotFoundException e) { 6636 entry = type = pkg = null; 6637 } 6638 structure.setId(id, pkg, type, entry); 6639 } else { 6640 structure.setId(id, null, null, null); 6641 } 6642 structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop); 6643 if (!hasIdentityMatrix()) { 6644 structure.setTransformation(getMatrix()); 6645 } 6646 structure.setElevation(getZ()); 6647 structure.setVisibility(getVisibility()); 6648 structure.setEnabled(isEnabled()); 6649 if (isClickable()) { 6650 structure.setClickable(true); 6651 } 6652 if (isFocusable()) { 6653 structure.setFocusable(true); 6654 } 6655 if (isFocused()) { 6656 structure.setFocused(true); 6657 } 6658 if (isAccessibilityFocused()) { 6659 structure.setAccessibilityFocused(true); 6660 } 6661 if (isSelected()) { 6662 structure.setSelected(true); 6663 } 6664 if (isActivated()) { 6665 structure.setActivated(true); 6666 } 6667 if (isLongClickable()) { 6668 structure.setLongClickable(true); 6669 } 6670 if (this instanceof Checkable) { 6671 structure.setCheckable(true); 6672 if (((Checkable)this).isChecked()) { 6673 structure.setChecked(true); 6674 } 6675 } 6676 if (isContextClickable()) { 6677 structure.setContextClickable(true); 6678 } 6679 structure.setClassName(getAccessibilityClassName().toString()); 6680 structure.setContentDescription(getContentDescription()); 6681 } 6682 6683 /** 6684 * Called when assist structure is being retrieved from a view as part of 6685 * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to 6686 * generate additional virtual structure under this view. The defaullt implementation 6687 * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the 6688 * view's virtual accessibility nodes, if any. You can override this for a more 6689 * optimal implementation providing this data. 6690 */ onProvideVirtualStructure(ViewStructure structure)6691 public void onProvideVirtualStructure(ViewStructure structure) { 6692 AccessibilityNodeProvider provider = getAccessibilityNodeProvider(); 6693 if (provider != null) { 6694 AccessibilityNodeInfo info = createAccessibilityNodeInfo(); 6695 structure.setChildCount(1); 6696 ViewStructure root = structure.newChild(0); 6697 populateVirtualStructure(root, provider, info); 6698 info.recycle(); 6699 } 6700 } 6701 populateVirtualStructure(ViewStructure structure, AccessibilityNodeProvider provider, AccessibilityNodeInfo info)6702 private void populateVirtualStructure(ViewStructure structure, 6703 AccessibilityNodeProvider provider, AccessibilityNodeInfo info) { 6704 structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()), 6705 null, null, null); 6706 Rect rect = structure.getTempRect(); 6707 info.getBoundsInParent(rect); 6708 structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height()); 6709 structure.setVisibility(VISIBLE); 6710 structure.setEnabled(info.isEnabled()); 6711 if (info.isClickable()) { 6712 structure.setClickable(true); 6713 } 6714 if (info.isFocusable()) { 6715 structure.setFocusable(true); 6716 } 6717 if (info.isFocused()) { 6718 structure.setFocused(true); 6719 } 6720 if (info.isAccessibilityFocused()) { 6721 structure.setAccessibilityFocused(true); 6722 } 6723 if (info.isSelected()) { 6724 structure.setSelected(true); 6725 } 6726 if (info.isLongClickable()) { 6727 structure.setLongClickable(true); 6728 } 6729 if (info.isCheckable()) { 6730 structure.setCheckable(true); 6731 if (info.isChecked()) { 6732 structure.setChecked(true); 6733 } 6734 } 6735 if (info.isContextClickable()) { 6736 structure.setContextClickable(true); 6737 } 6738 CharSequence cname = info.getClassName(); 6739 structure.setClassName(cname != null ? cname.toString() : null); 6740 structure.setContentDescription(info.getContentDescription()); 6741 if (info.getText() != null || info.getError() != null) { 6742 structure.setText(info.getText(), info.getTextSelectionStart(), 6743 info.getTextSelectionEnd()); 6744 } 6745 final int NCHILDREN = info.getChildCount(); 6746 if (NCHILDREN > 0) { 6747 structure.setChildCount(NCHILDREN); 6748 for (int i=0; i<NCHILDREN; i++) { 6749 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo( 6750 AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i))); 6751 ViewStructure child = structure.newChild(i); 6752 populateVirtualStructure(child, provider, cinfo); 6753 cinfo.recycle(); 6754 } 6755 } 6756 } 6757 6758 /** 6759 * Dispatch creation of {@link ViewStructure} down the hierarchy. The default 6760 * implementation calls {@link #onProvideStructure} and 6761 * {@link #onProvideVirtualStructure}. 6762 */ dispatchProvideStructure(ViewStructure structure)6763 public void dispatchProvideStructure(ViewStructure structure) { 6764 if (!isAssistBlocked()) { 6765 onProvideStructure(structure); 6766 onProvideVirtualStructure(structure); 6767 } else { 6768 structure.setClassName(getAccessibilityClassName().toString()); 6769 structure.setAssistBlocked(true); 6770 } 6771 } 6772 6773 /** 6774 * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 6775 * 6776 * Note: Called from the default {@link AccessibilityDelegate}. 6777 * 6778 * @hide 6779 */ onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info)6780 public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) { 6781 if (mAttachInfo == null) { 6782 return; 6783 } 6784 6785 Rect bounds = mAttachInfo.mTmpInvalRect; 6786 6787 getDrawingRect(bounds); 6788 info.setBoundsInParent(bounds); 6789 6790 getBoundsOnScreen(bounds, true); 6791 info.setBoundsInScreen(bounds); 6792 6793 ViewParent parent = getParentForAccessibility(); 6794 if (parent instanceof View) { 6795 info.setParent((View) parent); 6796 } 6797 6798 if (mID != View.NO_ID) { 6799 View rootView = getRootView(); 6800 if (rootView == null) { 6801 rootView = this; 6802 } 6803 6804 View label = rootView.findLabelForView(this, mID); 6805 if (label != null) { 6806 info.setLabeledBy(label); 6807 } 6808 6809 if ((mAttachInfo.mAccessibilityFetchFlags 6810 & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0 6811 && Resources.resourceHasPackage(mID)) { 6812 try { 6813 String viewId = getResources().getResourceName(mID); 6814 info.setViewIdResourceName(viewId); 6815 } catch (Resources.NotFoundException nfe) { 6816 /* ignore */ 6817 } 6818 } 6819 } 6820 6821 if (mLabelForId != View.NO_ID) { 6822 View rootView = getRootView(); 6823 if (rootView == null) { 6824 rootView = this; 6825 } 6826 View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId); 6827 if (labeled != null) { 6828 info.setLabelFor(labeled); 6829 } 6830 } 6831 6832 if (mAccessibilityTraversalBeforeId != View.NO_ID) { 6833 View rootView = getRootView(); 6834 if (rootView == null) { 6835 rootView = this; 6836 } 6837 View next = rootView.findViewInsideOutShouldExist(this, 6838 mAccessibilityTraversalBeforeId); 6839 if (next != null && next.includeForAccessibility()) { 6840 info.setTraversalBefore(next); 6841 } 6842 } 6843 6844 if (mAccessibilityTraversalAfterId != View.NO_ID) { 6845 View rootView = getRootView(); 6846 if (rootView == null) { 6847 rootView = this; 6848 } 6849 View next = rootView.findViewInsideOutShouldExist(this, 6850 mAccessibilityTraversalAfterId); 6851 if (next != null && next.includeForAccessibility()) { 6852 info.setTraversalAfter(next); 6853 } 6854 } 6855 6856 info.setVisibleToUser(isVisibleToUser()); 6857 6858 if ((mAttachInfo != null) && ((mAttachInfo.mAccessibilityFetchFlags 6859 & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0)) { 6860 info.setImportantForAccessibility(isImportantForAccessibility()); 6861 } else { 6862 info.setImportantForAccessibility(true); 6863 } 6864 6865 info.setPackageName(mContext.getPackageName()); 6866 info.setClassName(getAccessibilityClassName()); 6867 info.setContentDescription(getContentDescription()); 6868 6869 info.setEnabled(isEnabled()); 6870 info.setClickable(isClickable()); 6871 info.setFocusable(isFocusable()); 6872 info.setFocused(isFocused()); 6873 info.setAccessibilityFocused(isAccessibilityFocused()); 6874 info.setSelected(isSelected()); 6875 info.setLongClickable(isLongClickable()); 6876 info.setContextClickable(isContextClickable()); 6877 info.setLiveRegion(getAccessibilityLiveRegion()); 6878 6879 // TODO: These make sense only if we are in an AdapterView but all 6880 // views can be selected. Maybe from accessibility perspective 6881 // we should report as selectable view in an AdapterView. 6882 info.addAction(AccessibilityNodeInfo.ACTION_SELECT); 6883 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION); 6884 6885 if (isFocusable()) { 6886 if (isFocused()) { 6887 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS); 6888 } else { 6889 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS); 6890 } 6891 } 6892 6893 if (!isAccessibilityFocused()) { 6894 info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS); 6895 } else { 6896 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS); 6897 } 6898 6899 if (isClickable() && isEnabled()) { 6900 info.addAction(AccessibilityNodeInfo.ACTION_CLICK); 6901 } 6902 6903 if (isLongClickable() && isEnabled()) { 6904 info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK); 6905 } 6906 6907 if (isContextClickable() && isEnabled()) { 6908 info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK); 6909 } 6910 6911 CharSequence text = getIterableTextForAccessibility(); 6912 if (text != null && text.length() > 0) { 6913 info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd()); 6914 6915 info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION); 6916 info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY); 6917 info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY); 6918 info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER 6919 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD 6920 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH); 6921 } 6922 6923 info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN); 6924 populateAccessibilityNodeInfoDrawingOrderInParent(info); 6925 } 6926 6927 /** 6928 * Determine the order in which this view will be drawn relative to its siblings for a11y 6929 * 6930 * @param info The info whose drawing order should be populated 6931 */ populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info)6932 private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) { 6933 /* 6934 * If the view's bounds haven't been set yet, layout has not completed. In that situation, 6935 * drawing order may not be well-defined, and some Views with custom drawing order may 6936 * not be initialized sufficiently to respond properly getChildDrawingOrder. 6937 */ 6938 if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) { 6939 info.setDrawingOrder(0); 6940 return; 6941 } 6942 int drawingOrderInParent = 1; 6943 // Iterate up the hierarchy if parents are not important for a11y 6944 View viewAtDrawingLevel = this; 6945 final ViewParent parent = getParentForAccessibility(); 6946 while (viewAtDrawingLevel != parent) { 6947 final ViewParent currentParent = viewAtDrawingLevel.getParent(); 6948 if (!(currentParent instanceof ViewGroup)) { 6949 // Should only happen for the Decor 6950 drawingOrderInParent = 0; 6951 break; 6952 } else { 6953 final ViewGroup parentGroup = (ViewGroup) currentParent; 6954 final int childCount = parentGroup.getChildCount(); 6955 if (childCount > 1) { 6956 List<View> preorderedList = parentGroup.buildOrderedChildList(); 6957 if (preorderedList != null) { 6958 final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel); 6959 for (int i = 0; i < childDrawIndex; i++) { 6960 drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i)); 6961 } 6962 } else { 6963 final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel); 6964 final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled(); 6965 final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup 6966 .getChildDrawingOrder(childCount, childIndex) : childIndex; 6967 final int numChildrenToIterate = customOrder ? childCount : childDrawIndex; 6968 if (childDrawIndex != 0) { 6969 for (int i = 0; i < numChildrenToIterate; i++) { 6970 final int otherDrawIndex = (customOrder ? 6971 parentGroup.getChildDrawingOrder(childCount, i) : i); 6972 if (otherDrawIndex < childDrawIndex) { 6973 drawingOrderInParent += 6974 numViewsForAccessibility(parentGroup.getChildAt(i)); 6975 } 6976 } 6977 } 6978 } 6979 } 6980 } 6981 viewAtDrawingLevel = (View) currentParent; 6982 } 6983 info.setDrawingOrder(drawingOrderInParent); 6984 } 6985 numViewsForAccessibility(View view)6986 private static int numViewsForAccessibility(View view) { 6987 if (view != null) { 6988 if (view.includeForAccessibility()) { 6989 return 1; 6990 } else if (view instanceof ViewGroup) { 6991 return ((ViewGroup) view).getNumChildrenForAccessibility(); 6992 } 6993 } 6994 return 0; 6995 } 6996 findLabelForView(View view, int labeledId)6997 private View findLabelForView(View view, int labeledId) { 6998 if (mMatchLabelForPredicate == null) { 6999 mMatchLabelForPredicate = new MatchLabelForPredicate(); 7000 } 7001 mMatchLabelForPredicate.mLabeledId = labeledId; 7002 return findViewByPredicateInsideOut(view, mMatchLabelForPredicate); 7003 } 7004 7005 /** 7006 * Computes whether this view is visible to the user. Such a view is 7007 * attached, visible, all its predecessors are visible, it is not clipped 7008 * entirely by its predecessors, and has an alpha greater than zero. 7009 * 7010 * @return Whether the view is visible on the screen. 7011 * 7012 * @hide 7013 */ isVisibleToUser()7014 protected boolean isVisibleToUser() { 7015 return isVisibleToUser(null); 7016 } 7017 7018 /** 7019 * Computes whether the given portion of this view is visible to the user. 7020 * Such a view is attached, visible, all its predecessors are visible, 7021 * has an alpha greater than zero, and the specified portion is not 7022 * clipped entirely by its predecessors. 7023 * 7024 * @param boundInView the portion of the view to test; coordinates should be relative; may be 7025 * <code>null</code>, and the entire view will be tested in this case. 7026 * When <code>true</code> is returned by the function, the actual visible 7027 * region will be stored in this parameter; that is, if boundInView is fully 7028 * contained within the view, no modification will be made, otherwise regions 7029 * outside of the visible area of the view will be clipped. 7030 * 7031 * @return Whether the specified portion of the view is visible on the screen. 7032 * 7033 * @hide 7034 */ isVisibleToUser(Rect boundInView)7035 protected boolean isVisibleToUser(Rect boundInView) { 7036 if (mAttachInfo != null) { 7037 // Attached to invisible window means this view is not visible. 7038 if (mAttachInfo.mWindowVisibility != View.VISIBLE) { 7039 return false; 7040 } 7041 // An invisible predecessor or one with alpha zero means 7042 // that this view is not visible to the user. 7043 Object current = this; 7044 while (current instanceof View) { 7045 View view = (View) current; 7046 // We have attach info so this view is attached and there is no 7047 // need to check whether we reach to ViewRootImpl on the way up. 7048 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 || 7049 view.getVisibility() != VISIBLE) { 7050 return false; 7051 } 7052 current = view.mParent; 7053 } 7054 // Check if the view is entirely covered by its predecessors. 7055 Rect visibleRect = mAttachInfo.mTmpInvalRect; 7056 Point offset = mAttachInfo.mPoint; 7057 if (!getGlobalVisibleRect(visibleRect, offset)) { 7058 return false; 7059 } 7060 // Check if the visible portion intersects the rectangle of interest. 7061 if (boundInView != null) { 7062 visibleRect.offset(-offset.x, -offset.y); 7063 return boundInView.intersect(visibleRect); 7064 } 7065 return true; 7066 } 7067 return false; 7068 } 7069 7070 /** 7071 * Returns the delegate for implementing accessibility support via 7072 * composition. For more details see {@link AccessibilityDelegate}. 7073 * 7074 * @return The delegate, or null if none set. 7075 * 7076 * @hide 7077 */ getAccessibilityDelegate()7078 public AccessibilityDelegate getAccessibilityDelegate() { 7079 return mAccessibilityDelegate; 7080 } 7081 7082 /** 7083 * Sets a delegate for implementing accessibility support via composition 7084 * (as opposed to inheritance). For more details, see 7085 * {@link AccessibilityDelegate}. 7086 * <p> 7087 * <strong>Note:</strong> On platform versions prior to 7088 * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on 7089 * views in the {@code android.widget.*} package are called <i>before</i> 7090 * host methods. This prevents certain properties such as class name from 7091 * being modified by overriding 7092 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}, 7093 * as any changes will be overwritten by the host class. 7094 * <p> 7095 * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate 7096 * methods are called <i>after</i> host methods, which all properties to be 7097 * modified without being overwritten by the host class. 7098 * 7099 * @param delegate the object to which accessibility method calls should be 7100 * delegated 7101 * @see AccessibilityDelegate 7102 */ setAccessibilityDelegate(@ullable AccessibilityDelegate delegate)7103 public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) { 7104 mAccessibilityDelegate = delegate; 7105 } 7106 7107 /** 7108 * Gets the provider for managing a virtual view hierarchy rooted at this View 7109 * and reported to {@link android.accessibilityservice.AccessibilityService}s 7110 * that explore the window content. 7111 * <p> 7112 * If this method returns an instance, this instance is responsible for managing 7113 * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this 7114 * View including the one representing the View itself. Similarly the returned 7115 * instance is responsible for performing accessibility actions on any virtual 7116 * view or the root view itself. 7117 * </p> 7118 * <p> 7119 * If an {@link AccessibilityDelegate} has been specified via calling 7120 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 7121 * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)} 7122 * is responsible for handling this call. 7123 * </p> 7124 * 7125 * @return The provider. 7126 * 7127 * @see AccessibilityNodeProvider 7128 */ getAccessibilityNodeProvider()7129 public AccessibilityNodeProvider getAccessibilityNodeProvider() { 7130 if (mAccessibilityDelegate != null) { 7131 return mAccessibilityDelegate.getAccessibilityNodeProvider(this); 7132 } else { 7133 return null; 7134 } 7135 } 7136 7137 /** 7138 * Gets the unique identifier of this view on the screen for accessibility purposes. 7139 * If this {@link View} is not attached to any window, {@value #NO_ID} is returned. 7140 * 7141 * @return The view accessibility id. 7142 * 7143 * @hide 7144 */ getAccessibilityViewId()7145 public int getAccessibilityViewId() { 7146 if (mAccessibilityViewId == NO_ID) { 7147 mAccessibilityViewId = sNextAccessibilityViewId++; 7148 } 7149 return mAccessibilityViewId; 7150 } 7151 7152 /** 7153 * Gets the unique identifier of the window in which this View reseides. 7154 * 7155 * @return The window accessibility id. 7156 * 7157 * @hide 7158 */ getAccessibilityWindowId()7159 public int getAccessibilityWindowId() { 7160 return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId 7161 : AccessibilityNodeInfo.UNDEFINED_ITEM_ID; 7162 } 7163 7164 /** 7165 * Returns the {@link View}'s content description. 7166 * <p> 7167 * <strong>Note:</strong> Do not override this method, as it will have no 7168 * effect on the content description presented to accessibility services. 7169 * You must call {@link #setContentDescription(CharSequence)} to modify the 7170 * content description. 7171 * 7172 * @return the content description 7173 * @see #setContentDescription(CharSequence) 7174 * @attr ref android.R.styleable#View_contentDescription 7175 */ 7176 @ViewDebug.ExportedProperty(category = "accessibility") getContentDescription()7177 public CharSequence getContentDescription() { 7178 return mContentDescription; 7179 } 7180 7181 /** 7182 * Sets the {@link View}'s content description. 7183 * <p> 7184 * A content description briefly describes the view and is primarily used 7185 * for accessibility support to determine how a view should be presented to 7186 * the user. In the case of a view with no textual representation, such as 7187 * {@link android.widget.ImageButton}, a useful content description 7188 * explains what the view does. For example, an image button with a phone 7189 * icon that is used to place a call may use "Call" as its content 7190 * description. An image of a floppy disk that is used to save a file may 7191 * use "Save". 7192 * 7193 * @param contentDescription The content description. 7194 * @see #getContentDescription() 7195 * @attr ref android.R.styleable#View_contentDescription 7196 */ 7197 @RemotableViewMethod setContentDescription(CharSequence contentDescription)7198 public void setContentDescription(CharSequence contentDescription) { 7199 if (mContentDescription == null) { 7200 if (contentDescription == null) { 7201 return; 7202 } 7203 } else if (mContentDescription.equals(contentDescription)) { 7204 return; 7205 } 7206 mContentDescription = contentDescription; 7207 final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0; 7208 if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { 7209 setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); 7210 notifySubtreeAccessibilityStateChangedIfNeeded(); 7211 } else { 7212 notifyViewAccessibilityStateChangedIfNeeded( 7213 AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION); 7214 } 7215 } 7216 7217 /** 7218 * Sets the id of a view before which this one is visited in accessibility traversal. 7219 * A screen-reader must visit the content of this view before the content of the one 7220 * it precedes. For example, if view B is set to be before view A, then a screen-reader 7221 * will traverse the entire content of B before traversing the entire content of A, 7222 * regardles of what traversal strategy it is using. 7223 * <p> 7224 * Views that do not have specified before/after relationships are traversed in order 7225 * determined by the screen-reader. 7226 * </p> 7227 * <p> 7228 * Setting that this view is before a view that is not important for accessibility 7229 * or if this view is not important for accessibility will have no effect as the 7230 * screen-reader is not aware of unimportant views. 7231 * </p> 7232 * 7233 * @param beforeId The id of a view this one precedes in accessibility traversal. 7234 * 7235 * @attr ref android.R.styleable#View_accessibilityTraversalBefore 7236 * 7237 * @see #setImportantForAccessibility(int) 7238 */ 7239 @RemotableViewMethod setAccessibilityTraversalBefore(int beforeId)7240 public void setAccessibilityTraversalBefore(int beforeId) { 7241 if (mAccessibilityTraversalBeforeId == beforeId) { 7242 return; 7243 } 7244 mAccessibilityTraversalBeforeId = beforeId; 7245 notifyViewAccessibilityStateChangedIfNeeded( 7246 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 7247 } 7248 7249 /** 7250 * Gets the id of a view before which this one is visited in accessibility traversal. 7251 * 7252 * @return The id of a view this one precedes in accessibility traversal if 7253 * specified, otherwise {@link #NO_ID}. 7254 * 7255 * @see #setAccessibilityTraversalBefore(int) 7256 */ getAccessibilityTraversalBefore()7257 public int getAccessibilityTraversalBefore() { 7258 return mAccessibilityTraversalBeforeId; 7259 } 7260 7261 /** 7262 * Sets the id of a view after which this one is visited in accessibility traversal. 7263 * A screen-reader must visit the content of the other view before the content of this 7264 * one. For example, if view B is set to be after view A, then a screen-reader 7265 * will traverse the entire content of A before traversing the entire content of B, 7266 * regardles of what traversal strategy it is using. 7267 * <p> 7268 * Views that do not have specified before/after relationships are traversed in order 7269 * determined by the screen-reader. 7270 * </p> 7271 * <p> 7272 * Setting that this view is after a view that is not important for accessibility 7273 * or if this view is not important for accessibility will have no effect as the 7274 * screen-reader is not aware of unimportant views. 7275 * </p> 7276 * 7277 * @param afterId The id of a view this one succedees in accessibility traversal. 7278 * 7279 * @attr ref android.R.styleable#View_accessibilityTraversalAfter 7280 * 7281 * @see #setImportantForAccessibility(int) 7282 */ 7283 @RemotableViewMethod setAccessibilityTraversalAfter(int afterId)7284 public void setAccessibilityTraversalAfter(int afterId) { 7285 if (mAccessibilityTraversalAfterId == afterId) { 7286 return; 7287 } 7288 mAccessibilityTraversalAfterId = afterId; 7289 notifyViewAccessibilityStateChangedIfNeeded( 7290 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 7291 } 7292 7293 /** 7294 * Gets the id of a view after which this one is visited in accessibility traversal. 7295 * 7296 * @return The id of a view this one succeedes in accessibility traversal if 7297 * specified, otherwise {@link #NO_ID}. 7298 * 7299 * @see #setAccessibilityTraversalAfter(int) 7300 */ getAccessibilityTraversalAfter()7301 public int getAccessibilityTraversalAfter() { 7302 return mAccessibilityTraversalAfterId; 7303 } 7304 7305 /** 7306 * Gets the id of a view for which this view serves as a label for 7307 * accessibility purposes. 7308 * 7309 * @return The labeled view id. 7310 */ 7311 @ViewDebug.ExportedProperty(category = "accessibility") getLabelFor()7312 public int getLabelFor() { 7313 return mLabelForId; 7314 } 7315 7316 /** 7317 * Sets the id of a view for which this view serves as a label for 7318 * accessibility purposes. 7319 * 7320 * @param id The labeled view id. 7321 */ 7322 @RemotableViewMethod setLabelFor(@dRes int id)7323 public void setLabelFor(@IdRes int id) { 7324 if (mLabelForId == id) { 7325 return; 7326 } 7327 mLabelForId = id; 7328 if (mLabelForId != View.NO_ID 7329 && mID == View.NO_ID) { 7330 mID = generateViewId(); 7331 } 7332 notifyViewAccessibilityStateChangedIfNeeded( 7333 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 7334 } 7335 7336 /** 7337 * Invoked whenever this view loses focus, either by losing window focus or by losing 7338 * focus within its window. This method can be used to clear any state tied to the 7339 * focus. For instance, if a button is held pressed with the trackball and the window 7340 * loses focus, this method can be used to cancel the press. 7341 * 7342 * Subclasses of View overriding this method should always call super.onFocusLost(). 7343 * 7344 * @see #onFocusChanged(boolean, int, android.graphics.Rect) 7345 * @see #onWindowFocusChanged(boolean) 7346 * 7347 * @hide pending API council approval 7348 */ 7349 @CallSuper onFocusLost()7350 protected void onFocusLost() { 7351 resetPressedState(); 7352 } 7353 resetPressedState()7354 private void resetPressedState() { 7355 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 7356 return; 7357 } 7358 7359 if (isPressed()) { 7360 setPressed(false); 7361 7362 if (!mHasPerformedLongPress) { 7363 removeLongPressCallback(); 7364 } 7365 } 7366 } 7367 7368 /** 7369 * Returns true if this view has focus 7370 * 7371 * @return True if this view has focus, false otherwise. 7372 */ 7373 @ViewDebug.ExportedProperty(category = "focus") isFocused()7374 public boolean isFocused() { 7375 return (mPrivateFlags & PFLAG_FOCUSED) != 0; 7376 } 7377 7378 /** 7379 * Find the view in the hierarchy rooted at this view that currently has 7380 * focus. 7381 * 7382 * @return The view that currently has focus, or null if no focused view can 7383 * be found. 7384 */ findFocus()7385 public View findFocus() { 7386 return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null; 7387 } 7388 7389 /** 7390 * Indicates whether this view is one of the set of scrollable containers in 7391 * its window. 7392 * 7393 * @return whether this view is one of the set of scrollable containers in 7394 * its window 7395 * 7396 * @attr ref android.R.styleable#View_isScrollContainer 7397 */ isScrollContainer()7398 public boolean isScrollContainer() { 7399 return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0; 7400 } 7401 7402 /** 7403 * Change whether this view is one of the set of scrollable containers in 7404 * its window. This will be used to determine whether the window can 7405 * resize or must pan when a soft input area is open -- scrollable 7406 * containers allow the window to use resize mode since the container 7407 * will appropriately shrink. 7408 * 7409 * @attr ref android.R.styleable#View_isScrollContainer 7410 */ setScrollContainer(boolean isScrollContainer)7411 public void setScrollContainer(boolean isScrollContainer) { 7412 if (isScrollContainer) { 7413 if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) { 7414 mAttachInfo.mScrollContainers.add(this); 7415 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED; 7416 } 7417 mPrivateFlags |= PFLAG_SCROLL_CONTAINER; 7418 } else { 7419 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) { 7420 mAttachInfo.mScrollContainers.remove(this); 7421 } 7422 mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED); 7423 } 7424 } 7425 7426 /** 7427 * Returns the quality of the drawing cache. 7428 * 7429 * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO}, 7430 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH} 7431 * 7432 * @see #setDrawingCacheQuality(int) 7433 * @see #setDrawingCacheEnabled(boolean) 7434 * @see #isDrawingCacheEnabled() 7435 * 7436 * @attr ref android.R.styleable#View_drawingCacheQuality 7437 */ 7438 @DrawingCacheQuality getDrawingCacheQuality()7439 public int getDrawingCacheQuality() { 7440 return mViewFlags & DRAWING_CACHE_QUALITY_MASK; 7441 } 7442 7443 /** 7444 * Set the drawing cache quality of this view. This value is used only when the 7445 * drawing cache is enabled 7446 * 7447 * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO}, 7448 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH} 7449 * 7450 * @see #getDrawingCacheQuality() 7451 * @see #setDrawingCacheEnabled(boolean) 7452 * @see #isDrawingCacheEnabled() 7453 * 7454 * @attr ref android.R.styleable#View_drawingCacheQuality 7455 */ setDrawingCacheQuality(@rawingCacheQuality int quality)7456 public void setDrawingCacheQuality(@DrawingCacheQuality int quality) { 7457 setFlags(quality, DRAWING_CACHE_QUALITY_MASK); 7458 } 7459 7460 /** 7461 * Returns whether the screen should remain on, corresponding to the current 7462 * value of {@link #KEEP_SCREEN_ON}. 7463 * 7464 * @return Returns true if {@link #KEEP_SCREEN_ON} is set. 7465 * 7466 * @see #setKeepScreenOn(boolean) 7467 * 7468 * @attr ref android.R.styleable#View_keepScreenOn 7469 */ getKeepScreenOn()7470 public boolean getKeepScreenOn() { 7471 return (mViewFlags & KEEP_SCREEN_ON) != 0; 7472 } 7473 7474 /** 7475 * Controls whether the screen should remain on, modifying the 7476 * value of {@link #KEEP_SCREEN_ON}. 7477 * 7478 * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}. 7479 * 7480 * @see #getKeepScreenOn() 7481 * 7482 * @attr ref android.R.styleable#View_keepScreenOn 7483 */ setKeepScreenOn(boolean keepScreenOn)7484 public void setKeepScreenOn(boolean keepScreenOn) { 7485 setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON); 7486 } 7487 7488 /** 7489 * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}. 7490 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 7491 * 7492 * @attr ref android.R.styleable#View_nextFocusLeft 7493 */ getNextFocusLeftId()7494 public int getNextFocusLeftId() { 7495 return mNextFocusLeftId; 7496 } 7497 7498 /** 7499 * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}. 7500 * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should 7501 * decide automatically. 7502 * 7503 * @attr ref android.R.styleable#View_nextFocusLeft 7504 */ setNextFocusLeftId(int nextFocusLeftId)7505 public void setNextFocusLeftId(int nextFocusLeftId) { 7506 mNextFocusLeftId = nextFocusLeftId; 7507 } 7508 7509 /** 7510 * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}. 7511 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 7512 * 7513 * @attr ref android.R.styleable#View_nextFocusRight 7514 */ getNextFocusRightId()7515 public int getNextFocusRightId() { 7516 return mNextFocusRightId; 7517 } 7518 7519 /** 7520 * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}. 7521 * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should 7522 * decide automatically. 7523 * 7524 * @attr ref android.R.styleable#View_nextFocusRight 7525 */ setNextFocusRightId(int nextFocusRightId)7526 public void setNextFocusRightId(int nextFocusRightId) { 7527 mNextFocusRightId = nextFocusRightId; 7528 } 7529 7530 /** 7531 * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}. 7532 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 7533 * 7534 * @attr ref android.R.styleable#View_nextFocusUp 7535 */ getNextFocusUpId()7536 public int getNextFocusUpId() { 7537 return mNextFocusUpId; 7538 } 7539 7540 /** 7541 * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}. 7542 * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should 7543 * decide automatically. 7544 * 7545 * @attr ref android.R.styleable#View_nextFocusUp 7546 */ setNextFocusUpId(int nextFocusUpId)7547 public void setNextFocusUpId(int nextFocusUpId) { 7548 mNextFocusUpId = nextFocusUpId; 7549 } 7550 7551 /** 7552 * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}. 7553 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 7554 * 7555 * @attr ref android.R.styleable#View_nextFocusDown 7556 */ getNextFocusDownId()7557 public int getNextFocusDownId() { 7558 return mNextFocusDownId; 7559 } 7560 7561 /** 7562 * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}. 7563 * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should 7564 * decide automatically. 7565 * 7566 * @attr ref android.R.styleable#View_nextFocusDown 7567 */ setNextFocusDownId(int nextFocusDownId)7568 public void setNextFocusDownId(int nextFocusDownId) { 7569 mNextFocusDownId = nextFocusDownId; 7570 } 7571 7572 /** 7573 * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}. 7574 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 7575 * 7576 * @attr ref android.R.styleable#View_nextFocusForward 7577 */ getNextFocusForwardId()7578 public int getNextFocusForwardId() { 7579 return mNextFocusForwardId; 7580 } 7581 7582 /** 7583 * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}. 7584 * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should 7585 * decide automatically. 7586 * 7587 * @attr ref android.R.styleable#View_nextFocusForward 7588 */ setNextFocusForwardId(int nextFocusForwardId)7589 public void setNextFocusForwardId(int nextFocusForwardId) { 7590 mNextFocusForwardId = nextFocusForwardId; 7591 } 7592 7593 /** 7594 * Returns the visibility of this view and all of its ancestors 7595 * 7596 * @return True if this view and all of its ancestors are {@link #VISIBLE} 7597 */ isShown()7598 public boolean isShown() { 7599 View current = this; 7600 //noinspection ConstantConditions 7601 do { 7602 if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) { 7603 return false; 7604 } 7605 ViewParent parent = current.mParent; 7606 if (parent == null) { 7607 return false; // We are not attached to the view root 7608 } 7609 if (!(parent instanceof View)) { 7610 return true; 7611 } 7612 current = (View) parent; 7613 } while (current != null); 7614 7615 return false; 7616 } 7617 7618 /** 7619 * Called by the view hierarchy when the content insets for a window have 7620 * changed, to allow it to adjust its content to fit within those windows. 7621 * The content insets tell you the space that the status bar, input method, 7622 * and other system windows infringe on the application's window. 7623 * 7624 * <p>You do not normally need to deal with this function, since the default 7625 * window decoration given to applications takes care of applying it to the 7626 * content of the window. If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} 7627 * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case, 7628 * and your content can be placed under those system elements. You can then 7629 * use this method within your view hierarchy if you have parts of your UI 7630 * which you would like to ensure are not being covered. 7631 * 7632 * <p>The default implementation of this method simply applies the content 7633 * insets to the view's padding, consuming that content (modifying the 7634 * insets to be 0), and returning true. This behavior is off by default, but can 7635 * be enabled through {@link #setFitsSystemWindows(boolean)}. 7636 * 7637 * <p>This function's traversal down the hierarchy is depth-first. The same content 7638 * insets object is propagated down the hierarchy, so any changes made to it will 7639 * be seen by all following views (including potentially ones above in 7640 * the hierarchy since this is a depth-first traversal). The first view 7641 * that returns true will abort the entire traversal. 7642 * 7643 * <p>The default implementation works well for a situation where it is 7644 * used with a container that covers the entire window, allowing it to 7645 * apply the appropriate insets to its content on all edges. If you need 7646 * a more complicated layout (such as two different views fitting system 7647 * windows, one on the top of the window, and one on the bottom), 7648 * you can override the method and handle the insets however you would like. 7649 * Note that the insets provided by the framework are always relative to the 7650 * far edges of the window, not accounting for the location of the called view 7651 * within that window. (In fact when this method is called you do not yet know 7652 * where the layout will place the view, as it is done before layout happens.) 7653 * 7654 * <p>Note: unlike many View methods, there is no dispatch phase to this 7655 * call. If you are overriding it in a ViewGroup and want to allow the 7656 * call to continue to your children, you must be sure to call the super 7657 * implementation. 7658 * 7659 * <p>Here is a sample layout that makes use of fitting system windows 7660 * to have controls for a video view placed inside of the window decorations 7661 * that it hides and shows. This can be used with code like the second 7662 * sample (video player) shown in {@link #setSystemUiVisibility(int)}. 7663 * 7664 * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete} 7665 * 7666 * @param insets Current content insets of the window. Prior to 7667 * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify 7668 * the insets or else you and Android will be unhappy. 7669 * 7670 * @return {@code true} if this view applied the insets and it should not 7671 * continue propagating further down the hierarchy, {@code false} otherwise. 7672 * @see #getFitsSystemWindows() 7673 * @see #setFitsSystemWindows(boolean) 7674 * @see #setSystemUiVisibility(int) 7675 * 7676 * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply 7677 * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use 7678 * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)} 7679 * to implement handling their own insets. 7680 */ fitSystemWindows(Rect insets)7681 protected boolean fitSystemWindows(Rect insets) { 7682 if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) { 7683 if (insets == null) { 7684 // Null insets by definition have already been consumed. 7685 // This call cannot apply insets since there are none to apply, 7686 // so return false. 7687 return false; 7688 } 7689 // If we're not in the process of dispatching the newer apply insets call, 7690 // that means we're not in the compatibility path. Dispatch into the newer 7691 // apply insets path and take things from there. 7692 try { 7693 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS; 7694 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed(); 7695 } finally { 7696 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS; 7697 } 7698 } else { 7699 // We're being called from the newer apply insets path. 7700 // Perform the standard fallback behavior. 7701 return fitSystemWindowsInt(insets); 7702 } 7703 } 7704 fitSystemWindowsInt(Rect insets)7705 private boolean fitSystemWindowsInt(Rect insets) { 7706 if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) { 7707 mUserPaddingStart = UNDEFINED_PADDING; 7708 mUserPaddingEnd = UNDEFINED_PADDING; 7709 Rect localInsets = sThreadLocal.get(); 7710 if (localInsets == null) { 7711 localInsets = new Rect(); 7712 sThreadLocal.set(localInsets); 7713 } 7714 boolean res = computeFitSystemWindows(insets, localInsets); 7715 mUserPaddingLeftInitial = localInsets.left; 7716 mUserPaddingRightInitial = localInsets.right; 7717 internalSetPadding(localInsets.left, localInsets.top, 7718 localInsets.right, localInsets.bottom); 7719 return res; 7720 } 7721 return false; 7722 } 7723 7724 /** 7725 * Called when the view should apply {@link WindowInsets} according to its internal policy. 7726 * 7727 * <p>This method should be overridden by views that wish to apply a policy different from or 7728 * in addition to the default behavior. Clients that wish to force a view subtree 7729 * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p> 7730 * 7731 * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set 7732 * it will be called during dispatch instead of this method. The listener may optionally 7733 * call this method from its own implementation if it wishes to apply the view's default 7734 * insets policy in addition to its own.</p> 7735 * 7736 * <p>Implementations of this method should either return the insets parameter unchanged 7737 * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed 7738 * that this view applied itself. This allows new inset types added in future platform 7739 * versions to pass through existing implementations unchanged without being erroneously 7740 * consumed.</p> 7741 * 7742 * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows} 7743 * property is set then the view will consume the system window insets and apply them 7744 * as padding for the view.</p> 7745 * 7746 * @param insets Insets to apply 7747 * @return The supplied insets with any applied insets consumed 7748 */ onApplyWindowInsets(WindowInsets insets)7749 public WindowInsets onApplyWindowInsets(WindowInsets insets) { 7750 if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) { 7751 // We weren't called from within a direct call to fitSystemWindows, 7752 // call into it as a fallback in case we're in a class that overrides it 7753 // and has logic to perform. 7754 if (fitSystemWindows(insets.getSystemWindowInsets())) { 7755 return insets.consumeSystemWindowInsets(); 7756 } 7757 } else { 7758 // We were called from within a direct call to fitSystemWindows. 7759 if (fitSystemWindowsInt(insets.getSystemWindowInsets())) { 7760 return insets.consumeSystemWindowInsets(); 7761 } 7762 } 7763 return insets; 7764 } 7765 7766 /** 7767 * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying 7768 * window insets to this view. The listener's 7769 * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets} 7770 * method will be called instead of the view's 7771 * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. 7772 * 7773 * @param listener Listener to set 7774 * 7775 * @see #onApplyWindowInsets(WindowInsets) 7776 */ setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener)7777 public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) { 7778 getListenerInfo().mOnApplyWindowInsetsListener = listener; 7779 } 7780 7781 /** 7782 * Request to apply the given window insets to this view or another view in its subtree. 7783 * 7784 * <p>This method should be called by clients wishing to apply insets corresponding to areas 7785 * obscured by window decorations or overlays. This can include the status and navigation bars, 7786 * action bars, input methods and more. New inset categories may be added in the future. 7787 * The method returns the insets provided minus any that were applied by this view or its 7788 * children.</p> 7789 * 7790 * <p>Clients wishing to provide custom behavior should override the 7791 * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a 7792 * {@link OnApplyWindowInsetsListener} via the 7793 * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener} 7794 * method.</p> 7795 * 7796 * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method. 7797 * </p> 7798 * 7799 * @param insets Insets to apply 7800 * @return The provided insets minus the insets that were consumed 7801 */ dispatchApplyWindowInsets(WindowInsets insets)7802 public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) { 7803 try { 7804 mPrivateFlags3 |= PFLAG3_APPLYING_INSETS; 7805 if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) { 7806 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets); 7807 } else { 7808 return onApplyWindowInsets(insets); 7809 } 7810 } finally { 7811 mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS; 7812 } 7813 } 7814 7815 /** 7816 * Compute the view's coordinate within the surface. 7817 * 7818 * <p>Computes the coordinates of this view in its surface. The argument 7819 * must be an array of two integers. After the method returns, the array 7820 * contains the x and y location in that order.</p> 7821 * @hide 7822 * @param location an array of two integers in which to hold the coordinates 7823 */ getLocationInSurface(@ize2) int[] location)7824 public void getLocationInSurface(@Size(2) int[] location) { 7825 getLocationInWindow(location); 7826 if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) { 7827 location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left; 7828 location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top; 7829 } 7830 } 7831 7832 /** 7833 * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are 7834 * only available if the view is attached. 7835 * 7836 * @return WindowInsets from the top of the view hierarchy or null if View is detached 7837 */ getRootWindowInsets()7838 public WindowInsets getRootWindowInsets() { 7839 if (mAttachInfo != null) { 7840 return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */); 7841 } 7842 return null; 7843 } 7844 7845 /** 7846 * @hide Compute the insets that should be consumed by this view and the ones 7847 * that should propagate to those under it. 7848 */ computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets)7849 protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) { 7850 if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0 7851 || mAttachInfo == null 7852 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0 7853 && !mAttachInfo.mOverscanRequested)) { 7854 outLocalInsets.set(inoutInsets); 7855 inoutInsets.set(0, 0, 0, 0); 7856 return true; 7857 } else { 7858 // The application wants to take care of fitting system window for 7859 // the content... however we still need to take care of any overscan here. 7860 final Rect overscan = mAttachInfo.mOverscanInsets; 7861 outLocalInsets.set(overscan); 7862 inoutInsets.left -= overscan.left; 7863 inoutInsets.top -= overscan.top; 7864 inoutInsets.right -= overscan.right; 7865 inoutInsets.bottom -= overscan.bottom; 7866 return false; 7867 } 7868 } 7869 7870 /** 7871 * Compute insets that should be consumed by this view and the ones that should propagate 7872 * to those under it. 7873 * 7874 * @param in Insets currently being processed by this View, likely received as a parameter 7875 * to {@link #onApplyWindowInsets(WindowInsets)}. 7876 * @param outLocalInsets A Rect that will receive the insets that should be consumed 7877 * by this view 7878 * @return Insets that should be passed along to views under this one 7879 */ computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets)7880 public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) { 7881 if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0 7882 || mAttachInfo == null 7883 || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) { 7884 outLocalInsets.set(in.getSystemWindowInsets()); 7885 return in.consumeSystemWindowInsets(); 7886 } else { 7887 outLocalInsets.set(0, 0, 0, 0); 7888 return in; 7889 } 7890 } 7891 7892 /** 7893 * Sets whether or not this view should account for system screen decorations 7894 * such as the status bar and inset its content; that is, controlling whether 7895 * the default implementation of {@link #fitSystemWindows(Rect)} will be 7896 * executed. See that method for more details. 7897 * 7898 * <p>Note that if you are providing your own implementation of 7899 * {@link #fitSystemWindows(Rect)}, then there is no need to set this 7900 * flag to true -- your implementation will be overriding the default 7901 * implementation that checks this flag. 7902 * 7903 * @param fitSystemWindows If true, then the default implementation of 7904 * {@link #fitSystemWindows(Rect)} will be executed. 7905 * 7906 * @attr ref android.R.styleable#View_fitsSystemWindows 7907 * @see #getFitsSystemWindows() 7908 * @see #fitSystemWindows(Rect) 7909 * @see #setSystemUiVisibility(int) 7910 */ setFitsSystemWindows(boolean fitSystemWindows)7911 public void setFitsSystemWindows(boolean fitSystemWindows) { 7912 setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS); 7913 } 7914 7915 /** 7916 * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method 7917 * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)} 7918 * will be executed. 7919 * 7920 * @return {@code true} if the default implementation of 7921 * {@link #fitSystemWindows(Rect)} will be executed. 7922 * 7923 * @attr ref android.R.styleable#View_fitsSystemWindows 7924 * @see #setFitsSystemWindows(boolean) 7925 * @see #fitSystemWindows(Rect) 7926 * @see #setSystemUiVisibility(int) 7927 */ 7928 @ViewDebug.ExportedProperty getFitsSystemWindows()7929 public boolean getFitsSystemWindows() { 7930 return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS; 7931 } 7932 7933 /** @hide */ fitsSystemWindows()7934 public boolean fitsSystemWindows() { 7935 return getFitsSystemWindows(); 7936 } 7937 7938 /** 7939 * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed. 7940 * @deprecated Use {@link #requestApplyInsets()} for newer platform versions. 7941 */ requestFitSystemWindows()7942 public void requestFitSystemWindows() { 7943 if (mParent != null) { 7944 mParent.requestFitSystemWindows(); 7945 } 7946 } 7947 7948 /** 7949 * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed. 7950 */ requestApplyInsets()7951 public void requestApplyInsets() { 7952 requestFitSystemWindows(); 7953 } 7954 7955 /** 7956 * For use by PhoneWindow to make its own system window fitting optional. 7957 * @hide 7958 */ makeOptionalFitsSystemWindows()7959 public void makeOptionalFitsSystemWindows() { 7960 setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS); 7961 } 7962 7963 /** 7964 * Returns the outsets, which areas of the device that aren't a surface, but we would like to 7965 * treat them as such. 7966 * @hide 7967 */ getOutsets(Rect outOutsetRect)7968 public void getOutsets(Rect outOutsetRect) { 7969 if (mAttachInfo != null) { 7970 outOutsetRect.set(mAttachInfo.mOutsets); 7971 } else { 7972 outOutsetRect.setEmpty(); 7973 } 7974 } 7975 7976 /** 7977 * Returns the visibility status for this view. 7978 * 7979 * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. 7980 * @attr ref android.R.styleable#View_visibility 7981 */ 7982 @ViewDebug.ExportedProperty(mapping = { 7983 @ViewDebug.IntToString(from = VISIBLE, to = "VISIBLE"), 7984 @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"), 7985 @ViewDebug.IntToString(from = GONE, to = "GONE") 7986 }) 7987 @Visibility getVisibility()7988 public int getVisibility() { 7989 return mViewFlags & VISIBILITY_MASK; 7990 } 7991 7992 /** 7993 * Set the enabled state of this view. 7994 * 7995 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. 7996 * @attr ref android.R.styleable#View_visibility 7997 */ 7998 @RemotableViewMethod setVisibility(@isibility int visibility)7999 public void setVisibility(@Visibility int visibility) { 8000 setFlags(visibility, VISIBILITY_MASK); 8001 } 8002 8003 /** 8004 * Returns the enabled status for this view. The interpretation of the 8005 * enabled state varies by subclass. 8006 * 8007 * @return True if this view is enabled, false otherwise. 8008 */ 8009 @ViewDebug.ExportedProperty isEnabled()8010 public boolean isEnabled() { 8011 return (mViewFlags & ENABLED_MASK) == ENABLED; 8012 } 8013 8014 /** 8015 * Set the enabled state of this view. The interpretation of the enabled 8016 * state varies by subclass. 8017 * 8018 * @param enabled True if this view is enabled, false otherwise. 8019 */ 8020 @RemotableViewMethod setEnabled(boolean enabled)8021 public void setEnabled(boolean enabled) { 8022 if (enabled == isEnabled()) return; 8023 8024 setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK); 8025 8026 /* 8027 * The View most likely has to change its appearance, so refresh 8028 * the drawable state. 8029 */ 8030 refreshDrawableState(); 8031 8032 // Invalidate too, since the default behavior for views is to be 8033 // be drawn at 50% alpha rather than to change the drawable. 8034 invalidate(true); 8035 8036 if (!enabled) { 8037 cancelPendingInputEvents(); 8038 } 8039 } 8040 8041 /** 8042 * Set whether this view can receive the focus. 8043 * 8044 * Setting this to false will also ensure that this view is not focusable 8045 * in touch mode. 8046 * 8047 * @param focusable If true, this view can receive the focus. 8048 * 8049 * @see #setFocusableInTouchMode(boolean) 8050 * @attr ref android.R.styleable#View_focusable 8051 */ setFocusable(boolean focusable)8052 public void setFocusable(boolean focusable) { 8053 if (!focusable) { 8054 setFlags(0, FOCUSABLE_IN_TOUCH_MODE); 8055 } 8056 setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK); 8057 } 8058 8059 /** 8060 * Set whether this view can receive focus while in touch mode. 8061 * 8062 * Setting this to true will also ensure that this view is focusable. 8063 * 8064 * @param focusableInTouchMode If true, this view can receive the focus while 8065 * in touch mode. 8066 * 8067 * @see #setFocusable(boolean) 8068 * @attr ref android.R.styleable#View_focusableInTouchMode 8069 */ setFocusableInTouchMode(boolean focusableInTouchMode)8070 public void setFocusableInTouchMode(boolean focusableInTouchMode) { 8071 // Focusable in touch mode should always be set before the focusable flag 8072 // otherwise, setting the focusable flag will trigger a focusableViewAvailable() 8073 // which, in touch mode, will not successfully request focus on this view 8074 // because the focusable in touch mode flag is not set 8075 setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE); 8076 if (focusableInTouchMode) { 8077 setFlags(FOCUSABLE, FOCUSABLE_MASK); 8078 } 8079 } 8080 8081 /** 8082 * Set whether this view should have sound effects enabled for events such as 8083 * clicking and touching. 8084 * 8085 * <p>You may wish to disable sound effects for a view if you already play sounds, 8086 * for instance, a dial key that plays dtmf tones. 8087 * 8088 * @param soundEffectsEnabled whether sound effects are enabled for this view. 8089 * @see #isSoundEffectsEnabled() 8090 * @see #playSoundEffect(int) 8091 * @attr ref android.R.styleable#View_soundEffectsEnabled 8092 */ setSoundEffectsEnabled(boolean soundEffectsEnabled)8093 public void setSoundEffectsEnabled(boolean soundEffectsEnabled) { 8094 setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED); 8095 } 8096 8097 /** 8098 * @return whether this view should have sound effects enabled for events such as 8099 * clicking and touching. 8100 * 8101 * @see #setSoundEffectsEnabled(boolean) 8102 * @see #playSoundEffect(int) 8103 * @attr ref android.R.styleable#View_soundEffectsEnabled 8104 */ 8105 @ViewDebug.ExportedProperty isSoundEffectsEnabled()8106 public boolean isSoundEffectsEnabled() { 8107 return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED); 8108 } 8109 8110 /** 8111 * Set whether this view should have haptic feedback for events such as 8112 * long presses. 8113 * 8114 * <p>You may wish to disable haptic feedback if your view already controls 8115 * its own haptic feedback. 8116 * 8117 * @param hapticFeedbackEnabled whether haptic feedback enabled for this view. 8118 * @see #isHapticFeedbackEnabled() 8119 * @see #performHapticFeedback(int) 8120 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 8121 */ setHapticFeedbackEnabled(boolean hapticFeedbackEnabled)8122 public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) { 8123 setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED); 8124 } 8125 8126 /** 8127 * @return whether this view should have haptic feedback enabled for events 8128 * long presses. 8129 * 8130 * @see #setHapticFeedbackEnabled(boolean) 8131 * @see #performHapticFeedback(int) 8132 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 8133 */ 8134 @ViewDebug.ExportedProperty isHapticFeedbackEnabled()8135 public boolean isHapticFeedbackEnabled() { 8136 return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED); 8137 } 8138 8139 /** 8140 * Returns the layout direction for this view. 8141 * 8142 * @return One of {@link #LAYOUT_DIRECTION_LTR}, 8143 * {@link #LAYOUT_DIRECTION_RTL}, 8144 * {@link #LAYOUT_DIRECTION_INHERIT} or 8145 * {@link #LAYOUT_DIRECTION_LOCALE}. 8146 * 8147 * @attr ref android.R.styleable#View_layoutDirection 8148 * 8149 * @hide 8150 */ 8151 @ViewDebug.ExportedProperty(category = "layout", mapping = { 8152 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "LTR"), 8153 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RTL"), 8154 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"), 8155 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE, to = "LOCALE") 8156 }) 8157 @LayoutDir getRawLayoutDirection()8158 public int getRawLayoutDirection() { 8159 return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 8160 } 8161 8162 /** 8163 * Set the layout direction for this view. This will propagate a reset of layout direction 8164 * resolution to the view's children and resolve layout direction for this view. 8165 * 8166 * @param layoutDirection the layout direction to set. Should be one of: 8167 * 8168 * {@link #LAYOUT_DIRECTION_LTR}, 8169 * {@link #LAYOUT_DIRECTION_RTL}, 8170 * {@link #LAYOUT_DIRECTION_INHERIT}, 8171 * {@link #LAYOUT_DIRECTION_LOCALE}. 8172 * 8173 * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution 8174 * proceeds up the parent chain of the view to get the value. If there is no parent, then it 8175 * will return the default {@link #LAYOUT_DIRECTION_LTR}. 8176 * 8177 * @attr ref android.R.styleable#View_layoutDirection 8178 */ 8179 @RemotableViewMethod setLayoutDirection(@ayoutDir int layoutDirection)8180 public void setLayoutDirection(@LayoutDir int layoutDirection) { 8181 if (getRawLayoutDirection() != layoutDirection) { 8182 // Reset the current layout direction and the resolved one 8183 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK; 8184 resetRtlProperties(); 8185 // Set the new layout direction (filtered) 8186 mPrivateFlags2 |= 8187 ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK); 8188 // We need to resolve all RTL properties as they all depend on layout direction 8189 resolveRtlPropertiesIfNeeded(); 8190 requestLayout(); 8191 invalidate(true); 8192 } 8193 } 8194 8195 /** 8196 * Returns the resolved layout direction for this view. 8197 * 8198 * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns 8199 * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL. 8200 * 8201 * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version 8202 * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}. 8203 * 8204 * @attr ref android.R.styleable#View_layoutDirection 8205 */ 8206 @ViewDebug.ExportedProperty(category = "layout", mapping = { 8207 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"), 8208 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL") 8209 }) 8210 @ResolvedLayoutDir getLayoutDirection()8211 public int getLayoutDirection() { 8212 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion; 8213 if (targetSdkVersion < JELLY_BEAN_MR1) { 8214 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED; 8215 return LAYOUT_DIRECTION_RESOLVED_DEFAULT; 8216 } 8217 return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) == 8218 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR; 8219 } 8220 8221 /** 8222 * Indicates whether or not this view's layout is right-to-left. This is resolved from 8223 * layout attribute and/or the inherited value from the parent 8224 * 8225 * @return true if the layout is right-to-left. 8226 * 8227 * @hide 8228 */ 8229 @ViewDebug.ExportedProperty(category = "layout") isLayoutRtl()8230 public boolean isLayoutRtl() { 8231 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL); 8232 } 8233 8234 /** 8235 * Indicates whether the view is currently tracking transient state that the 8236 * app should not need to concern itself with saving and restoring, but that 8237 * the framework should take special note to preserve when possible. 8238 * 8239 * <p>A view with transient state cannot be trivially rebound from an external 8240 * data source, such as an adapter binding item views in a list. This may be 8241 * because the view is performing an animation, tracking user selection 8242 * of content, or similar.</p> 8243 * 8244 * @return true if the view has transient state 8245 */ 8246 @ViewDebug.ExportedProperty(category = "layout") hasTransientState()8247 public boolean hasTransientState() { 8248 return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE; 8249 } 8250 8251 /** 8252 * Set whether this view is currently tracking transient state that the 8253 * framework should attempt to preserve when possible. This flag is reference counted, 8254 * so every call to setHasTransientState(true) should be paired with a later call 8255 * to setHasTransientState(false). 8256 * 8257 * <p>A view with transient state cannot be trivially rebound from an external 8258 * data source, such as an adapter binding item views in a list. This may be 8259 * because the view is performing an animation, tracking user selection 8260 * of content, or similar.</p> 8261 * 8262 * @param hasTransientState true if this view has transient state 8263 */ setHasTransientState(boolean hasTransientState)8264 public void setHasTransientState(boolean hasTransientState) { 8265 mTransientStateCount = hasTransientState ? mTransientStateCount + 1 : 8266 mTransientStateCount - 1; 8267 if (mTransientStateCount < 0) { 8268 mTransientStateCount = 0; 8269 Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " + 8270 "unmatched pair of setHasTransientState calls"); 8271 } else if ((hasTransientState && mTransientStateCount == 1) || 8272 (!hasTransientState && mTransientStateCount == 0)) { 8273 // update flag if we've just incremented up from 0 or decremented down to 0 8274 mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) | 8275 (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0); 8276 if (mParent != null) { 8277 try { 8278 mParent.childHasTransientStateChanged(this, hasTransientState); 8279 } catch (AbstractMethodError e) { 8280 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 8281 " does not fully implement ViewParent", e); 8282 } 8283 } 8284 } 8285 } 8286 8287 /** 8288 * Returns true if this view is currently attached to a window. 8289 */ isAttachedToWindow()8290 public boolean isAttachedToWindow() { 8291 return mAttachInfo != null; 8292 } 8293 8294 /** 8295 * Returns true if this view has been through at least one layout since it 8296 * was last attached to or detached from a window. 8297 */ isLaidOut()8298 public boolean isLaidOut() { 8299 return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT; 8300 } 8301 8302 /** 8303 * If this view doesn't do any drawing on its own, set this flag to 8304 * allow further optimizations. By default, this flag is not set on 8305 * View, but could be set on some View subclasses such as ViewGroup. 8306 * 8307 * Typically, if you override {@link #onDraw(android.graphics.Canvas)} 8308 * you should clear this flag. 8309 * 8310 * @param willNotDraw whether or not this View draw on its own 8311 */ setWillNotDraw(boolean willNotDraw)8312 public void setWillNotDraw(boolean willNotDraw) { 8313 setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK); 8314 } 8315 8316 /** 8317 * Returns whether or not this View draws on its own. 8318 * 8319 * @return true if this view has nothing to draw, false otherwise 8320 */ 8321 @ViewDebug.ExportedProperty(category = "drawing") willNotDraw()8322 public boolean willNotDraw() { 8323 return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW; 8324 } 8325 8326 /** 8327 * When a View's drawing cache is enabled, drawing is redirected to an 8328 * offscreen bitmap. Some views, like an ImageView, must be able to 8329 * bypass this mechanism if they already draw a single bitmap, to avoid 8330 * unnecessary usage of the memory. 8331 * 8332 * @param willNotCacheDrawing true if this view does not cache its 8333 * drawing, false otherwise 8334 */ setWillNotCacheDrawing(boolean willNotCacheDrawing)8335 public void setWillNotCacheDrawing(boolean willNotCacheDrawing) { 8336 setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING); 8337 } 8338 8339 /** 8340 * Returns whether or not this View can cache its drawing or not. 8341 * 8342 * @return true if this view does not cache its drawing, false otherwise 8343 */ 8344 @ViewDebug.ExportedProperty(category = "drawing") willNotCacheDrawing()8345 public boolean willNotCacheDrawing() { 8346 return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING; 8347 } 8348 8349 /** 8350 * Indicates whether this view reacts to click events or not. 8351 * 8352 * @return true if the view is clickable, false otherwise 8353 * 8354 * @see #setClickable(boolean) 8355 * @attr ref android.R.styleable#View_clickable 8356 */ 8357 @ViewDebug.ExportedProperty isClickable()8358 public boolean isClickable() { 8359 return (mViewFlags & CLICKABLE) == CLICKABLE; 8360 } 8361 8362 /** 8363 * Enables or disables click events for this view. When a view 8364 * is clickable it will change its state to "pressed" on every click. 8365 * Subclasses should set the view clickable to visually react to 8366 * user's clicks. 8367 * 8368 * @param clickable true to make the view clickable, false otherwise 8369 * 8370 * @see #isClickable() 8371 * @attr ref android.R.styleable#View_clickable 8372 */ setClickable(boolean clickable)8373 public void setClickable(boolean clickable) { 8374 setFlags(clickable ? CLICKABLE : 0, CLICKABLE); 8375 } 8376 8377 /** 8378 * Indicates whether this view reacts to long click events or not. 8379 * 8380 * @return true if the view is long clickable, false otherwise 8381 * 8382 * @see #setLongClickable(boolean) 8383 * @attr ref android.R.styleable#View_longClickable 8384 */ isLongClickable()8385 public boolean isLongClickable() { 8386 return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE; 8387 } 8388 8389 /** 8390 * Enables or disables long click events for this view. When a view is long 8391 * clickable it reacts to the user holding down the button for a longer 8392 * duration than a tap. This event can either launch the listener or a 8393 * context menu. 8394 * 8395 * @param longClickable true to make the view long clickable, false otherwise 8396 * @see #isLongClickable() 8397 * @attr ref android.R.styleable#View_longClickable 8398 */ setLongClickable(boolean longClickable)8399 public void setLongClickable(boolean longClickable) { 8400 setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE); 8401 } 8402 8403 /** 8404 * Indicates whether this view reacts to context clicks or not. 8405 * 8406 * @return true if the view is context clickable, false otherwise 8407 * @see #setContextClickable(boolean) 8408 * @attr ref android.R.styleable#View_contextClickable 8409 */ isContextClickable()8410 public boolean isContextClickable() { 8411 return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE; 8412 } 8413 8414 /** 8415 * Enables or disables context clicking for this view. This event can launch the listener. 8416 * 8417 * @param contextClickable true to make the view react to a context click, false otherwise 8418 * @see #isContextClickable() 8419 * @attr ref android.R.styleable#View_contextClickable 8420 */ setContextClickable(boolean contextClickable)8421 public void setContextClickable(boolean contextClickable) { 8422 setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE); 8423 } 8424 8425 /** 8426 * Sets the pressed state for this view and provides a touch coordinate for 8427 * animation hinting. 8428 * 8429 * @param pressed Pass true to set the View's internal state to "pressed", 8430 * or false to reverts the View's internal state from a 8431 * previously set "pressed" state. 8432 * @param x The x coordinate of the touch that caused the press 8433 * @param y The y coordinate of the touch that caused the press 8434 */ setPressed(boolean pressed, float x, float y)8435 private void setPressed(boolean pressed, float x, float y) { 8436 if (pressed) { 8437 drawableHotspotChanged(x, y); 8438 } 8439 8440 setPressed(pressed); 8441 } 8442 8443 /** 8444 * Sets the pressed state for this view. 8445 * 8446 * @see #isClickable() 8447 * @see #setClickable(boolean) 8448 * 8449 * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts 8450 * the View's internal state from a previously set "pressed" state. 8451 */ setPressed(boolean pressed)8452 public void setPressed(boolean pressed) { 8453 final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED); 8454 8455 if (pressed) { 8456 mPrivateFlags |= PFLAG_PRESSED; 8457 } else { 8458 mPrivateFlags &= ~PFLAG_PRESSED; 8459 } 8460 8461 if (needsRefresh) { 8462 refreshDrawableState(); 8463 } 8464 dispatchSetPressed(pressed); 8465 } 8466 8467 /** 8468 * Dispatch setPressed to all of this View's children. 8469 * 8470 * @see #setPressed(boolean) 8471 * 8472 * @param pressed The new pressed state 8473 */ dispatchSetPressed(boolean pressed)8474 protected void dispatchSetPressed(boolean pressed) { 8475 } 8476 8477 /** 8478 * Indicates whether the view is currently in pressed state. Unless 8479 * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter 8480 * the pressed state. 8481 * 8482 * @see #setPressed(boolean) 8483 * @see #isClickable() 8484 * @see #setClickable(boolean) 8485 * 8486 * @return true if the view is currently pressed, false otherwise 8487 */ 8488 @ViewDebug.ExportedProperty isPressed()8489 public boolean isPressed() { 8490 return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED; 8491 } 8492 8493 /** 8494 * @hide 8495 * Indicates whether this view will participate in data collection through 8496 * {@link ViewStructure}. If true, it will not provide any data 8497 * for itself or its children. If false, the normal data collection will be allowed. 8498 * 8499 * @return Returns false if assist data collection is not blocked, else true. 8500 * 8501 * @see #setAssistBlocked(boolean) 8502 * @attr ref android.R.styleable#View_assistBlocked 8503 */ isAssistBlocked()8504 public boolean isAssistBlocked() { 8505 return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0; 8506 } 8507 8508 /** 8509 * @hide 8510 * Controls whether assist data collection from this view and its children is enabled 8511 * (that is, whether {@link #onProvideStructure} and 8512 * {@link #onProvideVirtualStructure} will be called). The default value is false, 8513 * allowing normal assist collection. Setting this to false will disable assist collection. 8514 * 8515 * @param enabled Set to true to <em>disable</em> assist data collection, or false 8516 * (the default) to allow it. 8517 * 8518 * @see #isAssistBlocked() 8519 * @see #onProvideStructure 8520 * @see #onProvideVirtualStructure 8521 * @attr ref android.R.styleable#View_assistBlocked 8522 */ setAssistBlocked(boolean enabled)8523 public void setAssistBlocked(boolean enabled) { 8524 if (enabled) { 8525 mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED; 8526 } else { 8527 mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED; 8528 } 8529 } 8530 8531 /** 8532 * Indicates whether this view will save its state (that is, 8533 * whether its {@link #onSaveInstanceState} method will be called). 8534 * 8535 * @return Returns true if the view state saving is enabled, else false. 8536 * 8537 * @see #setSaveEnabled(boolean) 8538 * @attr ref android.R.styleable#View_saveEnabled 8539 */ isSaveEnabled()8540 public boolean isSaveEnabled() { 8541 return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED; 8542 } 8543 8544 /** 8545 * Controls whether the saving of this view's state is 8546 * enabled (that is, whether its {@link #onSaveInstanceState} method 8547 * will be called). Note that even if freezing is enabled, the 8548 * view still must have an id assigned to it (via {@link #setId(int)}) 8549 * for its state to be saved. This flag can only disable the 8550 * saving of this view; any child views may still have their state saved. 8551 * 8552 * @param enabled Set to false to <em>disable</em> state saving, or true 8553 * (the default) to allow it. 8554 * 8555 * @see #isSaveEnabled() 8556 * @see #setId(int) 8557 * @see #onSaveInstanceState() 8558 * @attr ref android.R.styleable#View_saveEnabled 8559 */ setSaveEnabled(boolean enabled)8560 public void setSaveEnabled(boolean enabled) { 8561 setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK); 8562 } 8563 8564 /** 8565 * Gets whether the framework should discard touches when the view's 8566 * window is obscured by another visible window. 8567 * Refer to the {@link View} security documentation for more details. 8568 * 8569 * @return True if touch filtering is enabled. 8570 * 8571 * @see #setFilterTouchesWhenObscured(boolean) 8572 * @attr ref android.R.styleable#View_filterTouchesWhenObscured 8573 */ 8574 @ViewDebug.ExportedProperty getFilterTouchesWhenObscured()8575 public boolean getFilterTouchesWhenObscured() { 8576 return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0; 8577 } 8578 8579 /** 8580 * Sets whether the framework should discard touches when the view's 8581 * window is obscured by another visible window. 8582 * Refer to the {@link View} security documentation for more details. 8583 * 8584 * @param enabled True if touch filtering should be enabled. 8585 * 8586 * @see #getFilterTouchesWhenObscured 8587 * @attr ref android.R.styleable#View_filterTouchesWhenObscured 8588 */ setFilterTouchesWhenObscured(boolean enabled)8589 public void setFilterTouchesWhenObscured(boolean enabled) { 8590 setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0, 8591 FILTER_TOUCHES_WHEN_OBSCURED); 8592 } 8593 8594 /** 8595 * Indicates whether the entire hierarchy under this view will save its 8596 * state when a state saving traversal occurs from its parent. The default 8597 * is true; if false, these views will not be saved unless 8598 * {@link #saveHierarchyState(SparseArray)} is called directly on this view. 8599 * 8600 * @return Returns true if the view state saving from parent is enabled, else false. 8601 * 8602 * @see #setSaveFromParentEnabled(boolean) 8603 */ isSaveFromParentEnabled()8604 public boolean isSaveFromParentEnabled() { 8605 return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED; 8606 } 8607 8608 /** 8609 * Controls whether the entire hierarchy under this view will save its 8610 * state when a state saving traversal occurs from its parent. The default 8611 * is true; if false, these views will not be saved unless 8612 * {@link #saveHierarchyState(SparseArray)} is called directly on this view. 8613 * 8614 * @param enabled Set to false to <em>disable</em> state saving, or true 8615 * (the default) to allow it. 8616 * 8617 * @see #isSaveFromParentEnabled() 8618 * @see #setId(int) 8619 * @see #onSaveInstanceState() 8620 */ setSaveFromParentEnabled(boolean enabled)8621 public void setSaveFromParentEnabled(boolean enabled) { 8622 setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK); 8623 } 8624 8625 8626 /** 8627 * Returns whether this View is able to take focus. 8628 * 8629 * @return True if this view can take focus, or false otherwise. 8630 * @attr ref android.R.styleable#View_focusable 8631 */ 8632 @ViewDebug.ExportedProperty(category = "focus") isFocusable()8633 public final boolean isFocusable() { 8634 return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK); 8635 } 8636 8637 /** 8638 * When a view is focusable, it may not want to take focus when in touch mode. 8639 * For example, a button would like focus when the user is navigating via a D-pad 8640 * so that the user can click on it, but once the user starts touching the screen, 8641 * the button shouldn't take focus 8642 * @return Whether the view is focusable in touch mode. 8643 * @attr ref android.R.styleable#View_focusableInTouchMode 8644 */ 8645 @ViewDebug.ExportedProperty isFocusableInTouchMode()8646 public final boolean isFocusableInTouchMode() { 8647 return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE); 8648 } 8649 8650 /** 8651 * Find the nearest view in the specified direction that can take focus. 8652 * This does not actually give focus to that view. 8653 * 8654 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 8655 * 8656 * @return The nearest focusable in the specified direction, or null if none 8657 * can be found. 8658 */ focusSearch(@ocusRealDirection int direction)8659 public View focusSearch(@FocusRealDirection int direction) { 8660 if (mParent != null) { 8661 return mParent.focusSearch(this, direction); 8662 } else { 8663 return null; 8664 } 8665 } 8666 8667 /** 8668 * This method is the last chance for the focused view and its ancestors to 8669 * respond to an arrow key. This is called when the focused view did not 8670 * consume the key internally, nor could the view system find a new view in 8671 * the requested direction to give focus to. 8672 * 8673 * @param focused The currently focused view. 8674 * @param direction The direction focus wants to move. One of FOCUS_UP, 8675 * FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT. 8676 * @return True if the this view consumed this unhandled move. 8677 */ dispatchUnhandledMove(View focused, @FocusRealDirection int direction)8678 public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) { 8679 return false; 8680 } 8681 8682 /** 8683 * If a user manually specified the next view id for a particular direction, 8684 * use the root to look up the view. 8685 * @param root The root view of the hierarchy containing this view. 8686 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD, 8687 * or FOCUS_BACKWARD. 8688 * @return The user specified next view, or null if there is none. 8689 */ findUserSetNextFocus(View root, @FocusDirection int direction)8690 View findUserSetNextFocus(View root, @FocusDirection int direction) { 8691 switch (direction) { 8692 case FOCUS_LEFT: 8693 if (mNextFocusLeftId == View.NO_ID) return null; 8694 return findViewInsideOutShouldExist(root, mNextFocusLeftId); 8695 case FOCUS_RIGHT: 8696 if (mNextFocusRightId == View.NO_ID) return null; 8697 return findViewInsideOutShouldExist(root, mNextFocusRightId); 8698 case FOCUS_UP: 8699 if (mNextFocusUpId == View.NO_ID) return null; 8700 return findViewInsideOutShouldExist(root, mNextFocusUpId); 8701 case FOCUS_DOWN: 8702 if (mNextFocusDownId == View.NO_ID) return null; 8703 return findViewInsideOutShouldExist(root, mNextFocusDownId); 8704 case FOCUS_FORWARD: 8705 if (mNextFocusForwardId == View.NO_ID) return null; 8706 return findViewInsideOutShouldExist(root, mNextFocusForwardId); 8707 case FOCUS_BACKWARD: { 8708 if (mID == View.NO_ID) return null; 8709 final int id = mID; 8710 return root.findViewByPredicateInsideOut(this, new Predicate<View>() { 8711 @Override 8712 public boolean apply(View t) { 8713 return t.mNextFocusForwardId == id; 8714 } 8715 }); 8716 } 8717 } 8718 return null; 8719 } 8720 findViewInsideOutShouldExist(View root, int id)8721 private View findViewInsideOutShouldExist(View root, int id) { 8722 if (mMatchIdPredicate == null) { 8723 mMatchIdPredicate = new MatchIdPredicate(); 8724 } 8725 mMatchIdPredicate.mId = id; 8726 View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate); 8727 if (result == null) { 8728 Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id); 8729 } 8730 return result; 8731 } 8732 8733 /** 8734 * Find and return all focusable views that are descendants of this view, 8735 * possibly including this view if it is focusable itself. 8736 * 8737 * @param direction The direction of the focus 8738 * @return A list of focusable views 8739 */ getFocusables(@ocusDirection int direction)8740 public ArrayList<View> getFocusables(@FocusDirection int direction) { 8741 ArrayList<View> result = new ArrayList<View>(24); 8742 addFocusables(result, direction); 8743 return result; 8744 } 8745 8746 /** 8747 * Add any focusable views that are descendants of this view (possibly 8748 * including this view if it is focusable itself) to views. If we are in touch mode, 8749 * only add views that are also focusable in touch mode. 8750 * 8751 * @param views Focusable views found so far 8752 * @param direction The direction of the focus 8753 */ addFocusables(ArrayList<View> views, @FocusDirection int direction)8754 public void addFocusables(ArrayList<View> views, @FocusDirection int direction) { 8755 addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL); 8756 } 8757 8758 /** 8759 * Adds any focusable views that are descendants of this view (possibly 8760 * including this view if it is focusable itself) to views. This method 8761 * adds all focusable views regardless if we are in touch mode or 8762 * only views focusable in touch mode if we are in touch mode or 8763 * only views that can take accessibility focus if accessibility is enabled 8764 * depending on the focusable mode parameter. 8765 * 8766 * @param views Focusable views found so far or null if all we are interested is 8767 * the number of focusables. 8768 * @param direction The direction of the focus. 8769 * @param focusableMode The type of focusables to be added. 8770 * 8771 * @see #FOCUSABLES_ALL 8772 * @see #FOCUSABLES_TOUCH_MODE 8773 */ addFocusables(ArrayList<View> views, @FocusDirection int direction, @FocusableMode int focusableMode)8774 public void addFocusables(ArrayList<View> views, @FocusDirection int direction, 8775 @FocusableMode int focusableMode) { 8776 if (views == null) { 8777 return; 8778 } 8779 if (!isFocusable()) { 8780 return; 8781 } 8782 if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE 8783 && !isFocusableInTouchMode()) { 8784 return; 8785 } 8786 views.add(this); 8787 } 8788 8789 /** 8790 * Finds the Views that contain given text. The containment is case insensitive. 8791 * The search is performed by either the text that the View renders or the content 8792 * description that describes the view for accessibility purposes and the view does 8793 * not render or both. Clients can specify how the search is to be performed via 8794 * passing the {@link #FIND_VIEWS_WITH_TEXT} and 8795 * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags. 8796 * 8797 * @param outViews The output list of matching Views. 8798 * @param searched The text to match against. 8799 * 8800 * @see #FIND_VIEWS_WITH_TEXT 8801 * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION 8802 * @see #setContentDescription(CharSequence) 8803 */ findViewsWithText(ArrayList<View> outViews, CharSequence searched, @FindViewFlags int flags)8804 public void findViewsWithText(ArrayList<View> outViews, CharSequence searched, 8805 @FindViewFlags int flags) { 8806 if (getAccessibilityNodeProvider() != null) { 8807 if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) { 8808 outViews.add(this); 8809 } 8810 } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0 8811 && (searched != null && searched.length() > 0) 8812 && (mContentDescription != null && mContentDescription.length() > 0)) { 8813 String searchedLowerCase = searched.toString().toLowerCase(); 8814 String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase(); 8815 if (contentDescriptionLowerCase.contains(searchedLowerCase)) { 8816 outViews.add(this); 8817 } 8818 } 8819 } 8820 8821 /** 8822 * Find and return all touchable views that are descendants of this view, 8823 * possibly including this view if it is touchable itself. 8824 * 8825 * @return A list of touchable views 8826 */ getTouchables()8827 public ArrayList<View> getTouchables() { 8828 ArrayList<View> result = new ArrayList<View>(); 8829 addTouchables(result); 8830 return result; 8831 } 8832 8833 /** 8834 * Add any touchable views that are descendants of this view (possibly 8835 * including this view if it is touchable itself) to views. 8836 * 8837 * @param views Touchable views found so far 8838 */ addTouchables(ArrayList<View> views)8839 public void addTouchables(ArrayList<View> views) { 8840 final int viewFlags = mViewFlags; 8841 8842 if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE 8843 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) 8844 && (viewFlags & ENABLED_MASK) == ENABLED) { 8845 views.add(this); 8846 } 8847 } 8848 8849 /** 8850 * Returns whether this View is accessibility focused. 8851 * 8852 * @return True if this View is accessibility focused. 8853 */ isAccessibilityFocused()8854 public boolean isAccessibilityFocused() { 8855 return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0; 8856 } 8857 8858 /** 8859 * Call this to try to give accessibility focus to this view. 8860 * 8861 * A view will not actually take focus if {@link AccessibilityManager#isEnabled()} 8862 * returns false or the view is no visible or the view already has accessibility 8863 * focus. 8864 * 8865 * See also {@link #focusSearch(int)}, which is what you call to say that you 8866 * have focus, and you want your parent to look for the next one. 8867 * 8868 * @return Whether this view actually took accessibility focus. 8869 * 8870 * @hide 8871 */ requestAccessibilityFocus()8872 public boolean requestAccessibilityFocus() { 8873 AccessibilityManager manager = AccessibilityManager.getInstance(mContext); 8874 if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) { 8875 return false; 8876 } 8877 if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) { 8878 return false; 8879 } 8880 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) { 8881 mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED; 8882 ViewRootImpl viewRootImpl = getViewRootImpl(); 8883 if (viewRootImpl != null) { 8884 viewRootImpl.setAccessibilityFocus(this, null); 8885 } 8886 invalidate(); 8887 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); 8888 return true; 8889 } 8890 return false; 8891 } 8892 8893 /** 8894 * Call this to try to clear accessibility focus of this view. 8895 * 8896 * See also {@link #focusSearch(int)}, which is what you call to say that you 8897 * have focus, and you want your parent to look for the next one. 8898 * 8899 * @hide 8900 */ clearAccessibilityFocus()8901 public void clearAccessibilityFocus() { 8902 clearAccessibilityFocusNoCallbacks(0); 8903 8904 // Clear the global reference of accessibility focus if this view or 8905 // any of its descendants had accessibility focus. This will NOT send 8906 // an event or update internal state if focus is cleared from a 8907 // descendant view, which may leave views in inconsistent states. 8908 final ViewRootImpl viewRootImpl = getViewRootImpl(); 8909 if (viewRootImpl != null) { 8910 final View focusHost = viewRootImpl.getAccessibilityFocusedHost(); 8911 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) { 8912 viewRootImpl.setAccessibilityFocus(null, null); 8913 } 8914 } 8915 } 8916 sendAccessibilityHoverEvent(int eventType)8917 private void sendAccessibilityHoverEvent(int eventType) { 8918 // Since we are not delivering to a client accessibility events from not 8919 // important views (unless the clinet request that) we need to fire the 8920 // event from the deepest view exposed to the client. As a consequence if 8921 // the user crosses a not exposed view the client will see enter and exit 8922 // of the exposed predecessor followed by and enter and exit of that same 8923 // predecessor when entering and exiting the not exposed descendant. This 8924 // is fine since the client has a clear idea which view is hovered at the 8925 // price of a couple more events being sent. This is a simple and 8926 // working solution. 8927 View source = this; 8928 while (true) { 8929 if (source.includeForAccessibility()) { 8930 source.sendAccessibilityEvent(eventType); 8931 return; 8932 } 8933 ViewParent parent = source.getParent(); 8934 if (parent instanceof View) { 8935 source = (View) parent; 8936 } else { 8937 return; 8938 } 8939 } 8940 } 8941 8942 /** 8943 * Clears accessibility focus without calling any callback methods 8944 * normally invoked in {@link #clearAccessibilityFocus()}. This method 8945 * is used separately from that one for clearing accessibility focus when 8946 * giving this focus to another view. 8947 * 8948 * @param action The action, if any, that led to focus being cleared. Set to 8949 * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within 8950 * the window. 8951 */ clearAccessibilityFocusNoCallbacks(int action)8952 void clearAccessibilityFocusNoCallbacks(int action) { 8953 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) { 8954 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED; 8955 invalidate(); 8956 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 8957 AccessibilityEvent event = AccessibilityEvent.obtain( 8958 AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); 8959 event.setAction(action); 8960 if (mAccessibilityDelegate != null) { 8961 mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event); 8962 } else { 8963 sendAccessibilityEventUnchecked(event); 8964 } 8965 } 8966 } 8967 } 8968 8969 /** 8970 * Call this to try to give focus to a specific view or to one of its 8971 * descendants. 8972 * 8973 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns 8974 * false), or if it is focusable and it is not focusable in touch mode 8975 * ({@link #isFocusableInTouchMode}) while the device is in touch mode. 8976 * 8977 * See also {@link #focusSearch(int)}, which is what you call to say that you 8978 * have focus, and you want your parent to look for the next one. 8979 * 8980 * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments 8981 * {@link #FOCUS_DOWN} and <code>null</code>. 8982 * 8983 * @return Whether this view or one of its descendants actually took focus. 8984 */ requestFocus()8985 public final boolean requestFocus() { 8986 return requestFocus(View.FOCUS_DOWN); 8987 } 8988 8989 /** 8990 * Call this to try to give focus to a specific view or to one of its 8991 * descendants and give it a hint about what direction focus is heading. 8992 * 8993 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns 8994 * false), or if it is focusable and it is not focusable in touch mode 8995 * ({@link #isFocusableInTouchMode}) while the device is in touch mode. 8996 * 8997 * See also {@link #focusSearch(int)}, which is what you call to say that you 8998 * have focus, and you want your parent to look for the next one. 8999 * 9000 * This is equivalent to calling {@link #requestFocus(int, Rect)} with 9001 * <code>null</code> set for the previously focused rectangle. 9002 * 9003 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 9004 * @return Whether this view or one of its descendants actually took focus. 9005 */ requestFocus(int direction)9006 public final boolean requestFocus(int direction) { 9007 return requestFocus(direction, null); 9008 } 9009 9010 /** 9011 * Call this to try to give focus to a specific view or to one of its descendants 9012 * and give it hints about the direction and a specific rectangle that the focus 9013 * is coming from. The rectangle can help give larger views a finer grained hint 9014 * about where focus is coming from, and therefore, where to show selection, or 9015 * forward focus change internally. 9016 * 9017 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns 9018 * false), or if it is focusable and it is not focusable in touch mode 9019 * ({@link #isFocusableInTouchMode}) while the device is in touch mode. 9020 * 9021 * A View will not take focus if it is not visible. 9022 * 9023 * A View will not take focus if one of its parents has 9024 * {@link android.view.ViewGroup#getDescendantFocusability()} equal to 9025 * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}. 9026 * 9027 * See also {@link #focusSearch(int)}, which is what you call to say that you 9028 * have focus, and you want your parent to look for the next one. 9029 * 9030 * You may wish to override this method if your custom {@link View} has an internal 9031 * {@link View} that it wishes to forward the request to. 9032 * 9033 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 9034 * @param previouslyFocusedRect The rectangle (in this View's coordinate system) 9035 * to give a finer grained hint about where focus is coming from. May be null 9036 * if there is no hint. 9037 * @return Whether this view or one of its descendants actually took focus. 9038 */ requestFocus(int direction, Rect previouslyFocusedRect)9039 public boolean requestFocus(int direction, Rect previouslyFocusedRect) { 9040 return requestFocusNoSearch(direction, previouslyFocusedRect); 9041 } 9042 requestFocusNoSearch(int direction, Rect previouslyFocusedRect)9043 private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) { 9044 // need to be focusable 9045 if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE || 9046 (mViewFlags & VISIBILITY_MASK) != VISIBLE) { 9047 return false; 9048 } 9049 9050 // need to be focusable in touch mode if in touch mode 9051 if (isInTouchMode() && 9052 (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) { 9053 return false; 9054 } 9055 9056 // need to not have any parents blocking us 9057 if (hasAncestorThatBlocksDescendantFocus()) { 9058 return false; 9059 } 9060 9061 handleFocusGainInternal(direction, previouslyFocusedRect); 9062 return true; 9063 } 9064 9065 /** 9066 * Call this to try to give focus to a specific view or to one of its descendants. This is a 9067 * special variant of {@link #requestFocus() } that will allow views that are not focusable in 9068 * touch mode to request focus when they are touched. 9069 * 9070 * @return Whether this view or one of its descendants actually took focus. 9071 * 9072 * @see #isInTouchMode() 9073 * 9074 */ requestFocusFromTouch()9075 public final boolean requestFocusFromTouch() { 9076 // Leave touch mode if we need to 9077 if (isInTouchMode()) { 9078 ViewRootImpl viewRoot = getViewRootImpl(); 9079 if (viewRoot != null) { 9080 viewRoot.ensureTouchMode(false); 9081 } 9082 } 9083 return requestFocus(View.FOCUS_DOWN); 9084 } 9085 9086 /** 9087 * @return Whether any ancestor of this view blocks descendant focus. 9088 */ hasAncestorThatBlocksDescendantFocus()9089 private boolean hasAncestorThatBlocksDescendantFocus() { 9090 final boolean focusableInTouchMode = isFocusableInTouchMode(); 9091 ViewParent ancestor = mParent; 9092 while (ancestor instanceof ViewGroup) { 9093 final ViewGroup vgAncestor = (ViewGroup) ancestor; 9094 if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS 9095 || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) { 9096 return true; 9097 } else { 9098 ancestor = vgAncestor.getParent(); 9099 } 9100 } 9101 return false; 9102 } 9103 9104 /** 9105 * Gets the mode for determining whether this View is important for accessibility 9106 * which is if it fires accessibility events and if it is reported to 9107 * accessibility services that query the screen. 9108 * 9109 * @return The mode for determining whether a View is important for accessibility. 9110 * 9111 * @attr ref android.R.styleable#View_importantForAccessibility 9112 * 9113 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES 9114 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO 9115 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS 9116 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO 9117 */ 9118 @ViewDebug.ExportedProperty(category = "accessibility", mapping = { 9119 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"), 9120 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"), 9121 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"), 9122 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS, 9123 to = "noHideDescendants") 9124 }) getImportantForAccessibility()9125 public int getImportantForAccessibility() { 9126 return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK) 9127 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT; 9128 } 9129 9130 /** 9131 * Sets the live region mode for this view. This indicates to accessibility 9132 * services whether they should automatically notify the user about changes 9133 * to the view's content description or text, or to the content descriptions 9134 * or text of the view's children (where applicable). 9135 * <p> 9136 * For example, in a login screen with a TextView that displays an "incorrect 9137 * password" notification, that view should be marked as a live region with 9138 * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}. 9139 * <p> 9140 * To disable change notifications for this view, use 9141 * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region 9142 * mode for most views. 9143 * <p> 9144 * To indicate that the user should be notified of changes, use 9145 * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}. 9146 * <p> 9147 * If the view's changes should interrupt ongoing speech and notify the user 9148 * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}. 9149 * 9150 * @param mode The live region mode for this view, one of: 9151 * <ul> 9152 * <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE} 9153 * <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE} 9154 * <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE} 9155 * </ul> 9156 * @attr ref android.R.styleable#View_accessibilityLiveRegion 9157 */ setAccessibilityLiveRegion(int mode)9158 public void setAccessibilityLiveRegion(int mode) { 9159 if (mode != getAccessibilityLiveRegion()) { 9160 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK; 9161 mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT) 9162 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK; 9163 notifyViewAccessibilityStateChangedIfNeeded( 9164 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 9165 } 9166 } 9167 9168 /** 9169 * Gets the live region mode for this View. 9170 * 9171 * @return The live region mode for the view. 9172 * 9173 * @attr ref android.R.styleable#View_accessibilityLiveRegion 9174 * 9175 * @see #setAccessibilityLiveRegion(int) 9176 */ getAccessibilityLiveRegion()9177 public int getAccessibilityLiveRegion() { 9178 return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK) 9179 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT; 9180 } 9181 9182 /** 9183 * Sets how to determine whether this view is important for accessibility 9184 * which is if it fires accessibility events and if it is reported to 9185 * accessibility services that query the screen. 9186 * 9187 * @param mode How to determine whether this view is important for accessibility. 9188 * 9189 * @attr ref android.R.styleable#View_importantForAccessibility 9190 * 9191 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES 9192 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO 9193 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS 9194 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO 9195 */ setImportantForAccessibility(int mode)9196 public void setImportantForAccessibility(int mode) { 9197 final int oldMode = getImportantForAccessibility(); 9198 if (mode != oldMode) { 9199 final boolean hideDescendants = 9200 mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS; 9201 9202 // If this node or its descendants are no longer important, try to 9203 // clear accessibility focus. 9204 if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) { 9205 final View focusHost = findAccessibilityFocusHost(hideDescendants); 9206 if (focusHost != null) { 9207 focusHost.clearAccessibilityFocus(); 9208 } 9209 } 9210 9211 // If we're moving between AUTO and another state, we might not need 9212 // to send a subtree changed notification. We'll store the computed 9213 // importance, since we'll need to check it later to make sure. 9214 final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO 9215 || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO; 9216 final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility(); 9217 mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK; 9218 mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT) 9219 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK; 9220 if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) { 9221 notifySubtreeAccessibilityStateChangedIfNeeded(); 9222 } else { 9223 notifyViewAccessibilityStateChangedIfNeeded( 9224 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 9225 } 9226 } 9227 } 9228 9229 /** 9230 * Returns the view within this view's hierarchy that is hosting 9231 * accessibility focus. 9232 * 9233 * @param searchDescendants whether to search for focus in descendant views 9234 * @return the view hosting accessibility focus, or {@code null} 9235 */ findAccessibilityFocusHost(boolean searchDescendants)9236 private View findAccessibilityFocusHost(boolean searchDescendants) { 9237 if (isAccessibilityFocusedViewOrHost()) { 9238 return this; 9239 } 9240 9241 if (searchDescendants) { 9242 final ViewRootImpl viewRoot = getViewRootImpl(); 9243 if (viewRoot != null) { 9244 final View focusHost = viewRoot.getAccessibilityFocusedHost(); 9245 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) { 9246 return focusHost; 9247 } 9248 } 9249 } 9250 9251 return null; 9252 } 9253 9254 /** 9255 * Computes whether this view should be exposed for accessibility. In 9256 * general, views that are interactive or provide information are exposed 9257 * while views that serve only as containers are hidden. 9258 * <p> 9259 * If an ancestor of this view has importance 9260 * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method 9261 * returns <code>false</code>. 9262 * <p> 9263 * Otherwise, the value is computed according to the view's 9264 * {@link #getImportantForAccessibility()} value: 9265 * <ol> 9266 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or 9267 * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false 9268 * </code> 9269 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code> 9270 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if 9271 * view satisfies any of the following: 9272 * <ul> 9273 * <li>Is actionable, e.g. {@link #isClickable()}, 9274 * {@link #isLongClickable()}, or {@link #isFocusable()} 9275 * <li>Has an {@link AccessibilityDelegate} 9276 * <li>Has an interaction listener, e.g. {@link OnTouchListener}, 9277 * {@link OnKeyListener}, etc. 9278 * <li>Is an accessibility live region, e.g. 9279 * {@link #getAccessibilityLiveRegion()} is not 9280 * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. 9281 * </ul> 9282 * </ol> 9283 * 9284 * @return Whether the view is exposed for accessibility. 9285 * @see #setImportantForAccessibility(int) 9286 * @see #getImportantForAccessibility() 9287 */ isImportantForAccessibility()9288 public boolean isImportantForAccessibility() { 9289 final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK) 9290 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT; 9291 if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO 9292 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) { 9293 return false; 9294 } 9295 9296 // Check parent mode to ensure we're not hidden. 9297 ViewParent parent = mParent; 9298 while (parent instanceof View) { 9299 if (((View) parent).getImportantForAccessibility() 9300 == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) { 9301 return false; 9302 } 9303 parent = parent.getParent(); 9304 } 9305 9306 return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility() 9307 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null 9308 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE; 9309 } 9310 9311 /** 9312 * Gets the parent for accessibility purposes. Note that the parent for 9313 * accessibility is not necessary the immediate parent. It is the first 9314 * predecessor that is important for accessibility. 9315 * 9316 * @return The parent for accessibility purposes. 9317 */ getParentForAccessibility()9318 public ViewParent getParentForAccessibility() { 9319 if (mParent instanceof View) { 9320 View parentView = (View) mParent; 9321 if (parentView.includeForAccessibility()) { 9322 return mParent; 9323 } else { 9324 return mParent.getParentForAccessibility(); 9325 } 9326 } 9327 return null; 9328 } 9329 9330 /** 9331 * Adds the children of this View relevant for accessibility to the given list 9332 * as output. Since some Views are not important for accessibility the added 9333 * child views are not necessarily direct children of this view, rather they are 9334 * the first level of descendants important for accessibility. 9335 * 9336 * @param outChildren The output list that will receive children for accessibility. 9337 */ addChildrenForAccessibility(ArrayList<View> outChildren)9338 public void addChildrenForAccessibility(ArrayList<View> outChildren) { 9339 9340 } 9341 9342 /** 9343 * Whether to regard this view for accessibility. A view is regarded for 9344 * accessibility if it is important for accessibility or the querying 9345 * accessibility service has explicitly requested that view not 9346 * important for accessibility are regarded. 9347 * 9348 * @return Whether to regard the view for accessibility. 9349 * 9350 * @hide 9351 */ includeForAccessibility()9352 public boolean includeForAccessibility() { 9353 if (mAttachInfo != null) { 9354 return (mAttachInfo.mAccessibilityFetchFlags 9355 & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0 9356 || isImportantForAccessibility(); 9357 } 9358 return false; 9359 } 9360 9361 /** 9362 * Returns whether the View is considered actionable from 9363 * accessibility perspective. Such view are important for 9364 * accessibility. 9365 * 9366 * @return True if the view is actionable for accessibility. 9367 * 9368 * @hide 9369 */ isActionableForAccessibility()9370 public boolean isActionableForAccessibility() { 9371 return (isClickable() || isLongClickable() || isFocusable()); 9372 } 9373 9374 /** 9375 * Returns whether the View has registered callbacks which makes it 9376 * important for accessibility. 9377 * 9378 * @return True if the view is actionable for accessibility. 9379 */ hasListenersForAccessibility()9380 private boolean hasListenersForAccessibility() { 9381 ListenerInfo info = getListenerInfo(); 9382 return mTouchDelegate != null || info.mOnKeyListener != null 9383 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null 9384 || info.mOnHoverListener != null || info.mOnDragListener != null; 9385 } 9386 9387 /** 9388 * Notifies that the accessibility state of this view changed. The change 9389 * is local to this view and does not represent structural changes such 9390 * as children and parent. For example, the view became focusable. The 9391 * notification is at at most once every 9392 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()} 9393 * to avoid unnecessary load to the system. Also once a view has a pending 9394 * notification this method is a NOP until the notification has been sent. 9395 * 9396 * @hide 9397 */ notifyViewAccessibilityStateChangedIfNeeded(int changeType)9398 public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) { 9399 if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) { 9400 return; 9401 } 9402 if (mSendViewStateChangedAccessibilityEvent == null) { 9403 mSendViewStateChangedAccessibilityEvent = 9404 new SendViewStateChangedAccessibilityEvent(); 9405 } 9406 mSendViewStateChangedAccessibilityEvent.runOrPost(changeType); 9407 } 9408 9409 /** 9410 * Notifies that the accessibility state of this view changed. The change 9411 * is *not* local to this view and does represent structural changes such 9412 * as children and parent. For example, the view size changed. The 9413 * notification is at at most once every 9414 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()} 9415 * to avoid unnecessary load to the system. Also once a view has a pending 9416 * notification this method is a NOP until the notification has been sent. 9417 * 9418 * @hide 9419 */ notifySubtreeAccessibilityStateChangedIfNeeded()9420 public void notifySubtreeAccessibilityStateChangedIfNeeded() { 9421 if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) { 9422 return; 9423 } 9424 if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) { 9425 mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED; 9426 if (mParent != null) { 9427 try { 9428 mParent.notifySubtreeAccessibilityStateChanged( 9429 this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE); 9430 } catch (AbstractMethodError e) { 9431 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 9432 " does not fully implement ViewParent", e); 9433 } 9434 } 9435 } 9436 } 9437 9438 /** 9439 * Change the visibility of the View without triggering any other changes. This is 9440 * important for transitions, where visibility changes should not adjust focus or 9441 * trigger a new layout. This is only used when the visibility has already been changed 9442 * and we need a transient value during an animation. When the animation completes, 9443 * the original visibility value is always restored. 9444 * 9445 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. 9446 * @hide 9447 */ setTransitionVisibility(@isibility int visibility)9448 public void setTransitionVisibility(@Visibility int visibility) { 9449 mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility; 9450 } 9451 9452 /** 9453 * Reset the flag indicating the accessibility state of the subtree rooted 9454 * at this view changed. 9455 */ resetSubtreeAccessibilityStateChanged()9456 void resetSubtreeAccessibilityStateChanged() { 9457 mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED; 9458 } 9459 9460 /** 9461 * Report an accessibility action to this view's parents for delegated processing. 9462 * 9463 * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally 9464 * call this method to delegate an accessibility action to a supporting parent. If the parent 9465 * returns true from its 9466 * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)} 9467 * method this method will return true to signify that the action was consumed.</p> 9468 * 9469 * <p>This method is useful for implementing nested scrolling child views. If 9470 * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action 9471 * a custom view implementation may invoke this method to allow a parent to consume the 9472 * scroll first. If this method returns true the custom view should skip its own scrolling 9473 * behavior.</p> 9474 * 9475 * @param action Accessibility action to delegate 9476 * @param arguments Optional action arguments 9477 * @return true if the action was consumed by a parent 9478 */ dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments)9479 public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) { 9480 for (ViewParent p = getParent(); p != null; p = p.getParent()) { 9481 if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) { 9482 return true; 9483 } 9484 } 9485 return false; 9486 } 9487 9488 /** 9489 * Performs the specified accessibility action on the view. For 9490 * possible accessibility actions look at {@link AccessibilityNodeInfo}. 9491 * <p> 9492 * If an {@link AccessibilityDelegate} has been specified via calling 9493 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 9494 * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)} 9495 * is responsible for handling this call. 9496 * </p> 9497 * 9498 * <p>The default implementation will delegate 9499 * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and 9500 * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if 9501 * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p> 9502 * 9503 * @param action The action to perform. 9504 * @param arguments Optional action arguments. 9505 * @return Whether the action was performed. 9506 */ performAccessibilityAction(int action, Bundle arguments)9507 public boolean performAccessibilityAction(int action, Bundle arguments) { 9508 if (mAccessibilityDelegate != null) { 9509 return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments); 9510 } else { 9511 return performAccessibilityActionInternal(action, arguments); 9512 } 9513 } 9514 9515 /** 9516 * @see #performAccessibilityAction(int, Bundle) 9517 * 9518 * Note: Called from the default {@link AccessibilityDelegate}. 9519 * 9520 * @hide 9521 */ performAccessibilityActionInternal(int action, Bundle arguments)9522 public boolean performAccessibilityActionInternal(int action, Bundle arguments) { 9523 if (isNestedScrollingEnabled() 9524 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD 9525 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD 9526 || action == R.id.accessibilityActionScrollUp 9527 || action == R.id.accessibilityActionScrollLeft 9528 || action == R.id.accessibilityActionScrollDown 9529 || action == R.id.accessibilityActionScrollRight)) { 9530 if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) { 9531 return true; 9532 } 9533 } 9534 9535 switch (action) { 9536 case AccessibilityNodeInfo.ACTION_CLICK: { 9537 if (isClickable()) { 9538 performClick(); 9539 return true; 9540 } 9541 } break; 9542 case AccessibilityNodeInfo.ACTION_LONG_CLICK: { 9543 if (isLongClickable()) { 9544 performLongClick(); 9545 return true; 9546 } 9547 } break; 9548 case AccessibilityNodeInfo.ACTION_FOCUS: { 9549 if (!hasFocus()) { 9550 // Get out of touch mode since accessibility 9551 // wants to move focus around. 9552 getViewRootImpl().ensureTouchMode(false); 9553 return requestFocus(); 9554 } 9555 } break; 9556 case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: { 9557 if (hasFocus()) { 9558 clearFocus(); 9559 return !isFocused(); 9560 } 9561 } break; 9562 case AccessibilityNodeInfo.ACTION_SELECT: { 9563 if (!isSelected()) { 9564 setSelected(true); 9565 return isSelected(); 9566 } 9567 } break; 9568 case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: { 9569 if (isSelected()) { 9570 setSelected(false); 9571 return !isSelected(); 9572 } 9573 } break; 9574 case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: { 9575 if (!isAccessibilityFocused()) { 9576 return requestAccessibilityFocus(); 9577 } 9578 } break; 9579 case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: { 9580 if (isAccessibilityFocused()) { 9581 clearAccessibilityFocus(); 9582 return true; 9583 } 9584 } break; 9585 case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: { 9586 if (arguments != null) { 9587 final int granularity = arguments.getInt( 9588 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT); 9589 final boolean extendSelection = arguments.getBoolean( 9590 AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN); 9591 return traverseAtGranularity(granularity, true, extendSelection); 9592 } 9593 } break; 9594 case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: { 9595 if (arguments != null) { 9596 final int granularity = arguments.getInt( 9597 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT); 9598 final boolean extendSelection = arguments.getBoolean( 9599 AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN); 9600 return traverseAtGranularity(granularity, false, extendSelection); 9601 } 9602 } break; 9603 case AccessibilityNodeInfo.ACTION_SET_SELECTION: { 9604 CharSequence text = getIterableTextForAccessibility(); 9605 if (text == null) { 9606 return false; 9607 } 9608 final int start = (arguments != null) ? arguments.getInt( 9609 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1; 9610 final int end = (arguments != null) ? arguments.getInt( 9611 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1; 9612 // Only cursor position can be specified (selection length == 0) 9613 if ((getAccessibilitySelectionStart() != start 9614 || getAccessibilitySelectionEnd() != end) 9615 && (start == end)) { 9616 setAccessibilitySelection(start, end); 9617 notifyViewAccessibilityStateChangedIfNeeded( 9618 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 9619 return true; 9620 } 9621 } break; 9622 case R.id.accessibilityActionShowOnScreen: { 9623 if (mAttachInfo != null) { 9624 final Rect r = mAttachInfo.mTmpInvalRect; 9625 getDrawingRect(r); 9626 return requestRectangleOnScreen(r, true); 9627 } 9628 } break; 9629 case R.id.accessibilityActionContextClick: { 9630 if (isContextClickable()) { 9631 performContextClick(); 9632 return true; 9633 } 9634 } break; 9635 } 9636 return false; 9637 } 9638 traverseAtGranularity(int granularity, boolean forward, boolean extendSelection)9639 private boolean traverseAtGranularity(int granularity, boolean forward, 9640 boolean extendSelection) { 9641 CharSequence text = getIterableTextForAccessibility(); 9642 if (text == null || text.length() == 0) { 9643 return false; 9644 } 9645 TextSegmentIterator iterator = getIteratorForGranularity(granularity); 9646 if (iterator == null) { 9647 return false; 9648 } 9649 int current = getAccessibilitySelectionEnd(); 9650 if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) { 9651 current = forward ? 0 : text.length(); 9652 } 9653 final int[] range = forward ? iterator.following(current) : iterator.preceding(current); 9654 if (range == null) { 9655 return false; 9656 } 9657 final int segmentStart = range[0]; 9658 final int segmentEnd = range[1]; 9659 int selectionStart; 9660 int selectionEnd; 9661 if (extendSelection && isAccessibilitySelectionExtendable()) { 9662 selectionStart = getAccessibilitySelectionStart(); 9663 if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) { 9664 selectionStart = forward ? segmentStart : segmentEnd; 9665 } 9666 selectionEnd = forward ? segmentEnd : segmentStart; 9667 } else { 9668 selectionStart = selectionEnd= forward ? segmentEnd : segmentStart; 9669 } 9670 setAccessibilitySelection(selectionStart, selectionEnd); 9671 final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY 9672 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY; 9673 sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd); 9674 return true; 9675 } 9676 9677 /** 9678 * Gets the text reported for accessibility purposes. 9679 * 9680 * @return The accessibility text. 9681 * 9682 * @hide 9683 */ getIterableTextForAccessibility()9684 public CharSequence getIterableTextForAccessibility() { 9685 return getContentDescription(); 9686 } 9687 9688 /** 9689 * Gets whether accessibility selection can be extended. 9690 * 9691 * @return If selection is extensible. 9692 * 9693 * @hide 9694 */ isAccessibilitySelectionExtendable()9695 public boolean isAccessibilitySelectionExtendable() { 9696 return false; 9697 } 9698 9699 /** 9700 * @hide 9701 */ getAccessibilitySelectionStart()9702 public int getAccessibilitySelectionStart() { 9703 return mAccessibilityCursorPosition; 9704 } 9705 9706 /** 9707 * @hide 9708 */ getAccessibilitySelectionEnd()9709 public int getAccessibilitySelectionEnd() { 9710 return getAccessibilitySelectionStart(); 9711 } 9712 9713 /** 9714 * @hide 9715 */ setAccessibilitySelection(int start, int end)9716 public void setAccessibilitySelection(int start, int end) { 9717 if (start == end && end == mAccessibilityCursorPosition) { 9718 return; 9719 } 9720 if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) { 9721 mAccessibilityCursorPosition = start; 9722 } else { 9723 mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED; 9724 } 9725 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED); 9726 } 9727 sendViewTextTraversedAtGranularityEvent(int action, int granularity, int fromIndex, int toIndex)9728 private void sendViewTextTraversedAtGranularityEvent(int action, int granularity, 9729 int fromIndex, int toIndex) { 9730 if (mParent == null) { 9731 return; 9732 } 9733 AccessibilityEvent event = AccessibilityEvent.obtain( 9734 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY); 9735 onInitializeAccessibilityEvent(event); 9736 onPopulateAccessibilityEvent(event); 9737 event.setFromIndex(fromIndex); 9738 event.setToIndex(toIndex); 9739 event.setAction(action); 9740 event.setMovementGranularity(granularity); 9741 mParent.requestSendAccessibilityEvent(this, event); 9742 } 9743 9744 /** 9745 * @hide 9746 */ getIteratorForGranularity(int granularity)9747 public TextSegmentIterator getIteratorForGranularity(int granularity) { 9748 switch (granularity) { 9749 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: { 9750 CharSequence text = getIterableTextForAccessibility(); 9751 if (text != null && text.length() > 0) { 9752 CharacterTextSegmentIterator iterator = 9753 CharacterTextSegmentIterator.getInstance( 9754 mContext.getResources().getConfiguration().locale); 9755 iterator.initialize(text.toString()); 9756 return iterator; 9757 } 9758 } break; 9759 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: { 9760 CharSequence text = getIterableTextForAccessibility(); 9761 if (text != null && text.length() > 0) { 9762 WordTextSegmentIterator iterator = 9763 WordTextSegmentIterator.getInstance( 9764 mContext.getResources().getConfiguration().locale); 9765 iterator.initialize(text.toString()); 9766 return iterator; 9767 } 9768 } break; 9769 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: { 9770 CharSequence text = getIterableTextForAccessibility(); 9771 if (text != null && text.length() > 0) { 9772 ParagraphTextSegmentIterator iterator = 9773 ParagraphTextSegmentIterator.getInstance(); 9774 iterator.initialize(text.toString()); 9775 return iterator; 9776 } 9777 } break; 9778 } 9779 return null; 9780 } 9781 9782 /** 9783 * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()} 9784 * and {@link #onFinishTemporaryDetach()}. 9785 */ isTemporarilyDetached()9786 public final boolean isTemporarilyDetached() { 9787 return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0; 9788 } 9789 9790 /** 9791 * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is 9792 * a container View. 9793 */ 9794 @CallSuper dispatchStartTemporaryDetach()9795 public void dispatchStartTemporaryDetach() { 9796 mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH; 9797 onStartTemporaryDetach(); 9798 } 9799 9800 /** 9801 * This is called when a container is going to temporarily detach a child, with 9802 * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}. 9803 * It will either be followed by {@link #onFinishTemporaryDetach()} or 9804 * {@link #onDetachedFromWindow()} when the container is done. 9805 */ onStartTemporaryDetach()9806 public void onStartTemporaryDetach() { 9807 removeUnsetPressCallback(); 9808 mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT; 9809 } 9810 9811 /** 9812 * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is 9813 * a container View. 9814 */ 9815 @CallSuper dispatchFinishTemporaryDetach()9816 public void dispatchFinishTemporaryDetach() { 9817 onFinishTemporaryDetach(); 9818 mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH; 9819 } 9820 9821 /** 9822 * Called after {@link #onStartTemporaryDetach} when the container is done 9823 * changing the view. 9824 */ onFinishTemporaryDetach()9825 public void onFinishTemporaryDetach() { 9826 } 9827 9828 /** 9829 * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState} 9830 * for this view's window. Returns null if the view is not currently attached 9831 * to the window. Normally you will not need to use this directly, but 9832 * just use the standard high-level event callbacks like 9833 * {@link #onKeyDown(int, KeyEvent)}. 9834 */ getKeyDispatcherState()9835 public KeyEvent.DispatcherState getKeyDispatcherState() { 9836 return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null; 9837 } 9838 9839 /** 9840 * Dispatch a key event before it is processed by any input method 9841 * associated with the view hierarchy. This can be used to intercept 9842 * key events in special situations before the IME consumes them; a 9843 * typical example would be handling the BACK key to update the application's 9844 * UI instead of allowing the IME to see it and close itself. 9845 * 9846 * @param event The key event to be dispatched. 9847 * @return True if the event was handled, false otherwise. 9848 */ dispatchKeyEventPreIme(KeyEvent event)9849 public boolean dispatchKeyEventPreIme(KeyEvent event) { 9850 return onKeyPreIme(event.getKeyCode(), event); 9851 } 9852 9853 /** 9854 * Dispatch a key event to the next view on the focus path. This path runs 9855 * from the top of the view tree down to the currently focused view. If this 9856 * view has focus, it will dispatch to itself. Otherwise it will dispatch 9857 * the next node down the focus path. This method also fires any key 9858 * listeners. 9859 * 9860 * @param event The key event to be dispatched. 9861 * @return True if the event was handled, false otherwise. 9862 */ dispatchKeyEvent(KeyEvent event)9863 public boolean dispatchKeyEvent(KeyEvent event) { 9864 if (mInputEventConsistencyVerifier != null) { 9865 mInputEventConsistencyVerifier.onKeyEvent(event, 0); 9866 } 9867 9868 // Give any attached key listener a first crack at the event. 9869 //noinspection SimplifiableIfStatement 9870 ListenerInfo li = mListenerInfo; 9871 if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED 9872 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) { 9873 return true; 9874 } 9875 9876 if (event.dispatch(this, mAttachInfo != null 9877 ? mAttachInfo.mKeyDispatchState : null, this)) { 9878 return true; 9879 } 9880 9881 if (mInputEventConsistencyVerifier != null) { 9882 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 9883 } 9884 return false; 9885 } 9886 9887 /** 9888 * Dispatches a key shortcut event. 9889 * 9890 * @param event The key event to be dispatched. 9891 * @return True if the event was handled by the view, false otherwise. 9892 */ dispatchKeyShortcutEvent(KeyEvent event)9893 public boolean dispatchKeyShortcutEvent(KeyEvent event) { 9894 return onKeyShortcut(event.getKeyCode(), event); 9895 } 9896 9897 /** 9898 * Pass the touch screen motion event down to the target view, or this 9899 * view if it is the target. 9900 * 9901 * @param event The motion event to be dispatched. 9902 * @return True if the event was handled by the view, false otherwise. 9903 */ dispatchTouchEvent(MotionEvent event)9904 public boolean dispatchTouchEvent(MotionEvent event) { 9905 // If the event should be handled by accessibility focus first. 9906 if (event.isTargetAccessibilityFocus()) { 9907 // We don't have focus or no virtual descendant has it, do not handle the event. 9908 if (!isAccessibilityFocusedViewOrHost()) { 9909 return false; 9910 } 9911 // We have focus and got the event, then use normal event dispatch. 9912 event.setTargetAccessibilityFocus(false); 9913 } 9914 9915 boolean result = false; 9916 9917 if (mInputEventConsistencyVerifier != null) { 9918 mInputEventConsistencyVerifier.onTouchEvent(event, 0); 9919 } 9920 9921 final int actionMasked = event.getActionMasked(); 9922 if (actionMasked == MotionEvent.ACTION_DOWN) { 9923 // Defensive cleanup for new gesture 9924 stopNestedScroll(); 9925 } 9926 9927 if (onFilterTouchEventForSecurity(event)) { 9928 if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) { 9929 result = true; 9930 } 9931 //noinspection SimplifiableIfStatement 9932 ListenerInfo li = mListenerInfo; 9933 if (li != null && li.mOnTouchListener != null 9934 && (mViewFlags & ENABLED_MASK) == ENABLED 9935 && li.mOnTouchListener.onTouch(this, event)) { 9936 result = true; 9937 } 9938 9939 if (!result && onTouchEvent(event)) { 9940 result = true; 9941 } 9942 } 9943 9944 if (!result && mInputEventConsistencyVerifier != null) { 9945 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 9946 } 9947 9948 // Clean up after nested scrolls if this is the end of a gesture; 9949 // also cancel it if we tried an ACTION_DOWN but we didn't want the rest 9950 // of the gesture. 9951 if (actionMasked == MotionEvent.ACTION_UP || 9952 actionMasked == MotionEvent.ACTION_CANCEL || 9953 (actionMasked == MotionEvent.ACTION_DOWN && !result)) { 9954 stopNestedScroll(); 9955 } 9956 9957 return result; 9958 } 9959 isAccessibilityFocusedViewOrHost()9960 boolean isAccessibilityFocusedViewOrHost() { 9961 return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl() 9962 .getAccessibilityFocusedHost() == this); 9963 } 9964 9965 /** 9966 * Filter the touch event to apply security policies. 9967 * 9968 * @param event The motion event to be filtered. 9969 * @return True if the event should be dispatched, false if the event should be dropped. 9970 * 9971 * @see #getFilterTouchesWhenObscured 9972 */ onFilterTouchEventForSecurity(MotionEvent event)9973 public boolean onFilterTouchEventForSecurity(MotionEvent event) { 9974 //noinspection RedundantIfStatement 9975 if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0 9976 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) { 9977 // Window is obscured, drop this touch. 9978 return false; 9979 } 9980 return true; 9981 } 9982 9983 /** 9984 * Pass a trackball motion event down to the focused view. 9985 * 9986 * @param event The motion event to be dispatched. 9987 * @return True if the event was handled by the view, false otherwise. 9988 */ dispatchTrackballEvent(MotionEvent event)9989 public boolean dispatchTrackballEvent(MotionEvent event) { 9990 if (mInputEventConsistencyVerifier != null) { 9991 mInputEventConsistencyVerifier.onTrackballEvent(event, 0); 9992 } 9993 9994 return onTrackballEvent(event); 9995 } 9996 9997 /** 9998 * Dispatch a generic motion event. 9999 * <p> 10000 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER} 10001 * are delivered to the view under the pointer. All other generic motion events are 10002 * delivered to the focused view. Hover events are handled specially and are delivered 10003 * to {@link #onHoverEvent(MotionEvent)}. 10004 * </p> 10005 * 10006 * @param event The motion event to be dispatched. 10007 * @return True if the event was handled by the view, false otherwise. 10008 */ dispatchGenericMotionEvent(MotionEvent event)10009 public boolean dispatchGenericMotionEvent(MotionEvent event) { 10010 if (mInputEventConsistencyVerifier != null) { 10011 mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0); 10012 } 10013 10014 final int source = event.getSource(); 10015 if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) { 10016 final int action = event.getAction(); 10017 if (action == MotionEvent.ACTION_HOVER_ENTER 10018 || action == MotionEvent.ACTION_HOVER_MOVE 10019 || action == MotionEvent.ACTION_HOVER_EXIT) { 10020 if (dispatchHoverEvent(event)) { 10021 return true; 10022 } 10023 } else if (dispatchGenericPointerEvent(event)) { 10024 return true; 10025 } 10026 } else if (dispatchGenericFocusedEvent(event)) { 10027 return true; 10028 } 10029 10030 if (dispatchGenericMotionEventInternal(event)) { 10031 return true; 10032 } 10033 10034 if (mInputEventConsistencyVerifier != null) { 10035 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 10036 } 10037 return false; 10038 } 10039 dispatchGenericMotionEventInternal(MotionEvent event)10040 private boolean dispatchGenericMotionEventInternal(MotionEvent event) { 10041 //noinspection SimplifiableIfStatement 10042 ListenerInfo li = mListenerInfo; 10043 if (li != null && li.mOnGenericMotionListener != null 10044 && (mViewFlags & ENABLED_MASK) == ENABLED 10045 && li.mOnGenericMotionListener.onGenericMotion(this, event)) { 10046 return true; 10047 } 10048 10049 if (onGenericMotionEvent(event)) { 10050 return true; 10051 } 10052 10053 final int actionButton = event.getActionButton(); 10054 switch (event.getActionMasked()) { 10055 case MotionEvent.ACTION_BUTTON_PRESS: 10056 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress 10057 && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY 10058 || actionButton == MotionEvent.BUTTON_SECONDARY)) { 10059 if (performContextClick(event.getX(), event.getY())) { 10060 mInContextButtonPress = true; 10061 setPressed(true, event.getX(), event.getY()); 10062 removeTapCallback(); 10063 removeLongPressCallback(); 10064 return true; 10065 } 10066 } 10067 break; 10068 10069 case MotionEvent.ACTION_BUTTON_RELEASE: 10070 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY 10071 || actionButton == MotionEvent.BUTTON_SECONDARY)) { 10072 mInContextButtonPress = false; 10073 mIgnoreNextUpEvent = true; 10074 } 10075 break; 10076 } 10077 10078 if (mInputEventConsistencyVerifier != null) { 10079 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 10080 } 10081 return false; 10082 } 10083 10084 /** 10085 * Dispatch a hover event. 10086 * <p> 10087 * Do not call this method directly. 10088 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead. 10089 * </p> 10090 * 10091 * @param event The motion event to be dispatched. 10092 * @return True if the event was handled by the view, false otherwise. 10093 */ dispatchHoverEvent(MotionEvent event)10094 protected boolean dispatchHoverEvent(MotionEvent event) { 10095 ListenerInfo li = mListenerInfo; 10096 //noinspection SimplifiableIfStatement 10097 if (li != null && li.mOnHoverListener != null 10098 && (mViewFlags & ENABLED_MASK) == ENABLED 10099 && li.mOnHoverListener.onHover(this, event)) { 10100 return true; 10101 } 10102 10103 return onHoverEvent(event); 10104 } 10105 10106 /** 10107 * Returns true if the view has a child to which it has recently sent 10108 * {@link MotionEvent#ACTION_HOVER_ENTER}. If this view is hovered and 10109 * it does not have a hovered child, then it must be the innermost hovered view. 10110 * @hide 10111 */ hasHoveredChild()10112 protected boolean hasHoveredChild() { 10113 return false; 10114 } 10115 10116 /** 10117 * Dispatch a generic motion event to the view under the first pointer. 10118 * <p> 10119 * Do not call this method directly. 10120 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead. 10121 * </p> 10122 * 10123 * @param event The motion event to be dispatched. 10124 * @return True if the event was handled by the view, false otherwise. 10125 */ dispatchGenericPointerEvent(MotionEvent event)10126 protected boolean dispatchGenericPointerEvent(MotionEvent event) { 10127 return false; 10128 } 10129 10130 /** 10131 * Dispatch a generic motion event to the currently focused view. 10132 * <p> 10133 * Do not call this method directly. 10134 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead. 10135 * </p> 10136 * 10137 * @param event The motion event to be dispatched. 10138 * @return True if the event was handled by the view, false otherwise. 10139 */ dispatchGenericFocusedEvent(MotionEvent event)10140 protected boolean dispatchGenericFocusedEvent(MotionEvent event) { 10141 return false; 10142 } 10143 10144 /** 10145 * Dispatch a pointer event. 10146 * <p> 10147 * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all 10148 * other events to {@link #onGenericMotionEvent(MotionEvent)}. This separation of concerns 10149 * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches 10150 * and should not be expected to handle other pointing device features. 10151 * </p> 10152 * 10153 * @param event The motion event to be dispatched. 10154 * @return True if the event was handled by the view, false otherwise. 10155 * @hide 10156 */ dispatchPointerEvent(MotionEvent event)10157 public final boolean dispatchPointerEvent(MotionEvent event) { 10158 if (event.isTouchEvent()) { 10159 return dispatchTouchEvent(event); 10160 } else { 10161 return dispatchGenericMotionEvent(event); 10162 } 10163 } 10164 10165 /** 10166 * Called when the window containing this view gains or loses window focus. 10167 * ViewGroups should override to route to their children. 10168 * 10169 * @param hasFocus True if the window containing this view now has focus, 10170 * false otherwise. 10171 */ dispatchWindowFocusChanged(boolean hasFocus)10172 public void dispatchWindowFocusChanged(boolean hasFocus) { 10173 onWindowFocusChanged(hasFocus); 10174 } 10175 10176 /** 10177 * Called when the window containing this view gains or loses focus. Note 10178 * that this is separate from view focus: to receive key events, both 10179 * your view and its window must have focus. If a window is displayed 10180 * on top of yours that takes input focus, then your own window will lose 10181 * focus but the view focus will remain unchanged. 10182 * 10183 * @param hasWindowFocus True if the window containing this view now has 10184 * focus, false otherwise. 10185 */ onWindowFocusChanged(boolean hasWindowFocus)10186 public void onWindowFocusChanged(boolean hasWindowFocus) { 10187 InputMethodManager imm = InputMethodManager.peekInstance(); 10188 if (!hasWindowFocus) { 10189 if (isPressed()) { 10190 setPressed(false); 10191 } 10192 if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) { 10193 imm.focusOut(this); 10194 } 10195 removeLongPressCallback(); 10196 removeTapCallback(); 10197 onFocusLost(); 10198 } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) { 10199 imm.focusIn(this); 10200 } 10201 refreshDrawableState(); 10202 } 10203 10204 /** 10205 * Returns true if this view is in a window that currently has window focus. 10206 * Note that this is not the same as the view itself having focus. 10207 * 10208 * @return True if this view is in a window that currently has window focus. 10209 */ hasWindowFocus()10210 public boolean hasWindowFocus() { 10211 return mAttachInfo != null && mAttachInfo.mHasWindowFocus; 10212 } 10213 10214 /** 10215 * Dispatch a view visibility change down the view hierarchy. 10216 * ViewGroups should override to route to their children. 10217 * @param changedView The view whose visibility changed. Could be 'this' or 10218 * an ancestor view. 10219 * @param visibility The new visibility of changedView: {@link #VISIBLE}, 10220 * {@link #INVISIBLE} or {@link #GONE}. 10221 */ dispatchVisibilityChanged(@onNull View changedView, @Visibility int visibility)10222 protected void dispatchVisibilityChanged(@NonNull View changedView, 10223 @Visibility int visibility) { 10224 onVisibilityChanged(changedView, visibility); 10225 } 10226 10227 /** 10228 * Called when the visibility of the view or an ancestor of the view has 10229 * changed. 10230 * 10231 * @param changedView The view whose visibility changed. May be 10232 * {@code this} or an ancestor view. 10233 * @param visibility The new visibility, one of {@link #VISIBLE}, 10234 * {@link #INVISIBLE} or {@link #GONE}. 10235 */ onVisibilityChanged(@onNull View changedView, @Visibility int visibility)10236 protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) { 10237 } 10238 10239 /** 10240 * Dispatch a hint about whether this view is displayed. For instance, when 10241 * a View moves out of the screen, it might receives a display hint indicating 10242 * the view is not displayed. Applications should not <em>rely</em> on this hint 10243 * as there is no guarantee that they will receive one. 10244 * 10245 * @param hint A hint about whether or not this view is displayed: 10246 * {@link #VISIBLE} or {@link #INVISIBLE}. 10247 */ dispatchDisplayHint(@isibility int hint)10248 public void dispatchDisplayHint(@Visibility int hint) { 10249 onDisplayHint(hint); 10250 } 10251 10252 /** 10253 * Gives this view a hint about whether is displayed or not. For instance, when 10254 * a View moves out of the screen, it might receives a display hint indicating 10255 * the view is not displayed. Applications should not <em>rely</em> on this hint 10256 * as there is no guarantee that they will receive one. 10257 * 10258 * @param hint A hint about whether or not this view is displayed: 10259 * {@link #VISIBLE} or {@link #INVISIBLE}. 10260 */ onDisplayHint(@isibility int hint)10261 protected void onDisplayHint(@Visibility int hint) { 10262 } 10263 10264 /** 10265 * Dispatch a window visibility change down the view hierarchy. 10266 * ViewGroups should override to route to their children. 10267 * 10268 * @param visibility The new visibility of the window. 10269 * 10270 * @see #onWindowVisibilityChanged(int) 10271 */ dispatchWindowVisibilityChanged(@isibility int visibility)10272 public void dispatchWindowVisibilityChanged(@Visibility int visibility) { 10273 onWindowVisibilityChanged(visibility); 10274 } 10275 10276 /** 10277 * Called when the window containing has change its visibility 10278 * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}). Note 10279 * that this tells you whether or not your window is being made visible 10280 * to the window manager; this does <em>not</em> tell you whether or not 10281 * your window is obscured by other windows on the screen, even if it 10282 * is itself visible. 10283 * 10284 * @param visibility The new visibility of the window. 10285 */ onWindowVisibilityChanged(@isibility int visibility)10286 protected void onWindowVisibilityChanged(@Visibility int visibility) { 10287 if (visibility == VISIBLE) { 10288 initialAwakenScrollBars(); 10289 } 10290 } 10291 10292 /** 10293 * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by 10294 * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()}, 10295 * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}. 10296 * 10297 * @param isVisible true if this view's visibility to the user is uninterrupted by its 10298 * ancestors or by window visibility 10299 * @return true if this view is visible to the user, not counting clipping or overlapping 10300 */ dispatchVisibilityAggregated(boolean isVisible)10301 @Visibility boolean dispatchVisibilityAggregated(boolean isVisible) { 10302 final boolean thisVisible = getVisibility() == VISIBLE; 10303 // If we're not visible but something is telling us we are, ignore it. 10304 if (thisVisible || !isVisible) { 10305 onVisibilityAggregated(isVisible); 10306 } 10307 return thisVisible && isVisible; 10308 } 10309 10310 /** 10311 * Called when the user-visibility of this View is potentially affected by a change 10312 * to this view itself, an ancestor view or the window this view is attached to. 10313 * 10314 * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE} 10315 * and this view's window is also visible 10316 */ 10317 @CallSuper onVisibilityAggregated(boolean isVisible)10318 public void onVisibilityAggregated(boolean isVisible) { 10319 if (isVisible && mAttachInfo != null) { 10320 initialAwakenScrollBars(); 10321 } 10322 10323 final Drawable dr = mBackground; 10324 if (dr != null && isVisible != dr.isVisible()) { 10325 dr.setVisible(isVisible, false); 10326 } 10327 final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null; 10328 if (fg != null && isVisible != fg.isVisible()) { 10329 fg.setVisible(isVisible, false); 10330 } 10331 } 10332 10333 /** 10334 * Returns the current visibility of the window this view is attached to 10335 * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}). 10336 * 10337 * @return Returns the current visibility of the view's window. 10338 */ 10339 @Visibility getWindowVisibility()10340 public int getWindowVisibility() { 10341 return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE; 10342 } 10343 10344 /** 10345 * Retrieve the overall visible display size in which the window this view is 10346 * attached to has been positioned in. This takes into account screen 10347 * decorations above the window, for both cases where the window itself 10348 * is being position inside of them or the window is being placed under 10349 * then and covered insets are used for the window to position its content 10350 * inside. In effect, this tells you the available area where content can 10351 * be placed and remain visible to users. 10352 * 10353 * <p>This function requires an IPC back to the window manager to retrieve 10354 * the requested information, so should not be used in performance critical 10355 * code like drawing. 10356 * 10357 * @param outRect Filled in with the visible display frame. If the view 10358 * is not attached to a window, this is simply the raw display size. 10359 */ getWindowVisibleDisplayFrame(Rect outRect)10360 public void getWindowVisibleDisplayFrame(Rect outRect) { 10361 if (mAttachInfo != null) { 10362 try { 10363 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect); 10364 } catch (RemoteException e) { 10365 return; 10366 } 10367 // XXX This is really broken, and probably all needs to be done 10368 // in the window manager, and we need to know more about whether 10369 // we want the area behind or in front of the IME. 10370 final Rect insets = mAttachInfo.mVisibleInsets; 10371 outRect.left += insets.left; 10372 outRect.top += insets.top; 10373 outRect.right -= insets.right; 10374 outRect.bottom -= insets.bottom; 10375 return; 10376 } 10377 // The view is not attached to a display so we don't have a context. 10378 // Make a best guess about the display size. 10379 Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY); 10380 d.getRectSize(outRect); 10381 } 10382 10383 /** 10384 * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window 10385 * is currently in without any insets. 10386 * 10387 * @hide 10388 */ getWindowDisplayFrame(Rect outRect)10389 public void getWindowDisplayFrame(Rect outRect) { 10390 if (mAttachInfo != null) { 10391 try { 10392 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect); 10393 } catch (RemoteException e) { 10394 return; 10395 } 10396 return; 10397 } 10398 // The view is not attached to a display so we don't have a context. 10399 // Make a best guess about the display size. 10400 Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY); 10401 d.getRectSize(outRect); 10402 } 10403 10404 /** 10405 * Dispatch a notification about a resource configuration change down 10406 * the view hierarchy. 10407 * ViewGroups should override to route to their children. 10408 * 10409 * @param newConfig The new resource configuration. 10410 * 10411 * @see #onConfigurationChanged(android.content.res.Configuration) 10412 */ dispatchConfigurationChanged(Configuration newConfig)10413 public void dispatchConfigurationChanged(Configuration newConfig) { 10414 onConfigurationChanged(newConfig); 10415 } 10416 10417 /** 10418 * Called when the current configuration of the resources being used 10419 * by the application have changed. You can use this to decide when 10420 * to reload resources that can changed based on orientation and other 10421 * configuration characteristics. You only need to use this if you are 10422 * not relying on the normal {@link android.app.Activity} mechanism of 10423 * recreating the activity instance upon a configuration change. 10424 * 10425 * @param newConfig The new resource configuration. 10426 */ onConfigurationChanged(Configuration newConfig)10427 protected void onConfigurationChanged(Configuration newConfig) { 10428 } 10429 10430 /** 10431 * Private function to aggregate all per-view attributes in to the view 10432 * root. 10433 */ dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility)10434 void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) { 10435 performCollectViewAttributes(attachInfo, visibility); 10436 } 10437 performCollectViewAttributes(AttachInfo attachInfo, int visibility)10438 void performCollectViewAttributes(AttachInfo attachInfo, int visibility) { 10439 if ((visibility & VISIBILITY_MASK) == VISIBLE) { 10440 if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) { 10441 attachInfo.mKeepScreenOn = true; 10442 } 10443 attachInfo.mSystemUiVisibility |= mSystemUiVisibility; 10444 ListenerInfo li = mListenerInfo; 10445 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) { 10446 attachInfo.mHasSystemUiListeners = true; 10447 } 10448 } 10449 } 10450 needGlobalAttributesUpdate(boolean force)10451 void needGlobalAttributesUpdate(boolean force) { 10452 final AttachInfo ai = mAttachInfo; 10453 if (ai != null && !ai.mRecomputeGlobalAttributes) { 10454 if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0) 10455 || ai.mHasSystemUiListeners) { 10456 ai.mRecomputeGlobalAttributes = true; 10457 } 10458 } 10459 } 10460 10461 /** 10462 * Returns whether the device is currently in touch mode. Touch mode is entered 10463 * once the user begins interacting with the device by touch, and affects various 10464 * things like whether focus is always visible to the user. 10465 * 10466 * @return Whether the device is in touch mode. 10467 */ 10468 @ViewDebug.ExportedProperty isInTouchMode()10469 public boolean isInTouchMode() { 10470 if (mAttachInfo != null) { 10471 return mAttachInfo.mInTouchMode; 10472 } else { 10473 return ViewRootImpl.isInTouchMode(); 10474 } 10475 } 10476 10477 /** 10478 * Returns the context the view is running in, through which it can 10479 * access the current theme, resources, etc. 10480 * 10481 * @return The view's Context. 10482 */ 10483 @ViewDebug.CapturedViewProperty getContext()10484 public final Context getContext() { 10485 return mContext; 10486 } 10487 10488 /** 10489 * Handle a key event before it is processed by any input method 10490 * associated with the view hierarchy. This can be used to intercept 10491 * key events in special situations before the IME consumes them; a 10492 * typical example would be handling the BACK key to update the application's 10493 * UI instead of allowing the IME to see it and close itself. 10494 * 10495 * @param keyCode The value in event.getKeyCode(). 10496 * @param event Description of the key event. 10497 * @return If you handled the event, return true. If you want to allow the 10498 * event to be handled by the next receiver, return false. 10499 */ onKeyPreIme(int keyCode, KeyEvent event)10500 public boolean onKeyPreIme(int keyCode, KeyEvent event) { 10501 return false; 10502 } 10503 10504 /** 10505 * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent) 10506 * KeyEvent.Callback.onKeyDown()}: perform press of the view 10507 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER} 10508 * is released, if the view is enabled and clickable. 10509 * <p> 10510 * Key presses in software keyboards will generally NOT trigger this 10511 * listener, although some may elect to do so in some situations. Do not 10512 * rely on this to catch software key presses. 10513 * 10514 * @param keyCode a key code that represents the button pressed, from 10515 * {@link android.view.KeyEvent} 10516 * @param event the KeyEvent object that defines the button action 10517 */ onKeyDown(int keyCode, KeyEvent event)10518 public boolean onKeyDown(int keyCode, KeyEvent event) { 10519 if (KeyEvent.isConfirmKey(keyCode)) { 10520 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 10521 return true; 10522 } 10523 10524 // Long clickable items don't necessarily have to be clickable. 10525 if (((mViewFlags & CLICKABLE) == CLICKABLE 10526 || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) 10527 && (event.getRepeatCount() == 0)) { 10528 // For the purposes of menu anchoring and drawable hotspots, 10529 // key events are considered to be at the center of the view. 10530 final float x = getWidth() / 2f; 10531 final float y = getHeight() / 2f; 10532 setPressed(true, x, y); 10533 checkForLongClick(0, x, y); 10534 return true; 10535 } 10536 } 10537 10538 return false; 10539 } 10540 10541 /** 10542 * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent) 10543 * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle 10544 * the event). 10545 * <p>Key presses in software keyboards will generally NOT trigger this listener, 10546 * although some may elect to do so in some situations. Do not rely on this to 10547 * catch software key presses. 10548 */ onKeyLongPress(int keyCode, KeyEvent event)10549 public boolean onKeyLongPress(int keyCode, KeyEvent event) { 10550 return false; 10551 } 10552 10553 /** 10554 * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent) 10555 * KeyEvent.Callback.onKeyUp()}: perform clicking of the view 10556 * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER} 10557 * or {@link KeyEvent#KEYCODE_SPACE} is released. 10558 * <p>Key presses in software keyboards will generally NOT trigger this listener, 10559 * although some may elect to do so in some situations. Do not rely on this to 10560 * catch software key presses. 10561 * 10562 * @param keyCode A key code that represents the button pressed, from 10563 * {@link android.view.KeyEvent}. 10564 * @param event The KeyEvent object that defines the button action. 10565 */ onKeyUp(int keyCode, KeyEvent event)10566 public boolean onKeyUp(int keyCode, KeyEvent event) { 10567 if (KeyEvent.isConfirmKey(keyCode)) { 10568 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 10569 return true; 10570 } 10571 if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) { 10572 setPressed(false); 10573 10574 if (!mHasPerformedLongPress) { 10575 // This is a tap, so remove the longpress check 10576 removeLongPressCallback(); 10577 return performClick(); 10578 } 10579 } 10580 } 10581 return false; 10582 } 10583 10584 /** 10585 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent) 10586 * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle 10587 * the event). 10588 * <p>Key presses in software keyboards will generally NOT trigger this listener, 10589 * although some may elect to do so in some situations. Do not rely on this to 10590 * catch software key presses. 10591 * 10592 * @param keyCode A key code that represents the button pressed, from 10593 * {@link android.view.KeyEvent}. 10594 * @param repeatCount The number of times the action was made. 10595 * @param event The KeyEvent object that defines the button action. 10596 */ onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)10597 public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { 10598 return false; 10599 } 10600 10601 /** 10602 * Called on the focused view when a key shortcut event is not handled. 10603 * Override this method to implement local key shortcuts for the View. 10604 * Key shortcuts can also be implemented by setting the 10605 * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items. 10606 * 10607 * @param keyCode The value in event.getKeyCode(). 10608 * @param event Description of the key event. 10609 * @return If you handled the event, return true. If you want to allow the 10610 * event to be handled by the next receiver, return false. 10611 */ onKeyShortcut(int keyCode, KeyEvent event)10612 public boolean onKeyShortcut(int keyCode, KeyEvent event) { 10613 return false; 10614 } 10615 10616 /** 10617 * Check whether the called view is a text editor, in which case it 10618 * would make sense to automatically display a soft input window for 10619 * it. Subclasses should override this if they implement 10620 * {@link #onCreateInputConnection(EditorInfo)} to return true if 10621 * a call on that method would return a non-null InputConnection, and 10622 * they are really a first-class editor that the user would normally 10623 * start typing on when the go into a window containing your view. 10624 * 10625 * <p>The default implementation always returns false. This does 10626 * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)} 10627 * will not be called or the user can not otherwise perform edits on your 10628 * view; it is just a hint to the system that this is not the primary 10629 * purpose of this view. 10630 * 10631 * @return Returns true if this view is a text editor, else false. 10632 */ onCheckIsTextEditor()10633 public boolean onCheckIsTextEditor() { 10634 return false; 10635 } 10636 10637 /** 10638 * Create a new InputConnection for an InputMethod to interact 10639 * with the view. The default implementation returns null, since it doesn't 10640 * support input methods. You can override this to implement such support. 10641 * This is only needed for views that take focus and text input. 10642 * 10643 * <p>When implementing this, you probably also want to implement 10644 * {@link #onCheckIsTextEditor()} to indicate you will return a 10645 * non-null InputConnection.</p> 10646 * 10647 * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo} 10648 * object correctly and in its entirety, so that the connected IME can rely 10649 * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart} 10650 * and {@link android.view.inputmethod.EditorInfo#initialSelEnd} members 10651 * must be filled in with the correct cursor position for IMEs to work correctly 10652 * with your application.</p> 10653 * 10654 * @param outAttrs Fill in with attribute information about the connection. 10655 */ onCreateInputConnection(EditorInfo outAttrs)10656 public InputConnection onCreateInputConnection(EditorInfo outAttrs) { 10657 return null; 10658 } 10659 10660 /** 10661 * Called by the {@link android.view.inputmethod.InputMethodManager} 10662 * when a view who is not the current 10663 * input connection target is trying to make a call on the manager. The 10664 * default implementation returns false; you can override this to return 10665 * true for certain views if you are performing InputConnection proxying 10666 * to them. 10667 * @param view The View that is making the InputMethodManager call. 10668 * @return Return true to allow the call, false to reject. 10669 */ checkInputConnectionProxy(View view)10670 public boolean checkInputConnectionProxy(View view) { 10671 return false; 10672 } 10673 10674 /** 10675 * Show the context menu for this view. It is not safe to hold on to the 10676 * menu after returning from this method. 10677 * 10678 * You should normally not overload this method. Overload 10679 * {@link #onCreateContextMenu(ContextMenu)} or define an 10680 * {@link OnCreateContextMenuListener} to add items to the context menu. 10681 * 10682 * @param menu The context menu to populate 10683 */ createContextMenu(ContextMenu menu)10684 public void createContextMenu(ContextMenu menu) { 10685 ContextMenuInfo menuInfo = getContextMenuInfo(); 10686 10687 // Sets the current menu info so all items added to menu will have 10688 // my extra info set. 10689 ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo); 10690 10691 onCreateContextMenu(menu); 10692 ListenerInfo li = mListenerInfo; 10693 if (li != null && li.mOnCreateContextMenuListener != null) { 10694 li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo); 10695 } 10696 10697 // Clear the extra information so subsequent items that aren't mine don't 10698 // have my extra info. 10699 ((MenuBuilder)menu).setCurrentMenuInfo(null); 10700 10701 if (mParent != null) { 10702 mParent.createContextMenu(menu); 10703 } 10704 } 10705 10706 /** 10707 * Views should implement this if they have extra information to associate 10708 * with the context menu. The return result is supplied as a parameter to 10709 * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} 10710 * callback. 10711 * 10712 * @return Extra information about the item for which the context menu 10713 * should be shown. This information will vary across different 10714 * subclasses of View. 10715 */ getContextMenuInfo()10716 protected ContextMenuInfo getContextMenuInfo() { 10717 return null; 10718 } 10719 10720 /** 10721 * Views should implement this if the view itself is going to add items to 10722 * the context menu. 10723 * 10724 * @param menu the context menu to populate 10725 */ onCreateContextMenu(ContextMenu menu)10726 protected void onCreateContextMenu(ContextMenu menu) { 10727 } 10728 10729 /** 10730 * Implement this method to handle trackball motion events. The 10731 * <em>relative</em> movement of the trackball since the last event 10732 * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and 10733 * {@link MotionEvent#getY MotionEvent.getY()}. These are normalized so 10734 * that a movement of 1 corresponds to the user pressing one DPAD key (so 10735 * they will often be fractional values, representing the more fine-grained 10736 * movement information available from a trackball). 10737 * 10738 * @param event The motion event. 10739 * @return True if the event was handled, false otherwise. 10740 */ onTrackballEvent(MotionEvent event)10741 public boolean onTrackballEvent(MotionEvent event) { 10742 return false; 10743 } 10744 10745 /** 10746 * Implement this method to handle generic motion events. 10747 * <p> 10748 * Generic motion events describe joystick movements, mouse hovers, track pad 10749 * touches, scroll wheel movements and other input events. The 10750 * {@link MotionEvent#getSource() source} of the motion event specifies 10751 * the class of input that was received. Implementations of this method 10752 * must examine the bits in the source before processing the event. 10753 * The following code example shows how this is done. 10754 * </p><p> 10755 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER} 10756 * are delivered to the view under the pointer. All other generic motion events are 10757 * delivered to the focused view. 10758 * </p> 10759 * <pre> public boolean onGenericMotionEvent(MotionEvent event) { 10760 * if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) { 10761 * if (event.getAction() == MotionEvent.ACTION_MOVE) { 10762 * // process the joystick movement... 10763 * return true; 10764 * } 10765 * } 10766 * if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { 10767 * switch (event.getAction()) { 10768 * case MotionEvent.ACTION_HOVER_MOVE: 10769 * // process the mouse hover movement... 10770 * return true; 10771 * case MotionEvent.ACTION_SCROLL: 10772 * // process the scroll wheel movement... 10773 * return true; 10774 * } 10775 * } 10776 * return super.onGenericMotionEvent(event); 10777 * }</pre> 10778 * 10779 * @param event The generic motion event being processed. 10780 * @return True if the event was handled, false otherwise. 10781 */ onGenericMotionEvent(MotionEvent event)10782 public boolean onGenericMotionEvent(MotionEvent event) { 10783 return false; 10784 } 10785 10786 /** 10787 * Implement this method to handle hover events. 10788 * <p> 10789 * This method is called whenever a pointer is hovering into, over, or out of the 10790 * bounds of a view and the view is not currently being touched. 10791 * Hover events are represented as pointer events with action 10792 * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE}, 10793 * or {@link MotionEvent#ACTION_HOVER_EXIT}. 10794 * </p> 10795 * <ul> 10796 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER} 10797 * when the pointer enters the bounds of the view.</li> 10798 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE} 10799 * when the pointer has already entered the bounds of the view and has moved.</li> 10800 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT} 10801 * when the pointer has exited the bounds of the view or when the pointer is 10802 * about to go down due to a button click, tap, or similar user action that 10803 * causes the view to be touched.</li> 10804 * </ul> 10805 * <p> 10806 * The view should implement this method to return true to indicate that it is 10807 * handling the hover event, such as by changing its drawable state. 10808 * </p><p> 10809 * The default implementation calls {@link #setHovered} to update the hovered state 10810 * of the view when a hover enter or hover exit event is received, if the view 10811 * is enabled and is clickable. The default implementation also sends hover 10812 * accessibility events. 10813 * </p> 10814 * 10815 * @param event The motion event that describes the hover. 10816 * @return True if the view handled the hover event. 10817 * 10818 * @see #isHovered 10819 * @see #setHovered 10820 * @see #onHoverChanged 10821 */ onHoverEvent(MotionEvent event)10822 public boolean onHoverEvent(MotionEvent event) { 10823 // The root view may receive hover (or touch) events that are outside the bounds of 10824 // the window. This code ensures that we only send accessibility events for 10825 // hovers that are actually within the bounds of the root view. 10826 final int action = event.getActionMasked(); 10827 if (!mSendingHoverAccessibilityEvents) { 10828 if ((action == MotionEvent.ACTION_HOVER_ENTER 10829 || action == MotionEvent.ACTION_HOVER_MOVE) 10830 && !hasHoveredChild() 10831 && pointInView(event.getX(), event.getY())) { 10832 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER); 10833 mSendingHoverAccessibilityEvents = true; 10834 } 10835 } else { 10836 if (action == MotionEvent.ACTION_HOVER_EXIT 10837 || (action == MotionEvent.ACTION_MOVE 10838 && !pointInView(event.getX(), event.getY()))) { 10839 mSendingHoverAccessibilityEvents = false; 10840 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT); 10841 } 10842 } 10843 10844 if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE) 10845 && event.isFromSource(InputDevice.SOURCE_MOUSE) 10846 && isOnScrollbar(event.getX(), event.getY())) { 10847 awakenScrollBars(); 10848 } 10849 if (isHoverable()) { 10850 switch (action) { 10851 case MotionEvent.ACTION_HOVER_ENTER: 10852 setHovered(true); 10853 break; 10854 case MotionEvent.ACTION_HOVER_EXIT: 10855 setHovered(false); 10856 break; 10857 } 10858 10859 // Dispatch the event to onGenericMotionEvent before returning true. 10860 // This is to provide compatibility with existing applications that 10861 // handled HOVER_MOVE events in onGenericMotionEvent and that would 10862 // break because of the new default handling for hoverable views 10863 // in onHoverEvent. 10864 // Note that onGenericMotionEvent will be called by default when 10865 // onHoverEvent returns false (refer to dispatchGenericMotionEvent). 10866 dispatchGenericMotionEventInternal(event); 10867 // The event was already handled by calling setHovered(), so always 10868 // return true. 10869 return true; 10870 } 10871 10872 return false; 10873 } 10874 10875 /** 10876 * Returns true if the view should handle {@link #onHoverEvent} 10877 * by calling {@link #setHovered} to change its hovered state. 10878 * 10879 * @return True if the view is hoverable. 10880 */ isHoverable()10881 private boolean isHoverable() { 10882 final int viewFlags = mViewFlags; 10883 if ((viewFlags & ENABLED_MASK) == DISABLED) { 10884 return false; 10885 } 10886 10887 return (viewFlags & CLICKABLE) == CLICKABLE 10888 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE 10889 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE; 10890 } 10891 10892 /** 10893 * Returns true if the view is currently hovered. 10894 * 10895 * @return True if the view is currently hovered. 10896 * 10897 * @see #setHovered 10898 * @see #onHoverChanged 10899 */ 10900 @ViewDebug.ExportedProperty isHovered()10901 public boolean isHovered() { 10902 return (mPrivateFlags & PFLAG_HOVERED) != 0; 10903 } 10904 10905 /** 10906 * Sets whether the view is currently hovered. 10907 * <p> 10908 * Calling this method also changes the drawable state of the view. This 10909 * enables the view to react to hover by using different drawable resources 10910 * to change its appearance. 10911 * </p><p> 10912 * The {@link #onHoverChanged} method is called when the hovered state changes. 10913 * </p> 10914 * 10915 * @param hovered True if the view is hovered. 10916 * 10917 * @see #isHovered 10918 * @see #onHoverChanged 10919 */ setHovered(boolean hovered)10920 public void setHovered(boolean hovered) { 10921 if (hovered) { 10922 if ((mPrivateFlags & PFLAG_HOVERED) == 0) { 10923 mPrivateFlags |= PFLAG_HOVERED; 10924 refreshDrawableState(); 10925 onHoverChanged(true); 10926 } 10927 } else { 10928 if ((mPrivateFlags & PFLAG_HOVERED) != 0) { 10929 mPrivateFlags &= ~PFLAG_HOVERED; 10930 refreshDrawableState(); 10931 onHoverChanged(false); 10932 } 10933 } 10934 } 10935 10936 /** 10937 * Implement this method to handle hover state changes. 10938 * <p> 10939 * This method is called whenever the hover state changes as a result of a 10940 * call to {@link #setHovered}. 10941 * </p> 10942 * 10943 * @param hovered The current hover state, as returned by {@link #isHovered}. 10944 * 10945 * @see #isHovered 10946 * @see #setHovered 10947 */ onHoverChanged(boolean hovered)10948 public void onHoverChanged(boolean hovered) { 10949 } 10950 10951 /** 10952 * Handles scroll bar dragging by mouse input. 10953 * 10954 * @hide 10955 * @param event The motion event. 10956 * 10957 * @return true if the event was handled as a scroll bar dragging, false otherwise. 10958 */ handleScrollBarDragging(MotionEvent event)10959 protected boolean handleScrollBarDragging(MotionEvent event) { 10960 if (mScrollCache == null) { 10961 return false; 10962 } 10963 final float x = event.getX(); 10964 final float y = event.getY(); 10965 final int action = event.getAction(); 10966 if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING 10967 && action != MotionEvent.ACTION_DOWN) 10968 || !event.isFromSource(InputDevice.SOURCE_MOUSE) 10969 || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) { 10970 mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING; 10971 return false; 10972 } 10973 10974 switch (action) { 10975 case MotionEvent.ACTION_MOVE: 10976 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) { 10977 return false; 10978 } 10979 if (mScrollCache.mScrollBarDraggingState 10980 == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) { 10981 final Rect bounds = mScrollCache.mScrollBarBounds; 10982 getVerticalScrollBarBounds(bounds); 10983 final int range = computeVerticalScrollRange(); 10984 final int offset = computeVerticalScrollOffset(); 10985 final int extent = computeVerticalScrollExtent(); 10986 10987 final int thumbLength = ScrollBarUtils.getThumbLength( 10988 bounds.height(), bounds.width(), extent, range); 10989 final int thumbOffset = ScrollBarUtils.getThumbOffset( 10990 bounds.height(), thumbLength, extent, range, offset); 10991 10992 final float diff = y - mScrollCache.mScrollBarDraggingPos; 10993 final float maxThumbOffset = bounds.height() - thumbLength; 10994 final float newThumbOffset = 10995 Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset); 10996 final int height = getHeight(); 10997 if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0 10998 && height > 0 && extent > 0) { 10999 final int newY = Math.round((range - extent) 11000 / ((float)extent / height) * (newThumbOffset / maxThumbOffset)); 11001 if (newY != getScrollY()) { 11002 mScrollCache.mScrollBarDraggingPos = y; 11003 setScrollY(newY); 11004 } 11005 } 11006 return true; 11007 } 11008 if (mScrollCache.mScrollBarDraggingState 11009 == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) { 11010 final Rect bounds = mScrollCache.mScrollBarBounds; 11011 getHorizontalScrollBarBounds(bounds); 11012 final int range = computeHorizontalScrollRange(); 11013 final int offset = computeHorizontalScrollOffset(); 11014 final int extent = computeHorizontalScrollExtent(); 11015 11016 final int thumbLength = ScrollBarUtils.getThumbLength( 11017 bounds.width(), bounds.height(), extent, range); 11018 final int thumbOffset = ScrollBarUtils.getThumbOffset( 11019 bounds.width(), thumbLength, extent, range, offset); 11020 11021 final float diff = x - mScrollCache.mScrollBarDraggingPos; 11022 final float maxThumbOffset = bounds.width() - thumbLength; 11023 final float newThumbOffset = 11024 Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset); 11025 final int width = getWidth(); 11026 if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0 11027 && width > 0 && extent > 0) { 11028 final int newX = Math.round((range - extent) 11029 / ((float)extent / width) * (newThumbOffset / maxThumbOffset)); 11030 if (newX != getScrollX()) { 11031 mScrollCache.mScrollBarDraggingPos = x; 11032 setScrollX(newX); 11033 } 11034 } 11035 return true; 11036 } 11037 case MotionEvent.ACTION_DOWN: 11038 if (mScrollCache.state == ScrollabilityCache.OFF) { 11039 return false; 11040 } 11041 if (isOnVerticalScrollbarThumb(x, y)) { 11042 mScrollCache.mScrollBarDraggingState = 11043 ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR; 11044 mScrollCache.mScrollBarDraggingPos = y; 11045 return true; 11046 } 11047 if (isOnHorizontalScrollbarThumb(x, y)) { 11048 mScrollCache.mScrollBarDraggingState = 11049 ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR; 11050 mScrollCache.mScrollBarDraggingPos = x; 11051 return true; 11052 } 11053 } 11054 mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING; 11055 return false; 11056 } 11057 11058 /** 11059 * Implement this method to handle touch screen motion events. 11060 * <p> 11061 * If this method is used to detect click actions, it is recommended that 11062 * the actions be performed by implementing and calling 11063 * {@link #performClick()}. This will ensure consistent system behavior, 11064 * including: 11065 * <ul> 11066 * <li>obeying click sound preferences 11067 * <li>dispatching OnClickListener calls 11068 * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when 11069 * accessibility features are enabled 11070 * </ul> 11071 * 11072 * @param event The motion event. 11073 * @return True if the event was handled, false otherwise. 11074 */ onTouchEvent(MotionEvent event)11075 public boolean onTouchEvent(MotionEvent event) { 11076 final float x = event.getX(); 11077 final float y = event.getY(); 11078 final int viewFlags = mViewFlags; 11079 final int action = event.getAction(); 11080 11081 if ((viewFlags & ENABLED_MASK) == DISABLED) { 11082 if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) { 11083 setPressed(false); 11084 } 11085 // A disabled view that is clickable still consumes the touch 11086 // events, it just doesn't respond to them. 11087 return (((viewFlags & CLICKABLE) == CLICKABLE 11088 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) 11089 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE); 11090 } 11091 if (mTouchDelegate != null) { 11092 if (mTouchDelegate.onTouchEvent(event)) { 11093 return true; 11094 } 11095 } 11096 11097 if (((viewFlags & CLICKABLE) == CLICKABLE || 11098 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) || 11099 (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) { 11100 switch (action) { 11101 case MotionEvent.ACTION_UP: 11102 boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0; 11103 if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) { 11104 // take focus if we don't have it already and we should in 11105 // touch mode. 11106 boolean focusTaken = false; 11107 if (isFocusable() && isFocusableInTouchMode() && !isFocused()) { 11108 focusTaken = requestFocus(); 11109 } 11110 11111 if (prepressed) { 11112 // The button is being released before we actually 11113 // showed it as pressed. Make it show the pressed 11114 // state now (before scheduling the click) to ensure 11115 // the user sees it. 11116 setPressed(true, x, y); 11117 } 11118 11119 if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) { 11120 // This is a tap, so remove the longpress check 11121 removeLongPressCallback(); 11122 11123 // Only perform take click actions if we were in the pressed state 11124 if (!focusTaken) { 11125 // Use a Runnable and post this rather than calling 11126 // performClick directly. This lets other visual state 11127 // of the view update before click actions start. 11128 if (mPerformClick == null) { 11129 mPerformClick = new PerformClick(); 11130 } 11131 if (!post(mPerformClick)) { 11132 performClick(); 11133 } 11134 } 11135 } 11136 11137 if (mUnsetPressedState == null) { 11138 mUnsetPressedState = new UnsetPressedState(); 11139 } 11140 11141 if (prepressed) { 11142 postDelayed(mUnsetPressedState, 11143 ViewConfiguration.getPressedStateDuration()); 11144 } else if (!post(mUnsetPressedState)) { 11145 // If the post failed, unpress right now 11146 mUnsetPressedState.run(); 11147 } 11148 11149 removeTapCallback(); 11150 } 11151 mIgnoreNextUpEvent = false; 11152 break; 11153 11154 case MotionEvent.ACTION_DOWN: 11155 mHasPerformedLongPress = false; 11156 11157 if (performButtonActionOnTouchDown(event)) { 11158 break; 11159 } 11160 11161 // Walk up the hierarchy to determine if we're inside a scrolling container. 11162 boolean isInScrollingContainer = isInScrollingContainer(); 11163 11164 // For views inside a scrolling container, delay the pressed feedback for 11165 // a short period in case this is a scroll. 11166 if (isInScrollingContainer) { 11167 mPrivateFlags |= PFLAG_PREPRESSED; 11168 if (mPendingCheckForTap == null) { 11169 mPendingCheckForTap = new CheckForTap(); 11170 } 11171 mPendingCheckForTap.x = event.getX(); 11172 mPendingCheckForTap.y = event.getY(); 11173 postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout()); 11174 } else { 11175 // Not inside a scrolling container, so show the feedback right away 11176 setPressed(true, x, y); 11177 checkForLongClick(0, x, y); 11178 } 11179 break; 11180 11181 case MotionEvent.ACTION_CANCEL: 11182 setPressed(false); 11183 removeTapCallback(); 11184 removeLongPressCallback(); 11185 mInContextButtonPress = false; 11186 mHasPerformedLongPress = false; 11187 mIgnoreNextUpEvent = false; 11188 break; 11189 11190 case MotionEvent.ACTION_MOVE: 11191 drawableHotspotChanged(x, y); 11192 11193 // Be lenient about moving outside of buttons 11194 if (!pointInView(x, y, mTouchSlop)) { 11195 // Outside button 11196 removeTapCallback(); 11197 if ((mPrivateFlags & PFLAG_PRESSED) != 0) { 11198 // Remove any future long press/tap checks 11199 removeLongPressCallback(); 11200 11201 setPressed(false); 11202 } 11203 } 11204 break; 11205 } 11206 11207 return true; 11208 } 11209 11210 return false; 11211 } 11212 11213 /** 11214 * @hide 11215 */ isInScrollingContainer()11216 public boolean isInScrollingContainer() { 11217 ViewParent p = getParent(); 11218 while (p != null && p instanceof ViewGroup) { 11219 if (((ViewGroup) p).shouldDelayChildPressedState()) { 11220 return true; 11221 } 11222 p = p.getParent(); 11223 } 11224 return false; 11225 } 11226 11227 /** 11228 * Remove the longpress detection timer. 11229 */ removeLongPressCallback()11230 private void removeLongPressCallback() { 11231 if (mPendingCheckForLongPress != null) { 11232 removeCallbacks(mPendingCheckForLongPress); 11233 } 11234 } 11235 11236 /** 11237 * Remove the pending click action 11238 */ removePerformClickCallback()11239 private void removePerformClickCallback() { 11240 if (mPerformClick != null) { 11241 removeCallbacks(mPerformClick); 11242 } 11243 } 11244 11245 /** 11246 * Remove the prepress detection timer. 11247 */ removeUnsetPressCallback()11248 private void removeUnsetPressCallback() { 11249 if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) { 11250 setPressed(false); 11251 removeCallbacks(mUnsetPressedState); 11252 } 11253 } 11254 11255 /** 11256 * Remove the tap detection timer. 11257 */ removeTapCallback()11258 private void removeTapCallback() { 11259 if (mPendingCheckForTap != null) { 11260 mPrivateFlags &= ~PFLAG_PREPRESSED; 11261 removeCallbacks(mPendingCheckForTap); 11262 } 11263 } 11264 11265 /** 11266 * Cancels a pending long press. Your subclass can use this if you 11267 * want the context menu to come up if the user presses and holds 11268 * at the same place, but you don't want it to come up if they press 11269 * and then move around enough to cause scrolling. 11270 */ cancelLongPress()11271 public void cancelLongPress() { 11272 removeLongPressCallback(); 11273 11274 /* 11275 * The prepressed state handled by the tap callback is a display 11276 * construct, but the tap callback will post a long press callback 11277 * less its own timeout. Remove it here. 11278 */ 11279 removeTapCallback(); 11280 } 11281 11282 /** 11283 * Remove the pending callback for sending a 11284 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event. 11285 */ removeSendViewScrolledAccessibilityEventCallback()11286 private void removeSendViewScrolledAccessibilityEventCallback() { 11287 if (mSendViewScrolledAccessibilityEvent != null) { 11288 removeCallbacks(mSendViewScrolledAccessibilityEvent); 11289 mSendViewScrolledAccessibilityEvent.mIsPending = false; 11290 } 11291 } 11292 11293 /** 11294 * Sets the TouchDelegate for this View. 11295 */ setTouchDelegate(TouchDelegate delegate)11296 public void setTouchDelegate(TouchDelegate delegate) { 11297 mTouchDelegate = delegate; 11298 } 11299 11300 /** 11301 * Gets the TouchDelegate for this View. 11302 */ getTouchDelegate()11303 public TouchDelegate getTouchDelegate() { 11304 return mTouchDelegate; 11305 } 11306 11307 /** 11308 * Request unbuffered dispatch of the given stream of MotionEvents to this View. 11309 * 11310 * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input 11311 * system not batch {@link MotionEvent}s but instead deliver them as soon as they're 11312 * available. This method should only be called for touch events. 11313 * 11314 * <p class="note">This api is not intended for most applications. Buffered dispatch 11315 * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent 11316 * streams will not improve your input latency. Side effects include: increased latency, 11317 * jittery scrolls and inability to take advantage of system resampling. Talk to your input 11318 * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for 11319 * you.</p> 11320 */ requestUnbufferedDispatch(MotionEvent event)11321 public final void requestUnbufferedDispatch(MotionEvent event) { 11322 final int action = event.getAction(); 11323 if (mAttachInfo == null 11324 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE 11325 || !event.isTouchEvent()) { 11326 return; 11327 } 11328 mAttachInfo.mUnbufferedDispatchRequested = true; 11329 } 11330 11331 /** 11332 * Set flags controlling behavior of this view. 11333 * 11334 * @param flags Constant indicating the value which should be set 11335 * @param mask Constant indicating the bit range that should be changed 11336 */ setFlags(int flags, int mask)11337 void setFlags(int flags, int mask) { 11338 final boolean accessibilityEnabled = 11339 AccessibilityManager.getInstance(mContext).isEnabled(); 11340 final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility(); 11341 11342 int old = mViewFlags; 11343 mViewFlags = (mViewFlags & ~mask) | (flags & mask); 11344 11345 int changed = mViewFlags ^ old; 11346 if (changed == 0) { 11347 return; 11348 } 11349 int privateFlags = mPrivateFlags; 11350 11351 /* Check if the FOCUSABLE bit has changed */ 11352 if (((changed & FOCUSABLE_MASK) != 0) && 11353 ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) { 11354 if (((old & FOCUSABLE_MASK) == FOCUSABLE) 11355 && ((privateFlags & PFLAG_FOCUSED) != 0)) { 11356 /* Give up focus if we are no longer focusable */ 11357 clearFocus(); 11358 } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE) 11359 && ((privateFlags & PFLAG_FOCUSED) == 0)) { 11360 /* 11361 * Tell the view system that we are now available to take focus 11362 * if no one else already has it. 11363 */ 11364 if (mParent != null) mParent.focusableViewAvailable(this); 11365 } 11366 } 11367 11368 final int newVisibility = flags & VISIBILITY_MASK; 11369 if (newVisibility == VISIBLE) { 11370 if ((changed & VISIBILITY_MASK) != 0) { 11371 /* 11372 * If this view is becoming visible, invalidate it in case it changed while 11373 * it was not visible. Marking it drawn ensures that the invalidation will 11374 * go through. 11375 */ 11376 mPrivateFlags |= PFLAG_DRAWN; 11377 invalidate(true); 11378 11379 needGlobalAttributesUpdate(true); 11380 11381 // a view becoming visible is worth notifying the parent 11382 // about in case nothing has focus. even if this specific view 11383 // isn't focusable, it may contain something that is, so let 11384 // the root view try to give this focus if nothing else does. 11385 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) { 11386 mParent.focusableViewAvailable(this); 11387 } 11388 } 11389 } 11390 11391 /* Check if the GONE bit has changed */ 11392 if ((changed & GONE) != 0) { 11393 needGlobalAttributesUpdate(false); 11394 requestLayout(); 11395 11396 if (((mViewFlags & VISIBILITY_MASK) == GONE)) { 11397 if (hasFocus()) clearFocus(); 11398 clearAccessibilityFocus(); 11399 destroyDrawingCache(); 11400 if (mParent instanceof View) { 11401 // GONE views noop invalidation, so invalidate the parent 11402 ((View) mParent).invalidate(true); 11403 } 11404 // Mark the view drawn to ensure that it gets invalidated properly the next 11405 // time it is visible and gets invalidated 11406 mPrivateFlags |= PFLAG_DRAWN; 11407 } 11408 if (mAttachInfo != null) { 11409 mAttachInfo.mViewVisibilityChanged = true; 11410 } 11411 } 11412 11413 /* Check if the VISIBLE bit has changed */ 11414 if ((changed & INVISIBLE) != 0) { 11415 needGlobalAttributesUpdate(false); 11416 /* 11417 * If this view is becoming invisible, set the DRAWN flag so that 11418 * the next invalidate() will not be skipped. 11419 */ 11420 mPrivateFlags |= PFLAG_DRAWN; 11421 11422 if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) { 11423 // root view becoming invisible shouldn't clear focus and accessibility focus 11424 if (getRootView() != this) { 11425 if (hasFocus()) clearFocus(); 11426 clearAccessibilityFocus(); 11427 } 11428 } 11429 if (mAttachInfo != null) { 11430 mAttachInfo.mViewVisibilityChanged = true; 11431 } 11432 } 11433 11434 if ((changed & VISIBILITY_MASK) != 0) { 11435 // If the view is invisible, cleanup its display list to free up resources 11436 if (newVisibility != VISIBLE && mAttachInfo != null) { 11437 cleanupDraw(); 11438 } 11439 11440 if (mParent instanceof ViewGroup) { 11441 ((ViewGroup) mParent).onChildVisibilityChanged(this, 11442 (changed & VISIBILITY_MASK), newVisibility); 11443 ((View) mParent).invalidate(true); 11444 } else if (mParent != null) { 11445 mParent.invalidateChild(this, null); 11446 } 11447 11448 if (mAttachInfo != null) { 11449 dispatchVisibilityChanged(this, newVisibility); 11450 11451 // Aggregated visibility changes are dispatched to attached views 11452 // in visible windows where the parent is currently shown/drawn 11453 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot), 11454 // discounting clipping or overlapping. This makes it a good place 11455 // to change animation states. 11456 if (mParent != null && getWindowVisibility() == VISIBLE && 11457 ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) { 11458 dispatchVisibilityAggregated(newVisibility == VISIBLE); 11459 } 11460 notifySubtreeAccessibilityStateChangedIfNeeded(); 11461 } 11462 } 11463 11464 if ((changed & WILL_NOT_CACHE_DRAWING) != 0) { 11465 destroyDrawingCache(); 11466 } 11467 11468 if ((changed & DRAWING_CACHE_ENABLED) != 0) { 11469 destroyDrawingCache(); 11470 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 11471 invalidateParentCaches(); 11472 } 11473 11474 if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) { 11475 destroyDrawingCache(); 11476 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 11477 } 11478 11479 if ((changed & DRAW_MASK) != 0) { 11480 if ((mViewFlags & WILL_NOT_DRAW) != 0) { 11481 if (mBackground != null 11482 || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) { 11483 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 11484 } else { 11485 mPrivateFlags |= PFLAG_SKIP_DRAW; 11486 } 11487 } else { 11488 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 11489 } 11490 requestLayout(); 11491 invalidate(true); 11492 } 11493 11494 if ((changed & KEEP_SCREEN_ON) != 0) { 11495 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { 11496 mParent.recomputeViewAttributes(this); 11497 } 11498 } 11499 11500 if (accessibilityEnabled) { 11501 if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0 11502 || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0 11503 || (changed & CONTEXT_CLICKABLE) != 0) { 11504 if (oldIncludeForAccessibility != includeForAccessibility()) { 11505 notifySubtreeAccessibilityStateChangedIfNeeded(); 11506 } else { 11507 notifyViewAccessibilityStateChangedIfNeeded( 11508 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 11509 } 11510 } else if ((changed & ENABLED_MASK) != 0) { 11511 notifyViewAccessibilityStateChangedIfNeeded( 11512 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 11513 } 11514 } 11515 } 11516 11517 /** 11518 * Change the view's z order in the tree, so it's on top of other sibling 11519 * views. This ordering change may affect layout, if the parent container 11520 * uses an order-dependent layout scheme (e.g., LinearLayout). Prior 11521 * to {@link android.os.Build.VERSION_CODES#KITKAT} this 11522 * method should be followed by calls to {@link #requestLayout()} and 11523 * {@link View#invalidate()} on the view's parent to force the parent to redraw 11524 * with the new child ordering. 11525 * 11526 * @see ViewGroup#bringChildToFront(View) 11527 */ bringToFront()11528 public void bringToFront() { 11529 if (mParent != null) { 11530 mParent.bringChildToFront(this); 11531 } 11532 } 11533 11534 /** 11535 * This is called in response to an internal scroll in this view (i.e., the 11536 * view scrolled its own contents). This is typically as a result of 11537 * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been 11538 * called. 11539 * 11540 * @param l Current horizontal scroll origin. 11541 * @param t Current vertical scroll origin. 11542 * @param oldl Previous horizontal scroll origin. 11543 * @param oldt Previous vertical scroll origin. 11544 */ onScrollChanged(int l, int t, int oldl, int oldt)11545 protected void onScrollChanged(int l, int t, int oldl, int oldt) { 11546 notifySubtreeAccessibilityStateChangedIfNeeded(); 11547 11548 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 11549 postSendViewScrolledAccessibilityEventCallback(); 11550 } 11551 11552 mBackgroundSizeChanged = true; 11553 if (mForegroundInfo != null) { 11554 mForegroundInfo.mBoundsChanged = true; 11555 } 11556 11557 final AttachInfo ai = mAttachInfo; 11558 if (ai != null) { 11559 ai.mViewScrollChanged = true; 11560 } 11561 11562 if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) { 11563 mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt); 11564 } 11565 } 11566 11567 /** 11568 * Interface definition for a callback to be invoked when the scroll 11569 * X or Y positions of a view change. 11570 * <p> 11571 * <b>Note:</b> Some views handle scrolling independently from View and may 11572 * have their own separate listeners for scroll-type events. For example, 11573 * {@link android.widget.ListView ListView} allows clients to register an 11574 * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener} 11575 * to listen for changes in list scroll position. 11576 * 11577 * @see #setOnScrollChangeListener(View.OnScrollChangeListener) 11578 */ 11579 public interface OnScrollChangeListener { 11580 /** 11581 * Called when the scroll position of a view changes. 11582 * 11583 * @param v The view whose scroll position has changed. 11584 * @param scrollX Current horizontal scroll origin. 11585 * @param scrollY Current vertical scroll origin. 11586 * @param oldScrollX Previous horizontal scroll origin. 11587 * @param oldScrollY Previous vertical scroll origin. 11588 */ onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)11589 void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY); 11590 } 11591 11592 /** 11593 * Interface definition for a callback to be invoked when the layout bounds of a view 11594 * changes due to layout processing. 11595 */ 11596 public interface OnLayoutChangeListener { 11597 /** 11598 * Called when the layout bounds of a view changes due to layout processing. 11599 * 11600 * @param v The view whose bounds have changed. 11601 * @param left The new value of the view's left property. 11602 * @param top The new value of the view's top property. 11603 * @param right The new value of the view's right property. 11604 * @param bottom The new value of the view's bottom property. 11605 * @param oldLeft The previous value of the view's left property. 11606 * @param oldTop The previous value of the view's top property. 11607 * @param oldRight The previous value of the view's right property. 11608 * @param oldBottom The previous value of the view's bottom property. 11609 */ onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)11610 void onLayoutChange(View v, int left, int top, int right, int bottom, 11611 int oldLeft, int oldTop, int oldRight, int oldBottom); 11612 } 11613 11614 /** 11615 * This is called during layout when the size of this view has changed. If 11616 * you were just added to the view hierarchy, you're called with the old 11617 * values of 0. 11618 * 11619 * @param w Current width of this view. 11620 * @param h Current height of this view. 11621 * @param oldw Old width of this view. 11622 * @param oldh Old height of this view. 11623 */ onSizeChanged(int w, int h, int oldw, int oldh)11624 protected void onSizeChanged(int w, int h, int oldw, int oldh) { 11625 } 11626 11627 /** 11628 * Called by draw to draw the child views. This may be overridden 11629 * by derived classes to gain control just before its children are drawn 11630 * (but after its own view has been drawn). 11631 * @param canvas the canvas on which to draw the view 11632 */ dispatchDraw(Canvas canvas)11633 protected void dispatchDraw(Canvas canvas) { 11634 11635 } 11636 11637 /** 11638 * Gets the parent of this view. Note that the parent is a 11639 * ViewParent and not necessarily a View. 11640 * 11641 * @return Parent of this view. 11642 */ getParent()11643 public final ViewParent getParent() { 11644 return mParent; 11645 } 11646 11647 /** 11648 * Set the horizontal scrolled position of your view. This will cause a call to 11649 * {@link #onScrollChanged(int, int, int, int)} and the view will be 11650 * invalidated. 11651 * @param value the x position to scroll to 11652 */ setScrollX(int value)11653 public void setScrollX(int value) { 11654 scrollTo(value, mScrollY); 11655 } 11656 11657 /** 11658 * Set the vertical scrolled position of your view. This will cause a call to 11659 * {@link #onScrollChanged(int, int, int, int)} and the view will be 11660 * invalidated. 11661 * @param value the y position to scroll to 11662 */ setScrollY(int value)11663 public void setScrollY(int value) { 11664 scrollTo(mScrollX, value); 11665 } 11666 11667 /** 11668 * Return the scrolled left position of this view. This is the left edge of 11669 * the displayed part of your view. You do not need to draw any pixels 11670 * farther left, since those are outside of the frame of your view on 11671 * screen. 11672 * 11673 * @return The left edge of the displayed part of your view, in pixels. 11674 */ getScrollX()11675 public final int getScrollX() { 11676 return mScrollX; 11677 } 11678 11679 /** 11680 * Return the scrolled top position of this view. This is the top edge of 11681 * the displayed part of your view. You do not need to draw any pixels above 11682 * it, since those are outside of the frame of your view on screen. 11683 * 11684 * @return The top edge of the displayed part of your view, in pixels. 11685 */ getScrollY()11686 public final int getScrollY() { 11687 return mScrollY; 11688 } 11689 11690 /** 11691 * Return the width of the your view. 11692 * 11693 * @return The width of your view, in pixels. 11694 */ 11695 @ViewDebug.ExportedProperty(category = "layout") getWidth()11696 public final int getWidth() { 11697 return mRight - mLeft; 11698 } 11699 11700 /** 11701 * Return the height of your view. 11702 * 11703 * @return The height of your view, in pixels. 11704 */ 11705 @ViewDebug.ExportedProperty(category = "layout") getHeight()11706 public final int getHeight() { 11707 return mBottom - mTop; 11708 } 11709 11710 /** 11711 * Return the visible drawing bounds of your view. Fills in the output 11712 * rectangle with the values from getScrollX(), getScrollY(), 11713 * getWidth(), and getHeight(). These bounds do not account for any 11714 * transformation properties currently set on the view, such as 11715 * {@link #setScaleX(float)} or {@link #setRotation(float)}. 11716 * 11717 * @param outRect The (scrolled) drawing bounds of the view. 11718 */ getDrawingRect(Rect outRect)11719 public void getDrawingRect(Rect outRect) { 11720 outRect.left = mScrollX; 11721 outRect.top = mScrollY; 11722 outRect.right = mScrollX + (mRight - mLeft); 11723 outRect.bottom = mScrollY + (mBottom - mTop); 11724 } 11725 11726 /** 11727 * Like {@link #getMeasuredWidthAndState()}, but only returns the 11728 * raw width component (that is the result is masked by 11729 * {@link #MEASURED_SIZE_MASK}). 11730 * 11731 * @return The raw measured width of this view. 11732 */ getMeasuredWidth()11733 public final int getMeasuredWidth() { 11734 return mMeasuredWidth & MEASURED_SIZE_MASK; 11735 } 11736 11737 /** 11738 * Return the full width measurement information for this view as computed 11739 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask 11740 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}. 11741 * This should be used during measurement and layout calculations only. Use 11742 * {@link #getWidth()} to see how wide a view is after layout. 11743 * 11744 * @return The measured width of this view as a bit mask. 11745 */ 11746 @ViewDebug.ExportedProperty(category = "measurement", flagMapping = { 11747 @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL, 11748 name = "MEASURED_STATE_TOO_SMALL"), 11749 }) getMeasuredWidthAndState()11750 public final int getMeasuredWidthAndState() { 11751 return mMeasuredWidth; 11752 } 11753 11754 /** 11755 * Like {@link #getMeasuredHeightAndState()}, but only returns the 11756 * raw width component (that is the result is masked by 11757 * {@link #MEASURED_SIZE_MASK}). 11758 * 11759 * @return The raw measured height of this view. 11760 */ getMeasuredHeight()11761 public final int getMeasuredHeight() { 11762 return mMeasuredHeight & MEASURED_SIZE_MASK; 11763 } 11764 11765 /** 11766 * Return the full height measurement information for this view as computed 11767 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask 11768 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}. 11769 * This should be used during measurement and layout calculations only. Use 11770 * {@link #getHeight()} to see how wide a view is after layout. 11771 * 11772 * @return The measured width of this view as a bit mask. 11773 */ 11774 @ViewDebug.ExportedProperty(category = "measurement", flagMapping = { 11775 @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL, 11776 name = "MEASURED_STATE_TOO_SMALL"), 11777 }) getMeasuredHeightAndState()11778 public final int getMeasuredHeightAndState() { 11779 return mMeasuredHeight; 11780 } 11781 11782 /** 11783 * Return only the state bits of {@link #getMeasuredWidthAndState()} 11784 * and {@link #getMeasuredHeightAndState()}, combined into one integer. 11785 * The width component is in the regular bits {@link #MEASURED_STATE_MASK} 11786 * and the height component is at the shifted bits 11787 * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}. 11788 */ getMeasuredState()11789 public final int getMeasuredState() { 11790 return (mMeasuredWidth&MEASURED_STATE_MASK) 11791 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT) 11792 & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT)); 11793 } 11794 11795 /** 11796 * The transform matrix of this view, which is calculated based on the current 11797 * rotation, scale, and pivot properties. 11798 * 11799 * @see #getRotation() 11800 * @see #getScaleX() 11801 * @see #getScaleY() 11802 * @see #getPivotX() 11803 * @see #getPivotY() 11804 * @return The current transform matrix for the view 11805 */ getMatrix()11806 public Matrix getMatrix() { 11807 ensureTransformationInfo(); 11808 final Matrix matrix = mTransformationInfo.mMatrix; 11809 mRenderNode.getMatrix(matrix); 11810 return matrix; 11811 } 11812 11813 /** 11814 * Returns true if the transform matrix is the identity matrix. 11815 * Recomputes the matrix if necessary. 11816 * 11817 * @return True if the transform matrix is the identity matrix, false otherwise. 11818 */ hasIdentityMatrix()11819 final boolean hasIdentityMatrix() { 11820 return mRenderNode.hasIdentityMatrix(); 11821 } 11822 ensureTransformationInfo()11823 void ensureTransformationInfo() { 11824 if (mTransformationInfo == null) { 11825 mTransformationInfo = new TransformationInfo(); 11826 } 11827 } 11828 11829 /** 11830 * Utility method to retrieve the inverse of the current mMatrix property. 11831 * We cache the matrix to avoid recalculating it when transform properties 11832 * have not changed. 11833 * 11834 * @return The inverse of the current matrix of this view. 11835 * @hide 11836 */ getInverseMatrix()11837 public final Matrix getInverseMatrix() { 11838 ensureTransformationInfo(); 11839 if (mTransformationInfo.mInverseMatrix == null) { 11840 mTransformationInfo.mInverseMatrix = new Matrix(); 11841 } 11842 final Matrix matrix = mTransformationInfo.mInverseMatrix; 11843 mRenderNode.getInverseMatrix(matrix); 11844 return matrix; 11845 } 11846 11847 /** 11848 * Gets the distance along the Z axis from the camera to this view. 11849 * 11850 * @see #setCameraDistance(float) 11851 * 11852 * @return The distance along the Z axis. 11853 */ getCameraDistance()11854 public float getCameraDistance() { 11855 final float dpi = mResources.getDisplayMetrics().densityDpi; 11856 return -(mRenderNode.getCameraDistance() * dpi); 11857 } 11858 11859 /** 11860 * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which 11861 * views are drawn) from the camera to this view. The camera's distance 11862 * affects 3D transformations, for instance rotations around the X and Y 11863 * axis. If the rotationX or rotationY properties are changed and this view is 11864 * large (more than half the size of the screen), it is recommended to always 11865 * use a camera distance that's greater than the height (X axis rotation) or 11866 * the width (Y axis rotation) of this view.</p> 11867 * 11868 * <p>The distance of the camera from the view plane can have an affect on the 11869 * perspective distortion of the view when it is rotated around the x or y axis. 11870 * For example, a large distance will result in a large viewing angle, and there 11871 * will not be much perspective distortion of the view as it rotates. A short 11872 * distance may cause much more perspective distortion upon rotation, and can 11873 * also result in some drawing artifacts if the rotated view ends up partially 11874 * behind the camera (which is why the recommendation is to use a distance at 11875 * least as far as the size of the view, if the view is to be rotated.)</p> 11876 * 11877 * <p>The distance is expressed in "depth pixels." The default distance depends 11878 * on the screen density. For instance, on a medium density display, the 11879 * default distance is 1280. On a high density display, the default distance 11880 * is 1920.</p> 11881 * 11882 * <p>If you want to specify a distance that leads to visually consistent 11883 * results across various densities, use the following formula:</p> 11884 * <pre> 11885 * float scale = context.getResources().getDisplayMetrics().density; 11886 * view.setCameraDistance(distance * scale); 11887 * </pre> 11888 * 11889 * <p>The density scale factor of a high density display is 1.5, 11890 * and 1920 = 1280 * 1.5.</p> 11891 * 11892 * @param distance The distance in "depth pixels", if negative the opposite 11893 * value is used 11894 * 11895 * @see #setRotationX(float) 11896 * @see #setRotationY(float) 11897 */ setCameraDistance(float distance)11898 public void setCameraDistance(float distance) { 11899 final float dpi = mResources.getDisplayMetrics().densityDpi; 11900 11901 invalidateViewProperty(true, false); 11902 mRenderNode.setCameraDistance(-Math.abs(distance) / dpi); 11903 invalidateViewProperty(false, false); 11904 11905 invalidateParentIfNeededAndWasQuickRejected(); 11906 } 11907 11908 /** 11909 * The degrees that the view is rotated around the pivot point. 11910 * 11911 * @see #setRotation(float) 11912 * @see #getPivotX() 11913 * @see #getPivotY() 11914 * 11915 * @return The degrees of rotation. 11916 */ 11917 @ViewDebug.ExportedProperty(category = "drawing") getRotation()11918 public float getRotation() { 11919 return mRenderNode.getRotation(); 11920 } 11921 11922 /** 11923 * Sets the degrees that the view is rotated around the pivot point. Increasing values 11924 * result in clockwise rotation. 11925 * 11926 * @param rotation The degrees of rotation. 11927 * 11928 * @see #getRotation() 11929 * @see #getPivotX() 11930 * @see #getPivotY() 11931 * @see #setRotationX(float) 11932 * @see #setRotationY(float) 11933 * 11934 * @attr ref android.R.styleable#View_rotation 11935 */ setRotation(float rotation)11936 public void setRotation(float rotation) { 11937 if (rotation != getRotation()) { 11938 // Double-invalidation is necessary to capture view's old and new areas 11939 invalidateViewProperty(true, false); 11940 mRenderNode.setRotation(rotation); 11941 invalidateViewProperty(false, true); 11942 11943 invalidateParentIfNeededAndWasQuickRejected(); 11944 notifySubtreeAccessibilityStateChangedIfNeeded(); 11945 } 11946 } 11947 11948 /** 11949 * The degrees that the view is rotated around the vertical axis through the pivot point. 11950 * 11951 * @see #getPivotX() 11952 * @see #getPivotY() 11953 * @see #setRotationY(float) 11954 * 11955 * @return The degrees of Y rotation. 11956 */ 11957 @ViewDebug.ExportedProperty(category = "drawing") getRotationY()11958 public float getRotationY() { 11959 return mRenderNode.getRotationY(); 11960 } 11961 11962 /** 11963 * Sets the degrees that the view is rotated around the vertical axis through the pivot point. 11964 * Increasing values result in counter-clockwise rotation from the viewpoint of looking 11965 * down the y axis. 11966 * 11967 * When rotating large views, it is recommended to adjust the camera distance 11968 * accordingly. Refer to {@link #setCameraDistance(float)} for more information. 11969 * 11970 * @param rotationY The degrees of Y rotation. 11971 * 11972 * @see #getRotationY() 11973 * @see #getPivotX() 11974 * @see #getPivotY() 11975 * @see #setRotation(float) 11976 * @see #setRotationX(float) 11977 * @see #setCameraDistance(float) 11978 * 11979 * @attr ref android.R.styleable#View_rotationY 11980 */ setRotationY(float rotationY)11981 public void setRotationY(float rotationY) { 11982 if (rotationY != getRotationY()) { 11983 invalidateViewProperty(true, false); 11984 mRenderNode.setRotationY(rotationY); 11985 invalidateViewProperty(false, true); 11986 11987 invalidateParentIfNeededAndWasQuickRejected(); 11988 notifySubtreeAccessibilityStateChangedIfNeeded(); 11989 } 11990 } 11991 11992 /** 11993 * The degrees that the view is rotated around the horizontal axis through the pivot point. 11994 * 11995 * @see #getPivotX() 11996 * @see #getPivotY() 11997 * @see #setRotationX(float) 11998 * 11999 * @return The degrees of X rotation. 12000 */ 12001 @ViewDebug.ExportedProperty(category = "drawing") getRotationX()12002 public float getRotationX() { 12003 return mRenderNode.getRotationX(); 12004 } 12005 12006 /** 12007 * Sets the degrees that the view is rotated around the horizontal axis through the pivot point. 12008 * Increasing values result in clockwise rotation from the viewpoint of looking down the 12009 * x axis. 12010 * 12011 * When rotating large views, it is recommended to adjust the camera distance 12012 * accordingly. Refer to {@link #setCameraDistance(float)} for more information. 12013 * 12014 * @param rotationX The degrees of X rotation. 12015 * 12016 * @see #getRotationX() 12017 * @see #getPivotX() 12018 * @see #getPivotY() 12019 * @see #setRotation(float) 12020 * @see #setRotationY(float) 12021 * @see #setCameraDistance(float) 12022 * 12023 * @attr ref android.R.styleable#View_rotationX 12024 */ setRotationX(float rotationX)12025 public void setRotationX(float rotationX) { 12026 if (rotationX != getRotationX()) { 12027 invalidateViewProperty(true, false); 12028 mRenderNode.setRotationX(rotationX); 12029 invalidateViewProperty(false, true); 12030 12031 invalidateParentIfNeededAndWasQuickRejected(); 12032 notifySubtreeAccessibilityStateChangedIfNeeded(); 12033 } 12034 } 12035 12036 /** 12037 * The amount that the view is scaled in x around the pivot point, as a proportion of 12038 * the view's unscaled width. A value of 1, the default, means that no scaling is applied. 12039 * 12040 * <p>By default, this is 1.0f. 12041 * 12042 * @see #getPivotX() 12043 * @see #getPivotY() 12044 * @return The scaling factor. 12045 */ 12046 @ViewDebug.ExportedProperty(category = "drawing") getScaleX()12047 public float getScaleX() { 12048 return mRenderNode.getScaleX(); 12049 } 12050 12051 /** 12052 * Sets the amount that the view is scaled in x around the pivot point, as a proportion of 12053 * the view's unscaled width. A value of 1 means that no scaling is applied. 12054 * 12055 * @param scaleX The scaling factor. 12056 * @see #getPivotX() 12057 * @see #getPivotY() 12058 * 12059 * @attr ref android.R.styleable#View_scaleX 12060 */ setScaleX(float scaleX)12061 public void setScaleX(float scaleX) { 12062 if (scaleX != getScaleX()) { 12063 invalidateViewProperty(true, false); 12064 mRenderNode.setScaleX(scaleX); 12065 invalidateViewProperty(false, true); 12066 12067 invalidateParentIfNeededAndWasQuickRejected(); 12068 notifySubtreeAccessibilityStateChangedIfNeeded(); 12069 } 12070 } 12071 12072 /** 12073 * The amount that the view is scaled in y around the pivot point, as a proportion of 12074 * the view's unscaled height. A value of 1, the default, means that no scaling is applied. 12075 * 12076 * <p>By default, this is 1.0f. 12077 * 12078 * @see #getPivotX() 12079 * @see #getPivotY() 12080 * @return The scaling factor. 12081 */ 12082 @ViewDebug.ExportedProperty(category = "drawing") getScaleY()12083 public float getScaleY() { 12084 return mRenderNode.getScaleY(); 12085 } 12086 12087 /** 12088 * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of 12089 * the view's unscaled width. A value of 1 means that no scaling is applied. 12090 * 12091 * @param scaleY The scaling factor. 12092 * @see #getPivotX() 12093 * @see #getPivotY() 12094 * 12095 * @attr ref android.R.styleable#View_scaleY 12096 */ setScaleY(float scaleY)12097 public void setScaleY(float scaleY) { 12098 if (scaleY != getScaleY()) { 12099 invalidateViewProperty(true, false); 12100 mRenderNode.setScaleY(scaleY); 12101 invalidateViewProperty(false, true); 12102 12103 invalidateParentIfNeededAndWasQuickRejected(); 12104 notifySubtreeAccessibilityStateChangedIfNeeded(); 12105 } 12106 } 12107 12108 /** 12109 * The x location of the point around which the view is {@link #setRotation(float) rotated} 12110 * and {@link #setScaleX(float) scaled}. 12111 * 12112 * @see #getRotation() 12113 * @see #getScaleX() 12114 * @see #getScaleY() 12115 * @see #getPivotY() 12116 * @return The x location of the pivot point. 12117 * 12118 * @attr ref android.R.styleable#View_transformPivotX 12119 */ 12120 @ViewDebug.ExportedProperty(category = "drawing") getPivotX()12121 public float getPivotX() { 12122 return mRenderNode.getPivotX(); 12123 } 12124 12125 /** 12126 * Sets the x location of the point around which the view is 12127 * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}. 12128 * By default, the pivot point is centered on the object. 12129 * Setting this property disables this behavior and causes the view to use only the 12130 * explicitly set pivotX and pivotY values. 12131 * 12132 * @param pivotX The x location of the pivot point. 12133 * @see #getRotation() 12134 * @see #getScaleX() 12135 * @see #getScaleY() 12136 * @see #getPivotY() 12137 * 12138 * @attr ref android.R.styleable#View_transformPivotX 12139 */ setPivotX(float pivotX)12140 public void setPivotX(float pivotX) { 12141 if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) { 12142 invalidateViewProperty(true, false); 12143 mRenderNode.setPivotX(pivotX); 12144 invalidateViewProperty(false, true); 12145 12146 invalidateParentIfNeededAndWasQuickRejected(); 12147 } 12148 } 12149 12150 /** 12151 * The y location of the point around which the view is {@link #setRotation(float) rotated} 12152 * and {@link #setScaleY(float) scaled}. 12153 * 12154 * @see #getRotation() 12155 * @see #getScaleX() 12156 * @see #getScaleY() 12157 * @see #getPivotY() 12158 * @return The y location of the pivot point. 12159 * 12160 * @attr ref android.R.styleable#View_transformPivotY 12161 */ 12162 @ViewDebug.ExportedProperty(category = "drawing") getPivotY()12163 public float getPivotY() { 12164 return mRenderNode.getPivotY(); 12165 } 12166 12167 /** 12168 * Sets the y location of the point around which the view is {@link #setRotation(float) rotated} 12169 * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object. 12170 * Setting this property disables this behavior and causes the view to use only the 12171 * explicitly set pivotX and pivotY values. 12172 * 12173 * @param pivotY The y location of the pivot point. 12174 * @see #getRotation() 12175 * @see #getScaleX() 12176 * @see #getScaleY() 12177 * @see #getPivotY() 12178 * 12179 * @attr ref android.R.styleable#View_transformPivotY 12180 */ setPivotY(float pivotY)12181 public void setPivotY(float pivotY) { 12182 if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) { 12183 invalidateViewProperty(true, false); 12184 mRenderNode.setPivotY(pivotY); 12185 invalidateViewProperty(false, true); 12186 12187 invalidateParentIfNeededAndWasQuickRejected(); 12188 } 12189 } 12190 12191 /** 12192 * The opacity of the view. This is a value from 0 to 1, where 0 means the view is 12193 * completely transparent and 1 means the view is completely opaque. 12194 * 12195 * <p>By default this is 1.0f. 12196 * @return The opacity of the view. 12197 */ 12198 @ViewDebug.ExportedProperty(category = "drawing") getAlpha()12199 public float getAlpha() { 12200 return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1; 12201 } 12202 12203 /** 12204 * Sets the behavior for overlapping rendering for this view (see {@link 12205 * #hasOverlappingRendering()} for more details on this behavior). Calling this method 12206 * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass, 12207 * providing the value which is then used internally. That is, when {@link 12208 * #forceHasOverlappingRendering(boolean)} is called, the value of {@link 12209 * #hasOverlappingRendering()} is ignored and the value passed into this method is used 12210 * instead. 12211 * 12212 * @param hasOverlappingRendering The value for overlapping rendering to be used internally 12213 * instead of that returned by {@link #hasOverlappingRendering()}. 12214 * 12215 * @attr ref android.R.styleable#View_forceHasOverlappingRendering 12216 */ forceHasOverlappingRendering(boolean hasOverlappingRendering)12217 public void forceHasOverlappingRendering(boolean hasOverlappingRendering) { 12218 mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED; 12219 if (hasOverlappingRendering) { 12220 mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE; 12221 } else { 12222 mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE; 12223 } 12224 } 12225 12226 /** 12227 * Returns the value for overlapping rendering that is used internally. This is either 12228 * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or 12229 * the return value of {@link #hasOverlappingRendering()}, otherwise. 12230 * 12231 * @return The value for overlapping rendering being used internally. 12232 */ getHasOverlappingRendering()12233 public final boolean getHasOverlappingRendering() { 12234 return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ? 12235 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 : 12236 hasOverlappingRendering(); 12237 } 12238 12239 /** 12240 * Returns whether this View has content which overlaps. 12241 * 12242 * <p>This function, intended to be overridden by specific View types, is an optimization when 12243 * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to 12244 * an offscreen buffer and then composited into place, which can be expensive. If the view has 12245 * no overlapping rendering, the view can draw each primitive with the appropriate alpha value 12246 * directly. An example of overlapping rendering is a TextView with a background image, such as 12247 * a Button. An example of non-overlapping rendering is a TextView with no background, or an 12248 * ImageView with only the foreground image. The default implementation returns true; subclasses 12249 * should override if they have cases which can be optimized.</p> 12250 * 12251 * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas} 12252 * necessitates that a View return true if it uses the methods internally without passing the 12253 * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p> 12254 * 12255 * <p><strong>Note:</strong> The return value of this method is ignored if {@link 12256 * #forceHasOverlappingRendering(boolean)} has been called on this view.</p> 12257 * 12258 * @return true if the content in this view might overlap, false otherwise. 12259 */ 12260 @ViewDebug.ExportedProperty(category = "drawing") hasOverlappingRendering()12261 public boolean hasOverlappingRendering() { 12262 return true; 12263 } 12264 12265 /** 12266 * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is 12267 * completely transparent and 1 means the view is completely opaque. 12268 * 12269 * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1) 12270 * can have significant performance implications, especially for large views. It is best to use 12271 * the alpha property sparingly and transiently, as in the case of fading animations.</p> 12272 * 12273 * <p>For a view with a frequently changing alpha, such as during a fading animation, it is 12274 * strongly recommended for performance reasons to either override 12275 * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a 12276 * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration 12277 * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below, 12278 * the default path for rendering an unlayered View with alpha could add multiple milliseconds 12279 * of rendering cost, even for simple or small views. Starting with 12280 * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically 12281 * applied to the view at the rendering level.</p> 12282 * 12283 * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is 12284 * responsible for applying the opacity itself.</p> 12285 * 12286 * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if 12287 * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is 12288 * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an 12289 * alpha value less than 1.0 will supersede the alpha of the layer paint.</p> 12290 * 12291 * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha 12292 * value will clip a View to its bounds, unless the View returns <code>false</code> from 12293 * {@link #hasOverlappingRendering}.</p> 12294 * 12295 * @param alpha The opacity of the view. 12296 * 12297 * @see #hasOverlappingRendering() 12298 * @see #setLayerType(int, android.graphics.Paint) 12299 * 12300 * @attr ref android.R.styleable#View_alpha 12301 */ setAlpha(@loatRangefrom=0.0, to=1.0) float alpha)12302 public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) { 12303 ensureTransformationInfo(); 12304 if (mTransformationInfo.mAlpha != alpha) { 12305 mTransformationInfo.mAlpha = alpha; 12306 if (onSetAlpha((int) (alpha * 255))) { 12307 mPrivateFlags |= PFLAG_ALPHA_SET; 12308 // subclass is handling alpha - don't optimize rendering cache invalidation 12309 invalidateParentCaches(); 12310 invalidate(true); 12311 } else { 12312 mPrivateFlags &= ~PFLAG_ALPHA_SET; 12313 invalidateViewProperty(true, false); 12314 mRenderNode.setAlpha(getFinalAlpha()); 12315 notifyViewAccessibilityStateChangedIfNeeded( 12316 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 12317 } 12318 } 12319 } 12320 12321 /** 12322 * Faster version of setAlpha() which performs the same steps except there are 12323 * no calls to invalidate(). The caller of this function should perform proper invalidation 12324 * on the parent and this object. The return value indicates whether the subclass handles 12325 * alpha (the return value for onSetAlpha()). 12326 * 12327 * @param alpha The new value for the alpha property 12328 * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and 12329 * the new value for the alpha property is different from the old value 12330 */ setAlphaNoInvalidation(float alpha)12331 boolean setAlphaNoInvalidation(float alpha) { 12332 ensureTransformationInfo(); 12333 if (mTransformationInfo.mAlpha != alpha) { 12334 mTransformationInfo.mAlpha = alpha; 12335 boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255)); 12336 if (subclassHandlesAlpha) { 12337 mPrivateFlags |= PFLAG_ALPHA_SET; 12338 return true; 12339 } else { 12340 mPrivateFlags &= ~PFLAG_ALPHA_SET; 12341 mRenderNode.setAlpha(getFinalAlpha()); 12342 } 12343 } 12344 return false; 12345 } 12346 12347 /** 12348 * This property is hidden and intended only for use by the Fade transition, which 12349 * animates it to produce a visual translucency that does not side-effect (or get 12350 * affected by) the real alpha property. This value is composited with the other 12351 * alpha value (and the AlphaAnimation value, when that is present) to produce 12352 * a final visual translucency result, which is what is passed into the DisplayList. 12353 * 12354 * @hide 12355 */ setTransitionAlpha(float alpha)12356 public void setTransitionAlpha(float alpha) { 12357 ensureTransformationInfo(); 12358 if (mTransformationInfo.mTransitionAlpha != alpha) { 12359 mTransformationInfo.mTransitionAlpha = alpha; 12360 mPrivateFlags &= ~PFLAG_ALPHA_SET; 12361 invalidateViewProperty(true, false); 12362 mRenderNode.setAlpha(getFinalAlpha()); 12363 } 12364 } 12365 12366 /** 12367 * Calculates the visual alpha of this view, which is a combination of the actual 12368 * alpha value and the transitionAlpha value (if set). 12369 */ getFinalAlpha()12370 private float getFinalAlpha() { 12371 if (mTransformationInfo != null) { 12372 return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha; 12373 } 12374 return 1; 12375 } 12376 12377 /** 12378 * This property is hidden and intended only for use by the Fade transition, which 12379 * animates it to produce a visual translucency that does not side-effect (or get 12380 * affected by) the real alpha property. This value is composited with the other 12381 * alpha value (and the AlphaAnimation value, when that is present) to produce 12382 * a final visual translucency result, which is what is passed into the DisplayList. 12383 * 12384 * @hide 12385 */ 12386 @ViewDebug.ExportedProperty(category = "drawing") getTransitionAlpha()12387 public float getTransitionAlpha() { 12388 return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1; 12389 } 12390 12391 /** 12392 * Top position of this view relative to its parent. 12393 * 12394 * @return The top of this view, in pixels. 12395 */ 12396 @ViewDebug.CapturedViewProperty getTop()12397 public final int getTop() { 12398 return mTop; 12399 } 12400 12401 /** 12402 * Sets the top position of this view relative to its parent. This method is meant to be called 12403 * by the layout system and should not generally be called otherwise, because the property 12404 * may be changed at any time by the layout. 12405 * 12406 * @param top The top of this view, in pixels. 12407 */ setTop(int top)12408 public final void setTop(int top) { 12409 if (top != mTop) { 12410 final boolean matrixIsIdentity = hasIdentityMatrix(); 12411 if (matrixIsIdentity) { 12412 if (mAttachInfo != null) { 12413 int minTop; 12414 int yLoc; 12415 if (top < mTop) { 12416 minTop = top; 12417 yLoc = top - mTop; 12418 } else { 12419 minTop = mTop; 12420 yLoc = 0; 12421 } 12422 invalidate(0, yLoc, mRight - mLeft, mBottom - minTop); 12423 } 12424 } else { 12425 // Double-invalidation is necessary to capture view's old and new areas 12426 invalidate(true); 12427 } 12428 12429 int width = mRight - mLeft; 12430 int oldHeight = mBottom - mTop; 12431 12432 mTop = top; 12433 mRenderNode.setTop(mTop); 12434 12435 sizeChange(width, mBottom - mTop, width, oldHeight); 12436 12437 if (!matrixIsIdentity) { 12438 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 12439 invalidate(true); 12440 } 12441 mBackgroundSizeChanged = true; 12442 if (mForegroundInfo != null) { 12443 mForegroundInfo.mBoundsChanged = true; 12444 } 12445 invalidateParentIfNeeded(); 12446 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 12447 // View was rejected last time it was drawn by its parent; this may have changed 12448 invalidateParentIfNeeded(); 12449 } 12450 } 12451 } 12452 12453 /** 12454 * Bottom position of this view relative to its parent. 12455 * 12456 * @return The bottom of this view, in pixels. 12457 */ 12458 @ViewDebug.CapturedViewProperty getBottom()12459 public final int getBottom() { 12460 return mBottom; 12461 } 12462 12463 /** 12464 * True if this view has changed since the last time being drawn. 12465 * 12466 * @return The dirty state of this view. 12467 */ isDirty()12468 public boolean isDirty() { 12469 return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0; 12470 } 12471 12472 /** 12473 * Sets the bottom position of this view relative to its parent. This method is meant to be 12474 * called by the layout system and should not generally be called otherwise, because the 12475 * property may be changed at any time by the layout. 12476 * 12477 * @param bottom The bottom of this view, in pixels. 12478 */ setBottom(int bottom)12479 public final void setBottom(int bottom) { 12480 if (bottom != mBottom) { 12481 final boolean matrixIsIdentity = hasIdentityMatrix(); 12482 if (matrixIsIdentity) { 12483 if (mAttachInfo != null) { 12484 int maxBottom; 12485 if (bottom < mBottom) { 12486 maxBottom = mBottom; 12487 } else { 12488 maxBottom = bottom; 12489 } 12490 invalidate(0, 0, mRight - mLeft, maxBottom - mTop); 12491 } 12492 } else { 12493 // Double-invalidation is necessary to capture view's old and new areas 12494 invalidate(true); 12495 } 12496 12497 int width = mRight - mLeft; 12498 int oldHeight = mBottom - mTop; 12499 12500 mBottom = bottom; 12501 mRenderNode.setBottom(mBottom); 12502 12503 sizeChange(width, mBottom - mTop, width, oldHeight); 12504 12505 if (!matrixIsIdentity) { 12506 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 12507 invalidate(true); 12508 } 12509 mBackgroundSizeChanged = true; 12510 if (mForegroundInfo != null) { 12511 mForegroundInfo.mBoundsChanged = true; 12512 } 12513 invalidateParentIfNeeded(); 12514 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 12515 // View was rejected last time it was drawn by its parent; this may have changed 12516 invalidateParentIfNeeded(); 12517 } 12518 } 12519 } 12520 12521 /** 12522 * Left position of this view relative to its parent. 12523 * 12524 * @return The left edge of this view, in pixels. 12525 */ 12526 @ViewDebug.CapturedViewProperty getLeft()12527 public final int getLeft() { 12528 return mLeft; 12529 } 12530 12531 /** 12532 * Sets the left position of this view relative to its parent. This method is meant to be called 12533 * by the layout system and should not generally be called otherwise, because the property 12534 * may be changed at any time by the layout. 12535 * 12536 * @param left The left of this view, in pixels. 12537 */ setLeft(int left)12538 public final void setLeft(int left) { 12539 if (left != mLeft) { 12540 final boolean matrixIsIdentity = hasIdentityMatrix(); 12541 if (matrixIsIdentity) { 12542 if (mAttachInfo != null) { 12543 int minLeft; 12544 int xLoc; 12545 if (left < mLeft) { 12546 minLeft = left; 12547 xLoc = left - mLeft; 12548 } else { 12549 minLeft = mLeft; 12550 xLoc = 0; 12551 } 12552 invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop); 12553 } 12554 } else { 12555 // Double-invalidation is necessary to capture view's old and new areas 12556 invalidate(true); 12557 } 12558 12559 int oldWidth = mRight - mLeft; 12560 int height = mBottom - mTop; 12561 12562 mLeft = left; 12563 mRenderNode.setLeft(left); 12564 12565 sizeChange(mRight - mLeft, height, oldWidth, height); 12566 12567 if (!matrixIsIdentity) { 12568 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 12569 invalidate(true); 12570 } 12571 mBackgroundSizeChanged = true; 12572 if (mForegroundInfo != null) { 12573 mForegroundInfo.mBoundsChanged = true; 12574 } 12575 invalidateParentIfNeeded(); 12576 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 12577 // View was rejected last time it was drawn by its parent; this may have changed 12578 invalidateParentIfNeeded(); 12579 } 12580 } 12581 } 12582 12583 /** 12584 * Right position of this view relative to its parent. 12585 * 12586 * @return The right edge of this view, in pixels. 12587 */ 12588 @ViewDebug.CapturedViewProperty getRight()12589 public final int getRight() { 12590 return mRight; 12591 } 12592 12593 /** 12594 * Sets the right position of this view relative to its parent. This method is meant to be called 12595 * by the layout system and should not generally be called otherwise, because the property 12596 * may be changed at any time by the layout. 12597 * 12598 * @param right The right of this view, in pixels. 12599 */ setRight(int right)12600 public final void setRight(int right) { 12601 if (right != mRight) { 12602 final boolean matrixIsIdentity = hasIdentityMatrix(); 12603 if (matrixIsIdentity) { 12604 if (mAttachInfo != null) { 12605 int maxRight; 12606 if (right < mRight) { 12607 maxRight = mRight; 12608 } else { 12609 maxRight = right; 12610 } 12611 invalidate(0, 0, maxRight - mLeft, mBottom - mTop); 12612 } 12613 } else { 12614 // Double-invalidation is necessary to capture view's old and new areas 12615 invalidate(true); 12616 } 12617 12618 int oldWidth = mRight - mLeft; 12619 int height = mBottom - mTop; 12620 12621 mRight = right; 12622 mRenderNode.setRight(mRight); 12623 12624 sizeChange(mRight - mLeft, height, oldWidth, height); 12625 12626 if (!matrixIsIdentity) { 12627 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 12628 invalidate(true); 12629 } 12630 mBackgroundSizeChanged = true; 12631 if (mForegroundInfo != null) { 12632 mForegroundInfo.mBoundsChanged = true; 12633 } 12634 invalidateParentIfNeeded(); 12635 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 12636 // View was rejected last time it was drawn by its parent; this may have changed 12637 invalidateParentIfNeeded(); 12638 } 12639 } 12640 } 12641 12642 /** 12643 * The visual x position of this view, in pixels. This is equivalent to the 12644 * {@link #setTranslationX(float) translationX} property plus the current 12645 * {@link #getLeft() left} property. 12646 * 12647 * @return The visual x position of this view, in pixels. 12648 */ 12649 @ViewDebug.ExportedProperty(category = "drawing") getX()12650 public float getX() { 12651 return mLeft + getTranslationX(); 12652 } 12653 12654 /** 12655 * Sets the visual x position of this view, in pixels. This is equivalent to setting the 12656 * {@link #setTranslationX(float) translationX} property to be the difference between 12657 * the x value passed in and the current {@link #getLeft() left} property. 12658 * 12659 * @param x The visual x position of this view, in pixels. 12660 */ setX(float x)12661 public void setX(float x) { 12662 setTranslationX(x - mLeft); 12663 } 12664 12665 /** 12666 * The visual y position of this view, in pixels. This is equivalent to the 12667 * {@link #setTranslationY(float) translationY} property plus the current 12668 * {@link #getTop() top} property. 12669 * 12670 * @return The visual y position of this view, in pixels. 12671 */ 12672 @ViewDebug.ExportedProperty(category = "drawing") getY()12673 public float getY() { 12674 return mTop + getTranslationY(); 12675 } 12676 12677 /** 12678 * Sets the visual y position of this view, in pixels. This is equivalent to setting the 12679 * {@link #setTranslationY(float) translationY} property to be the difference between 12680 * the y value passed in and the current {@link #getTop() top} property. 12681 * 12682 * @param y The visual y position of this view, in pixels. 12683 */ setY(float y)12684 public void setY(float y) { 12685 setTranslationY(y - mTop); 12686 } 12687 12688 /** 12689 * The visual z position of this view, in pixels. This is equivalent to the 12690 * {@link #setTranslationZ(float) translationZ} property plus the current 12691 * {@link #getElevation() elevation} property. 12692 * 12693 * @return The visual z position of this view, in pixels. 12694 */ 12695 @ViewDebug.ExportedProperty(category = "drawing") getZ()12696 public float getZ() { 12697 return getElevation() + getTranslationZ(); 12698 } 12699 12700 /** 12701 * Sets the visual z position of this view, in pixels. This is equivalent to setting the 12702 * {@link #setTranslationZ(float) translationZ} property to be the difference between 12703 * the x value passed in and the current {@link #getElevation() elevation} property. 12704 * 12705 * @param z The visual z position of this view, in pixels. 12706 */ setZ(float z)12707 public void setZ(float z) { 12708 setTranslationZ(z - getElevation()); 12709 } 12710 12711 /** 12712 * The base elevation of this view relative to its parent, in pixels. 12713 * 12714 * @return The base depth position of the view, in pixels. 12715 */ 12716 @ViewDebug.ExportedProperty(category = "drawing") getElevation()12717 public float getElevation() { 12718 return mRenderNode.getElevation(); 12719 } 12720 12721 /** 12722 * Sets the base elevation of this view, in pixels. 12723 * 12724 * @attr ref android.R.styleable#View_elevation 12725 */ setElevation(float elevation)12726 public void setElevation(float elevation) { 12727 if (elevation != getElevation()) { 12728 invalidateViewProperty(true, false); 12729 mRenderNode.setElevation(elevation); 12730 invalidateViewProperty(false, true); 12731 12732 invalidateParentIfNeededAndWasQuickRejected(); 12733 } 12734 } 12735 12736 /** 12737 * The horizontal location of this view relative to its {@link #getLeft() left} position. 12738 * This position is post-layout, in addition to wherever the object's 12739 * layout placed it. 12740 * 12741 * @return The horizontal position of this view relative to its left position, in pixels. 12742 */ 12743 @ViewDebug.ExportedProperty(category = "drawing") getTranslationX()12744 public float getTranslationX() { 12745 return mRenderNode.getTranslationX(); 12746 } 12747 12748 /** 12749 * Sets the horizontal location of this view relative to its {@link #getLeft() left} position. 12750 * This effectively positions the object post-layout, in addition to wherever the object's 12751 * layout placed it. 12752 * 12753 * @param translationX The horizontal position of this view relative to its left position, 12754 * in pixels. 12755 * 12756 * @attr ref android.R.styleable#View_translationX 12757 */ setTranslationX(float translationX)12758 public void setTranslationX(float translationX) { 12759 if (translationX != getTranslationX()) { 12760 invalidateViewProperty(true, false); 12761 mRenderNode.setTranslationX(translationX); 12762 invalidateViewProperty(false, true); 12763 12764 invalidateParentIfNeededAndWasQuickRejected(); 12765 notifySubtreeAccessibilityStateChangedIfNeeded(); 12766 } 12767 } 12768 12769 /** 12770 * The vertical location of this view relative to its {@link #getTop() top} position. 12771 * This position is post-layout, in addition to wherever the object's 12772 * layout placed it. 12773 * 12774 * @return The vertical position of this view relative to its top position, 12775 * in pixels. 12776 */ 12777 @ViewDebug.ExportedProperty(category = "drawing") getTranslationY()12778 public float getTranslationY() { 12779 return mRenderNode.getTranslationY(); 12780 } 12781 12782 /** 12783 * Sets the vertical location of this view relative to its {@link #getTop() top} position. 12784 * This effectively positions the object post-layout, in addition to wherever the object's 12785 * layout placed it. 12786 * 12787 * @param translationY The vertical position of this view relative to its top position, 12788 * in pixels. 12789 * 12790 * @attr ref android.R.styleable#View_translationY 12791 */ setTranslationY(float translationY)12792 public void setTranslationY(float translationY) { 12793 if (translationY != getTranslationY()) { 12794 invalidateViewProperty(true, false); 12795 mRenderNode.setTranslationY(translationY); 12796 invalidateViewProperty(false, true); 12797 12798 invalidateParentIfNeededAndWasQuickRejected(); 12799 notifySubtreeAccessibilityStateChangedIfNeeded(); 12800 } 12801 } 12802 12803 /** 12804 * The depth location of this view relative to its {@link #getElevation() elevation}. 12805 * 12806 * @return The depth of this view relative to its elevation. 12807 */ 12808 @ViewDebug.ExportedProperty(category = "drawing") getTranslationZ()12809 public float getTranslationZ() { 12810 return mRenderNode.getTranslationZ(); 12811 } 12812 12813 /** 12814 * Sets the depth location of this view relative to its {@link #getElevation() elevation}. 12815 * 12816 * @attr ref android.R.styleable#View_translationZ 12817 */ setTranslationZ(float translationZ)12818 public void setTranslationZ(float translationZ) { 12819 if (translationZ != getTranslationZ()) { 12820 invalidateViewProperty(true, false); 12821 mRenderNode.setTranslationZ(translationZ); 12822 invalidateViewProperty(false, true); 12823 12824 invalidateParentIfNeededAndWasQuickRejected(); 12825 } 12826 } 12827 12828 /** @hide */ setAnimationMatrix(Matrix matrix)12829 public void setAnimationMatrix(Matrix matrix) { 12830 invalidateViewProperty(true, false); 12831 mRenderNode.setAnimationMatrix(matrix); 12832 invalidateViewProperty(false, true); 12833 12834 invalidateParentIfNeededAndWasQuickRejected(); 12835 } 12836 12837 /** 12838 * Returns the current StateListAnimator if exists. 12839 * 12840 * @return StateListAnimator or null if it does not exists 12841 * @see #setStateListAnimator(android.animation.StateListAnimator) 12842 */ getStateListAnimator()12843 public StateListAnimator getStateListAnimator() { 12844 return mStateListAnimator; 12845 } 12846 12847 /** 12848 * Attaches the provided StateListAnimator to this View. 12849 * <p> 12850 * Any previously attached StateListAnimator will be detached. 12851 * 12852 * @param stateListAnimator The StateListAnimator to update the view 12853 * @see {@link android.animation.StateListAnimator} 12854 */ setStateListAnimator(StateListAnimator stateListAnimator)12855 public void setStateListAnimator(StateListAnimator stateListAnimator) { 12856 if (mStateListAnimator == stateListAnimator) { 12857 return; 12858 } 12859 if (mStateListAnimator != null) { 12860 mStateListAnimator.setTarget(null); 12861 } 12862 mStateListAnimator = stateListAnimator; 12863 if (stateListAnimator != null) { 12864 stateListAnimator.setTarget(this); 12865 if (isAttachedToWindow()) { 12866 stateListAnimator.setState(getDrawableState()); 12867 } 12868 } 12869 } 12870 12871 /** 12872 * Returns whether the Outline should be used to clip the contents of the View. 12873 * <p> 12874 * Note that this flag will only be respected if the View's Outline returns true from 12875 * {@link Outline#canClip()}. 12876 * 12877 * @see #setOutlineProvider(ViewOutlineProvider) 12878 * @see #setClipToOutline(boolean) 12879 */ getClipToOutline()12880 public final boolean getClipToOutline() { 12881 return mRenderNode.getClipToOutline(); 12882 } 12883 12884 /** 12885 * Sets whether the View's Outline should be used to clip the contents of the View. 12886 * <p> 12887 * Only a single non-rectangular clip can be applied on a View at any time. 12888 * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float) 12889 * circular reveal} animation take priority over Outline clipping, and 12890 * child Outline clipping takes priority over Outline clipping done by a 12891 * parent. 12892 * <p> 12893 * Note that this flag will only be respected if the View's Outline returns true from 12894 * {@link Outline#canClip()}. 12895 * 12896 * @see #setOutlineProvider(ViewOutlineProvider) 12897 * @see #getClipToOutline() 12898 */ setClipToOutline(boolean clipToOutline)12899 public void setClipToOutline(boolean clipToOutline) { 12900 damageInParent(); 12901 if (getClipToOutline() != clipToOutline) { 12902 mRenderNode.setClipToOutline(clipToOutline); 12903 } 12904 } 12905 12906 // correspond to the enum values of View_outlineProvider 12907 private static final int PROVIDER_BACKGROUND = 0; 12908 private static final int PROVIDER_NONE = 1; 12909 private static final int PROVIDER_BOUNDS = 2; 12910 private static final int PROVIDER_PADDED_BOUNDS = 3; setOutlineProviderFromAttribute(int providerInt)12911 private void setOutlineProviderFromAttribute(int providerInt) { 12912 switch (providerInt) { 12913 case PROVIDER_BACKGROUND: 12914 setOutlineProvider(ViewOutlineProvider.BACKGROUND); 12915 break; 12916 case PROVIDER_NONE: 12917 setOutlineProvider(null); 12918 break; 12919 case PROVIDER_BOUNDS: 12920 setOutlineProvider(ViewOutlineProvider.BOUNDS); 12921 break; 12922 case PROVIDER_PADDED_BOUNDS: 12923 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS); 12924 break; 12925 } 12926 } 12927 12928 /** 12929 * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines 12930 * the shape of the shadow it casts, and enables outline clipping. 12931 * <p> 12932 * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline 12933 * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the 12934 * outline provider with this method allows this behavior to be overridden. 12935 * <p> 12936 * If the ViewOutlineProvider is null, if querying it for an outline returns false, 12937 * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast. 12938 * <p> 12939 * Only outlines that return true from {@link Outline#canClip()} may be used for clipping. 12940 * 12941 * @see #setClipToOutline(boolean) 12942 * @see #getClipToOutline() 12943 * @see #getOutlineProvider() 12944 */ setOutlineProvider(ViewOutlineProvider provider)12945 public void setOutlineProvider(ViewOutlineProvider provider) { 12946 mOutlineProvider = provider; 12947 invalidateOutline(); 12948 } 12949 12950 /** 12951 * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline 12952 * that defines the shape of the shadow it casts, and enables outline clipping. 12953 * 12954 * @see #setOutlineProvider(ViewOutlineProvider) 12955 */ getOutlineProvider()12956 public ViewOutlineProvider getOutlineProvider() { 12957 return mOutlineProvider; 12958 } 12959 12960 /** 12961 * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider} 12962 * 12963 * @see #setOutlineProvider(ViewOutlineProvider) 12964 */ invalidateOutline()12965 public void invalidateOutline() { 12966 rebuildOutline(); 12967 12968 notifySubtreeAccessibilityStateChangedIfNeeded(); 12969 invalidateViewProperty(false, false); 12970 } 12971 12972 /** 12973 * Internal version of {@link #invalidateOutline()} which invalidates the 12974 * outline without invalidating the view itself. This is intended to be called from 12975 * within methods in the View class itself which are the result of the view being 12976 * invalidated already. For example, when we are drawing the background of a View, 12977 * we invalidate the outline in case it changed in the meantime, but we do not 12978 * need to invalidate the view because we're already drawing the background as part 12979 * of drawing the view in response to an earlier invalidation of the view. 12980 */ rebuildOutline()12981 private void rebuildOutline() { 12982 // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow() 12983 if (mAttachInfo == null) return; 12984 12985 if (mOutlineProvider == null) { 12986 // no provider, remove outline 12987 mRenderNode.setOutline(null); 12988 } else { 12989 final Outline outline = mAttachInfo.mTmpOutline; 12990 outline.setEmpty(); 12991 outline.setAlpha(1.0f); 12992 12993 mOutlineProvider.getOutline(this, outline); 12994 mRenderNode.setOutline(outline); 12995 } 12996 } 12997 12998 /** 12999 * HierarchyViewer only 13000 * 13001 * @hide 13002 */ 13003 @ViewDebug.ExportedProperty(category = "drawing") hasShadow()13004 public boolean hasShadow() { 13005 return mRenderNode.hasShadow(); 13006 } 13007 13008 13009 /** @hide */ setRevealClip(boolean shouldClip, float x, float y, float radius)13010 public void setRevealClip(boolean shouldClip, float x, float y, float radius) { 13011 mRenderNode.setRevealClip(shouldClip, x, y, radius); 13012 invalidateViewProperty(false, false); 13013 } 13014 13015 /** 13016 * Hit rectangle in parent's coordinates 13017 * 13018 * @param outRect The hit rectangle of the view. 13019 */ getHitRect(Rect outRect)13020 public void getHitRect(Rect outRect) { 13021 if (hasIdentityMatrix() || mAttachInfo == null) { 13022 outRect.set(mLeft, mTop, mRight, mBottom); 13023 } else { 13024 final RectF tmpRect = mAttachInfo.mTmpTransformRect; 13025 tmpRect.set(0, 0, getWidth(), getHeight()); 13026 getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect) 13027 outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop, 13028 (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop); 13029 } 13030 } 13031 13032 /** 13033 * Determines whether the given point, in local coordinates is inside the view. 13034 */ pointInView(float localX, float localY)13035 /*package*/ final boolean pointInView(float localX, float localY) { 13036 return pointInView(localX, localY, 0); 13037 } 13038 13039 /** 13040 * Utility method to determine whether the given point, in local coordinates, 13041 * is inside the view, where the area of the view is expanded by the slop factor. 13042 * This method is called while processing touch-move events to determine if the event 13043 * is still within the view. 13044 * 13045 * @hide 13046 */ pointInView(float localX, float localY, float slop)13047 public boolean pointInView(float localX, float localY, float slop) { 13048 return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) && 13049 localY < ((mBottom - mTop) + slop); 13050 } 13051 13052 /** 13053 * When a view has focus and the user navigates away from it, the next view is searched for 13054 * starting from the rectangle filled in by this method. 13055 * 13056 * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)}) 13057 * of the view. However, if your view maintains some idea of internal selection, 13058 * such as a cursor, or a selected row or column, you should override this method and 13059 * fill in a more specific rectangle. 13060 * 13061 * @param r The rectangle to fill in, in this view's coordinates. 13062 */ getFocusedRect(Rect r)13063 public void getFocusedRect(Rect r) { 13064 getDrawingRect(r); 13065 } 13066 13067 /** 13068 * If some part of this view is not clipped by any of its parents, then 13069 * return that area in r in global (root) coordinates. To convert r to local 13070 * coordinates (without taking possible View rotations into account), offset 13071 * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)). 13072 * If the view is completely clipped or translated out, return false. 13073 * 13074 * @param r If true is returned, r holds the global coordinates of the 13075 * visible portion of this view. 13076 * @param globalOffset If true is returned, globalOffset holds the dx,dy 13077 * between this view and its root. globalOffet may be null. 13078 * @return true if r is non-empty (i.e. part of the view is visible at the 13079 * root level. 13080 */ getGlobalVisibleRect(Rect r, Point globalOffset)13081 public boolean getGlobalVisibleRect(Rect r, Point globalOffset) { 13082 int width = mRight - mLeft; 13083 int height = mBottom - mTop; 13084 if (width > 0 && height > 0) { 13085 r.set(0, 0, width, height); 13086 if (globalOffset != null) { 13087 globalOffset.set(-mScrollX, -mScrollY); 13088 } 13089 return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset); 13090 } 13091 return false; 13092 } 13093 getGlobalVisibleRect(Rect r)13094 public final boolean getGlobalVisibleRect(Rect r) { 13095 return getGlobalVisibleRect(r, null); 13096 } 13097 getLocalVisibleRect(Rect r)13098 public final boolean getLocalVisibleRect(Rect r) { 13099 final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point(); 13100 if (getGlobalVisibleRect(r, offset)) { 13101 r.offset(-offset.x, -offset.y); // make r local 13102 return true; 13103 } 13104 return false; 13105 } 13106 13107 /** 13108 * Offset this view's vertical location by the specified number of pixels. 13109 * 13110 * @param offset the number of pixels to offset the view by 13111 */ offsetTopAndBottom(int offset)13112 public void offsetTopAndBottom(int offset) { 13113 if (offset != 0) { 13114 final boolean matrixIsIdentity = hasIdentityMatrix(); 13115 if (matrixIsIdentity) { 13116 if (isHardwareAccelerated()) { 13117 invalidateViewProperty(false, false); 13118 } else { 13119 final ViewParent p = mParent; 13120 if (p != null && mAttachInfo != null) { 13121 final Rect r = mAttachInfo.mTmpInvalRect; 13122 int minTop; 13123 int maxBottom; 13124 int yLoc; 13125 if (offset < 0) { 13126 minTop = mTop + offset; 13127 maxBottom = mBottom; 13128 yLoc = offset; 13129 } else { 13130 minTop = mTop; 13131 maxBottom = mBottom + offset; 13132 yLoc = 0; 13133 } 13134 r.set(0, yLoc, mRight - mLeft, maxBottom - minTop); 13135 p.invalidateChild(this, r); 13136 } 13137 } 13138 } else { 13139 invalidateViewProperty(false, false); 13140 } 13141 13142 mTop += offset; 13143 mBottom += offset; 13144 mRenderNode.offsetTopAndBottom(offset); 13145 if (isHardwareAccelerated()) { 13146 invalidateViewProperty(false, false); 13147 invalidateParentIfNeededAndWasQuickRejected(); 13148 } else { 13149 if (!matrixIsIdentity) { 13150 invalidateViewProperty(false, true); 13151 } 13152 invalidateParentIfNeeded(); 13153 } 13154 notifySubtreeAccessibilityStateChangedIfNeeded(); 13155 } 13156 } 13157 13158 /** 13159 * Offset this view's horizontal location by the specified amount of pixels. 13160 * 13161 * @param offset the number of pixels to offset the view by 13162 */ offsetLeftAndRight(int offset)13163 public void offsetLeftAndRight(int offset) { 13164 if (offset != 0) { 13165 final boolean matrixIsIdentity = hasIdentityMatrix(); 13166 if (matrixIsIdentity) { 13167 if (isHardwareAccelerated()) { 13168 invalidateViewProperty(false, false); 13169 } else { 13170 final ViewParent p = mParent; 13171 if (p != null && mAttachInfo != null) { 13172 final Rect r = mAttachInfo.mTmpInvalRect; 13173 int minLeft; 13174 int maxRight; 13175 if (offset < 0) { 13176 minLeft = mLeft + offset; 13177 maxRight = mRight; 13178 } else { 13179 minLeft = mLeft; 13180 maxRight = mRight + offset; 13181 } 13182 r.set(0, 0, maxRight - minLeft, mBottom - mTop); 13183 p.invalidateChild(this, r); 13184 } 13185 } 13186 } else { 13187 invalidateViewProperty(false, false); 13188 } 13189 13190 mLeft += offset; 13191 mRight += offset; 13192 mRenderNode.offsetLeftAndRight(offset); 13193 if (isHardwareAccelerated()) { 13194 invalidateViewProperty(false, false); 13195 invalidateParentIfNeededAndWasQuickRejected(); 13196 } else { 13197 if (!matrixIsIdentity) { 13198 invalidateViewProperty(false, true); 13199 } 13200 invalidateParentIfNeeded(); 13201 } 13202 notifySubtreeAccessibilityStateChangedIfNeeded(); 13203 } 13204 } 13205 13206 /** 13207 * Get the LayoutParams associated with this view. All views should have 13208 * layout parameters. These supply parameters to the <i>parent</i> of this 13209 * view specifying how it should be arranged. There are many subclasses of 13210 * ViewGroup.LayoutParams, and these correspond to the different subclasses 13211 * of ViewGroup that are responsible for arranging their children. 13212 * 13213 * This method may return null if this View is not attached to a parent 13214 * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)} 13215 * was not invoked successfully. When a View is attached to a parent 13216 * ViewGroup, this method must not return null. 13217 * 13218 * @return The LayoutParams associated with this view, or null if no 13219 * parameters have been set yet 13220 */ 13221 @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_") getLayoutParams()13222 public ViewGroup.LayoutParams getLayoutParams() { 13223 return mLayoutParams; 13224 } 13225 13226 /** 13227 * Set the layout parameters associated with this view. These supply 13228 * parameters to the <i>parent</i> of this view specifying how it should be 13229 * arranged. There are many subclasses of ViewGroup.LayoutParams, and these 13230 * correspond to the different subclasses of ViewGroup that are responsible 13231 * for arranging their children. 13232 * 13233 * @param params The layout parameters for this view, cannot be null 13234 */ setLayoutParams(ViewGroup.LayoutParams params)13235 public void setLayoutParams(ViewGroup.LayoutParams params) { 13236 if (params == null) { 13237 throw new NullPointerException("Layout parameters cannot be null"); 13238 } 13239 mLayoutParams = params; 13240 resolveLayoutParams(); 13241 if (mParent instanceof ViewGroup) { 13242 ((ViewGroup) mParent).onSetLayoutParams(this, params); 13243 } 13244 requestLayout(); 13245 } 13246 13247 /** 13248 * Resolve the layout parameters depending on the resolved layout direction 13249 * 13250 * @hide 13251 */ resolveLayoutParams()13252 public void resolveLayoutParams() { 13253 if (mLayoutParams != null) { 13254 mLayoutParams.resolveLayoutDirection(getLayoutDirection()); 13255 } 13256 } 13257 13258 /** 13259 * Set the scrolled position of your view. This will cause a call to 13260 * {@link #onScrollChanged(int, int, int, int)} and the view will be 13261 * invalidated. 13262 * @param x the x position to scroll to 13263 * @param y the y position to scroll to 13264 */ scrollTo(int x, int y)13265 public void scrollTo(int x, int y) { 13266 if (mScrollX != x || mScrollY != y) { 13267 int oldX = mScrollX; 13268 int oldY = mScrollY; 13269 mScrollX = x; 13270 mScrollY = y; 13271 invalidateParentCaches(); 13272 onScrollChanged(mScrollX, mScrollY, oldX, oldY); 13273 if (!awakenScrollBars()) { 13274 postInvalidateOnAnimation(); 13275 } 13276 } 13277 } 13278 13279 /** 13280 * Move the scrolled position of your view. This will cause a call to 13281 * {@link #onScrollChanged(int, int, int, int)} and the view will be 13282 * invalidated. 13283 * @param x the amount of pixels to scroll by horizontally 13284 * @param y the amount of pixels to scroll by vertically 13285 */ scrollBy(int x, int y)13286 public void scrollBy(int x, int y) { 13287 scrollTo(mScrollX + x, mScrollY + y); 13288 } 13289 13290 /** 13291 * <p>Trigger the scrollbars to draw. When invoked this method starts an 13292 * animation to fade the scrollbars out after a default delay. If a subclass 13293 * provides animated scrolling, the start delay should equal the duration 13294 * of the scrolling animation.</p> 13295 * 13296 * <p>The animation starts only if at least one of the scrollbars is 13297 * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and 13298 * {@link #isVerticalScrollBarEnabled()}. When the animation is started, 13299 * this method returns true, and false otherwise. If the animation is 13300 * started, this method calls {@link #invalidate()}; in that case the 13301 * caller should not call {@link #invalidate()}.</p> 13302 * 13303 * <p>This method should be invoked every time a subclass directly updates 13304 * the scroll parameters.</p> 13305 * 13306 * <p>This method is automatically invoked by {@link #scrollBy(int, int)} 13307 * and {@link #scrollTo(int, int)}.</p> 13308 * 13309 * @return true if the animation is played, false otherwise 13310 * 13311 * @see #awakenScrollBars(int) 13312 * @see #scrollBy(int, int) 13313 * @see #scrollTo(int, int) 13314 * @see #isHorizontalScrollBarEnabled() 13315 * @see #isVerticalScrollBarEnabled() 13316 * @see #setHorizontalScrollBarEnabled(boolean) 13317 * @see #setVerticalScrollBarEnabled(boolean) 13318 */ awakenScrollBars()13319 protected boolean awakenScrollBars() { 13320 return mScrollCache != null && 13321 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true); 13322 } 13323 13324 /** 13325 * Trigger the scrollbars to draw. 13326 * This method differs from awakenScrollBars() only in its default duration. 13327 * initialAwakenScrollBars() will show the scroll bars for longer than 13328 * usual to give the user more of a chance to notice them. 13329 * 13330 * @return true if the animation is played, false otherwise. 13331 */ initialAwakenScrollBars()13332 private boolean initialAwakenScrollBars() { 13333 return mScrollCache != null && 13334 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true); 13335 } 13336 13337 /** 13338 * <p> 13339 * Trigger the scrollbars to draw. When invoked this method starts an 13340 * animation to fade the scrollbars out after a fixed delay. If a subclass 13341 * provides animated scrolling, the start delay should equal the duration of 13342 * the scrolling animation. 13343 * </p> 13344 * 13345 * <p> 13346 * The animation starts only if at least one of the scrollbars is enabled, 13347 * as specified by {@link #isHorizontalScrollBarEnabled()} and 13348 * {@link #isVerticalScrollBarEnabled()}. When the animation is started, 13349 * this method returns true, and false otherwise. If the animation is 13350 * started, this method calls {@link #invalidate()}; in that case the caller 13351 * should not call {@link #invalidate()}. 13352 * </p> 13353 * 13354 * <p> 13355 * This method should be invoked every time a subclass directly updates the 13356 * scroll parameters. 13357 * </p> 13358 * 13359 * @param startDelay the delay, in milliseconds, after which the animation 13360 * should start; when the delay is 0, the animation starts 13361 * immediately 13362 * @return true if the animation is played, false otherwise 13363 * 13364 * @see #scrollBy(int, int) 13365 * @see #scrollTo(int, int) 13366 * @see #isHorizontalScrollBarEnabled() 13367 * @see #isVerticalScrollBarEnabled() 13368 * @see #setHorizontalScrollBarEnabled(boolean) 13369 * @see #setVerticalScrollBarEnabled(boolean) 13370 */ awakenScrollBars(int startDelay)13371 protected boolean awakenScrollBars(int startDelay) { 13372 return awakenScrollBars(startDelay, true); 13373 } 13374 13375 /** 13376 * <p> 13377 * Trigger the scrollbars to draw. When invoked this method starts an 13378 * animation to fade the scrollbars out after a fixed delay. If a subclass 13379 * provides animated scrolling, the start delay should equal the duration of 13380 * the scrolling animation. 13381 * </p> 13382 * 13383 * <p> 13384 * The animation starts only if at least one of the scrollbars is enabled, 13385 * as specified by {@link #isHorizontalScrollBarEnabled()} and 13386 * {@link #isVerticalScrollBarEnabled()}. When the animation is started, 13387 * this method returns true, and false otherwise. If the animation is 13388 * started, this method calls {@link #invalidate()} if the invalidate parameter 13389 * is set to true; in that case the caller 13390 * should not call {@link #invalidate()}. 13391 * </p> 13392 * 13393 * <p> 13394 * This method should be invoked every time a subclass directly updates the 13395 * scroll parameters. 13396 * </p> 13397 * 13398 * @param startDelay the delay, in milliseconds, after which the animation 13399 * should start; when the delay is 0, the animation starts 13400 * immediately 13401 * 13402 * @param invalidate Whether this method should call invalidate 13403 * 13404 * @return true if the animation is played, false otherwise 13405 * 13406 * @see #scrollBy(int, int) 13407 * @see #scrollTo(int, int) 13408 * @see #isHorizontalScrollBarEnabled() 13409 * @see #isVerticalScrollBarEnabled() 13410 * @see #setHorizontalScrollBarEnabled(boolean) 13411 * @see #setVerticalScrollBarEnabled(boolean) 13412 */ awakenScrollBars(int startDelay, boolean invalidate)13413 protected boolean awakenScrollBars(int startDelay, boolean invalidate) { 13414 final ScrollabilityCache scrollCache = mScrollCache; 13415 13416 if (scrollCache == null || !scrollCache.fadeScrollBars) { 13417 return false; 13418 } 13419 13420 if (scrollCache.scrollBar == null) { 13421 scrollCache.scrollBar = new ScrollBarDrawable(); 13422 scrollCache.scrollBar.setState(getDrawableState()); 13423 scrollCache.scrollBar.setCallback(this); 13424 } 13425 13426 if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) { 13427 13428 if (invalidate) { 13429 // Invalidate to show the scrollbars 13430 postInvalidateOnAnimation(); 13431 } 13432 13433 if (scrollCache.state == ScrollabilityCache.OFF) { 13434 // FIXME: this is copied from WindowManagerService. 13435 // We should get this value from the system when it 13436 // is possible to do so. 13437 final int KEY_REPEAT_FIRST_DELAY = 750; 13438 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay); 13439 } 13440 13441 // Tell mScrollCache when we should start fading. This may 13442 // extend the fade start time if one was already scheduled 13443 long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay; 13444 scrollCache.fadeStartTime = fadeStartTime; 13445 scrollCache.state = ScrollabilityCache.ON; 13446 13447 // Schedule our fader to run, unscheduling any old ones first 13448 if (mAttachInfo != null) { 13449 mAttachInfo.mHandler.removeCallbacks(scrollCache); 13450 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime); 13451 } 13452 13453 return true; 13454 } 13455 13456 return false; 13457 } 13458 13459 /** 13460 * Do not invalidate views which are not visible and which are not running an animation. They 13461 * will not get drawn and they should not set dirty flags as if they will be drawn 13462 */ skipInvalidate()13463 private boolean skipInvalidate() { 13464 return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null && 13465 (!(mParent instanceof ViewGroup) || 13466 !((ViewGroup) mParent).isViewTransitioning(this)); 13467 } 13468 13469 /** 13470 * Mark the area defined by dirty as needing to be drawn. If the view is 13471 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some 13472 * point in the future. 13473 * <p> 13474 * This must be called from a UI thread. To call from a non-UI thread, call 13475 * {@link #postInvalidate()}. 13476 * <p> 13477 * <b>WARNING:</b> In API 19 and below, this method may be destructive to 13478 * {@code dirty}. 13479 * 13480 * @param dirty the rectangle representing the bounds of the dirty region 13481 */ invalidate(Rect dirty)13482 public void invalidate(Rect dirty) { 13483 final int scrollX = mScrollX; 13484 final int scrollY = mScrollY; 13485 invalidateInternal(dirty.left - scrollX, dirty.top - scrollY, 13486 dirty.right - scrollX, dirty.bottom - scrollY, true, false); 13487 } 13488 13489 /** 13490 * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The 13491 * coordinates of the dirty rect are relative to the view. If the view is 13492 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some 13493 * point in the future. 13494 * <p> 13495 * This must be called from a UI thread. To call from a non-UI thread, call 13496 * {@link #postInvalidate()}. 13497 * 13498 * @param l the left position of the dirty region 13499 * @param t the top position of the dirty region 13500 * @param r the right position of the dirty region 13501 * @param b the bottom position of the dirty region 13502 */ invalidate(int l, int t, int r, int b)13503 public void invalidate(int l, int t, int r, int b) { 13504 final int scrollX = mScrollX; 13505 final int scrollY = mScrollY; 13506 invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false); 13507 } 13508 13509 /** 13510 * Invalidate the whole view. If the view is visible, 13511 * {@link #onDraw(android.graphics.Canvas)} will be called at some point in 13512 * the future. 13513 * <p> 13514 * This must be called from a UI thread. To call from a non-UI thread, call 13515 * {@link #postInvalidate()}. 13516 */ invalidate()13517 public void invalidate() { 13518 invalidate(true); 13519 } 13520 13521 /** 13522 * This is where the invalidate() work actually happens. A full invalidate() 13523 * causes the drawing cache to be invalidated, but this function can be 13524 * called with invalidateCache set to false to skip that invalidation step 13525 * for cases that do not need it (for example, a component that remains at 13526 * the same dimensions with the same content). 13527 * 13528 * @param invalidateCache Whether the drawing cache for this view should be 13529 * invalidated as well. This is usually true for a full 13530 * invalidate, but may be set to false if the View's contents or 13531 * dimensions have not changed. 13532 */ invalidate(boolean invalidateCache)13533 void invalidate(boolean invalidateCache) { 13534 invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true); 13535 } 13536 invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, boolean fullInvalidate)13537 void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, 13538 boolean fullInvalidate) { 13539 if (mGhostView != null) { 13540 mGhostView.invalidate(true); 13541 return; 13542 } 13543 13544 if (skipInvalidate()) { 13545 return; 13546 } 13547 13548 if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) 13549 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) 13550 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED 13551 || (fullInvalidate && isOpaque() != mLastIsOpaque)) { 13552 if (fullInvalidate) { 13553 mLastIsOpaque = isOpaque(); 13554 mPrivateFlags &= ~PFLAG_DRAWN; 13555 } 13556 13557 mPrivateFlags |= PFLAG_DIRTY; 13558 13559 if (invalidateCache) { 13560 mPrivateFlags |= PFLAG_INVALIDATED; 13561 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 13562 } 13563 13564 // Propagate the damage rectangle to the parent view. 13565 final AttachInfo ai = mAttachInfo; 13566 final ViewParent p = mParent; 13567 if (p != null && ai != null && l < r && t < b) { 13568 final Rect damage = ai.mTmpInvalRect; 13569 damage.set(l, t, r, b); 13570 p.invalidateChild(this, damage); 13571 } 13572 13573 // Damage the entire projection receiver, if necessary. 13574 if (mBackground != null && mBackground.isProjected()) { 13575 final View receiver = getProjectionReceiver(); 13576 if (receiver != null) { 13577 receiver.damageInParent(); 13578 } 13579 } 13580 13581 // Damage the entire IsolatedZVolume receiving this view's shadow. 13582 if (isHardwareAccelerated() && getZ() != 0) { 13583 damageShadowReceiver(); 13584 } 13585 } 13586 } 13587 13588 /** 13589 * @return this view's projection receiver, or {@code null} if none exists 13590 */ getProjectionReceiver()13591 private View getProjectionReceiver() { 13592 ViewParent p = getParent(); 13593 while (p != null && p instanceof View) { 13594 final View v = (View) p; 13595 if (v.isProjectionReceiver()) { 13596 return v; 13597 } 13598 p = p.getParent(); 13599 } 13600 13601 return null; 13602 } 13603 13604 /** 13605 * @return whether the view is a projection receiver 13606 */ isProjectionReceiver()13607 private boolean isProjectionReceiver() { 13608 return mBackground != null; 13609 } 13610 13611 /** 13612 * Damage area of the screen that can be covered by this View's shadow. 13613 * 13614 * This method will guarantee that any changes to shadows cast by a View 13615 * are damaged on the screen for future redraw. 13616 */ damageShadowReceiver()13617 private void damageShadowReceiver() { 13618 final AttachInfo ai = mAttachInfo; 13619 if (ai != null) { 13620 ViewParent p = getParent(); 13621 if (p != null && p instanceof ViewGroup) { 13622 final ViewGroup vg = (ViewGroup) p; 13623 vg.damageInParent(); 13624 } 13625 } 13626 } 13627 13628 /** 13629 * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to 13630 * set any flags or handle all of the cases handled by the default invalidation methods. 13631 * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate 13632 * dirty rect. This method calls into fast invalidation methods in ViewGroup that 13633 * walk up the hierarchy, transforming the dirty rect as necessary. 13634 * 13635 * The method also handles normal invalidation logic if display list properties are not 13636 * being used in this view. The invalidateParent and forceRedraw flags are used by that 13637 * backup approach, to handle these cases used in the various property-setting methods. 13638 * 13639 * @param invalidateParent Force a call to invalidateParentCaches() if display list properties 13640 * are not being used in this view 13641 * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display 13642 * list properties are not being used in this view 13643 */ invalidateViewProperty(boolean invalidateParent, boolean forceRedraw)13644 void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) { 13645 if (!isHardwareAccelerated() 13646 || !mRenderNode.isValid() 13647 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) { 13648 if (invalidateParent) { 13649 invalidateParentCaches(); 13650 } 13651 if (forceRedraw) { 13652 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 13653 } 13654 invalidate(false); 13655 } else { 13656 damageInParent(); 13657 } 13658 if (isHardwareAccelerated() && invalidateParent && getZ() != 0) { 13659 damageShadowReceiver(); 13660 } 13661 } 13662 13663 /** 13664 * Tells the parent view to damage this view's bounds. 13665 * 13666 * @hide 13667 */ damageInParent()13668 protected void damageInParent() { 13669 final AttachInfo ai = mAttachInfo; 13670 final ViewParent p = mParent; 13671 if (p != null && ai != null) { 13672 final Rect r = ai.mTmpInvalRect; 13673 r.set(0, 0, mRight - mLeft, mBottom - mTop); 13674 if (mParent instanceof ViewGroup) { 13675 ((ViewGroup) mParent).damageChild(this, r); 13676 } else { 13677 mParent.invalidateChild(this, r); 13678 } 13679 } 13680 } 13681 13682 /** 13683 * Utility method to transform a given Rect by the current matrix of this view. 13684 */ transformRect(final Rect rect)13685 void transformRect(final Rect rect) { 13686 if (!getMatrix().isIdentity()) { 13687 RectF boundingRect = mAttachInfo.mTmpTransformRect; 13688 boundingRect.set(rect); 13689 getMatrix().mapRect(boundingRect); 13690 rect.set((int) Math.floor(boundingRect.left), 13691 (int) Math.floor(boundingRect.top), 13692 (int) Math.ceil(boundingRect.right), 13693 (int) Math.ceil(boundingRect.bottom)); 13694 } 13695 } 13696 13697 /** 13698 * Used to indicate that the parent of this view should clear its caches. This functionality 13699 * is used to force the parent to rebuild its display list (when hardware-accelerated), 13700 * which is necessary when various parent-managed properties of the view change, such as 13701 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only 13702 * clears the parent caches and does not causes an invalidate event. 13703 * 13704 * @hide 13705 */ invalidateParentCaches()13706 protected void invalidateParentCaches() { 13707 if (mParent instanceof View) { 13708 ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED; 13709 } 13710 } 13711 13712 /** 13713 * Used to indicate that the parent of this view should be invalidated. This functionality 13714 * is used to force the parent to rebuild its display list (when hardware-accelerated), 13715 * which is necessary when various parent-managed properties of the view change, such as 13716 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate 13717 * an invalidation event to the parent. 13718 * 13719 * @hide 13720 */ invalidateParentIfNeeded()13721 protected void invalidateParentIfNeeded() { 13722 if (isHardwareAccelerated() && mParent instanceof View) { 13723 ((View) mParent).invalidate(true); 13724 } 13725 } 13726 13727 /** 13728 * @hide 13729 */ invalidateParentIfNeededAndWasQuickRejected()13730 protected void invalidateParentIfNeededAndWasQuickRejected() { 13731 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) { 13732 // View was rejected last time it was drawn by its parent; this may have changed 13733 invalidateParentIfNeeded(); 13734 } 13735 } 13736 13737 /** 13738 * Indicates whether this View is opaque. An opaque View guarantees that it will 13739 * draw all the pixels overlapping its bounds using a fully opaque color. 13740 * 13741 * Subclasses of View should override this method whenever possible to indicate 13742 * whether an instance is opaque. Opaque Views are treated in a special way by 13743 * the View hierarchy, possibly allowing it to perform optimizations during 13744 * invalidate/draw passes. 13745 * 13746 * @return True if this View is guaranteed to be fully opaque, false otherwise. 13747 */ 13748 @ViewDebug.ExportedProperty(category = "drawing") isOpaque()13749 public boolean isOpaque() { 13750 return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK && 13751 getFinalAlpha() >= 1.0f; 13752 } 13753 13754 /** 13755 * @hide 13756 */ computeOpaqueFlags()13757 protected void computeOpaqueFlags() { 13758 // Opaque if: 13759 // - Has a background 13760 // - Background is opaque 13761 // - Doesn't have scrollbars or scrollbars overlay 13762 13763 if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) { 13764 mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND; 13765 } else { 13766 mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND; 13767 } 13768 13769 final int flags = mViewFlags; 13770 if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) || 13771 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY || 13772 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) { 13773 mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS; 13774 } else { 13775 mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS; 13776 } 13777 } 13778 13779 /** 13780 * @hide 13781 */ hasOpaqueScrollbars()13782 protected boolean hasOpaqueScrollbars() { 13783 return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS; 13784 } 13785 13786 /** 13787 * @return A handler associated with the thread running the View. This 13788 * handler can be used to pump events in the UI events queue. 13789 */ getHandler()13790 public Handler getHandler() { 13791 final AttachInfo attachInfo = mAttachInfo; 13792 if (attachInfo != null) { 13793 return attachInfo.mHandler; 13794 } 13795 return null; 13796 } 13797 13798 /** 13799 * Returns the queue of runnable for this view. 13800 * 13801 * @return the queue of runnables for this view 13802 */ getRunQueue()13803 private HandlerActionQueue getRunQueue() { 13804 if (mRunQueue == null) { 13805 mRunQueue = new HandlerActionQueue(); 13806 } 13807 return mRunQueue; 13808 } 13809 13810 /** 13811 * Gets the view root associated with the View. 13812 * @return The view root, or null if none. 13813 * @hide 13814 */ getViewRootImpl()13815 public ViewRootImpl getViewRootImpl() { 13816 if (mAttachInfo != null) { 13817 return mAttachInfo.mViewRootImpl; 13818 } 13819 return null; 13820 } 13821 13822 /** 13823 * @hide 13824 */ getHardwareRenderer()13825 public ThreadedRenderer getHardwareRenderer() { 13826 return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null; 13827 } 13828 13829 /** 13830 * <p>Causes the Runnable to be added to the message queue. 13831 * The runnable will be run on the user interface thread.</p> 13832 * 13833 * @param action The Runnable that will be executed. 13834 * 13835 * @return Returns true if the Runnable was successfully placed in to the 13836 * message queue. Returns false on failure, usually because the 13837 * looper processing the message queue is exiting. 13838 * 13839 * @see #postDelayed 13840 * @see #removeCallbacks 13841 */ post(Runnable action)13842 public boolean post(Runnable action) { 13843 final AttachInfo attachInfo = mAttachInfo; 13844 if (attachInfo != null) { 13845 return attachInfo.mHandler.post(action); 13846 } 13847 13848 // Postpone the runnable until we know on which thread it needs to run. 13849 // Assume that the runnable will be successfully placed after attach. 13850 getRunQueue().post(action); 13851 return true; 13852 } 13853 13854 /** 13855 * <p>Causes the Runnable to be added to the message queue, to be run 13856 * after the specified amount of time elapses. 13857 * The runnable will be run on the user interface thread.</p> 13858 * 13859 * @param action The Runnable that will be executed. 13860 * @param delayMillis The delay (in milliseconds) until the Runnable 13861 * will be executed. 13862 * 13863 * @return true if the Runnable was successfully placed in to the 13864 * message queue. Returns false on failure, usually because the 13865 * looper processing the message queue is exiting. Note that a 13866 * result of true does not mean the Runnable will be processed -- 13867 * if the looper is quit before the delivery time of the message 13868 * occurs then the message will be dropped. 13869 * 13870 * @see #post 13871 * @see #removeCallbacks 13872 */ postDelayed(Runnable action, long delayMillis)13873 public boolean postDelayed(Runnable action, long delayMillis) { 13874 final AttachInfo attachInfo = mAttachInfo; 13875 if (attachInfo != null) { 13876 return attachInfo.mHandler.postDelayed(action, delayMillis); 13877 } 13878 13879 // Postpone the runnable until we know on which thread it needs to run. 13880 // Assume that the runnable will be successfully placed after attach. 13881 getRunQueue().postDelayed(action, delayMillis); 13882 return true; 13883 } 13884 13885 /** 13886 * <p>Causes the Runnable to execute on the next animation time step. 13887 * The runnable will be run on the user interface thread.</p> 13888 * 13889 * @param action The Runnable that will be executed. 13890 * 13891 * @see #postOnAnimationDelayed 13892 * @see #removeCallbacks 13893 */ postOnAnimation(Runnable action)13894 public void postOnAnimation(Runnable action) { 13895 final AttachInfo attachInfo = mAttachInfo; 13896 if (attachInfo != null) { 13897 attachInfo.mViewRootImpl.mChoreographer.postCallback( 13898 Choreographer.CALLBACK_ANIMATION, action, null); 13899 } else { 13900 // Postpone the runnable until we know 13901 // on which thread it needs to run. 13902 getRunQueue().post(action); 13903 } 13904 } 13905 13906 /** 13907 * <p>Causes the Runnable to execute on the next animation time step, 13908 * after the specified amount of time elapses. 13909 * The runnable will be run on the user interface thread.</p> 13910 * 13911 * @param action The Runnable that will be executed. 13912 * @param delayMillis The delay (in milliseconds) until the Runnable 13913 * will be executed. 13914 * 13915 * @see #postOnAnimation 13916 * @see #removeCallbacks 13917 */ postOnAnimationDelayed(Runnable action, long delayMillis)13918 public void postOnAnimationDelayed(Runnable action, long delayMillis) { 13919 final AttachInfo attachInfo = mAttachInfo; 13920 if (attachInfo != null) { 13921 attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed( 13922 Choreographer.CALLBACK_ANIMATION, action, null, delayMillis); 13923 } else { 13924 // Postpone the runnable until we know 13925 // on which thread it needs to run. 13926 getRunQueue().postDelayed(action, delayMillis); 13927 } 13928 } 13929 13930 /** 13931 * <p>Removes the specified Runnable from the message queue.</p> 13932 * 13933 * @param action The Runnable to remove from the message handling queue 13934 * 13935 * @return true if this view could ask the Handler to remove the Runnable, 13936 * false otherwise. When the returned value is true, the Runnable 13937 * may or may not have been actually removed from the message queue 13938 * (for instance, if the Runnable was not in the queue already.) 13939 * 13940 * @see #post 13941 * @see #postDelayed 13942 * @see #postOnAnimation 13943 * @see #postOnAnimationDelayed 13944 */ removeCallbacks(Runnable action)13945 public boolean removeCallbacks(Runnable action) { 13946 if (action != null) { 13947 final AttachInfo attachInfo = mAttachInfo; 13948 if (attachInfo != null) { 13949 attachInfo.mHandler.removeCallbacks(action); 13950 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks( 13951 Choreographer.CALLBACK_ANIMATION, action, null); 13952 } 13953 getRunQueue().removeCallbacks(action); 13954 } 13955 return true; 13956 } 13957 13958 /** 13959 * <p>Cause an invalidate to happen on a subsequent cycle through the event loop. 13960 * Use this to invalidate the View from a non-UI thread.</p> 13961 * 13962 * <p>This method can be invoked from outside of the UI thread 13963 * only when this View is attached to a window.</p> 13964 * 13965 * @see #invalidate() 13966 * @see #postInvalidateDelayed(long) 13967 */ postInvalidate()13968 public void postInvalidate() { 13969 postInvalidateDelayed(0); 13970 } 13971 13972 /** 13973 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle 13974 * through the event loop. Use this to invalidate the View from a non-UI thread.</p> 13975 * 13976 * <p>This method can be invoked from outside of the UI thread 13977 * only when this View is attached to a window.</p> 13978 * 13979 * @param left The left coordinate of the rectangle to invalidate. 13980 * @param top The top coordinate of the rectangle to invalidate. 13981 * @param right The right coordinate of the rectangle to invalidate. 13982 * @param bottom The bottom coordinate of the rectangle to invalidate. 13983 * 13984 * @see #invalidate(int, int, int, int) 13985 * @see #invalidate(Rect) 13986 * @see #postInvalidateDelayed(long, int, int, int, int) 13987 */ postInvalidate(int left, int top, int right, int bottom)13988 public void postInvalidate(int left, int top, int right, int bottom) { 13989 postInvalidateDelayed(0, left, top, right, bottom); 13990 } 13991 13992 /** 13993 * <p>Cause an invalidate to happen on a subsequent cycle through the event 13994 * loop. Waits for the specified amount of time.</p> 13995 * 13996 * <p>This method can be invoked from outside of the UI thread 13997 * only when this View is attached to a window.</p> 13998 * 13999 * @param delayMilliseconds the duration in milliseconds to delay the 14000 * invalidation by 14001 * 14002 * @see #invalidate() 14003 * @see #postInvalidate() 14004 */ postInvalidateDelayed(long delayMilliseconds)14005 public void postInvalidateDelayed(long delayMilliseconds) { 14006 // We try only with the AttachInfo because there's no point in invalidating 14007 // if we are not attached to our window 14008 final AttachInfo attachInfo = mAttachInfo; 14009 if (attachInfo != null) { 14010 attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds); 14011 } 14012 } 14013 14014 /** 14015 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle 14016 * through the event loop. Waits for the specified amount of time.</p> 14017 * 14018 * <p>This method can be invoked from outside of the UI thread 14019 * only when this View is attached to a window.</p> 14020 * 14021 * @param delayMilliseconds the duration in milliseconds to delay the 14022 * invalidation by 14023 * @param left The left coordinate of the rectangle to invalidate. 14024 * @param top The top coordinate of the rectangle to invalidate. 14025 * @param right The right coordinate of the rectangle to invalidate. 14026 * @param bottom The bottom coordinate of the rectangle to invalidate. 14027 * 14028 * @see #invalidate(int, int, int, int) 14029 * @see #invalidate(Rect) 14030 * @see #postInvalidate(int, int, int, int) 14031 */ postInvalidateDelayed(long delayMilliseconds, int left, int top, int right, int bottom)14032 public void postInvalidateDelayed(long delayMilliseconds, int left, int top, 14033 int right, int bottom) { 14034 14035 // We try only with the AttachInfo because there's no point in invalidating 14036 // if we are not attached to our window 14037 final AttachInfo attachInfo = mAttachInfo; 14038 if (attachInfo != null) { 14039 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain(); 14040 info.target = this; 14041 info.left = left; 14042 info.top = top; 14043 info.right = right; 14044 info.bottom = bottom; 14045 14046 attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds); 14047 } 14048 } 14049 14050 /** 14051 * <p>Cause an invalidate to happen on the next animation time step, typically the 14052 * next display frame.</p> 14053 * 14054 * <p>This method can be invoked from outside of the UI thread 14055 * only when this View is attached to a window.</p> 14056 * 14057 * @see #invalidate() 14058 */ postInvalidateOnAnimation()14059 public void postInvalidateOnAnimation() { 14060 // We try only with the AttachInfo because there's no point in invalidating 14061 // if we are not attached to our window 14062 final AttachInfo attachInfo = mAttachInfo; 14063 if (attachInfo != null) { 14064 attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this); 14065 } 14066 } 14067 14068 /** 14069 * <p>Cause an invalidate of the specified area to happen on the next animation 14070 * time step, typically the next display frame.</p> 14071 * 14072 * <p>This method can be invoked from outside of the UI thread 14073 * only when this View is attached to a window.</p> 14074 * 14075 * @param left The left coordinate of the rectangle to invalidate. 14076 * @param top The top coordinate of the rectangle to invalidate. 14077 * @param right The right coordinate of the rectangle to invalidate. 14078 * @param bottom The bottom coordinate of the rectangle to invalidate. 14079 * 14080 * @see #invalidate(int, int, int, int) 14081 * @see #invalidate(Rect) 14082 */ postInvalidateOnAnimation(int left, int top, int right, int bottom)14083 public void postInvalidateOnAnimation(int left, int top, int right, int bottom) { 14084 // We try only with the AttachInfo because there's no point in invalidating 14085 // if we are not attached to our window 14086 final AttachInfo attachInfo = mAttachInfo; 14087 if (attachInfo != null) { 14088 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain(); 14089 info.target = this; 14090 info.left = left; 14091 info.top = top; 14092 info.right = right; 14093 info.bottom = bottom; 14094 14095 attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info); 14096 } 14097 } 14098 14099 /** 14100 * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. 14101 * This event is sent at most once every 14102 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}. 14103 */ postSendViewScrolledAccessibilityEventCallback()14104 private void postSendViewScrolledAccessibilityEventCallback() { 14105 if (mSendViewScrolledAccessibilityEvent == null) { 14106 mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent(); 14107 } 14108 if (!mSendViewScrolledAccessibilityEvent.mIsPending) { 14109 mSendViewScrolledAccessibilityEvent.mIsPending = true; 14110 postDelayed(mSendViewScrolledAccessibilityEvent, 14111 ViewConfiguration.getSendRecurringAccessibilityEventsInterval()); 14112 } 14113 } 14114 14115 /** 14116 * Called by a parent to request that a child update its values for mScrollX 14117 * and mScrollY if necessary. This will typically be done if the child is 14118 * animating a scroll using a {@link android.widget.Scroller Scroller} 14119 * object. 14120 */ computeScroll()14121 public void computeScroll() { 14122 } 14123 14124 /** 14125 * <p>Indicate whether the horizontal edges are faded when the view is 14126 * scrolled horizontally.</p> 14127 * 14128 * @return true if the horizontal edges should are faded on scroll, false 14129 * otherwise 14130 * 14131 * @see #setHorizontalFadingEdgeEnabled(boolean) 14132 * 14133 * @attr ref android.R.styleable#View_requiresFadingEdge 14134 */ isHorizontalFadingEdgeEnabled()14135 public boolean isHorizontalFadingEdgeEnabled() { 14136 return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL; 14137 } 14138 14139 /** 14140 * <p>Define whether the horizontal edges should be faded when this view 14141 * is scrolled horizontally.</p> 14142 * 14143 * @param horizontalFadingEdgeEnabled true if the horizontal edges should 14144 * be faded when the view is scrolled 14145 * horizontally 14146 * 14147 * @see #isHorizontalFadingEdgeEnabled() 14148 * 14149 * @attr ref android.R.styleable#View_requiresFadingEdge 14150 */ setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled)14151 public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) { 14152 if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) { 14153 if (horizontalFadingEdgeEnabled) { 14154 initScrollCache(); 14155 } 14156 14157 mViewFlags ^= FADING_EDGE_HORIZONTAL; 14158 } 14159 } 14160 14161 /** 14162 * <p>Indicate whether the vertical edges are faded when the view is 14163 * scrolled horizontally.</p> 14164 * 14165 * @return true if the vertical edges should are faded on scroll, false 14166 * otherwise 14167 * 14168 * @see #setVerticalFadingEdgeEnabled(boolean) 14169 * 14170 * @attr ref android.R.styleable#View_requiresFadingEdge 14171 */ isVerticalFadingEdgeEnabled()14172 public boolean isVerticalFadingEdgeEnabled() { 14173 return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL; 14174 } 14175 14176 /** 14177 * <p>Define whether the vertical edges should be faded when this view 14178 * is scrolled vertically.</p> 14179 * 14180 * @param verticalFadingEdgeEnabled true if the vertical edges should 14181 * be faded when the view is scrolled 14182 * vertically 14183 * 14184 * @see #isVerticalFadingEdgeEnabled() 14185 * 14186 * @attr ref android.R.styleable#View_requiresFadingEdge 14187 */ setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled)14188 public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) { 14189 if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) { 14190 if (verticalFadingEdgeEnabled) { 14191 initScrollCache(); 14192 } 14193 14194 mViewFlags ^= FADING_EDGE_VERTICAL; 14195 } 14196 } 14197 14198 /** 14199 * Returns the strength, or intensity, of the top faded edge. The strength is 14200 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 14201 * returns 0.0 or 1.0 but no value in between. 14202 * 14203 * Subclasses should override this method to provide a smoother fade transition 14204 * when scrolling occurs. 14205 * 14206 * @return the intensity of the top fade as a float between 0.0f and 1.0f 14207 */ getTopFadingEdgeStrength()14208 protected float getTopFadingEdgeStrength() { 14209 return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f; 14210 } 14211 14212 /** 14213 * Returns the strength, or intensity, of the bottom faded edge. The strength is 14214 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 14215 * returns 0.0 or 1.0 but no value in between. 14216 * 14217 * Subclasses should override this method to provide a smoother fade transition 14218 * when scrolling occurs. 14219 * 14220 * @return the intensity of the bottom fade as a float between 0.0f and 1.0f 14221 */ getBottomFadingEdgeStrength()14222 protected float getBottomFadingEdgeStrength() { 14223 return computeVerticalScrollOffset() + computeVerticalScrollExtent() < 14224 computeVerticalScrollRange() ? 1.0f : 0.0f; 14225 } 14226 14227 /** 14228 * Returns the strength, or intensity, of the left faded edge. The strength is 14229 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 14230 * returns 0.0 or 1.0 but no value in between. 14231 * 14232 * Subclasses should override this method to provide a smoother fade transition 14233 * when scrolling occurs. 14234 * 14235 * @return the intensity of the left fade as a float between 0.0f and 1.0f 14236 */ getLeftFadingEdgeStrength()14237 protected float getLeftFadingEdgeStrength() { 14238 return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f; 14239 } 14240 14241 /** 14242 * Returns the strength, or intensity, of the right faded edge. The strength is 14243 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 14244 * returns 0.0 or 1.0 but no value in between. 14245 * 14246 * Subclasses should override this method to provide a smoother fade transition 14247 * when scrolling occurs. 14248 * 14249 * @return the intensity of the right fade as a float between 0.0f and 1.0f 14250 */ getRightFadingEdgeStrength()14251 protected float getRightFadingEdgeStrength() { 14252 return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() < 14253 computeHorizontalScrollRange() ? 1.0f : 0.0f; 14254 } 14255 14256 /** 14257 * <p>Indicate whether the horizontal scrollbar should be drawn or not. The 14258 * scrollbar is not drawn by default.</p> 14259 * 14260 * @return true if the horizontal scrollbar should be painted, false 14261 * otherwise 14262 * 14263 * @see #setHorizontalScrollBarEnabled(boolean) 14264 */ isHorizontalScrollBarEnabled()14265 public boolean isHorizontalScrollBarEnabled() { 14266 return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL; 14267 } 14268 14269 /** 14270 * <p>Define whether the horizontal scrollbar should be drawn or not. The 14271 * scrollbar is not drawn by default.</p> 14272 * 14273 * @param horizontalScrollBarEnabled true if the horizontal scrollbar should 14274 * be painted 14275 * 14276 * @see #isHorizontalScrollBarEnabled() 14277 */ setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled)14278 public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) { 14279 if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) { 14280 mViewFlags ^= SCROLLBARS_HORIZONTAL; 14281 computeOpaqueFlags(); 14282 resolvePadding(); 14283 } 14284 } 14285 14286 /** 14287 * <p>Indicate whether the vertical scrollbar should be drawn or not. The 14288 * scrollbar is not drawn by default.</p> 14289 * 14290 * @return true if the vertical scrollbar should be painted, false 14291 * otherwise 14292 * 14293 * @see #setVerticalScrollBarEnabled(boolean) 14294 */ isVerticalScrollBarEnabled()14295 public boolean isVerticalScrollBarEnabled() { 14296 return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL; 14297 } 14298 14299 /** 14300 * <p>Define whether the vertical scrollbar should be drawn or not. The 14301 * scrollbar is not drawn by default.</p> 14302 * 14303 * @param verticalScrollBarEnabled true if the vertical scrollbar should 14304 * be painted 14305 * 14306 * @see #isVerticalScrollBarEnabled() 14307 */ setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled)14308 public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) { 14309 if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) { 14310 mViewFlags ^= SCROLLBARS_VERTICAL; 14311 computeOpaqueFlags(); 14312 resolvePadding(); 14313 } 14314 } 14315 14316 /** 14317 * @hide 14318 */ recomputePadding()14319 protected void recomputePadding() { 14320 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom); 14321 } 14322 14323 /** 14324 * Define whether scrollbars will fade when the view is not scrolling. 14325 * 14326 * @param fadeScrollbars whether to enable fading 14327 * 14328 * @attr ref android.R.styleable#View_fadeScrollbars 14329 */ setScrollbarFadingEnabled(boolean fadeScrollbars)14330 public void setScrollbarFadingEnabled(boolean fadeScrollbars) { 14331 initScrollCache(); 14332 final ScrollabilityCache scrollabilityCache = mScrollCache; 14333 scrollabilityCache.fadeScrollBars = fadeScrollbars; 14334 if (fadeScrollbars) { 14335 scrollabilityCache.state = ScrollabilityCache.OFF; 14336 } else { 14337 scrollabilityCache.state = ScrollabilityCache.ON; 14338 } 14339 } 14340 14341 /** 14342 * 14343 * Returns true if scrollbars will fade when this view is not scrolling 14344 * 14345 * @return true if scrollbar fading is enabled 14346 * 14347 * @attr ref android.R.styleable#View_fadeScrollbars 14348 */ isScrollbarFadingEnabled()14349 public boolean isScrollbarFadingEnabled() { 14350 return mScrollCache != null && mScrollCache.fadeScrollBars; 14351 } 14352 14353 /** 14354 * 14355 * Returns the delay before scrollbars fade. 14356 * 14357 * @return the delay before scrollbars fade 14358 * 14359 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade 14360 */ getScrollBarDefaultDelayBeforeFade()14361 public int getScrollBarDefaultDelayBeforeFade() { 14362 return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() : 14363 mScrollCache.scrollBarDefaultDelayBeforeFade; 14364 } 14365 14366 /** 14367 * Define the delay before scrollbars fade. 14368 * 14369 * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade 14370 * 14371 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade 14372 */ setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade)14373 public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) { 14374 getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade; 14375 } 14376 14377 /** 14378 * 14379 * Returns the scrollbar fade duration. 14380 * 14381 * @return the scrollbar fade duration 14382 * 14383 * @attr ref android.R.styleable#View_scrollbarFadeDuration 14384 */ getScrollBarFadeDuration()14385 public int getScrollBarFadeDuration() { 14386 return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() : 14387 mScrollCache.scrollBarFadeDuration; 14388 } 14389 14390 /** 14391 * Define the scrollbar fade duration. 14392 * 14393 * @param scrollBarFadeDuration - the scrollbar fade duration 14394 * 14395 * @attr ref android.R.styleable#View_scrollbarFadeDuration 14396 */ setScrollBarFadeDuration(int scrollBarFadeDuration)14397 public void setScrollBarFadeDuration(int scrollBarFadeDuration) { 14398 getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration; 14399 } 14400 14401 /** 14402 * 14403 * Returns the scrollbar size. 14404 * 14405 * @return the scrollbar size 14406 * 14407 * @attr ref android.R.styleable#View_scrollbarSize 14408 */ getScrollBarSize()14409 public int getScrollBarSize() { 14410 return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() : 14411 mScrollCache.scrollBarSize; 14412 } 14413 14414 /** 14415 * Define the scrollbar size. 14416 * 14417 * @param scrollBarSize - the scrollbar size 14418 * 14419 * @attr ref android.R.styleable#View_scrollbarSize 14420 */ setScrollBarSize(int scrollBarSize)14421 public void setScrollBarSize(int scrollBarSize) { 14422 getScrollCache().scrollBarSize = scrollBarSize; 14423 } 14424 14425 /** 14426 * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or 14427 * inset. When inset, they add to the padding of the view. And the scrollbars 14428 * can be drawn inside the padding area or on the edge of the view. For example, 14429 * if a view has a background drawable and you want to draw the scrollbars 14430 * inside the padding specified by the drawable, you can use 14431 * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to 14432 * appear at the edge of the view, ignoring the padding, then you can use 14433 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p> 14434 * @param style the style of the scrollbars. Should be one of 14435 * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET, 14436 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET. 14437 * @see #SCROLLBARS_INSIDE_OVERLAY 14438 * @see #SCROLLBARS_INSIDE_INSET 14439 * @see #SCROLLBARS_OUTSIDE_OVERLAY 14440 * @see #SCROLLBARS_OUTSIDE_INSET 14441 * 14442 * @attr ref android.R.styleable#View_scrollbarStyle 14443 */ setScrollBarStyle(@crollBarStyle int style)14444 public void setScrollBarStyle(@ScrollBarStyle int style) { 14445 if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) { 14446 mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK); 14447 computeOpaqueFlags(); 14448 resolvePadding(); 14449 } 14450 } 14451 14452 /** 14453 * <p>Returns the current scrollbar style.</p> 14454 * @return the current scrollbar style 14455 * @see #SCROLLBARS_INSIDE_OVERLAY 14456 * @see #SCROLLBARS_INSIDE_INSET 14457 * @see #SCROLLBARS_OUTSIDE_OVERLAY 14458 * @see #SCROLLBARS_OUTSIDE_INSET 14459 * 14460 * @attr ref android.R.styleable#View_scrollbarStyle 14461 */ 14462 @ViewDebug.ExportedProperty(mapping = { 14463 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"), 14464 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"), 14465 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"), 14466 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET") 14467 }) 14468 @ScrollBarStyle getScrollBarStyle()14469 public int getScrollBarStyle() { 14470 return mViewFlags & SCROLLBARS_STYLE_MASK; 14471 } 14472 14473 /** 14474 * <p>Compute the horizontal range that the horizontal scrollbar 14475 * represents.</p> 14476 * 14477 * <p>The range is expressed in arbitrary units that must be the same as the 14478 * units used by {@link #computeHorizontalScrollExtent()} and 14479 * {@link #computeHorizontalScrollOffset()}.</p> 14480 * 14481 * <p>The default range is the drawing width of this view.</p> 14482 * 14483 * @return the total horizontal range represented by the horizontal 14484 * scrollbar 14485 * 14486 * @see #computeHorizontalScrollExtent() 14487 * @see #computeHorizontalScrollOffset() 14488 * @see android.widget.ScrollBarDrawable 14489 */ computeHorizontalScrollRange()14490 protected int computeHorizontalScrollRange() { 14491 return getWidth(); 14492 } 14493 14494 /** 14495 * <p>Compute the horizontal offset of the horizontal scrollbar's thumb 14496 * within the horizontal range. This value is used to compute the position 14497 * of the thumb within the scrollbar's track.</p> 14498 * 14499 * <p>The range is expressed in arbitrary units that must be the same as the 14500 * units used by {@link #computeHorizontalScrollRange()} and 14501 * {@link #computeHorizontalScrollExtent()}.</p> 14502 * 14503 * <p>The default offset is the scroll offset of this view.</p> 14504 * 14505 * @return the horizontal offset of the scrollbar's thumb 14506 * 14507 * @see #computeHorizontalScrollRange() 14508 * @see #computeHorizontalScrollExtent() 14509 * @see android.widget.ScrollBarDrawable 14510 */ computeHorizontalScrollOffset()14511 protected int computeHorizontalScrollOffset() { 14512 return mScrollX; 14513 } 14514 14515 /** 14516 * <p>Compute the horizontal extent of the horizontal scrollbar's thumb 14517 * within the horizontal range. This value is used to compute the length 14518 * of the thumb within the scrollbar's track.</p> 14519 * 14520 * <p>The range is expressed in arbitrary units that must be the same as the 14521 * units used by {@link #computeHorizontalScrollRange()} and 14522 * {@link #computeHorizontalScrollOffset()}.</p> 14523 * 14524 * <p>The default extent is the drawing width of this view.</p> 14525 * 14526 * @return the horizontal extent of the scrollbar's thumb 14527 * 14528 * @see #computeHorizontalScrollRange() 14529 * @see #computeHorizontalScrollOffset() 14530 * @see android.widget.ScrollBarDrawable 14531 */ computeHorizontalScrollExtent()14532 protected int computeHorizontalScrollExtent() { 14533 return getWidth(); 14534 } 14535 14536 /** 14537 * <p>Compute the vertical range that the vertical scrollbar represents.</p> 14538 * 14539 * <p>The range is expressed in arbitrary units that must be the same as the 14540 * units used by {@link #computeVerticalScrollExtent()} and 14541 * {@link #computeVerticalScrollOffset()}.</p> 14542 * 14543 * @return the total vertical range represented by the vertical scrollbar 14544 * 14545 * <p>The default range is the drawing height of this view.</p> 14546 * 14547 * @see #computeVerticalScrollExtent() 14548 * @see #computeVerticalScrollOffset() 14549 * @see android.widget.ScrollBarDrawable 14550 */ computeVerticalScrollRange()14551 protected int computeVerticalScrollRange() { 14552 return getHeight(); 14553 } 14554 14555 /** 14556 * <p>Compute the vertical offset of the vertical scrollbar's thumb 14557 * within the horizontal range. This value is used to compute the position 14558 * of the thumb within the scrollbar's track.</p> 14559 * 14560 * <p>The range is expressed in arbitrary units that must be the same as the 14561 * units used by {@link #computeVerticalScrollRange()} and 14562 * {@link #computeVerticalScrollExtent()}.</p> 14563 * 14564 * <p>The default offset is the scroll offset of this view.</p> 14565 * 14566 * @return the vertical offset of the scrollbar's thumb 14567 * 14568 * @see #computeVerticalScrollRange() 14569 * @see #computeVerticalScrollExtent() 14570 * @see android.widget.ScrollBarDrawable 14571 */ computeVerticalScrollOffset()14572 protected int computeVerticalScrollOffset() { 14573 return mScrollY; 14574 } 14575 14576 /** 14577 * <p>Compute the vertical extent of the vertical scrollbar's thumb 14578 * within the vertical range. This value is used to compute the length 14579 * of the thumb within the scrollbar's track.</p> 14580 * 14581 * <p>The range is expressed in arbitrary units that must be the same as the 14582 * units used by {@link #computeVerticalScrollRange()} and 14583 * {@link #computeVerticalScrollOffset()}.</p> 14584 * 14585 * <p>The default extent is the drawing height of this view.</p> 14586 * 14587 * @return the vertical extent of the scrollbar's thumb 14588 * 14589 * @see #computeVerticalScrollRange() 14590 * @see #computeVerticalScrollOffset() 14591 * @see android.widget.ScrollBarDrawable 14592 */ computeVerticalScrollExtent()14593 protected int computeVerticalScrollExtent() { 14594 return getHeight(); 14595 } 14596 14597 /** 14598 * Check if this view can be scrolled horizontally in a certain direction. 14599 * 14600 * @param direction Negative to check scrolling left, positive to check scrolling right. 14601 * @return true if this view can be scrolled in the specified direction, false otherwise. 14602 */ canScrollHorizontally(int direction)14603 public boolean canScrollHorizontally(int direction) { 14604 final int offset = computeHorizontalScrollOffset(); 14605 final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent(); 14606 if (range == 0) return false; 14607 if (direction < 0) { 14608 return offset > 0; 14609 } else { 14610 return offset < range - 1; 14611 } 14612 } 14613 14614 /** 14615 * Check if this view can be scrolled vertically in a certain direction. 14616 * 14617 * @param direction Negative to check scrolling up, positive to check scrolling down. 14618 * @return true if this view can be scrolled in the specified direction, false otherwise. 14619 */ canScrollVertically(int direction)14620 public boolean canScrollVertically(int direction) { 14621 final int offset = computeVerticalScrollOffset(); 14622 final int range = computeVerticalScrollRange() - computeVerticalScrollExtent(); 14623 if (range == 0) return false; 14624 if (direction < 0) { 14625 return offset > 0; 14626 } else { 14627 return offset < range - 1; 14628 } 14629 } 14630 getScrollIndicatorBounds(@onNull Rect out)14631 void getScrollIndicatorBounds(@NonNull Rect out) { 14632 out.left = mScrollX; 14633 out.right = mScrollX + mRight - mLeft; 14634 out.top = mScrollY; 14635 out.bottom = mScrollY + mBottom - mTop; 14636 } 14637 onDrawScrollIndicators(Canvas c)14638 private void onDrawScrollIndicators(Canvas c) { 14639 if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) { 14640 // No scroll indicators enabled. 14641 return; 14642 } 14643 14644 final Drawable dr = mScrollIndicatorDrawable; 14645 if (dr == null) { 14646 // Scroll indicators aren't supported here. 14647 return; 14648 } 14649 14650 final int h = dr.getIntrinsicHeight(); 14651 final int w = dr.getIntrinsicWidth(); 14652 final Rect rect = mAttachInfo.mTmpInvalRect; 14653 getScrollIndicatorBounds(rect); 14654 14655 if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) { 14656 final boolean canScrollUp = canScrollVertically(-1); 14657 if (canScrollUp) { 14658 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h); 14659 dr.draw(c); 14660 } 14661 } 14662 14663 if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) { 14664 final boolean canScrollDown = canScrollVertically(1); 14665 if (canScrollDown) { 14666 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom); 14667 dr.draw(c); 14668 } 14669 } 14670 14671 final int leftRtl; 14672 final int rightRtl; 14673 if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) { 14674 leftRtl = PFLAG3_SCROLL_INDICATOR_END; 14675 rightRtl = PFLAG3_SCROLL_INDICATOR_START; 14676 } else { 14677 leftRtl = PFLAG3_SCROLL_INDICATOR_START; 14678 rightRtl = PFLAG3_SCROLL_INDICATOR_END; 14679 } 14680 14681 final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl; 14682 if ((mPrivateFlags3 & leftMask) != 0) { 14683 final boolean canScrollLeft = canScrollHorizontally(-1); 14684 if (canScrollLeft) { 14685 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom); 14686 dr.draw(c); 14687 } 14688 } 14689 14690 final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl; 14691 if ((mPrivateFlags3 & rightMask) != 0) { 14692 final boolean canScrollRight = canScrollHorizontally(1); 14693 if (canScrollRight) { 14694 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom); 14695 dr.draw(c); 14696 } 14697 } 14698 } 14699 getHorizontalScrollBarBounds(Rect bounds)14700 private void getHorizontalScrollBarBounds(Rect bounds) { 14701 final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; 14702 final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled() 14703 && !isVerticalScrollBarHidden(); 14704 final int size = getHorizontalScrollbarHeight(); 14705 final int verticalScrollBarGap = drawVerticalScrollBar ? 14706 getVerticalScrollbarWidth() : 0; 14707 final int width = mRight - mLeft; 14708 final int height = mBottom - mTop; 14709 bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside); 14710 bounds.left = mScrollX + (mPaddingLeft & inside); 14711 bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap; 14712 bounds.bottom = bounds.top + size; 14713 } 14714 getVerticalScrollBarBounds(Rect bounds)14715 private void getVerticalScrollBarBounds(Rect bounds) { 14716 final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; 14717 final int size = getVerticalScrollbarWidth(); 14718 int verticalScrollbarPosition = mVerticalScrollbarPosition; 14719 if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) { 14720 verticalScrollbarPosition = isLayoutRtl() ? 14721 SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT; 14722 } 14723 final int width = mRight - mLeft; 14724 final int height = mBottom - mTop; 14725 switch (verticalScrollbarPosition) { 14726 default: 14727 case SCROLLBAR_POSITION_RIGHT: 14728 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside); 14729 break; 14730 case SCROLLBAR_POSITION_LEFT: 14731 bounds.left = mScrollX + (mUserPaddingLeft & inside); 14732 break; 14733 } 14734 bounds.top = mScrollY + (mPaddingTop & inside); 14735 bounds.right = bounds.left + size; 14736 bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside); 14737 } 14738 14739 /** 14740 * <p>Request the drawing of the horizontal and the vertical scrollbar. The 14741 * scrollbars are painted only if they have been awakened first.</p> 14742 * 14743 * @param canvas the canvas on which to draw the scrollbars 14744 * 14745 * @see #awakenScrollBars(int) 14746 */ onDrawScrollBars(Canvas canvas)14747 protected final void onDrawScrollBars(Canvas canvas) { 14748 // scrollbars are drawn only when the animation is running 14749 final ScrollabilityCache cache = mScrollCache; 14750 if (cache != null) { 14751 14752 int state = cache.state; 14753 14754 if (state == ScrollabilityCache.OFF) { 14755 return; 14756 } 14757 14758 boolean invalidate = false; 14759 14760 if (state == ScrollabilityCache.FADING) { 14761 // We're fading -- get our fade interpolation 14762 if (cache.interpolatorValues == null) { 14763 cache.interpolatorValues = new float[1]; 14764 } 14765 14766 float[] values = cache.interpolatorValues; 14767 14768 // Stops the animation if we're done 14769 if (cache.scrollBarInterpolator.timeToValues(values) == 14770 Interpolator.Result.FREEZE_END) { 14771 cache.state = ScrollabilityCache.OFF; 14772 } else { 14773 cache.scrollBar.mutate().setAlpha(Math.round(values[0])); 14774 } 14775 14776 // This will make the scroll bars inval themselves after 14777 // drawing. We only want this when we're fading so that 14778 // we prevent excessive redraws 14779 invalidate = true; 14780 } else { 14781 // We're just on -- but we may have been fading before so 14782 // reset alpha 14783 cache.scrollBar.mutate().setAlpha(255); 14784 } 14785 14786 final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled(); 14787 final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled() 14788 && !isVerticalScrollBarHidden(); 14789 14790 if (drawVerticalScrollBar || drawHorizontalScrollBar) { 14791 final ScrollBarDrawable scrollBar = cache.scrollBar; 14792 14793 if (drawHorizontalScrollBar) { 14794 scrollBar.setParameters(computeHorizontalScrollRange(), 14795 computeHorizontalScrollOffset(), 14796 computeHorizontalScrollExtent(), false); 14797 final Rect bounds = cache.mScrollBarBounds; 14798 getHorizontalScrollBarBounds(bounds); 14799 onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top, 14800 bounds.right, bounds.bottom); 14801 if (invalidate) { 14802 invalidate(bounds); 14803 } 14804 } 14805 14806 if (drawVerticalScrollBar) { 14807 scrollBar.setParameters(computeVerticalScrollRange(), 14808 computeVerticalScrollOffset(), 14809 computeVerticalScrollExtent(), true); 14810 final Rect bounds = cache.mScrollBarBounds; 14811 getVerticalScrollBarBounds(bounds); 14812 onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top, 14813 bounds.right, bounds.bottom); 14814 if (invalidate) { 14815 invalidate(bounds); 14816 } 14817 } 14818 } 14819 } 14820 } 14821 14822 /** 14823 * Override this if the vertical scrollbar needs to be hidden in a subclass, like when 14824 * FastScroller is visible. 14825 * @return whether to temporarily hide the vertical scrollbar 14826 * @hide 14827 */ isVerticalScrollBarHidden()14828 protected boolean isVerticalScrollBarHidden() { 14829 return false; 14830 } 14831 14832 /** 14833 * <p>Draw the horizontal scrollbar if 14834 * {@link #isHorizontalScrollBarEnabled()} returns true.</p> 14835 * 14836 * @param canvas the canvas on which to draw the scrollbar 14837 * @param scrollBar the scrollbar's drawable 14838 * 14839 * @see #isHorizontalScrollBarEnabled() 14840 * @see #computeHorizontalScrollRange() 14841 * @see #computeHorizontalScrollExtent() 14842 * @see #computeHorizontalScrollOffset() 14843 * @see android.widget.ScrollBarDrawable 14844 * @hide 14845 */ onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)14846 protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, 14847 int l, int t, int r, int b) { 14848 scrollBar.setBounds(l, t, r, b); 14849 scrollBar.draw(canvas); 14850 } 14851 14852 /** 14853 * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()} 14854 * returns true.</p> 14855 * 14856 * @param canvas the canvas on which to draw the scrollbar 14857 * @param scrollBar the scrollbar's drawable 14858 * 14859 * @see #isVerticalScrollBarEnabled() 14860 * @see #computeVerticalScrollRange() 14861 * @see #computeVerticalScrollExtent() 14862 * @see #computeVerticalScrollOffset() 14863 * @see android.widget.ScrollBarDrawable 14864 * @hide 14865 */ onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)14866 protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, 14867 int l, int t, int r, int b) { 14868 scrollBar.setBounds(l, t, r, b); 14869 scrollBar.draw(canvas); 14870 } 14871 14872 /** 14873 * Implement this to do your drawing. 14874 * 14875 * @param canvas the canvas on which the background will be drawn 14876 */ onDraw(Canvas canvas)14877 protected void onDraw(Canvas canvas) { 14878 } 14879 14880 /* 14881 * Caller is responsible for calling requestLayout if necessary. 14882 * (This allows addViewInLayout to not request a new layout.) 14883 */ assignParent(ViewParent parent)14884 void assignParent(ViewParent parent) { 14885 if (mParent == null) { 14886 mParent = parent; 14887 } else if (parent == null) { 14888 mParent = null; 14889 } else { 14890 throw new RuntimeException("view " + this + " being added, but" 14891 + " it already has a parent"); 14892 } 14893 } 14894 14895 /** 14896 * This is called when the view is attached to a window. At this point it 14897 * has a Surface and will start drawing. Note that this function is 14898 * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)}, 14899 * however it may be called any time before the first onDraw -- including 14900 * before or after {@link #onMeasure(int, int)}. 14901 * 14902 * @see #onDetachedFromWindow() 14903 */ 14904 @CallSuper onAttachedToWindow()14905 protected void onAttachedToWindow() { 14906 if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) { 14907 mParent.requestTransparentRegion(this); 14908 } 14909 14910 mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT; 14911 14912 jumpDrawablesToCurrentState(); 14913 14914 resetSubtreeAccessibilityStateChanged(); 14915 14916 // rebuild, since Outline not maintained while View is detached 14917 rebuildOutline(); 14918 14919 if (isFocused()) { 14920 InputMethodManager imm = InputMethodManager.peekInstance(); 14921 if (imm != null) { 14922 imm.focusIn(this); 14923 } 14924 } 14925 } 14926 14927 /** 14928 * Resolve all RTL related properties. 14929 * 14930 * @return true if resolution of RTL properties has been done 14931 * 14932 * @hide 14933 */ resolveRtlPropertiesIfNeeded()14934 public boolean resolveRtlPropertiesIfNeeded() { 14935 if (!needRtlPropertiesResolution()) return false; 14936 14937 // Order is important here: LayoutDirection MUST be resolved first 14938 if (!isLayoutDirectionResolved()) { 14939 resolveLayoutDirection(); 14940 resolveLayoutParams(); 14941 } 14942 // ... then we can resolve the others properties depending on the resolved LayoutDirection. 14943 if (!isTextDirectionResolved()) { 14944 resolveTextDirection(); 14945 } 14946 if (!isTextAlignmentResolved()) { 14947 resolveTextAlignment(); 14948 } 14949 // Should resolve Drawables before Padding because we need the layout direction of the 14950 // Drawable to correctly resolve Padding. 14951 if (!areDrawablesResolved()) { 14952 resolveDrawables(); 14953 } 14954 if (!isPaddingResolved()) { 14955 resolvePadding(); 14956 } 14957 onRtlPropertiesChanged(getLayoutDirection()); 14958 return true; 14959 } 14960 14961 /** 14962 * Reset resolution of all RTL related properties. 14963 * 14964 * @hide 14965 */ resetRtlProperties()14966 public void resetRtlProperties() { 14967 resetResolvedLayoutDirection(); 14968 resetResolvedTextDirection(); 14969 resetResolvedTextAlignment(); 14970 resetResolvedPadding(); 14971 resetResolvedDrawables(); 14972 } 14973 14974 /** 14975 * @see #onScreenStateChanged(int) 14976 */ dispatchScreenStateChanged(int screenState)14977 void dispatchScreenStateChanged(int screenState) { 14978 onScreenStateChanged(screenState); 14979 } 14980 14981 /** 14982 * This method is called whenever the state of the screen this view is 14983 * attached to changes. A state change will usually occurs when the screen 14984 * turns on or off (whether it happens automatically or the user does it 14985 * manually.) 14986 * 14987 * @param screenState The new state of the screen. Can be either 14988 * {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF} 14989 */ onScreenStateChanged(int screenState)14990 public void onScreenStateChanged(int screenState) { 14991 } 14992 14993 /** 14994 * Return true if the application tag in the AndroidManifest has set "supportRtl" to true 14995 */ hasRtlSupport()14996 private boolean hasRtlSupport() { 14997 return mContext.getApplicationInfo().hasRtlSupport(); 14998 } 14999 15000 /** 15001 * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or 15002 * RTL not supported) 15003 */ isRtlCompatibilityMode()15004 private boolean isRtlCompatibilityMode() { 15005 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion; 15006 return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport(); 15007 } 15008 15009 /** 15010 * @return true if RTL properties need resolution. 15011 * 15012 */ needRtlPropertiesResolution()15013 private boolean needRtlPropertiesResolution() { 15014 return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED; 15015 } 15016 15017 /** 15018 * Called when any RTL property (layout direction or text direction or text alignment) has 15019 * been changed. 15020 * 15021 * Subclasses need to override this method to take care of cached information that depends on the 15022 * resolved layout direction, or to inform child views that inherit their layout direction. 15023 * 15024 * The default implementation does nothing. 15025 * 15026 * @param layoutDirection the direction of the layout 15027 * 15028 * @see #LAYOUT_DIRECTION_LTR 15029 * @see #LAYOUT_DIRECTION_RTL 15030 */ onRtlPropertiesChanged(@esolvedLayoutDir int layoutDirection)15031 public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) { 15032 } 15033 15034 /** 15035 * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing 15036 * that the parent directionality can and will be resolved before its children. 15037 * 15038 * @return true if resolution has been done, false otherwise. 15039 * 15040 * @hide 15041 */ resolveLayoutDirection()15042 public boolean resolveLayoutDirection() { 15043 // Clear any previous layout direction resolution 15044 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK; 15045 15046 if (hasRtlSupport()) { 15047 // Set resolved depending on layout direction 15048 switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> 15049 PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) { 15050 case LAYOUT_DIRECTION_INHERIT: 15051 // We cannot resolve yet. LTR is by default and let the resolution happen again 15052 // later to get the correct resolved value 15053 if (!canResolveLayoutDirection()) return false; 15054 15055 // Parent has not yet resolved, LTR is still the default 15056 try { 15057 if (!mParent.isLayoutDirectionResolved()) return false; 15058 15059 if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) { 15060 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL; 15061 } 15062 } catch (AbstractMethodError e) { 15063 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 15064 " does not fully implement ViewParent", e); 15065 } 15066 break; 15067 case LAYOUT_DIRECTION_RTL: 15068 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL; 15069 break; 15070 case LAYOUT_DIRECTION_LOCALE: 15071 if((LAYOUT_DIRECTION_RTL == 15072 TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) { 15073 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL; 15074 } 15075 break; 15076 default: 15077 // Nothing to do, LTR by default 15078 } 15079 } 15080 15081 // Set to resolved 15082 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED; 15083 return true; 15084 } 15085 15086 /** 15087 * Check if layout direction resolution can be done. 15088 * 15089 * @return true if layout direction resolution can be done otherwise return false. 15090 */ canResolveLayoutDirection()15091 public boolean canResolveLayoutDirection() { 15092 switch (getRawLayoutDirection()) { 15093 case LAYOUT_DIRECTION_INHERIT: 15094 if (mParent != null) { 15095 try { 15096 return mParent.canResolveLayoutDirection(); 15097 } catch (AbstractMethodError e) { 15098 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 15099 " does not fully implement ViewParent", e); 15100 } 15101 } 15102 return false; 15103 15104 default: 15105 return true; 15106 } 15107 } 15108 15109 /** 15110 * Reset the resolved layout direction. Layout direction will be resolved during a call to 15111 * {@link #onMeasure(int, int)}. 15112 * 15113 * @hide 15114 */ resetResolvedLayoutDirection()15115 public void resetResolvedLayoutDirection() { 15116 // Reset the current resolved bits 15117 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK; 15118 } 15119 15120 /** 15121 * @return true if the layout direction is inherited. 15122 * 15123 * @hide 15124 */ isLayoutDirectionInherited()15125 public boolean isLayoutDirectionInherited() { 15126 return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT); 15127 } 15128 15129 /** 15130 * @return true if layout direction has been resolved. 15131 */ isLayoutDirectionResolved()15132 public boolean isLayoutDirectionResolved() { 15133 return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED; 15134 } 15135 15136 /** 15137 * Return if padding has been resolved 15138 * 15139 * @hide 15140 */ isPaddingResolved()15141 boolean isPaddingResolved() { 15142 return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED; 15143 } 15144 15145 /** 15146 * Resolves padding depending on layout direction, if applicable, and 15147 * recomputes internal padding values to adjust for scroll bars. 15148 * 15149 * @hide 15150 */ resolvePadding()15151 public void resolvePadding() { 15152 final int resolvedLayoutDirection = getLayoutDirection(); 15153 15154 if (!isRtlCompatibilityMode()) { 15155 // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account. 15156 // If start / end padding are defined, they will be resolved (hence overriding) to 15157 // left / right or right / left depending on the resolved layout direction. 15158 // If start / end padding are not defined, use the left / right ones. 15159 if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) { 15160 Rect padding = sThreadLocal.get(); 15161 if (padding == null) { 15162 padding = new Rect(); 15163 sThreadLocal.set(padding); 15164 } 15165 mBackground.getPadding(padding); 15166 if (!mLeftPaddingDefined) { 15167 mUserPaddingLeftInitial = padding.left; 15168 } 15169 if (!mRightPaddingDefined) { 15170 mUserPaddingRightInitial = padding.right; 15171 } 15172 } 15173 switch (resolvedLayoutDirection) { 15174 case LAYOUT_DIRECTION_RTL: 15175 if (mUserPaddingStart != UNDEFINED_PADDING) { 15176 mUserPaddingRight = mUserPaddingStart; 15177 } else { 15178 mUserPaddingRight = mUserPaddingRightInitial; 15179 } 15180 if (mUserPaddingEnd != UNDEFINED_PADDING) { 15181 mUserPaddingLeft = mUserPaddingEnd; 15182 } else { 15183 mUserPaddingLeft = mUserPaddingLeftInitial; 15184 } 15185 break; 15186 case LAYOUT_DIRECTION_LTR: 15187 default: 15188 if (mUserPaddingStart != UNDEFINED_PADDING) { 15189 mUserPaddingLeft = mUserPaddingStart; 15190 } else { 15191 mUserPaddingLeft = mUserPaddingLeftInitial; 15192 } 15193 if (mUserPaddingEnd != UNDEFINED_PADDING) { 15194 mUserPaddingRight = mUserPaddingEnd; 15195 } else { 15196 mUserPaddingRight = mUserPaddingRightInitial; 15197 } 15198 } 15199 15200 mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom; 15201 } 15202 15203 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom); 15204 onRtlPropertiesChanged(resolvedLayoutDirection); 15205 15206 mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED; 15207 } 15208 15209 /** 15210 * Reset the resolved layout direction. 15211 * 15212 * @hide 15213 */ resetResolvedPadding()15214 public void resetResolvedPadding() { 15215 resetResolvedPaddingInternal(); 15216 } 15217 15218 /** 15219 * Used when we only want to reset *this* view's padding and not trigger overrides 15220 * in ViewGroup that reset children too. 15221 */ resetResolvedPaddingInternal()15222 void resetResolvedPaddingInternal() { 15223 mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED; 15224 } 15225 15226 /** 15227 * This is called when the view is detached from a window. At this point it 15228 * no longer has a surface for drawing. 15229 * 15230 * @see #onAttachedToWindow() 15231 */ 15232 @CallSuper onDetachedFromWindow()15233 protected void onDetachedFromWindow() { 15234 } 15235 15236 /** 15237 * This is a framework-internal mirror of onDetachedFromWindow() that's called 15238 * after onDetachedFromWindow(). 15239 * 15240 * If you override this you *MUST* call super.onDetachedFromWindowInternal()! 15241 * The super method should be called at the end of the overridden method to ensure 15242 * subclasses are destroyed first 15243 * 15244 * @hide 15245 */ 15246 @CallSuper onDetachedFromWindowInternal()15247 protected void onDetachedFromWindowInternal() { 15248 mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT; 15249 mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT; 15250 mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH; 15251 15252 removeUnsetPressCallback(); 15253 removeLongPressCallback(); 15254 removePerformClickCallback(); 15255 removeSendViewScrolledAccessibilityEventCallback(); 15256 stopNestedScroll(); 15257 15258 // Anything that started animating right before detach should already 15259 // be in its final state when re-attached. 15260 jumpDrawablesToCurrentState(); 15261 15262 destroyDrawingCache(); 15263 15264 cleanupDraw(); 15265 mCurrentAnimation = null; 15266 } 15267 cleanupDraw()15268 private void cleanupDraw() { 15269 resetDisplayList(); 15270 if (mAttachInfo != null) { 15271 mAttachInfo.mViewRootImpl.cancelInvalidate(this); 15272 } 15273 } 15274 invalidateInheritedLayoutMode(int layoutModeOfRoot)15275 void invalidateInheritedLayoutMode(int layoutModeOfRoot) { 15276 } 15277 15278 /** 15279 * @return The number of times this view has been attached to a window 15280 */ getWindowAttachCount()15281 protected int getWindowAttachCount() { 15282 return mWindowAttachCount; 15283 } 15284 15285 /** 15286 * Retrieve a unique token identifying the window this view is attached to. 15287 * @return Return the window's token for use in 15288 * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}. 15289 */ getWindowToken()15290 public IBinder getWindowToken() { 15291 return mAttachInfo != null ? mAttachInfo.mWindowToken : null; 15292 } 15293 15294 /** 15295 * Retrieve the {@link WindowId} for the window this view is 15296 * currently attached to. 15297 */ getWindowId()15298 public WindowId getWindowId() { 15299 if (mAttachInfo == null) { 15300 return null; 15301 } 15302 if (mAttachInfo.mWindowId == null) { 15303 try { 15304 mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId( 15305 mAttachInfo.mWindowToken); 15306 mAttachInfo.mWindowId = new WindowId( 15307 mAttachInfo.mIWindowId); 15308 } catch (RemoteException e) { 15309 } 15310 } 15311 return mAttachInfo.mWindowId; 15312 } 15313 15314 /** 15315 * Retrieve a unique token identifying the top-level "real" window of 15316 * the window that this view is attached to. That is, this is like 15317 * {@link #getWindowToken}, except if the window this view in is a panel 15318 * window (attached to another containing window), then the token of 15319 * the containing window is returned instead. 15320 * 15321 * @return Returns the associated window token, either 15322 * {@link #getWindowToken()} or the containing window's token. 15323 */ getApplicationWindowToken()15324 public IBinder getApplicationWindowToken() { 15325 AttachInfo ai = mAttachInfo; 15326 if (ai != null) { 15327 IBinder appWindowToken = ai.mPanelParentWindowToken; 15328 if (appWindowToken == null) { 15329 appWindowToken = ai.mWindowToken; 15330 } 15331 return appWindowToken; 15332 } 15333 return null; 15334 } 15335 15336 /** 15337 * Gets the logical display to which the view's window has been attached. 15338 * 15339 * @return The logical display, or null if the view is not currently attached to a window. 15340 */ getDisplay()15341 public Display getDisplay() { 15342 return mAttachInfo != null ? mAttachInfo.mDisplay : null; 15343 } 15344 15345 /** 15346 * Retrieve private session object this view hierarchy is using to 15347 * communicate with the window manager. 15348 * @return the session object to communicate with the window manager 15349 */ getWindowSession()15350 /*package*/ IWindowSession getWindowSession() { 15351 return mAttachInfo != null ? mAttachInfo.mSession : null; 15352 } 15353 15354 /** 15355 * Return the visibility value of the least visible component passed. 15356 */ combineVisibility(int vis1, int vis2)15357 int combineVisibility(int vis1, int vis2) { 15358 // This works because VISIBLE < INVISIBLE < GONE. 15359 return Math.max(vis1, vis2); 15360 } 15361 15362 /** 15363 * @param info the {@link android.view.View.AttachInfo} to associated with 15364 * this view 15365 */ dispatchAttachedToWindow(AttachInfo info, int visibility)15366 void dispatchAttachedToWindow(AttachInfo info, int visibility) { 15367 mAttachInfo = info; 15368 if (mOverlay != null) { 15369 mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility); 15370 } 15371 mWindowAttachCount++; 15372 // We will need to evaluate the drawable state at least once. 15373 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY; 15374 if (mFloatingTreeObserver != null) { 15375 info.mTreeObserver.merge(mFloatingTreeObserver); 15376 mFloatingTreeObserver = null; 15377 } 15378 15379 registerPendingFrameMetricsObservers(); 15380 15381 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) { 15382 mAttachInfo.mScrollContainers.add(this); 15383 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED; 15384 } 15385 // Transfer all pending runnables. 15386 if (mRunQueue != null) { 15387 mRunQueue.executeActions(info.mHandler); 15388 mRunQueue = null; 15389 } 15390 performCollectViewAttributes(mAttachInfo, visibility); 15391 onAttachedToWindow(); 15392 15393 ListenerInfo li = mListenerInfo; 15394 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners = 15395 li != null ? li.mOnAttachStateChangeListeners : null; 15396 if (listeners != null && listeners.size() > 0) { 15397 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to 15398 // perform the dispatching. The iterator is a safe guard against listeners that 15399 // could mutate the list by calling the various add/remove methods. This prevents 15400 // the array from being modified while we iterate it. 15401 for (OnAttachStateChangeListener listener : listeners) { 15402 listener.onViewAttachedToWindow(this); 15403 } 15404 } 15405 15406 int vis = info.mWindowVisibility; 15407 if (vis != GONE) { 15408 onWindowVisibilityChanged(vis); 15409 if (isShown()) { 15410 // Calling onVisibilityChanged directly here since the subtree will also 15411 // receive dispatchAttachedToWindow and this same call 15412 onVisibilityAggregated(vis == VISIBLE); 15413 } 15414 } 15415 15416 // Send onVisibilityChanged directly instead of dispatchVisibilityChanged. 15417 // As all views in the subtree will already receive dispatchAttachedToWindow 15418 // traversing the subtree again here is not desired. 15419 onVisibilityChanged(this, visibility); 15420 15421 if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) { 15422 // If nobody has evaluated the drawable state yet, then do it now. 15423 refreshDrawableState(); 15424 } 15425 needGlobalAttributesUpdate(false); 15426 } 15427 dispatchDetachedFromWindow()15428 void dispatchDetachedFromWindow() { 15429 AttachInfo info = mAttachInfo; 15430 if (info != null) { 15431 int vis = info.mWindowVisibility; 15432 if (vis != GONE) { 15433 onWindowVisibilityChanged(GONE); 15434 if (isShown()) { 15435 // Invoking onVisibilityAggregated directly here since the subtree 15436 // will also receive detached from window 15437 onVisibilityAggregated(false); 15438 } 15439 } 15440 } 15441 15442 onDetachedFromWindow(); 15443 onDetachedFromWindowInternal(); 15444 15445 InputMethodManager imm = InputMethodManager.peekInstance(); 15446 if (imm != null) { 15447 imm.onViewDetachedFromWindow(this); 15448 } 15449 15450 ListenerInfo li = mListenerInfo; 15451 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners = 15452 li != null ? li.mOnAttachStateChangeListeners : null; 15453 if (listeners != null && listeners.size() > 0) { 15454 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to 15455 // perform the dispatching. The iterator is a safe guard against listeners that 15456 // could mutate the list by calling the various add/remove methods. This prevents 15457 // the array from being modified while we iterate it. 15458 for (OnAttachStateChangeListener listener : listeners) { 15459 listener.onViewDetachedFromWindow(this); 15460 } 15461 } 15462 15463 if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) { 15464 mAttachInfo.mScrollContainers.remove(this); 15465 mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED; 15466 } 15467 15468 mAttachInfo = null; 15469 if (mOverlay != null) { 15470 mOverlay.getOverlayView().dispatchDetachedFromWindow(); 15471 } 15472 } 15473 15474 /** 15475 * Cancel any deferred high-level input events that were previously posted to the event queue. 15476 * 15477 * <p>Many views post high-level events such as click handlers to the event queue 15478 * to run deferred in order to preserve a desired user experience - clearing visible 15479 * pressed states before executing, etc. This method will abort any events of this nature 15480 * that are currently in flight.</p> 15481 * 15482 * <p>Custom views that generate their own high-level deferred input events should override 15483 * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p> 15484 * 15485 * <p>This will also cancel pending input events for any child views.</p> 15486 * 15487 * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases. 15488 * This will not impact newer events posted after this call that may occur as a result of 15489 * lower-level input events still waiting in the queue. If you are trying to prevent 15490 * double-submitted events for the duration of some sort of asynchronous transaction 15491 * you should also take other steps to protect against unexpected double inputs e.g. calling 15492 * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when 15493 * the transaction completes, tracking already submitted transaction IDs, etc.</p> 15494 */ cancelPendingInputEvents()15495 public final void cancelPendingInputEvents() { 15496 dispatchCancelPendingInputEvents(); 15497 } 15498 15499 /** 15500 * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight. 15501 * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling. 15502 */ dispatchCancelPendingInputEvents()15503 void dispatchCancelPendingInputEvents() { 15504 mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER; 15505 onCancelPendingInputEvents(); 15506 if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) { 15507 throw new SuperNotCalledException("View " + getClass().getSimpleName() + 15508 " did not call through to super.onCancelPendingInputEvents()"); 15509 } 15510 } 15511 15512 /** 15513 * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or 15514 * a parent view. 15515 * 15516 * <p>This method is responsible for removing any pending high-level input events that were 15517 * posted to the event queue to run later. Custom view classes that post their own deferred 15518 * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or 15519 * {@link android.os.Handler} should override this method, call 15520 * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate. 15521 * </p> 15522 */ onCancelPendingInputEvents()15523 public void onCancelPendingInputEvents() { 15524 removePerformClickCallback(); 15525 cancelLongPress(); 15526 mPrivateFlags3 |= PFLAG3_CALLED_SUPER; 15527 } 15528 15529 /** 15530 * Store this view hierarchy's frozen state into the given container. 15531 * 15532 * @param container The SparseArray in which to save the view's state. 15533 * 15534 * @see #restoreHierarchyState(android.util.SparseArray) 15535 * @see #dispatchSaveInstanceState(android.util.SparseArray) 15536 * @see #onSaveInstanceState() 15537 */ saveHierarchyState(SparseArray<Parcelable> container)15538 public void saveHierarchyState(SparseArray<Parcelable> container) { 15539 dispatchSaveInstanceState(container); 15540 } 15541 15542 /** 15543 * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for 15544 * this view and its children. May be overridden to modify how freezing happens to a 15545 * view's children; for example, some views may want to not store state for their children. 15546 * 15547 * @param container The SparseArray in which to save the view's state. 15548 * 15549 * @see #dispatchRestoreInstanceState(android.util.SparseArray) 15550 * @see #saveHierarchyState(android.util.SparseArray) 15551 * @see #onSaveInstanceState() 15552 */ dispatchSaveInstanceState(SparseArray<Parcelable> container)15553 protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) { 15554 if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) { 15555 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED; 15556 Parcelable state = onSaveInstanceState(); 15557 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) { 15558 throw new IllegalStateException( 15559 "Derived class did not call super.onSaveInstanceState()"); 15560 } 15561 if (state != null) { 15562 // Log.i("View", "Freezing #" + Integer.toHexString(mID) 15563 // + ": " + state); 15564 container.put(mID, state); 15565 } 15566 } 15567 } 15568 15569 /** 15570 * Hook allowing a view to generate a representation of its internal state 15571 * that can later be used to create a new instance with that same state. 15572 * This state should only contain information that is not persistent or can 15573 * not be reconstructed later. For example, you will never store your 15574 * current position on screen because that will be computed again when a 15575 * new instance of the view is placed in its view hierarchy. 15576 * <p> 15577 * Some examples of things you may store here: the current cursor position 15578 * in a text view (but usually not the text itself since that is stored in a 15579 * content provider or other persistent storage), the currently selected 15580 * item in a list view. 15581 * 15582 * @return Returns a Parcelable object containing the view's current dynamic 15583 * state, or null if there is nothing interesting to save. The 15584 * default implementation returns null. 15585 * @see #onRestoreInstanceState(android.os.Parcelable) 15586 * @see #saveHierarchyState(android.util.SparseArray) 15587 * @see #dispatchSaveInstanceState(android.util.SparseArray) 15588 * @see #setSaveEnabled(boolean) 15589 */ 15590 @CallSuper onSaveInstanceState()15591 protected Parcelable onSaveInstanceState() { 15592 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED; 15593 if (mStartActivityRequestWho != null) { 15594 BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE); 15595 state.mStartActivityRequestWhoSaved = mStartActivityRequestWho; 15596 return state; 15597 } 15598 return BaseSavedState.EMPTY_STATE; 15599 } 15600 15601 /** 15602 * Restore this view hierarchy's frozen state from the given container. 15603 * 15604 * @param container The SparseArray which holds previously frozen states. 15605 * 15606 * @see #saveHierarchyState(android.util.SparseArray) 15607 * @see #dispatchRestoreInstanceState(android.util.SparseArray) 15608 * @see #onRestoreInstanceState(android.os.Parcelable) 15609 */ restoreHierarchyState(SparseArray<Parcelable> container)15610 public void restoreHierarchyState(SparseArray<Parcelable> container) { 15611 dispatchRestoreInstanceState(container); 15612 } 15613 15614 /** 15615 * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the 15616 * state for this view and its children. May be overridden to modify how restoring 15617 * happens to a view's children; for example, some views may want to not store state 15618 * for their children. 15619 * 15620 * @param container The SparseArray which holds previously saved state. 15621 * 15622 * @see #dispatchSaveInstanceState(android.util.SparseArray) 15623 * @see #restoreHierarchyState(android.util.SparseArray) 15624 * @see #onRestoreInstanceState(android.os.Parcelable) 15625 */ dispatchRestoreInstanceState(SparseArray<Parcelable> container)15626 protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) { 15627 if (mID != NO_ID) { 15628 Parcelable state = container.get(mID); 15629 if (state != null) { 15630 // Log.i("View", "Restoreing #" + Integer.toHexString(mID) 15631 // + ": " + state); 15632 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED; 15633 onRestoreInstanceState(state); 15634 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) { 15635 throw new IllegalStateException( 15636 "Derived class did not call super.onRestoreInstanceState()"); 15637 } 15638 } 15639 } 15640 } 15641 15642 /** 15643 * Hook allowing a view to re-apply a representation of its internal state that had previously 15644 * been generated by {@link #onSaveInstanceState}. This function will never be called with a 15645 * null state. 15646 * 15647 * @param state The frozen state that had previously been returned by 15648 * {@link #onSaveInstanceState}. 15649 * 15650 * @see #onSaveInstanceState() 15651 * @see #restoreHierarchyState(android.util.SparseArray) 15652 * @see #dispatchRestoreInstanceState(android.util.SparseArray) 15653 */ 15654 @CallSuper onRestoreInstanceState(Parcelable state)15655 protected void onRestoreInstanceState(Parcelable state) { 15656 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED; 15657 if (state != null && !(state instanceof AbsSavedState)) { 15658 throw new IllegalArgumentException("Wrong state class, expecting View State but " 15659 + "received " + state.getClass().toString() + " instead. This usually happens " 15660 + "when two views of different type have the same id in the same hierarchy. " 15661 + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure " 15662 + "other views do not use the same id."); 15663 } 15664 if (state != null && state instanceof BaseSavedState) { 15665 mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved; 15666 } 15667 } 15668 15669 /** 15670 * <p>Return the time at which the drawing of the view hierarchy started.</p> 15671 * 15672 * @return the drawing start time in milliseconds 15673 */ getDrawingTime()15674 public long getDrawingTime() { 15675 return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0; 15676 } 15677 15678 /** 15679 * <p>Enables or disables the duplication of the parent's state into this view. When 15680 * duplication is enabled, this view gets its drawable state from its parent rather 15681 * than from its own internal properties.</p> 15682 * 15683 * <p>Note: in the current implementation, setting this property to true after the 15684 * view was added to a ViewGroup might have no effect at all. This property should 15685 * always be used from XML or set to true before adding this view to a ViewGroup.</p> 15686 * 15687 * <p>Note: if this view's parent addStateFromChildren property is enabled and this 15688 * property is enabled, an exception will be thrown.</p> 15689 * 15690 * <p>Note: if the child view uses and updates additional states which are unknown to the 15691 * parent, these states should not be affected by this method.</p> 15692 * 15693 * @param enabled True to enable duplication of the parent's drawable state, false 15694 * to disable it. 15695 * 15696 * @see #getDrawableState() 15697 * @see #isDuplicateParentStateEnabled() 15698 */ setDuplicateParentStateEnabled(boolean enabled)15699 public void setDuplicateParentStateEnabled(boolean enabled) { 15700 setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE); 15701 } 15702 15703 /** 15704 * <p>Indicates whether this duplicates its drawable state from its parent.</p> 15705 * 15706 * @return True if this view's drawable state is duplicated from the parent, 15707 * false otherwise 15708 * 15709 * @see #getDrawableState() 15710 * @see #setDuplicateParentStateEnabled(boolean) 15711 */ isDuplicateParentStateEnabled()15712 public boolean isDuplicateParentStateEnabled() { 15713 return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE; 15714 } 15715 15716 /** 15717 * <p>Specifies the type of layer backing this view. The layer can be 15718 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or 15719 * {@link #LAYER_TYPE_HARDWARE}.</p> 15720 * 15721 * <p>A layer is associated with an optional {@link android.graphics.Paint} 15722 * instance that controls how the layer is composed on screen. The following 15723 * properties of the paint are taken into account when composing the layer:</p> 15724 * <ul> 15725 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li> 15726 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li> 15727 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li> 15728 * </ul> 15729 * 15730 * <p>If this view has an alpha value set to < 1.0 by calling 15731 * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded 15732 * by this view's alpha value.</p> 15733 * 15734 * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE}, 15735 * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE} 15736 * for more information on when and how to use layers.</p> 15737 * 15738 * @param layerType The type of layer to use with this view, must be one of 15739 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or 15740 * {@link #LAYER_TYPE_HARDWARE} 15741 * @param paint The paint used to compose the layer. This argument is optional 15742 * and can be null. It is ignored when the layer type is 15743 * {@link #LAYER_TYPE_NONE} 15744 * 15745 * @see #getLayerType() 15746 * @see #LAYER_TYPE_NONE 15747 * @see #LAYER_TYPE_SOFTWARE 15748 * @see #LAYER_TYPE_HARDWARE 15749 * @see #setAlpha(float) 15750 * 15751 * @attr ref android.R.styleable#View_layerType 15752 */ setLayerType(int layerType, @Nullable Paint paint)15753 public void setLayerType(int layerType, @Nullable Paint paint) { 15754 if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) { 15755 throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, " 15756 + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE"); 15757 } 15758 15759 boolean typeChanged = mRenderNode.setLayerType(layerType); 15760 15761 if (!typeChanged) { 15762 setLayerPaint(paint); 15763 return; 15764 } 15765 15766 if (layerType != LAYER_TYPE_SOFTWARE) { 15767 // Destroy any previous software drawing cache if present 15768 // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up 15769 // drawing cache created in View#draw when drawing to a SW canvas. 15770 destroyDrawingCache(); 15771 } 15772 15773 mLayerType = layerType; 15774 mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint; 15775 mRenderNode.setLayerPaint(mLayerPaint); 15776 15777 // draw() behaves differently if we are on a layer, so we need to 15778 // invalidate() here 15779 invalidateParentCaches(); 15780 invalidate(true); 15781 } 15782 15783 /** 15784 * Updates the {@link Paint} object used with the current layer (used only if the current 15785 * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint 15786 * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time 15787 * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to 15788 * ensure that the view gets redrawn immediately. 15789 * 15790 * <p>A layer is associated with an optional {@link android.graphics.Paint} 15791 * instance that controls how the layer is composed on screen. The following 15792 * properties of the paint are taken into account when composing the layer:</p> 15793 * <ul> 15794 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li> 15795 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li> 15796 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li> 15797 * </ul> 15798 * 15799 * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the 15800 * alpha value of the layer's paint is superseded by this view's alpha value.</p> 15801 * 15802 * @param paint The paint used to compose the layer. This argument is optional 15803 * and can be null. It is ignored when the layer type is 15804 * {@link #LAYER_TYPE_NONE} 15805 * 15806 * @see #setLayerType(int, android.graphics.Paint) 15807 */ setLayerPaint(@ullable Paint paint)15808 public void setLayerPaint(@Nullable Paint paint) { 15809 int layerType = getLayerType(); 15810 if (layerType != LAYER_TYPE_NONE) { 15811 mLayerPaint = paint; 15812 if (layerType == LAYER_TYPE_HARDWARE) { 15813 if (mRenderNode.setLayerPaint(paint)) { 15814 invalidateViewProperty(false, false); 15815 } 15816 } else { 15817 invalidate(); 15818 } 15819 } 15820 } 15821 15822 /** 15823 * Indicates what type of layer is currently associated with this view. By default 15824 * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}. 15825 * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)} 15826 * for more information on the different types of layers. 15827 * 15828 * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or 15829 * {@link #LAYER_TYPE_HARDWARE} 15830 * 15831 * @see #setLayerType(int, android.graphics.Paint) 15832 * @see #buildLayer() 15833 * @see #LAYER_TYPE_NONE 15834 * @see #LAYER_TYPE_SOFTWARE 15835 * @see #LAYER_TYPE_HARDWARE 15836 */ getLayerType()15837 public int getLayerType() { 15838 return mLayerType; 15839 } 15840 15841 /** 15842 * Forces this view's layer to be created and this view to be rendered 15843 * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE}, 15844 * invoking this method will have no effect. 15845 * 15846 * This method can for instance be used to render a view into its layer before 15847 * starting an animation. If this view is complex, rendering into the layer 15848 * before starting the animation will avoid skipping frames. 15849 * 15850 * @throws IllegalStateException If this view is not attached to a window 15851 * 15852 * @see #setLayerType(int, android.graphics.Paint) 15853 */ buildLayer()15854 public void buildLayer() { 15855 if (mLayerType == LAYER_TYPE_NONE) return; 15856 15857 final AttachInfo attachInfo = mAttachInfo; 15858 if (attachInfo == null) { 15859 throw new IllegalStateException("This view must be attached to a window first"); 15860 } 15861 15862 if (getWidth() == 0 || getHeight() == 0) { 15863 return; 15864 } 15865 15866 switch (mLayerType) { 15867 case LAYER_TYPE_HARDWARE: 15868 updateDisplayListIfDirty(); 15869 if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) { 15870 attachInfo.mHardwareRenderer.buildLayer(mRenderNode); 15871 } 15872 break; 15873 case LAYER_TYPE_SOFTWARE: 15874 buildDrawingCache(true); 15875 break; 15876 } 15877 } 15878 15879 /** 15880 * Destroys all hardware rendering resources. This method is invoked 15881 * when the system needs to reclaim resources. Upon execution of this 15882 * method, you should free any OpenGL resources created by the view. 15883 * 15884 * Note: you <strong>must</strong> call 15885 * <code>super.destroyHardwareResources()</code> when overriding 15886 * this method. 15887 * 15888 * @hide 15889 */ 15890 @CallSuper destroyHardwareResources()15891 protected void destroyHardwareResources() { 15892 // Although the Layer will be destroyed by RenderNode, we want to release 15893 // the staging display list, which is also a signal to RenderNode that it's 15894 // safe to free its copy of the display list as it knows that we will 15895 // push an updated DisplayList if we try to draw again 15896 resetDisplayList(); 15897 } 15898 15899 /** 15900 * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call 15901 * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a 15902 * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when 15903 * the cache is enabled. To benefit from the cache, you must request the drawing cache by 15904 * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not 15905 * null.</p> 15906 * 15907 * <p>Enabling the drawing cache is similar to 15908 * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware 15909 * acceleration is turned off. When hardware acceleration is turned on, enabling the 15910 * drawing cache has no effect on rendering because the system uses a different mechanism 15911 * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even 15912 * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)} 15913 * for information on how to enable software and hardware layers.</p> 15914 * 15915 * <p>This API can be used to manually generate 15916 * a bitmap copy of this view, by setting the flag to <code>true</code> and calling 15917 * {@link #getDrawingCache()}.</p> 15918 * 15919 * @param enabled true to enable the drawing cache, false otherwise 15920 * 15921 * @see #isDrawingCacheEnabled() 15922 * @see #getDrawingCache() 15923 * @see #buildDrawingCache() 15924 * @see #setLayerType(int, android.graphics.Paint) 15925 */ setDrawingCacheEnabled(boolean enabled)15926 public void setDrawingCacheEnabled(boolean enabled) { 15927 mCachingFailed = false; 15928 setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED); 15929 } 15930 15931 /** 15932 * <p>Indicates whether the drawing cache is enabled for this view.</p> 15933 * 15934 * @return true if the drawing cache is enabled 15935 * 15936 * @see #setDrawingCacheEnabled(boolean) 15937 * @see #getDrawingCache() 15938 */ 15939 @ViewDebug.ExportedProperty(category = "drawing") isDrawingCacheEnabled()15940 public boolean isDrawingCacheEnabled() { 15941 return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED; 15942 } 15943 15944 /** 15945 * Debugging utility which recursively outputs the dirty state of a view and its 15946 * descendants. 15947 * 15948 * @hide 15949 */ 15950 @SuppressWarnings({"UnusedDeclaration"}) outputDirtyFlags(String indent, boolean clear, int clearMask)15951 public void outputDirtyFlags(String indent, boolean clear, int clearMask) { 15952 Log.d("View", indent + this + " DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) + 15953 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" + 15954 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) + 15955 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")"); 15956 if (clear) { 15957 mPrivateFlags &= clearMask; 15958 } 15959 if (this instanceof ViewGroup) { 15960 ViewGroup parent = (ViewGroup) this; 15961 final int count = parent.getChildCount(); 15962 for (int i = 0; i < count; i++) { 15963 final View child = parent.getChildAt(i); 15964 child.outputDirtyFlags(indent + " ", clear, clearMask); 15965 } 15966 } 15967 } 15968 15969 /** 15970 * This method is used by ViewGroup to cause its children to restore or recreate their 15971 * display lists. It is called by getDisplayList() when the parent ViewGroup does not need 15972 * to recreate its own display list, which would happen if it went through the normal 15973 * draw/dispatchDraw mechanisms. 15974 * 15975 * @hide 15976 */ dispatchGetDisplayList()15977 protected void dispatchGetDisplayList() {} 15978 15979 /** 15980 * A view that is not attached or hardware accelerated cannot create a display list. 15981 * This method checks these conditions and returns the appropriate result. 15982 * 15983 * @return true if view has the ability to create a display list, false otherwise. 15984 * 15985 * @hide 15986 */ canHaveDisplayList()15987 public boolean canHaveDisplayList() { 15988 return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null); 15989 } 15990 15991 /** 15992 * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported) 15993 * @hide 15994 */ 15995 @NonNull updateDisplayListIfDirty()15996 public RenderNode updateDisplayListIfDirty() { 15997 final RenderNode renderNode = mRenderNode; 15998 if (!canHaveDisplayList()) { 15999 // can't populate RenderNode, don't try 16000 return renderNode; 16001 } 16002 16003 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 16004 || !renderNode.isValid() 16005 || (mRecreateDisplayList)) { 16006 // Don't need to recreate the display list, just need to tell our 16007 // children to restore/recreate theirs 16008 if (renderNode.isValid() 16009 && !mRecreateDisplayList) { 16010 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID; 16011 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 16012 dispatchGetDisplayList(); 16013 16014 return renderNode; // no work needed 16015 } 16016 16017 // If we got here, we're recreating it. Mark it as such to ensure that 16018 // we copy in child display lists into ours in drawChild() 16019 mRecreateDisplayList = true; 16020 16021 int width = mRight - mLeft; 16022 int height = mBottom - mTop; 16023 int layerType = getLayerType(); 16024 16025 final DisplayListCanvas canvas = renderNode.start(width, height); 16026 canvas.setHighContrastText(mAttachInfo.mHighContrastText); 16027 16028 try { 16029 if (layerType == LAYER_TYPE_SOFTWARE) { 16030 buildDrawingCache(true); 16031 Bitmap cache = getDrawingCache(true); 16032 if (cache != null) { 16033 canvas.drawBitmap(cache, 0, 0, mLayerPaint); 16034 } 16035 } else { 16036 computeScroll(); 16037 16038 canvas.translate(-mScrollX, -mScrollY); 16039 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID; 16040 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 16041 16042 // Fast path for layouts with no backgrounds 16043 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 16044 dispatchDraw(canvas); 16045 if (mOverlay != null && !mOverlay.isEmpty()) { 16046 mOverlay.getOverlayView().draw(canvas); 16047 } 16048 } else { 16049 draw(canvas); 16050 } 16051 } 16052 } finally { 16053 renderNode.end(canvas); 16054 setDisplayListProperties(renderNode); 16055 } 16056 } else { 16057 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID; 16058 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 16059 } 16060 return renderNode; 16061 } 16062 resetDisplayList()16063 private void resetDisplayList() { 16064 if (mRenderNode.isValid()) { 16065 mRenderNode.discardDisplayList(); 16066 } 16067 16068 if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) { 16069 mBackgroundRenderNode.discardDisplayList(); 16070 } 16071 } 16072 16073 /** 16074 * Called when the passed RenderNode is removed from the draw tree 16075 * @hide 16076 */ onRenderNodeDetached(RenderNode renderNode)16077 public void onRenderNodeDetached(RenderNode renderNode) { 16078 } 16079 16080 /** 16081 * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p> 16082 * 16083 * @return A non-scaled bitmap representing this view or null if cache is disabled. 16084 * 16085 * @see #getDrawingCache(boolean) 16086 */ getDrawingCache()16087 public Bitmap getDrawingCache() { 16088 return getDrawingCache(false); 16089 } 16090 16091 /** 16092 * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap 16093 * is null when caching is disabled. If caching is enabled and the cache is not ready, 16094 * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not 16095 * draw from the cache when the cache is enabled. To benefit from the cache, you must 16096 * request the drawing cache by calling this method and draw it on screen if the 16097 * returned bitmap is not null.</p> 16098 * 16099 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled, 16100 * this method will create a bitmap of the same size as this view. Because this bitmap 16101 * will be drawn scaled by the parent ViewGroup, the result on screen might show 16102 * scaling artifacts. To avoid such artifacts, you should call this method by setting 16103 * the auto scaling to true. Doing so, however, will generate a bitmap of a different 16104 * size than the view. This implies that your application must be able to handle this 16105 * size.</p> 16106 * 16107 * @param autoScale Indicates whether the generated bitmap should be scaled based on 16108 * the current density of the screen when the application is in compatibility 16109 * mode. 16110 * 16111 * @return A bitmap representing this view or null if cache is disabled. 16112 * 16113 * @see #setDrawingCacheEnabled(boolean) 16114 * @see #isDrawingCacheEnabled() 16115 * @see #buildDrawingCache(boolean) 16116 * @see #destroyDrawingCache() 16117 */ getDrawingCache(boolean autoScale)16118 public Bitmap getDrawingCache(boolean autoScale) { 16119 if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) { 16120 return null; 16121 } 16122 if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) { 16123 buildDrawingCache(autoScale); 16124 } 16125 return autoScale ? mDrawingCache : mUnscaledDrawingCache; 16126 } 16127 16128 /** 16129 * <p>Frees the resources used by the drawing cache. If you call 16130 * {@link #buildDrawingCache()} manually without calling 16131 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you 16132 * should cleanup the cache with this method afterwards.</p> 16133 * 16134 * @see #setDrawingCacheEnabled(boolean) 16135 * @see #buildDrawingCache() 16136 * @see #getDrawingCache() 16137 */ destroyDrawingCache()16138 public void destroyDrawingCache() { 16139 if (mDrawingCache != null) { 16140 mDrawingCache.recycle(); 16141 mDrawingCache = null; 16142 } 16143 if (mUnscaledDrawingCache != null) { 16144 mUnscaledDrawingCache.recycle(); 16145 mUnscaledDrawingCache = null; 16146 } 16147 } 16148 16149 /** 16150 * Setting a solid background color for the drawing cache's bitmaps will improve 16151 * performance and memory usage. Note, though that this should only be used if this 16152 * view will always be drawn on top of a solid color. 16153 * 16154 * @param color The background color to use for the drawing cache's bitmap 16155 * 16156 * @see #setDrawingCacheEnabled(boolean) 16157 * @see #buildDrawingCache() 16158 * @see #getDrawingCache() 16159 */ setDrawingCacheBackgroundColor(@olorInt int color)16160 public void setDrawingCacheBackgroundColor(@ColorInt int color) { 16161 if (color != mDrawingCacheBackgroundColor) { 16162 mDrawingCacheBackgroundColor = color; 16163 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 16164 } 16165 } 16166 16167 /** 16168 * @see #setDrawingCacheBackgroundColor(int) 16169 * 16170 * @return The background color to used for the drawing cache's bitmap 16171 */ 16172 @ColorInt getDrawingCacheBackgroundColor()16173 public int getDrawingCacheBackgroundColor() { 16174 return mDrawingCacheBackgroundColor; 16175 } 16176 16177 /** 16178 * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p> 16179 * 16180 * @see #buildDrawingCache(boolean) 16181 */ buildDrawingCache()16182 public void buildDrawingCache() { 16183 buildDrawingCache(false); 16184 } 16185 16186 /** 16187 * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p> 16188 * 16189 * <p>If you call {@link #buildDrawingCache()} manually without calling 16190 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you 16191 * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p> 16192 * 16193 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled, 16194 * this method will create a bitmap of the same size as this view. Because this bitmap 16195 * will be drawn scaled by the parent ViewGroup, the result on screen might show 16196 * scaling artifacts. To avoid such artifacts, you should call this method by setting 16197 * the auto scaling to true. Doing so, however, will generate a bitmap of a different 16198 * size than the view. This implies that your application must be able to handle this 16199 * size.</p> 16200 * 16201 * <p>You should avoid calling this method when hardware acceleration is enabled. If 16202 * you do not need the drawing cache bitmap, calling this method will increase memory 16203 * usage and cause the view to be rendered in software once, thus negatively impacting 16204 * performance.</p> 16205 * 16206 * @see #getDrawingCache() 16207 * @see #destroyDrawingCache() 16208 */ buildDrawingCache(boolean autoScale)16209 public void buildDrawingCache(boolean autoScale) { 16210 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ? 16211 mDrawingCache == null : mUnscaledDrawingCache == null)) { 16212 if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) { 16213 Trace.traceBegin(Trace.TRACE_TAG_VIEW, 16214 "buildDrawingCache/SW Layer for " + getClass().getSimpleName()); 16215 } 16216 try { 16217 buildDrawingCacheImpl(autoScale); 16218 } finally { 16219 Trace.traceEnd(Trace.TRACE_TAG_VIEW); 16220 } 16221 } 16222 } 16223 16224 /** 16225 * private, internal implementation of buildDrawingCache, used to enable tracing 16226 */ buildDrawingCacheImpl(boolean autoScale)16227 private void buildDrawingCacheImpl(boolean autoScale) { 16228 mCachingFailed = false; 16229 16230 int width = mRight - mLeft; 16231 int height = mBottom - mTop; 16232 16233 final AttachInfo attachInfo = mAttachInfo; 16234 final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired; 16235 16236 if (autoScale && scalingRequired) { 16237 width = (int) ((width * attachInfo.mApplicationScale) + 0.5f); 16238 height = (int) ((height * attachInfo.mApplicationScale) + 0.5f); 16239 } 16240 16241 final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor; 16242 final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque(); 16243 final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache; 16244 16245 final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4); 16246 final long drawingCacheSize = 16247 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize(); 16248 if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) { 16249 if (width > 0 && height > 0) { 16250 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is" 16251 + " too large to fit into a software layer (or drawing cache), needs " 16252 + projectedBitmapSize + " bytes, only " 16253 + drawingCacheSize + " available"); 16254 } 16255 destroyDrawingCache(); 16256 mCachingFailed = true; 16257 return; 16258 } 16259 16260 boolean clear = true; 16261 Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache; 16262 16263 if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) { 16264 Bitmap.Config quality; 16265 if (!opaque) { 16266 // Never pick ARGB_4444 because it looks awful 16267 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case 16268 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) { 16269 case DRAWING_CACHE_QUALITY_AUTO: 16270 case DRAWING_CACHE_QUALITY_LOW: 16271 case DRAWING_CACHE_QUALITY_HIGH: 16272 default: 16273 quality = Bitmap.Config.ARGB_8888; 16274 break; 16275 } 16276 } else { 16277 // Optimization for translucent windows 16278 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy() 16279 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; 16280 } 16281 16282 // Try to cleanup memory 16283 if (bitmap != null) bitmap.recycle(); 16284 16285 try { 16286 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(), 16287 width, height, quality); 16288 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi); 16289 if (autoScale) { 16290 mDrawingCache = bitmap; 16291 } else { 16292 mUnscaledDrawingCache = bitmap; 16293 } 16294 if (opaque && use32BitCache) bitmap.setHasAlpha(false); 16295 } catch (OutOfMemoryError e) { 16296 // If there is not enough memory to create the bitmap cache, just 16297 // ignore the issue as bitmap caches are not required to draw the 16298 // view hierarchy 16299 if (autoScale) { 16300 mDrawingCache = null; 16301 } else { 16302 mUnscaledDrawingCache = null; 16303 } 16304 mCachingFailed = true; 16305 return; 16306 } 16307 16308 clear = drawingCacheBackgroundColor != 0; 16309 } 16310 16311 Canvas canvas; 16312 if (attachInfo != null) { 16313 canvas = attachInfo.mCanvas; 16314 if (canvas == null) { 16315 canvas = new Canvas(); 16316 } 16317 canvas.setBitmap(bitmap); 16318 // Temporarily clobber the cached Canvas in case one of our children 16319 // is also using a drawing cache. Without this, the children would 16320 // steal the canvas by attaching their own bitmap to it and bad, bad 16321 // thing would happen (invisible views, corrupted drawings, etc.) 16322 attachInfo.mCanvas = null; 16323 } else { 16324 // This case should hopefully never or seldom happen 16325 canvas = new Canvas(bitmap); 16326 } 16327 16328 if (clear) { 16329 bitmap.eraseColor(drawingCacheBackgroundColor); 16330 } 16331 16332 computeScroll(); 16333 final int restoreCount = canvas.save(); 16334 16335 if (autoScale && scalingRequired) { 16336 final float scale = attachInfo.mApplicationScale; 16337 canvas.scale(scale, scale); 16338 } 16339 16340 canvas.translate(-mScrollX, -mScrollY); 16341 16342 mPrivateFlags |= PFLAG_DRAWN; 16343 if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated || 16344 mLayerType != LAYER_TYPE_NONE) { 16345 mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID; 16346 } 16347 16348 // Fast path for layouts with no backgrounds 16349 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 16350 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 16351 dispatchDraw(canvas); 16352 if (mOverlay != null && !mOverlay.isEmpty()) { 16353 mOverlay.getOverlayView().draw(canvas); 16354 } 16355 } else { 16356 draw(canvas); 16357 } 16358 16359 canvas.restoreToCount(restoreCount); 16360 canvas.setBitmap(null); 16361 16362 if (attachInfo != null) { 16363 // Restore the cached Canvas for our siblings 16364 attachInfo.mCanvas = canvas; 16365 } 16366 } 16367 16368 /** 16369 * Create a snapshot of the view into a bitmap. We should probably make 16370 * some form of this public, but should think about the API. 16371 * 16372 * @hide 16373 */ createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren)16374 public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) { 16375 int width = mRight - mLeft; 16376 int height = mBottom - mTop; 16377 16378 final AttachInfo attachInfo = mAttachInfo; 16379 final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f; 16380 width = (int) ((width * scale) + 0.5f); 16381 height = (int) ((height * scale) + 0.5f); 16382 16383 Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(), 16384 width > 0 ? width : 1, height > 0 ? height : 1, quality); 16385 if (bitmap == null) { 16386 throw new OutOfMemoryError(); 16387 } 16388 16389 Resources resources = getResources(); 16390 if (resources != null) { 16391 bitmap.setDensity(resources.getDisplayMetrics().densityDpi); 16392 } 16393 16394 Canvas canvas; 16395 if (attachInfo != null) { 16396 canvas = attachInfo.mCanvas; 16397 if (canvas == null) { 16398 canvas = new Canvas(); 16399 } 16400 canvas.setBitmap(bitmap); 16401 // Temporarily clobber the cached Canvas in case one of our children 16402 // is also using a drawing cache. Without this, the children would 16403 // steal the canvas by attaching their own bitmap to it and bad, bad 16404 // things would happen (invisible views, corrupted drawings, etc.) 16405 attachInfo.mCanvas = null; 16406 } else { 16407 // This case should hopefully never or seldom happen 16408 canvas = new Canvas(bitmap); 16409 } 16410 16411 if ((backgroundColor & 0xff000000) != 0) { 16412 bitmap.eraseColor(backgroundColor); 16413 } 16414 16415 computeScroll(); 16416 final int restoreCount = canvas.save(); 16417 canvas.scale(scale, scale); 16418 canvas.translate(-mScrollX, -mScrollY); 16419 16420 // Temporarily remove the dirty mask 16421 int flags = mPrivateFlags; 16422 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 16423 16424 // Fast path for layouts with no backgrounds 16425 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 16426 dispatchDraw(canvas); 16427 if (mOverlay != null && !mOverlay.isEmpty()) { 16428 mOverlay.getOverlayView().draw(canvas); 16429 } 16430 } else { 16431 draw(canvas); 16432 } 16433 16434 mPrivateFlags = flags; 16435 16436 canvas.restoreToCount(restoreCount); 16437 canvas.setBitmap(null); 16438 16439 if (attachInfo != null) { 16440 // Restore the cached Canvas for our siblings 16441 attachInfo.mCanvas = canvas; 16442 } 16443 16444 return bitmap; 16445 } 16446 16447 /** 16448 * Indicates whether this View is currently in edit mode. A View is usually 16449 * in edit mode when displayed within a developer tool. For instance, if 16450 * this View is being drawn by a visual user interface builder, this method 16451 * should return true. 16452 * 16453 * Subclasses should check the return value of this method to provide 16454 * different behaviors if their normal behavior might interfere with the 16455 * host environment. For instance: the class spawns a thread in its 16456 * constructor, the drawing code relies on device-specific features, etc. 16457 * 16458 * This method is usually checked in the drawing code of custom widgets. 16459 * 16460 * @return True if this View is in edit mode, false otherwise. 16461 */ isInEditMode()16462 public boolean isInEditMode() { 16463 return false; 16464 } 16465 16466 /** 16467 * If the View draws content inside its padding and enables fading edges, 16468 * it needs to support padding offsets. Padding offsets are added to the 16469 * fading edges to extend the length of the fade so that it covers pixels 16470 * drawn inside the padding. 16471 * 16472 * Subclasses of this class should override this method if they need 16473 * to draw content inside the padding. 16474 * 16475 * @return True if padding offset must be applied, false otherwise. 16476 * 16477 * @see #getLeftPaddingOffset() 16478 * @see #getRightPaddingOffset() 16479 * @see #getTopPaddingOffset() 16480 * @see #getBottomPaddingOffset() 16481 * 16482 * @since CURRENT 16483 */ isPaddingOffsetRequired()16484 protected boolean isPaddingOffsetRequired() { 16485 return false; 16486 } 16487 16488 /** 16489 * Amount by which to extend the left fading region. Called only when 16490 * {@link #isPaddingOffsetRequired()} returns true. 16491 * 16492 * @return The left padding offset in pixels. 16493 * 16494 * @see #isPaddingOffsetRequired() 16495 * 16496 * @since CURRENT 16497 */ getLeftPaddingOffset()16498 protected int getLeftPaddingOffset() { 16499 return 0; 16500 } 16501 16502 /** 16503 * Amount by which to extend the right fading region. Called only when 16504 * {@link #isPaddingOffsetRequired()} returns true. 16505 * 16506 * @return The right padding offset in pixels. 16507 * 16508 * @see #isPaddingOffsetRequired() 16509 * 16510 * @since CURRENT 16511 */ getRightPaddingOffset()16512 protected int getRightPaddingOffset() { 16513 return 0; 16514 } 16515 16516 /** 16517 * Amount by which to extend the top fading region. Called only when 16518 * {@link #isPaddingOffsetRequired()} returns true. 16519 * 16520 * @return The top padding offset in pixels. 16521 * 16522 * @see #isPaddingOffsetRequired() 16523 * 16524 * @since CURRENT 16525 */ getTopPaddingOffset()16526 protected int getTopPaddingOffset() { 16527 return 0; 16528 } 16529 16530 /** 16531 * Amount by which to extend the bottom fading region. Called only when 16532 * {@link #isPaddingOffsetRequired()} returns true. 16533 * 16534 * @return The bottom padding offset in pixels. 16535 * 16536 * @see #isPaddingOffsetRequired() 16537 * 16538 * @since CURRENT 16539 */ getBottomPaddingOffset()16540 protected int getBottomPaddingOffset() { 16541 return 0; 16542 } 16543 16544 /** 16545 * @hide 16546 * @param offsetRequired 16547 */ getFadeTop(boolean offsetRequired)16548 protected int getFadeTop(boolean offsetRequired) { 16549 int top = mPaddingTop; 16550 if (offsetRequired) top += getTopPaddingOffset(); 16551 return top; 16552 } 16553 16554 /** 16555 * @hide 16556 * @param offsetRequired 16557 */ getFadeHeight(boolean offsetRequired)16558 protected int getFadeHeight(boolean offsetRequired) { 16559 int padding = mPaddingTop; 16560 if (offsetRequired) padding += getTopPaddingOffset(); 16561 return mBottom - mTop - mPaddingBottom - padding; 16562 } 16563 16564 /** 16565 * <p>Indicates whether this view is attached to a hardware accelerated 16566 * window or not.</p> 16567 * 16568 * <p>Even if this method returns true, it does not mean that every call 16569 * to {@link #draw(android.graphics.Canvas)} will be made with an hardware 16570 * accelerated {@link android.graphics.Canvas}. For instance, if this view 16571 * is drawn onto an offscreen {@link android.graphics.Bitmap} and its 16572 * window is hardware accelerated, 16573 * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely 16574 * return false, and this method will return true.</p> 16575 * 16576 * @return True if the view is attached to a window and the window is 16577 * hardware accelerated; false in any other case. 16578 */ 16579 @ViewDebug.ExportedProperty(category = "drawing") isHardwareAccelerated()16580 public boolean isHardwareAccelerated() { 16581 return mAttachInfo != null && mAttachInfo.mHardwareAccelerated; 16582 } 16583 16584 /** 16585 * Sets a rectangular area on this view to which the view will be clipped 16586 * when it is drawn. Setting the value to null will remove the clip bounds 16587 * and the view will draw normally, using its full bounds. 16588 * 16589 * @param clipBounds The rectangular area, in the local coordinates of 16590 * this view, to which future drawing operations will be clipped. 16591 */ setClipBounds(Rect clipBounds)16592 public void setClipBounds(Rect clipBounds) { 16593 if (clipBounds == mClipBounds 16594 || (clipBounds != null && clipBounds.equals(mClipBounds))) { 16595 return; 16596 } 16597 if (clipBounds != null) { 16598 if (mClipBounds == null) { 16599 mClipBounds = new Rect(clipBounds); 16600 } else { 16601 mClipBounds.set(clipBounds); 16602 } 16603 } else { 16604 mClipBounds = null; 16605 } 16606 mRenderNode.setClipBounds(mClipBounds); 16607 invalidateViewProperty(false, false); 16608 } 16609 16610 /** 16611 * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}. 16612 * 16613 * @return A copy of the current clip bounds if clip bounds are set, 16614 * otherwise null. 16615 */ getClipBounds()16616 public Rect getClipBounds() { 16617 return (mClipBounds != null) ? new Rect(mClipBounds) : null; 16618 } 16619 16620 16621 /** 16622 * Populates an output rectangle with the clip bounds of the view, 16623 * returning {@code true} if successful or {@code false} if the view's 16624 * clip bounds are {@code null}. 16625 * 16626 * @param outRect rectangle in which to place the clip bounds of the view 16627 * @return {@code true} if successful or {@code false} if the view's 16628 * clip bounds are {@code null} 16629 */ getClipBounds(Rect outRect)16630 public boolean getClipBounds(Rect outRect) { 16631 if (mClipBounds != null) { 16632 outRect.set(mClipBounds); 16633 return true; 16634 } 16635 return false; 16636 } 16637 16638 /** 16639 * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common 16640 * case of an active Animation being run on the view. 16641 */ applyLegacyAnimation(ViewGroup parent, long drawingTime, Animation a, boolean scalingRequired)16642 private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime, 16643 Animation a, boolean scalingRequired) { 16644 Transformation invalidationTransform; 16645 final int flags = parent.mGroupFlags; 16646 final boolean initialized = a.isInitialized(); 16647 if (!initialized) { 16648 a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight()); 16649 a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop); 16650 if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler); 16651 onAnimationStart(); 16652 } 16653 16654 final Transformation t = parent.getChildTransformation(); 16655 boolean more = a.getTransformation(drawingTime, t, 1f); 16656 if (scalingRequired && mAttachInfo.mApplicationScale != 1f) { 16657 if (parent.mInvalidationTransformation == null) { 16658 parent.mInvalidationTransformation = new Transformation(); 16659 } 16660 invalidationTransform = parent.mInvalidationTransformation; 16661 a.getTransformation(drawingTime, invalidationTransform, 1f); 16662 } else { 16663 invalidationTransform = t; 16664 } 16665 16666 if (more) { 16667 if (!a.willChangeBounds()) { 16668 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) == 16669 ViewGroup.FLAG_OPTIMIZE_INVALIDATE) { 16670 parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED; 16671 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) { 16672 // The child need to draw an animation, potentially offscreen, so 16673 // make sure we do not cancel invalidate requests 16674 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION; 16675 parent.invalidate(mLeft, mTop, mRight, mBottom); 16676 } 16677 } else { 16678 if (parent.mInvalidateRegion == null) { 16679 parent.mInvalidateRegion = new RectF(); 16680 } 16681 final RectF region = parent.mInvalidateRegion; 16682 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region, 16683 invalidationTransform); 16684 16685 // The child need to draw an animation, potentially offscreen, so 16686 // make sure we do not cancel invalidate requests 16687 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION; 16688 16689 final int left = mLeft + (int) region.left; 16690 final int top = mTop + (int) region.top; 16691 parent.invalidate(left, top, left + (int) (region.width() + .5f), 16692 top + (int) (region.height() + .5f)); 16693 } 16694 } 16695 return more; 16696 } 16697 16698 /** 16699 * This method is called by getDisplayList() when a display list is recorded for a View. 16700 * It pushes any properties to the RenderNode that aren't managed by the RenderNode. 16701 */ setDisplayListProperties(RenderNode renderNode)16702 void setDisplayListProperties(RenderNode renderNode) { 16703 if (renderNode != null) { 16704 renderNode.setHasOverlappingRendering(getHasOverlappingRendering()); 16705 renderNode.setClipToBounds(mParent instanceof ViewGroup 16706 && ((ViewGroup) mParent).getClipChildren()); 16707 16708 float alpha = 1; 16709 if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags & 16710 ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { 16711 ViewGroup parentVG = (ViewGroup) mParent; 16712 final Transformation t = parentVG.getChildTransformation(); 16713 if (parentVG.getChildStaticTransformation(this, t)) { 16714 final int transformType = t.getTransformationType(); 16715 if (transformType != Transformation.TYPE_IDENTITY) { 16716 if ((transformType & Transformation.TYPE_ALPHA) != 0) { 16717 alpha = t.getAlpha(); 16718 } 16719 if ((transformType & Transformation.TYPE_MATRIX) != 0) { 16720 renderNode.setStaticMatrix(t.getMatrix()); 16721 } 16722 } 16723 } 16724 } 16725 if (mTransformationInfo != null) { 16726 alpha *= getFinalAlpha(); 16727 if (alpha < 1) { 16728 final int multipliedAlpha = (int) (255 * alpha); 16729 if (onSetAlpha(multipliedAlpha)) { 16730 alpha = 1; 16731 } 16732 } 16733 renderNode.setAlpha(alpha); 16734 } else if (alpha < 1) { 16735 renderNode.setAlpha(alpha); 16736 } 16737 } 16738 } 16739 16740 /** 16741 * This method is called by ViewGroup.drawChild() to have each child view draw itself. 16742 * 16743 * This is where the View specializes rendering behavior based on layer type, 16744 * and hardware acceleration. 16745 */ draw(Canvas canvas, ViewGroup parent, long drawingTime)16746 boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) { 16747 final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated(); 16748 /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList. 16749 * 16750 * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't 16751 * HW accelerated, it can't handle drawing RenderNodes. 16752 */ 16753 boolean drawingWithRenderNode = mAttachInfo != null 16754 && mAttachInfo.mHardwareAccelerated 16755 && hardwareAcceleratedCanvas; 16756 16757 boolean more = false; 16758 final boolean childHasIdentityMatrix = hasIdentityMatrix(); 16759 final int parentFlags = parent.mGroupFlags; 16760 16761 if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) { 16762 parent.getChildTransformation().clear(); 16763 parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION; 16764 } 16765 16766 Transformation transformToApply = null; 16767 boolean concatMatrix = false; 16768 final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired; 16769 final Animation a = getAnimation(); 16770 if (a != null) { 16771 more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired); 16772 concatMatrix = a.willChangeTransformationMatrix(); 16773 if (concatMatrix) { 16774 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM; 16775 } 16776 transformToApply = parent.getChildTransformation(); 16777 } else { 16778 if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) { 16779 // No longer animating: clear out old animation matrix 16780 mRenderNode.setAnimationMatrix(null); 16781 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM; 16782 } 16783 if (!drawingWithRenderNode 16784 && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { 16785 final Transformation t = parent.getChildTransformation(); 16786 final boolean hasTransform = parent.getChildStaticTransformation(this, t); 16787 if (hasTransform) { 16788 final int transformType = t.getTransformationType(); 16789 transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null; 16790 concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0; 16791 } 16792 } 16793 } 16794 16795 concatMatrix |= !childHasIdentityMatrix; 16796 16797 // Sets the flag as early as possible to allow draw() implementations 16798 // to call invalidate() successfully when doing animations 16799 mPrivateFlags |= PFLAG_DRAWN; 16800 16801 if (!concatMatrix && 16802 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS | 16803 ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN && 16804 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) && 16805 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) { 16806 mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED; 16807 return more; 16808 } 16809 mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED; 16810 16811 if (hardwareAcceleratedCanvas) { 16812 // Clear INVALIDATED flag to allow invalidation to occur during rendering, but 16813 // retain the flag's value temporarily in the mRecreateDisplayList flag 16814 mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0; 16815 mPrivateFlags &= ~PFLAG_INVALIDATED; 16816 } 16817 16818 RenderNode renderNode = null; 16819 Bitmap cache = null; 16820 int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local 16821 if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) { 16822 if (layerType != LAYER_TYPE_NONE) { 16823 // If not drawing with RenderNode, treat HW layers as SW 16824 layerType = LAYER_TYPE_SOFTWARE; 16825 buildDrawingCache(true); 16826 } 16827 cache = getDrawingCache(true); 16828 } 16829 16830 if (drawingWithRenderNode) { 16831 // Delay getting the display list until animation-driven alpha values are 16832 // set up and possibly passed on to the view 16833 renderNode = updateDisplayListIfDirty(); 16834 if (!renderNode.isValid()) { 16835 // Uncommon, but possible. If a view is removed from the hierarchy during the call 16836 // to getDisplayList(), the display list will be marked invalid and we should not 16837 // try to use it again. 16838 renderNode = null; 16839 drawingWithRenderNode = false; 16840 } 16841 } 16842 16843 int sx = 0; 16844 int sy = 0; 16845 if (!drawingWithRenderNode) { 16846 computeScroll(); 16847 sx = mScrollX; 16848 sy = mScrollY; 16849 } 16850 16851 final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode; 16852 final boolean offsetForScroll = cache == null && !drawingWithRenderNode; 16853 16854 int restoreTo = -1; 16855 if (!drawingWithRenderNode || transformToApply != null) { 16856 restoreTo = canvas.save(); 16857 } 16858 if (offsetForScroll) { 16859 canvas.translate(mLeft - sx, mTop - sy); 16860 } else { 16861 if (!drawingWithRenderNode) { 16862 canvas.translate(mLeft, mTop); 16863 } 16864 if (scalingRequired) { 16865 if (drawingWithRenderNode) { 16866 // TODO: Might not need this if we put everything inside the DL 16867 restoreTo = canvas.save(); 16868 } 16869 // mAttachInfo cannot be null, otherwise scalingRequired == false 16870 final float scale = 1.0f / mAttachInfo.mApplicationScale; 16871 canvas.scale(scale, scale); 16872 } 16873 } 16874 16875 float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha()); 16876 if (transformToApply != null 16877 || alpha < 1 16878 || !hasIdentityMatrix() 16879 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) { 16880 if (transformToApply != null || !childHasIdentityMatrix) { 16881 int transX = 0; 16882 int transY = 0; 16883 16884 if (offsetForScroll) { 16885 transX = -sx; 16886 transY = -sy; 16887 } 16888 16889 if (transformToApply != null) { 16890 if (concatMatrix) { 16891 if (drawingWithRenderNode) { 16892 renderNode.setAnimationMatrix(transformToApply.getMatrix()); 16893 } else { 16894 // Undo the scroll translation, apply the transformation matrix, 16895 // then redo the scroll translate to get the correct result. 16896 canvas.translate(-transX, -transY); 16897 canvas.concat(transformToApply.getMatrix()); 16898 canvas.translate(transX, transY); 16899 } 16900 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; 16901 } 16902 16903 float transformAlpha = transformToApply.getAlpha(); 16904 if (transformAlpha < 1) { 16905 alpha *= transformAlpha; 16906 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; 16907 } 16908 } 16909 16910 if (!childHasIdentityMatrix && !drawingWithRenderNode) { 16911 canvas.translate(-transX, -transY); 16912 canvas.concat(getMatrix()); 16913 canvas.translate(transX, transY); 16914 } 16915 } 16916 16917 // Deal with alpha if it is or used to be <1 16918 if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) { 16919 if (alpha < 1) { 16920 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA; 16921 } else { 16922 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA; 16923 } 16924 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; 16925 if (!drawingWithDrawingCache) { 16926 final int multipliedAlpha = (int) (255 * alpha); 16927 if (!onSetAlpha(multipliedAlpha)) { 16928 if (drawingWithRenderNode) { 16929 renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha()); 16930 } else if (layerType == LAYER_TYPE_NONE) { 16931 canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(), 16932 multipliedAlpha); 16933 } 16934 } else { 16935 // Alpha is handled by the child directly, clobber the layer's alpha 16936 mPrivateFlags |= PFLAG_ALPHA_SET; 16937 } 16938 } 16939 } 16940 } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) { 16941 onSetAlpha(255); 16942 mPrivateFlags &= ~PFLAG_ALPHA_SET; 16943 } 16944 16945 if (!drawingWithRenderNode) { 16946 // apply clips directly, since RenderNode won't do it for this draw 16947 if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) { 16948 if (offsetForScroll) { 16949 canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight()); 16950 } else { 16951 if (!scalingRequired || cache == null) { 16952 canvas.clipRect(0, 0, getWidth(), getHeight()); 16953 } else { 16954 canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight()); 16955 } 16956 } 16957 } 16958 16959 if (mClipBounds != null) { 16960 // clip bounds ignore scroll 16961 canvas.clipRect(mClipBounds); 16962 } 16963 } 16964 16965 if (!drawingWithDrawingCache) { 16966 if (drawingWithRenderNode) { 16967 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 16968 ((DisplayListCanvas) canvas).drawRenderNode(renderNode); 16969 } else { 16970 // Fast path for layouts with no backgrounds 16971 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 16972 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 16973 dispatchDraw(canvas); 16974 } else { 16975 draw(canvas); 16976 } 16977 } 16978 } else if (cache != null) { 16979 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 16980 if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) { 16981 // no layer paint, use temporary paint to draw bitmap 16982 Paint cachePaint = parent.mCachePaint; 16983 if (cachePaint == null) { 16984 cachePaint = new Paint(); 16985 cachePaint.setDither(false); 16986 parent.mCachePaint = cachePaint; 16987 } 16988 cachePaint.setAlpha((int) (alpha * 255)); 16989 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint); 16990 } else { 16991 // use layer paint to draw the bitmap, merging the two alphas, but also restore 16992 int layerPaintAlpha = mLayerPaint.getAlpha(); 16993 if (alpha < 1) { 16994 mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha)); 16995 } 16996 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint); 16997 if (alpha < 1) { 16998 mLayerPaint.setAlpha(layerPaintAlpha); 16999 } 17000 } 17001 } 17002 17003 if (restoreTo >= 0) { 17004 canvas.restoreToCount(restoreTo); 17005 } 17006 17007 if (a != null && !more) { 17008 if (!hardwareAcceleratedCanvas && !a.getFillAfter()) { 17009 onSetAlpha(255); 17010 } 17011 parent.finishAnimatingView(this, a); 17012 } 17013 17014 if (more && hardwareAcceleratedCanvas) { 17015 if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) { 17016 // alpha animations should cause the child to recreate its display list 17017 invalidate(true); 17018 } 17019 } 17020 17021 mRecreateDisplayList = false; 17022 17023 return more; 17024 } 17025 17026 /** 17027 * Manually render this view (and all of its children) to the given Canvas. 17028 * The view must have already done a full layout before this function is 17029 * called. When implementing a view, implement 17030 * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method. 17031 * If you do need to override this method, call the superclass version. 17032 * 17033 * @param canvas The Canvas to which the View is rendered. 17034 */ 17035 @CallSuper draw(Canvas canvas)17036 public void draw(Canvas canvas) { 17037 final int privateFlags = mPrivateFlags; 17038 final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE && 17039 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState); 17040 mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN; 17041 17042 /* 17043 * Draw traversal performs several drawing steps which must be executed 17044 * in the appropriate order: 17045 * 17046 * 1. Draw the background 17047 * 2. If necessary, save the canvas' layers to prepare for fading 17048 * 3. Draw view's content 17049 * 4. Draw children 17050 * 5. If necessary, draw the fading edges and restore layers 17051 * 6. Draw decorations (scrollbars for instance) 17052 */ 17053 17054 // Step 1, draw the background, if needed 17055 int saveCount; 17056 17057 if (!dirtyOpaque) { 17058 drawBackground(canvas); 17059 } 17060 17061 // skip step 2 & 5 if possible (common case) 17062 final int viewFlags = mViewFlags; 17063 boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0; 17064 boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0; 17065 if (!verticalEdges && !horizontalEdges) { 17066 // Step 3, draw the content 17067 if (!dirtyOpaque) onDraw(canvas); 17068 17069 // Step 4, draw the children 17070 dispatchDraw(canvas); 17071 17072 // Overlay is part of the content and draws beneath Foreground 17073 if (mOverlay != null && !mOverlay.isEmpty()) { 17074 mOverlay.getOverlayView().dispatchDraw(canvas); 17075 } 17076 17077 // Step 6, draw decorations (foreground, scrollbars) 17078 onDrawForeground(canvas); 17079 17080 // we're done... 17081 return; 17082 } 17083 17084 /* 17085 * Here we do the full fledged routine... 17086 * (this is an uncommon case where speed matters less, 17087 * this is why we repeat some of the tests that have been 17088 * done above) 17089 */ 17090 17091 boolean drawTop = false; 17092 boolean drawBottom = false; 17093 boolean drawLeft = false; 17094 boolean drawRight = false; 17095 17096 float topFadeStrength = 0.0f; 17097 float bottomFadeStrength = 0.0f; 17098 float leftFadeStrength = 0.0f; 17099 float rightFadeStrength = 0.0f; 17100 17101 // Step 2, save the canvas' layers 17102 int paddingLeft = mPaddingLeft; 17103 17104 final boolean offsetRequired = isPaddingOffsetRequired(); 17105 if (offsetRequired) { 17106 paddingLeft += getLeftPaddingOffset(); 17107 } 17108 17109 int left = mScrollX + paddingLeft; 17110 int right = left + mRight - mLeft - mPaddingRight - paddingLeft; 17111 int top = mScrollY + getFadeTop(offsetRequired); 17112 int bottom = top + getFadeHeight(offsetRequired); 17113 17114 if (offsetRequired) { 17115 right += getRightPaddingOffset(); 17116 bottom += getBottomPaddingOffset(); 17117 } 17118 17119 final ScrollabilityCache scrollabilityCache = mScrollCache; 17120 final float fadeHeight = scrollabilityCache.fadingEdgeLength; 17121 int length = (int) fadeHeight; 17122 17123 // clip the fade length if top and bottom fades overlap 17124 // overlapping fades produce odd-looking artifacts 17125 if (verticalEdges && (top + length > bottom - length)) { 17126 length = (bottom - top) / 2; 17127 } 17128 17129 // also clip horizontal fades if necessary 17130 if (horizontalEdges && (left + length > right - length)) { 17131 length = (right - left) / 2; 17132 } 17133 17134 if (verticalEdges) { 17135 topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength())); 17136 drawTop = topFadeStrength * fadeHeight > 1.0f; 17137 bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength())); 17138 drawBottom = bottomFadeStrength * fadeHeight > 1.0f; 17139 } 17140 17141 if (horizontalEdges) { 17142 leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength())); 17143 drawLeft = leftFadeStrength * fadeHeight > 1.0f; 17144 rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength())); 17145 drawRight = rightFadeStrength * fadeHeight > 1.0f; 17146 } 17147 17148 saveCount = canvas.getSaveCount(); 17149 17150 int solidColor = getSolidColor(); 17151 if (solidColor == 0) { 17152 final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG; 17153 17154 if (drawTop) { 17155 canvas.saveLayer(left, top, right, top + length, null, flags); 17156 } 17157 17158 if (drawBottom) { 17159 canvas.saveLayer(left, bottom - length, right, bottom, null, flags); 17160 } 17161 17162 if (drawLeft) { 17163 canvas.saveLayer(left, top, left + length, bottom, null, flags); 17164 } 17165 17166 if (drawRight) { 17167 canvas.saveLayer(right - length, top, right, bottom, null, flags); 17168 } 17169 } else { 17170 scrollabilityCache.setFadeColor(solidColor); 17171 } 17172 17173 // Step 3, draw the content 17174 if (!dirtyOpaque) onDraw(canvas); 17175 17176 // Step 4, draw the children 17177 dispatchDraw(canvas); 17178 17179 // Step 5, draw the fade effect and restore layers 17180 final Paint p = scrollabilityCache.paint; 17181 final Matrix matrix = scrollabilityCache.matrix; 17182 final Shader fade = scrollabilityCache.shader; 17183 17184 if (drawTop) { 17185 matrix.setScale(1, fadeHeight * topFadeStrength); 17186 matrix.postTranslate(left, top); 17187 fade.setLocalMatrix(matrix); 17188 p.setShader(fade); 17189 canvas.drawRect(left, top, right, top + length, p); 17190 } 17191 17192 if (drawBottom) { 17193 matrix.setScale(1, fadeHeight * bottomFadeStrength); 17194 matrix.postRotate(180); 17195 matrix.postTranslate(left, bottom); 17196 fade.setLocalMatrix(matrix); 17197 p.setShader(fade); 17198 canvas.drawRect(left, bottom - length, right, bottom, p); 17199 } 17200 17201 if (drawLeft) { 17202 matrix.setScale(1, fadeHeight * leftFadeStrength); 17203 matrix.postRotate(-90); 17204 matrix.postTranslate(left, top); 17205 fade.setLocalMatrix(matrix); 17206 p.setShader(fade); 17207 canvas.drawRect(left, top, left + length, bottom, p); 17208 } 17209 17210 if (drawRight) { 17211 matrix.setScale(1, fadeHeight * rightFadeStrength); 17212 matrix.postRotate(90); 17213 matrix.postTranslate(right, top); 17214 fade.setLocalMatrix(matrix); 17215 p.setShader(fade); 17216 canvas.drawRect(right - length, top, right, bottom, p); 17217 } 17218 17219 canvas.restoreToCount(saveCount); 17220 17221 // Overlay is part of the content and draws beneath Foreground 17222 if (mOverlay != null && !mOverlay.isEmpty()) { 17223 mOverlay.getOverlayView().dispatchDraw(canvas); 17224 } 17225 17226 // Step 6, draw decorations (foreground, scrollbars) 17227 onDrawForeground(canvas); 17228 } 17229 17230 /** 17231 * Draws the background onto the specified canvas. 17232 * 17233 * @param canvas Canvas on which to draw the background 17234 */ drawBackground(Canvas canvas)17235 private void drawBackground(Canvas canvas) { 17236 final Drawable background = mBackground; 17237 if (background == null) { 17238 return; 17239 } 17240 17241 setBackgroundBounds(); 17242 17243 // Attempt to use a display list if requested. 17244 if (canvas.isHardwareAccelerated() && mAttachInfo != null 17245 && mAttachInfo.mHardwareRenderer != null) { 17246 mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode); 17247 17248 final RenderNode renderNode = mBackgroundRenderNode; 17249 if (renderNode != null && renderNode.isValid()) { 17250 setBackgroundRenderNodeProperties(renderNode); 17251 ((DisplayListCanvas) canvas).drawRenderNode(renderNode); 17252 return; 17253 } 17254 } 17255 17256 final int scrollX = mScrollX; 17257 final int scrollY = mScrollY; 17258 if ((scrollX | scrollY) == 0) { 17259 background.draw(canvas); 17260 } else { 17261 canvas.translate(scrollX, scrollY); 17262 background.draw(canvas); 17263 canvas.translate(-scrollX, -scrollY); 17264 } 17265 } 17266 17267 /** 17268 * Sets the correct background bounds and rebuilds the outline, if needed. 17269 * <p/> 17270 * This is called by LayoutLib. 17271 */ setBackgroundBounds()17272 void setBackgroundBounds() { 17273 if (mBackgroundSizeChanged && mBackground != null) { 17274 mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop); 17275 mBackgroundSizeChanged = false; 17276 rebuildOutline(); 17277 } 17278 } 17279 setBackgroundRenderNodeProperties(RenderNode renderNode)17280 private void setBackgroundRenderNodeProperties(RenderNode renderNode) { 17281 renderNode.setTranslationX(mScrollX); 17282 renderNode.setTranslationY(mScrollY); 17283 } 17284 17285 /** 17286 * Creates a new display list or updates the existing display list for the 17287 * specified Drawable. 17288 * 17289 * @param drawable Drawable for which to create a display list 17290 * @param renderNode Existing RenderNode, or {@code null} 17291 * @return A valid display list for the specified drawable 17292 */ getDrawableRenderNode(Drawable drawable, RenderNode renderNode)17293 private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) { 17294 if (renderNode == null) { 17295 renderNode = RenderNode.create(drawable.getClass().getName(), this); 17296 } 17297 17298 final Rect bounds = drawable.getBounds(); 17299 final int width = bounds.width(); 17300 final int height = bounds.height(); 17301 final DisplayListCanvas canvas = renderNode.start(width, height); 17302 17303 // Reverse left/top translation done by drawable canvas, which will 17304 // instead be applied by rendernode's LTRB bounds below. This way, the 17305 // drawable's bounds match with its rendernode bounds and its content 17306 // will lie within those bounds in the rendernode tree. 17307 canvas.translate(-bounds.left, -bounds.top); 17308 17309 try { 17310 drawable.draw(canvas); 17311 } finally { 17312 renderNode.end(canvas); 17313 } 17314 17315 // Set up drawable properties that are view-independent. 17316 renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom); 17317 renderNode.setProjectBackwards(drawable.isProjected()); 17318 renderNode.setProjectionReceiver(true); 17319 renderNode.setClipToBounds(false); 17320 return renderNode; 17321 } 17322 17323 /** 17324 * Returns the overlay for this view, creating it if it does not yet exist. 17325 * Adding drawables to the overlay will cause them to be displayed whenever 17326 * the view itself is redrawn. Objects in the overlay should be actively 17327 * managed: remove them when they should not be displayed anymore. The 17328 * overlay will always have the same size as its host view. 17329 * 17330 * <p>Note: Overlays do not currently work correctly with {@link 17331 * SurfaceView} or {@link TextureView}; contents in overlays for these 17332 * types of views may not display correctly.</p> 17333 * 17334 * @return The ViewOverlay object for this view. 17335 * @see ViewOverlay 17336 */ getOverlay()17337 public ViewOverlay getOverlay() { 17338 if (mOverlay == null) { 17339 mOverlay = new ViewOverlay(mContext, this); 17340 } 17341 return mOverlay; 17342 } 17343 17344 /** 17345 * Override this if your view is known to always be drawn on top of a solid color background, 17346 * and needs to draw fading edges. Returning a non-zero color enables the view system to 17347 * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha 17348 * should be set to 0xFF. 17349 * 17350 * @see #setVerticalFadingEdgeEnabled(boolean) 17351 * @see #setHorizontalFadingEdgeEnabled(boolean) 17352 * 17353 * @return The known solid color background for this view, or 0 if the color may vary 17354 */ 17355 @ViewDebug.ExportedProperty(category = "drawing") 17356 @ColorInt getSolidColor()17357 public int getSolidColor() { 17358 return 0; 17359 } 17360 17361 /** 17362 * Build a human readable string representation of the specified view flags. 17363 * 17364 * @param flags the view flags to convert to a string 17365 * @return a String representing the supplied flags 17366 */ printFlags(int flags)17367 private static String printFlags(int flags) { 17368 String output = ""; 17369 int numFlags = 0; 17370 if ((flags & FOCUSABLE_MASK) == FOCUSABLE) { 17371 output += "TAKES_FOCUS"; 17372 numFlags++; 17373 } 17374 17375 switch (flags & VISIBILITY_MASK) { 17376 case INVISIBLE: 17377 if (numFlags > 0) { 17378 output += " "; 17379 } 17380 output += "INVISIBLE"; 17381 // USELESS HERE numFlags++; 17382 break; 17383 case GONE: 17384 if (numFlags > 0) { 17385 output += " "; 17386 } 17387 output += "GONE"; 17388 // USELESS HERE numFlags++; 17389 break; 17390 default: 17391 break; 17392 } 17393 return output; 17394 } 17395 17396 /** 17397 * Build a human readable string representation of the specified private 17398 * view flags. 17399 * 17400 * @param privateFlags the private view flags to convert to a string 17401 * @return a String representing the supplied flags 17402 */ printPrivateFlags(int privateFlags)17403 private static String printPrivateFlags(int privateFlags) { 17404 String output = ""; 17405 int numFlags = 0; 17406 17407 if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) { 17408 output += "WANTS_FOCUS"; 17409 numFlags++; 17410 } 17411 17412 if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) { 17413 if (numFlags > 0) { 17414 output += " "; 17415 } 17416 output += "FOCUSED"; 17417 numFlags++; 17418 } 17419 17420 if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) { 17421 if (numFlags > 0) { 17422 output += " "; 17423 } 17424 output += "SELECTED"; 17425 numFlags++; 17426 } 17427 17428 if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) { 17429 if (numFlags > 0) { 17430 output += " "; 17431 } 17432 output += "IS_ROOT_NAMESPACE"; 17433 numFlags++; 17434 } 17435 17436 if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) { 17437 if (numFlags > 0) { 17438 output += " "; 17439 } 17440 output += "HAS_BOUNDS"; 17441 numFlags++; 17442 } 17443 17444 if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) { 17445 if (numFlags > 0) { 17446 output += " "; 17447 } 17448 output += "DRAWN"; 17449 // USELESS HERE numFlags++; 17450 } 17451 return output; 17452 } 17453 17454 /** 17455 * <p>Indicates whether or not this view's layout will be requested during 17456 * the next hierarchy layout pass.</p> 17457 * 17458 * @return true if the layout will be forced during next layout pass 17459 */ isLayoutRequested()17460 public boolean isLayoutRequested() { 17461 return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT; 17462 } 17463 17464 /** 17465 * Return true if o is a ViewGroup that is laying out using optical bounds. 17466 * @hide 17467 */ isLayoutModeOptical(Object o)17468 public static boolean isLayoutModeOptical(Object o) { 17469 return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical(); 17470 } 17471 setOpticalFrame(int left, int top, int right, int bottom)17472 private boolean setOpticalFrame(int left, int top, int right, int bottom) { 17473 Insets parentInsets = mParent instanceof View ? 17474 ((View) mParent).getOpticalInsets() : Insets.NONE; 17475 Insets childInsets = getOpticalInsets(); 17476 return setFrame( 17477 left + parentInsets.left - childInsets.left, 17478 top + parentInsets.top - childInsets.top, 17479 right + parentInsets.left + childInsets.right, 17480 bottom + parentInsets.top + childInsets.bottom); 17481 } 17482 17483 /** 17484 * Assign a size and position to a view and all of its 17485 * descendants 17486 * 17487 * <p>This is the second phase of the layout mechanism. 17488 * (The first is measuring). In this phase, each parent calls 17489 * layout on all of its children to position them. 17490 * This is typically done using the child measurements 17491 * that were stored in the measure pass().</p> 17492 * 17493 * <p>Derived classes should not override this method. 17494 * Derived classes with children should override 17495 * onLayout. In that method, they should 17496 * call layout on each of their children.</p> 17497 * 17498 * @param l Left position, relative to parent 17499 * @param t Top position, relative to parent 17500 * @param r Right position, relative to parent 17501 * @param b Bottom position, relative to parent 17502 */ 17503 @SuppressWarnings({"unchecked"}) layout(int l, int t, int r, int b)17504 public void layout(int l, int t, int r, int b) { 17505 if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) { 17506 onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec); 17507 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; 17508 } 17509 17510 int oldL = mLeft; 17511 int oldT = mTop; 17512 int oldB = mBottom; 17513 int oldR = mRight; 17514 17515 boolean changed = isLayoutModeOptical(mParent) ? 17516 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b); 17517 17518 if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) { 17519 onLayout(changed, l, t, r, b); 17520 mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED; 17521 17522 ListenerInfo li = mListenerInfo; 17523 if (li != null && li.mOnLayoutChangeListeners != null) { 17524 ArrayList<OnLayoutChangeListener> listenersCopy = 17525 (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone(); 17526 int numListeners = listenersCopy.size(); 17527 for (int i = 0; i < numListeners; ++i) { 17528 listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB); 17529 } 17530 } 17531 } 17532 17533 mPrivateFlags &= ~PFLAG_FORCE_LAYOUT; 17534 mPrivateFlags3 |= PFLAG3_IS_LAID_OUT; 17535 } 17536 17537 /** 17538 * Called from layout when this view should 17539 * assign a size and position to each of its children. 17540 * 17541 * Derived classes with children should override 17542 * this method and call layout on each of 17543 * their children. 17544 * @param changed This is a new size or position for this view 17545 * @param left Left position, relative to parent 17546 * @param top Top position, relative to parent 17547 * @param right Right position, relative to parent 17548 * @param bottom Bottom position, relative to parent 17549 */ onLayout(boolean changed, int left, int top, int right, int bottom)17550 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 17551 } 17552 17553 /** 17554 * Assign a size and position to this view. 17555 * 17556 * This is called from layout. 17557 * 17558 * @param left Left position, relative to parent 17559 * @param top Top position, relative to parent 17560 * @param right Right position, relative to parent 17561 * @param bottom Bottom position, relative to parent 17562 * @return true if the new size and position are different than the 17563 * previous ones 17564 * {@hide} 17565 */ setFrame(int left, int top, int right, int bottom)17566 protected boolean setFrame(int left, int top, int right, int bottom) { 17567 boolean changed = false; 17568 17569 if (DBG) { 17570 Log.d("View", this + " View.setFrame(" + left + "," + top + "," 17571 + right + "," + bottom + ")"); 17572 } 17573 17574 if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) { 17575 changed = true; 17576 17577 // Remember our drawn bit 17578 int drawn = mPrivateFlags & PFLAG_DRAWN; 17579 17580 int oldWidth = mRight - mLeft; 17581 int oldHeight = mBottom - mTop; 17582 int newWidth = right - left; 17583 int newHeight = bottom - top; 17584 boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight); 17585 17586 // Invalidate our old position 17587 invalidate(sizeChanged); 17588 17589 mLeft = left; 17590 mTop = top; 17591 mRight = right; 17592 mBottom = bottom; 17593 mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom); 17594 17595 mPrivateFlags |= PFLAG_HAS_BOUNDS; 17596 17597 17598 if (sizeChanged) { 17599 sizeChange(newWidth, newHeight, oldWidth, oldHeight); 17600 } 17601 17602 if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) { 17603 // If we are visible, force the DRAWN bit to on so that 17604 // this invalidate will go through (at least to our parent). 17605 // This is because someone may have invalidated this view 17606 // before this call to setFrame came in, thereby clearing 17607 // the DRAWN bit. 17608 mPrivateFlags |= PFLAG_DRAWN; 17609 invalidate(sizeChanged); 17610 // parent display list may need to be recreated based on a change in the bounds 17611 // of any child 17612 invalidateParentCaches(); 17613 } 17614 17615 // Reset drawn bit to original value (invalidate turns it off) 17616 mPrivateFlags |= drawn; 17617 17618 mBackgroundSizeChanged = true; 17619 if (mForegroundInfo != null) { 17620 mForegroundInfo.mBoundsChanged = true; 17621 } 17622 17623 notifySubtreeAccessibilityStateChangedIfNeeded(); 17624 } 17625 return changed; 17626 } 17627 17628 /** 17629 * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}. 17630 * @hide 17631 */ setLeftTopRightBottom(int left, int top, int right, int bottom)17632 public void setLeftTopRightBottom(int left, int top, int right, int bottom) { 17633 setFrame(left, top, right, bottom); 17634 } 17635 sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight)17636 private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) { 17637 onSizeChanged(newWidth, newHeight, oldWidth, oldHeight); 17638 if (mOverlay != null) { 17639 mOverlay.getOverlayView().setRight(newWidth); 17640 mOverlay.getOverlayView().setBottom(newHeight); 17641 } 17642 rebuildOutline(); 17643 } 17644 17645 /** 17646 * Finalize inflating a view from XML. This is called as the last phase 17647 * of inflation, after all child views have been added. 17648 * 17649 * <p>Even if the subclass overrides onFinishInflate, they should always be 17650 * sure to call the super method, so that we get called. 17651 */ 17652 @CallSuper onFinishInflate()17653 protected void onFinishInflate() { 17654 } 17655 17656 /** 17657 * Returns the resources associated with this view. 17658 * 17659 * @return Resources object. 17660 */ getResources()17661 public Resources getResources() { 17662 return mResources; 17663 } 17664 17665 /** 17666 * Invalidates the specified Drawable. 17667 * 17668 * @param drawable the drawable to invalidate 17669 */ 17670 @Override invalidateDrawable(@onNull Drawable drawable)17671 public void invalidateDrawable(@NonNull Drawable drawable) { 17672 if (verifyDrawable(drawable)) { 17673 final Rect dirty = drawable.getDirtyBounds(); 17674 final int scrollX = mScrollX; 17675 final int scrollY = mScrollY; 17676 17677 invalidate(dirty.left + scrollX, dirty.top + scrollY, 17678 dirty.right + scrollX, dirty.bottom + scrollY); 17679 rebuildOutline(); 17680 } 17681 } 17682 17683 /** 17684 * Schedules an action on a drawable to occur at a specified time. 17685 * 17686 * @param who the recipient of the action 17687 * @param what the action to run on the drawable 17688 * @param when the time at which the action must occur. Uses the 17689 * {@link SystemClock#uptimeMillis} timebase. 17690 */ 17691 @Override scheduleDrawable(@onNull Drawable who, @NonNull Runnable what, long when)17692 public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) { 17693 if (verifyDrawable(who) && what != null) { 17694 final long delay = when - SystemClock.uptimeMillis(); 17695 if (mAttachInfo != null) { 17696 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed( 17697 Choreographer.CALLBACK_ANIMATION, what, who, 17698 Choreographer.subtractFrameDelay(delay)); 17699 } else { 17700 // Postpone the runnable until we know 17701 // on which thread it needs to run. 17702 getRunQueue().postDelayed(what, delay); 17703 } 17704 } 17705 } 17706 17707 /** 17708 * Cancels a scheduled action on a drawable. 17709 * 17710 * @param who the recipient of the action 17711 * @param what the action to cancel 17712 */ 17713 @Override unscheduleDrawable(@onNull Drawable who, @NonNull Runnable what)17714 public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) { 17715 if (verifyDrawable(who) && what != null) { 17716 if (mAttachInfo != null) { 17717 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks( 17718 Choreographer.CALLBACK_ANIMATION, what, who); 17719 } 17720 getRunQueue().removeCallbacks(what); 17721 } 17722 } 17723 17724 /** 17725 * Unschedule any events associated with the given Drawable. This can be 17726 * used when selecting a new Drawable into a view, so that the previous 17727 * one is completely unscheduled. 17728 * 17729 * @param who The Drawable to unschedule. 17730 * 17731 * @see #drawableStateChanged 17732 */ unscheduleDrawable(Drawable who)17733 public void unscheduleDrawable(Drawable who) { 17734 if (mAttachInfo != null && who != null) { 17735 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks( 17736 Choreographer.CALLBACK_ANIMATION, null, who); 17737 } 17738 } 17739 17740 /** 17741 * Resolve the Drawables depending on the layout direction. This is implicitly supposing 17742 * that the View directionality can and will be resolved before its Drawables. 17743 * 17744 * Will call {@link View#onResolveDrawables} when resolution is done. 17745 * 17746 * @hide 17747 */ resolveDrawables()17748 protected void resolveDrawables() { 17749 // Drawables resolution may need to happen before resolving the layout direction (which is 17750 // done only during the measure() call). 17751 // If the layout direction is not resolved yet, we cannot resolve the Drawables except in 17752 // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT. 17753 // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or 17754 // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout 17755 // direction to be resolved as its resolved value will be the same as its raw value. 17756 if (!isLayoutDirectionResolved() && 17757 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) { 17758 return; 17759 } 17760 17761 final int layoutDirection = isLayoutDirectionResolved() ? 17762 getLayoutDirection() : getRawLayoutDirection(); 17763 17764 if (mBackground != null) { 17765 mBackground.setLayoutDirection(layoutDirection); 17766 } 17767 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) { 17768 mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection); 17769 } 17770 mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED; 17771 onResolveDrawables(layoutDirection); 17772 } 17773 areDrawablesResolved()17774 boolean areDrawablesResolved() { 17775 return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED; 17776 } 17777 17778 /** 17779 * Called when layout direction has been resolved. 17780 * 17781 * The default implementation does nothing. 17782 * 17783 * @param layoutDirection The resolved layout direction. 17784 * 17785 * @see #LAYOUT_DIRECTION_LTR 17786 * @see #LAYOUT_DIRECTION_RTL 17787 * 17788 * @hide 17789 */ onResolveDrawables(@esolvedLayoutDir int layoutDirection)17790 public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) { 17791 } 17792 17793 /** 17794 * @hide 17795 */ resetResolvedDrawables()17796 protected void resetResolvedDrawables() { 17797 resetResolvedDrawablesInternal(); 17798 } 17799 resetResolvedDrawablesInternal()17800 void resetResolvedDrawablesInternal() { 17801 mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED; 17802 } 17803 17804 /** 17805 * If your view subclass is displaying its own Drawable objects, it should 17806 * override this function and return true for any Drawable it is 17807 * displaying. This allows animations for those drawables to be 17808 * scheduled. 17809 * 17810 * <p>Be sure to call through to the super class when overriding this 17811 * function. 17812 * 17813 * @param who The Drawable to verify. Return true if it is one you are 17814 * displaying, else return the result of calling through to the 17815 * super class. 17816 * 17817 * @return boolean If true than the Drawable is being displayed in the 17818 * view; else false and it is not allowed to animate. 17819 * 17820 * @see #unscheduleDrawable(android.graphics.drawable.Drawable) 17821 * @see #drawableStateChanged() 17822 */ 17823 @CallSuper verifyDrawable(@onNull Drawable who)17824 protected boolean verifyDrawable(@NonNull Drawable who) { 17825 // Avoid verifying the scroll bar drawable so that we don't end up in 17826 // an invalidation loop. This effectively prevents the scroll bar 17827 // drawable from triggering invalidations and scheduling runnables. 17828 return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who); 17829 } 17830 17831 /** 17832 * This function is called whenever the state of the view changes in such 17833 * a way that it impacts the state of drawables being shown. 17834 * <p> 17835 * If the View has a StateListAnimator, it will also be called to run necessary state 17836 * change animations. 17837 * <p> 17838 * Be sure to call through to the superclass when overriding this function. 17839 * 17840 * @see Drawable#setState(int[]) 17841 */ 17842 @CallSuper drawableStateChanged()17843 protected void drawableStateChanged() { 17844 final int[] state = getDrawableState(); 17845 boolean changed = false; 17846 17847 final Drawable bg = mBackground; 17848 if (bg != null && bg.isStateful()) { 17849 changed |= bg.setState(state); 17850 } 17851 17852 final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null; 17853 if (fg != null && fg.isStateful()) { 17854 changed |= fg.setState(state); 17855 } 17856 17857 if (mScrollCache != null) { 17858 final Drawable scrollBar = mScrollCache.scrollBar; 17859 if (scrollBar != null && scrollBar.isStateful()) { 17860 changed |= scrollBar.setState(state) 17861 && mScrollCache.state != ScrollabilityCache.OFF; 17862 } 17863 } 17864 17865 if (mStateListAnimator != null) { 17866 mStateListAnimator.setState(state); 17867 } 17868 17869 if (changed) { 17870 invalidate(); 17871 } 17872 } 17873 17874 /** 17875 * This function is called whenever the view hotspot changes and needs to 17876 * be propagated to drawables or child views managed by the view. 17877 * <p> 17878 * Dispatching to child views is handled by 17879 * {@link #dispatchDrawableHotspotChanged(float, float)}. 17880 * <p> 17881 * Be sure to call through to the superclass when overriding this function. 17882 * 17883 * @param x hotspot x coordinate 17884 * @param y hotspot y coordinate 17885 */ 17886 @CallSuper drawableHotspotChanged(float x, float y)17887 public void drawableHotspotChanged(float x, float y) { 17888 if (mBackground != null) { 17889 mBackground.setHotspot(x, y); 17890 } 17891 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) { 17892 mForegroundInfo.mDrawable.setHotspot(x, y); 17893 } 17894 17895 dispatchDrawableHotspotChanged(x, y); 17896 } 17897 17898 /** 17899 * Dispatches drawableHotspotChanged to all of this View's children. 17900 * 17901 * @param x hotspot x coordinate 17902 * @param y hotspot y coordinate 17903 * @see #drawableHotspotChanged(float, float) 17904 */ dispatchDrawableHotspotChanged(float x, float y)17905 public void dispatchDrawableHotspotChanged(float x, float y) { 17906 } 17907 17908 /** 17909 * Call this to force a view to update its drawable state. This will cause 17910 * drawableStateChanged to be called on this view. Views that are interested 17911 * in the new state should call getDrawableState. 17912 * 17913 * @see #drawableStateChanged 17914 * @see #getDrawableState 17915 */ refreshDrawableState()17916 public void refreshDrawableState() { 17917 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY; 17918 drawableStateChanged(); 17919 17920 ViewParent parent = mParent; 17921 if (parent != null) { 17922 parent.childDrawableStateChanged(this); 17923 } 17924 } 17925 17926 /** 17927 * Return an array of resource IDs of the drawable states representing the 17928 * current state of the view. 17929 * 17930 * @return The current drawable state 17931 * 17932 * @see Drawable#setState(int[]) 17933 * @see #drawableStateChanged() 17934 * @see #onCreateDrawableState(int) 17935 */ getDrawableState()17936 public final int[] getDrawableState() { 17937 if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) { 17938 return mDrawableState; 17939 } else { 17940 mDrawableState = onCreateDrawableState(0); 17941 mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY; 17942 return mDrawableState; 17943 } 17944 } 17945 17946 /** 17947 * Generate the new {@link android.graphics.drawable.Drawable} state for 17948 * this view. This is called by the view 17949 * system when the cached Drawable state is determined to be invalid. To 17950 * retrieve the current state, you should use {@link #getDrawableState}. 17951 * 17952 * @param extraSpace if non-zero, this is the number of extra entries you 17953 * would like in the returned array in which you can place your own 17954 * states. 17955 * 17956 * @return Returns an array holding the current {@link Drawable} state of 17957 * the view. 17958 * 17959 * @see #mergeDrawableStates(int[], int[]) 17960 */ onCreateDrawableState(int extraSpace)17961 protected int[] onCreateDrawableState(int extraSpace) { 17962 if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE && 17963 mParent instanceof View) { 17964 return ((View) mParent).onCreateDrawableState(extraSpace); 17965 } 17966 17967 int[] drawableState; 17968 17969 int privateFlags = mPrivateFlags; 17970 17971 int viewStateIndex = 0; 17972 if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED; 17973 if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED; 17974 if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED; 17975 if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED; 17976 if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED; 17977 if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED; 17978 if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested && 17979 ThreadedRenderer.isAvailable()) { 17980 // This is set if HW acceleration is requested, even if the current 17981 // process doesn't allow it. This is just to allow app preview 17982 // windows to better match their app. 17983 viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED; 17984 } 17985 if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED; 17986 17987 final int privateFlags2 = mPrivateFlags2; 17988 if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) { 17989 viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT; 17990 } 17991 if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) { 17992 viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED; 17993 } 17994 17995 drawableState = StateSet.get(viewStateIndex); 17996 17997 //noinspection ConstantIfStatement 17998 if (false) { 17999 Log.i("View", "drawableStateIndex=" + viewStateIndex); 18000 Log.i("View", toString() 18001 + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0) 18002 + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED) 18003 + " fo=" + hasFocus() 18004 + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0) 18005 + " wf=" + hasWindowFocus() 18006 + ": " + Arrays.toString(drawableState)); 18007 } 18008 18009 if (extraSpace == 0) { 18010 return drawableState; 18011 } 18012 18013 final int[] fullState; 18014 if (drawableState != null) { 18015 fullState = new int[drawableState.length + extraSpace]; 18016 System.arraycopy(drawableState, 0, fullState, 0, drawableState.length); 18017 } else { 18018 fullState = new int[extraSpace]; 18019 } 18020 18021 return fullState; 18022 } 18023 18024 /** 18025 * Merge your own state values in <var>additionalState</var> into the base 18026 * state values <var>baseState</var> that were returned by 18027 * {@link #onCreateDrawableState(int)}. 18028 * 18029 * @param baseState The base state values returned by 18030 * {@link #onCreateDrawableState(int)}, which will be modified to also hold your 18031 * own additional state values. 18032 * 18033 * @param additionalState The additional state values you would like 18034 * added to <var>baseState</var>; this array is not modified. 18035 * 18036 * @return As a convenience, the <var>baseState</var> array you originally 18037 * passed into the function is returned. 18038 * 18039 * @see #onCreateDrawableState(int) 18040 */ mergeDrawableStates(int[] baseState, int[] additionalState)18041 protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) { 18042 final int N = baseState.length; 18043 int i = N - 1; 18044 while (i >= 0 && baseState[i] == 0) { 18045 i--; 18046 } 18047 System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length); 18048 return baseState; 18049 } 18050 18051 /** 18052 * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()} 18053 * on all Drawable objects associated with this view. 18054 * <p> 18055 * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator 18056 * attached to this view. 18057 */ 18058 @CallSuper jumpDrawablesToCurrentState()18059 public void jumpDrawablesToCurrentState() { 18060 if (mBackground != null) { 18061 mBackground.jumpToCurrentState(); 18062 } 18063 if (mStateListAnimator != null) { 18064 mStateListAnimator.jumpToCurrentState(); 18065 } 18066 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) { 18067 mForegroundInfo.mDrawable.jumpToCurrentState(); 18068 } 18069 } 18070 18071 /** 18072 * Sets the background color for this view. 18073 * @param color the color of the background 18074 */ 18075 @RemotableViewMethod setBackgroundColor(@olorInt int color)18076 public void setBackgroundColor(@ColorInt int color) { 18077 if (mBackground instanceof ColorDrawable) { 18078 ((ColorDrawable) mBackground.mutate()).setColor(color); 18079 computeOpaqueFlags(); 18080 mBackgroundResource = 0; 18081 } else { 18082 setBackground(new ColorDrawable(color)); 18083 } 18084 } 18085 18086 /** 18087 * Set the background to a given resource. The resource should refer to 18088 * a Drawable object or 0 to remove the background. 18089 * @param resid The identifier of the resource. 18090 * 18091 * @attr ref android.R.styleable#View_background 18092 */ 18093 @RemotableViewMethod setBackgroundResource(@rawableRes int resid)18094 public void setBackgroundResource(@DrawableRes int resid) { 18095 if (resid != 0 && resid == mBackgroundResource) { 18096 return; 18097 } 18098 18099 Drawable d = null; 18100 if (resid != 0) { 18101 d = mContext.getDrawable(resid); 18102 } 18103 setBackground(d); 18104 18105 mBackgroundResource = resid; 18106 } 18107 18108 /** 18109 * Set the background to a given Drawable, or remove the background. If the 18110 * background has padding, this View's padding is set to the background's 18111 * padding. However, when a background is removed, this View's padding isn't 18112 * touched. If setting the padding is desired, please use 18113 * {@link #setPadding(int, int, int, int)}. 18114 * 18115 * @param background The Drawable to use as the background, or null to remove the 18116 * background 18117 */ setBackground(Drawable background)18118 public void setBackground(Drawable background) { 18119 //noinspection deprecation 18120 setBackgroundDrawable(background); 18121 } 18122 18123 /** 18124 * @deprecated use {@link #setBackground(Drawable)} instead 18125 */ 18126 @Deprecated setBackgroundDrawable(Drawable background)18127 public void setBackgroundDrawable(Drawable background) { 18128 computeOpaqueFlags(); 18129 18130 if (background == mBackground) { 18131 return; 18132 } 18133 18134 boolean requestLayout = false; 18135 18136 mBackgroundResource = 0; 18137 18138 /* 18139 * Regardless of whether we're setting a new background or not, we want 18140 * to clear the previous drawable. setVisible first while we still have the callback set. 18141 */ 18142 if (mBackground != null) { 18143 if (isAttachedToWindow()) { 18144 mBackground.setVisible(false, false); 18145 } 18146 mBackground.setCallback(null); 18147 unscheduleDrawable(mBackground); 18148 } 18149 18150 if (background != null) { 18151 Rect padding = sThreadLocal.get(); 18152 if (padding == null) { 18153 padding = new Rect(); 18154 sThreadLocal.set(padding); 18155 } 18156 resetResolvedDrawablesInternal(); 18157 background.setLayoutDirection(getLayoutDirection()); 18158 if (background.getPadding(padding)) { 18159 resetResolvedPaddingInternal(); 18160 switch (background.getLayoutDirection()) { 18161 case LAYOUT_DIRECTION_RTL: 18162 mUserPaddingLeftInitial = padding.right; 18163 mUserPaddingRightInitial = padding.left; 18164 internalSetPadding(padding.right, padding.top, padding.left, padding.bottom); 18165 break; 18166 case LAYOUT_DIRECTION_LTR: 18167 default: 18168 mUserPaddingLeftInitial = padding.left; 18169 mUserPaddingRightInitial = padding.right; 18170 internalSetPadding(padding.left, padding.top, padding.right, padding.bottom); 18171 } 18172 mLeftPaddingDefined = false; 18173 mRightPaddingDefined = false; 18174 } 18175 18176 // Compare the minimum sizes of the old Drawable and the new. If there isn't an old or 18177 // if it has a different minimum size, we should layout again 18178 if (mBackground == null 18179 || mBackground.getMinimumHeight() != background.getMinimumHeight() 18180 || mBackground.getMinimumWidth() != background.getMinimumWidth()) { 18181 requestLayout = true; 18182 } 18183 18184 // Set mBackground before we set this as the callback and start making other 18185 // background drawable state change calls. In particular, the setVisible call below 18186 // can result in drawables attempting to start animations or otherwise invalidate, 18187 // which requires the view set as the callback (us) to recognize the drawable as 18188 // belonging to it as per verifyDrawable. 18189 mBackground = background; 18190 if (background.isStateful()) { 18191 background.setState(getDrawableState()); 18192 } 18193 if (isAttachedToWindow()) { 18194 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false); 18195 } 18196 18197 applyBackgroundTint(); 18198 18199 // Set callback last, since the view may still be initializing. 18200 background.setCallback(this); 18201 18202 if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) { 18203 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 18204 requestLayout = true; 18205 } 18206 } else { 18207 /* Remove the background */ 18208 mBackground = null; 18209 if ((mViewFlags & WILL_NOT_DRAW) != 0 18210 && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) { 18211 mPrivateFlags |= PFLAG_SKIP_DRAW; 18212 } 18213 18214 /* 18215 * When the background is set, we try to apply its padding to this 18216 * View. When the background is removed, we don't touch this View's 18217 * padding. This is noted in the Javadocs. Hence, we don't need to 18218 * requestLayout(), the invalidate() below is sufficient. 18219 */ 18220 18221 // The old background's minimum size could have affected this 18222 // View's layout, so let's requestLayout 18223 requestLayout = true; 18224 } 18225 18226 computeOpaqueFlags(); 18227 18228 if (requestLayout) { 18229 requestLayout(); 18230 } 18231 18232 mBackgroundSizeChanged = true; 18233 invalidate(true); 18234 invalidateOutline(); 18235 } 18236 18237 /** 18238 * Gets the background drawable 18239 * 18240 * @return The drawable used as the background for this view, if any. 18241 * 18242 * @see #setBackground(Drawable) 18243 * 18244 * @attr ref android.R.styleable#View_background 18245 */ getBackground()18246 public Drawable getBackground() { 18247 return mBackground; 18248 } 18249 18250 /** 18251 * Applies a tint to the background drawable. Does not modify the current tint 18252 * mode, which is {@link PorterDuff.Mode#SRC_IN} by default. 18253 * <p> 18254 * Subsequent calls to {@link #setBackground(Drawable)} will automatically 18255 * mutate the drawable and apply the specified tint and tint mode using 18256 * {@link Drawable#setTintList(ColorStateList)}. 18257 * 18258 * @param tint the tint to apply, may be {@code null} to clear tint 18259 * 18260 * @attr ref android.R.styleable#View_backgroundTint 18261 * @see #getBackgroundTintList() 18262 * @see Drawable#setTintList(ColorStateList) 18263 */ setBackgroundTintList(@ullable ColorStateList tint)18264 public void setBackgroundTintList(@Nullable ColorStateList tint) { 18265 if (mBackgroundTint == null) { 18266 mBackgroundTint = new TintInfo(); 18267 } 18268 mBackgroundTint.mTintList = tint; 18269 mBackgroundTint.mHasTintList = true; 18270 18271 applyBackgroundTint(); 18272 } 18273 18274 /** 18275 * Return the tint applied to the background drawable, if specified. 18276 * 18277 * @return the tint applied to the background drawable 18278 * @attr ref android.R.styleable#View_backgroundTint 18279 * @see #setBackgroundTintList(ColorStateList) 18280 */ 18281 @Nullable getBackgroundTintList()18282 public ColorStateList getBackgroundTintList() { 18283 return mBackgroundTint != null ? mBackgroundTint.mTintList : null; 18284 } 18285 18286 /** 18287 * Specifies the blending mode used to apply the tint specified by 18288 * {@link #setBackgroundTintList(ColorStateList)}} to the background 18289 * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}. 18290 * 18291 * @param tintMode the blending mode used to apply the tint, may be 18292 * {@code null} to clear tint 18293 * @attr ref android.R.styleable#View_backgroundTintMode 18294 * @see #getBackgroundTintMode() 18295 * @see Drawable#setTintMode(PorterDuff.Mode) 18296 */ setBackgroundTintMode(@ullable PorterDuff.Mode tintMode)18297 public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) { 18298 if (mBackgroundTint == null) { 18299 mBackgroundTint = new TintInfo(); 18300 } 18301 mBackgroundTint.mTintMode = tintMode; 18302 mBackgroundTint.mHasTintMode = true; 18303 18304 applyBackgroundTint(); 18305 } 18306 18307 /** 18308 * Return the blending mode used to apply the tint to the background 18309 * drawable, if specified. 18310 * 18311 * @return the blending mode used to apply the tint to the background 18312 * drawable 18313 * @attr ref android.R.styleable#View_backgroundTintMode 18314 * @see #setBackgroundTintMode(PorterDuff.Mode) 18315 */ 18316 @Nullable getBackgroundTintMode()18317 public PorterDuff.Mode getBackgroundTintMode() { 18318 return mBackgroundTint != null ? mBackgroundTint.mTintMode : null; 18319 } 18320 applyBackgroundTint()18321 private void applyBackgroundTint() { 18322 if (mBackground != null && mBackgroundTint != null) { 18323 final TintInfo tintInfo = mBackgroundTint; 18324 if (tintInfo.mHasTintList || tintInfo.mHasTintMode) { 18325 mBackground = mBackground.mutate(); 18326 18327 if (tintInfo.mHasTintList) { 18328 mBackground.setTintList(tintInfo.mTintList); 18329 } 18330 18331 if (tintInfo.mHasTintMode) { 18332 mBackground.setTintMode(tintInfo.mTintMode); 18333 } 18334 18335 // The drawable (or one of its children) may not have been 18336 // stateful before applying the tint, so let's try again. 18337 if (mBackground.isStateful()) { 18338 mBackground.setState(getDrawableState()); 18339 } 18340 } 18341 } 18342 } 18343 18344 /** 18345 * Returns the drawable used as the foreground of this View. The 18346 * foreground drawable, if non-null, is always drawn on top of the view's content. 18347 * 18348 * @return a Drawable or null if no foreground was set 18349 * 18350 * @see #onDrawForeground(Canvas) 18351 */ getForeground()18352 public Drawable getForeground() { 18353 return mForegroundInfo != null ? mForegroundInfo.mDrawable : null; 18354 } 18355 18356 /** 18357 * Supply a Drawable that is to be rendered on top of all of the content in the view. 18358 * 18359 * @param foreground the Drawable to be drawn on top of the children 18360 * 18361 * @attr ref android.R.styleable#View_foreground 18362 */ setForeground(Drawable foreground)18363 public void setForeground(Drawable foreground) { 18364 if (mForegroundInfo == null) { 18365 if (foreground == null) { 18366 // Nothing to do. 18367 return; 18368 } 18369 mForegroundInfo = new ForegroundInfo(); 18370 } 18371 18372 if (foreground == mForegroundInfo.mDrawable) { 18373 // Nothing to do 18374 return; 18375 } 18376 18377 if (mForegroundInfo.mDrawable != null) { 18378 if (isAttachedToWindow()) { 18379 mForegroundInfo.mDrawable.setVisible(false, false); 18380 } 18381 mForegroundInfo.mDrawable.setCallback(null); 18382 unscheduleDrawable(mForegroundInfo.mDrawable); 18383 } 18384 18385 mForegroundInfo.mDrawable = foreground; 18386 mForegroundInfo.mBoundsChanged = true; 18387 if (foreground != null) { 18388 if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) { 18389 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 18390 } 18391 foreground.setLayoutDirection(getLayoutDirection()); 18392 if (foreground.isStateful()) { 18393 foreground.setState(getDrawableState()); 18394 } 18395 applyForegroundTint(); 18396 if (isAttachedToWindow()) { 18397 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false); 18398 } 18399 // Set callback last, since the view may still be initializing. 18400 foreground.setCallback(this); 18401 } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) { 18402 mPrivateFlags |= PFLAG_SKIP_DRAW; 18403 } 18404 requestLayout(); 18405 invalidate(); 18406 } 18407 18408 /** 18409 * Magic bit used to support features of framework-internal window decor implementation details. 18410 * This used to live exclusively in FrameLayout. 18411 * 18412 * @return true if the foreground should draw inside the padding region or false 18413 * if it should draw inset by the view's padding 18414 * @hide internal use only; only used by FrameLayout and internal screen layouts. 18415 */ isForegroundInsidePadding()18416 public boolean isForegroundInsidePadding() { 18417 return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true; 18418 } 18419 18420 /** 18421 * Describes how the foreground is positioned. 18422 * 18423 * @return foreground gravity. 18424 * 18425 * @see #setForegroundGravity(int) 18426 * 18427 * @attr ref android.R.styleable#View_foregroundGravity 18428 */ getForegroundGravity()18429 public int getForegroundGravity() { 18430 return mForegroundInfo != null ? mForegroundInfo.mGravity 18431 : Gravity.START | Gravity.TOP; 18432 } 18433 18434 /** 18435 * Describes how the foreground is positioned. Defaults to START and TOP. 18436 * 18437 * @param gravity see {@link android.view.Gravity} 18438 * 18439 * @see #getForegroundGravity() 18440 * 18441 * @attr ref android.R.styleable#View_foregroundGravity 18442 */ setForegroundGravity(int gravity)18443 public void setForegroundGravity(int gravity) { 18444 if (mForegroundInfo == null) { 18445 mForegroundInfo = new ForegroundInfo(); 18446 } 18447 18448 if (mForegroundInfo.mGravity != gravity) { 18449 if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) { 18450 gravity |= Gravity.START; 18451 } 18452 18453 if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) { 18454 gravity |= Gravity.TOP; 18455 } 18456 18457 mForegroundInfo.mGravity = gravity; 18458 requestLayout(); 18459 } 18460 } 18461 18462 /** 18463 * Applies a tint to the foreground drawable. Does not modify the current tint 18464 * mode, which is {@link PorterDuff.Mode#SRC_IN} by default. 18465 * <p> 18466 * Subsequent calls to {@link #setForeground(Drawable)} will automatically 18467 * mutate the drawable and apply the specified tint and tint mode using 18468 * {@link Drawable#setTintList(ColorStateList)}. 18469 * 18470 * @param tint the tint to apply, may be {@code null} to clear tint 18471 * 18472 * @attr ref android.R.styleable#View_foregroundTint 18473 * @see #getForegroundTintList() 18474 * @see Drawable#setTintList(ColorStateList) 18475 */ setForegroundTintList(@ullable ColorStateList tint)18476 public void setForegroundTintList(@Nullable ColorStateList tint) { 18477 if (mForegroundInfo == null) { 18478 mForegroundInfo = new ForegroundInfo(); 18479 } 18480 if (mForegroundInfo.mTintInfo == null) { 18481 mForegroundInfo.mTintInfo = new TintInfo(); 18482 } 18483 mForegroundInfo.mTintInfo.mTintList = tint; 18484 mForegroundInfo.mTintInfo.mHasTintList = true; 18485 18486 applyForegroundTint(); 18487 } 18488 18489 /** 18490 * Return the tint applied to the foreground drawable, if specified. 18491 * 18492 * @return the tint applied to the foreground drawable 18493 * @attr ref android.R.styleable#View_foregroundTint 18494 * @see #setForegroundTintList(ColorStateList) 18495 */ 18496 @Nullable getForegroundTintList()18497 public ColorStateList getForegroundTintList() { 18498 return mForegroundInfo != null && mForegroundInfo.mTintInfo != null 18499 ? mForegroundInfo.mTintInfo.mTintList : null; 18500 } 18501 18502 /** 18503 * Specifies the blending mode used to apply the tint specified by 18504 * {@link #setForegroundTintList(ColorStateList)}} to the background 18505 * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}. 18506 * 18507 * @param tintMode the blending mode used to apply the tint, may be 18508 * {@code null} to clear tint 18509 * @attr ref android.R.styleable#View_foregroundTintMode 18510 * @see #getForegroundTintMode() 18511 * @see Drawable#setTintMode(PorterDuff.Mode) 18512 */ setForegroundTintMode(@ullable PorterDuff.Mode tintMode)18513 public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) { 18514 if (mForegroundInfo == null) { 18515 mForegroundInfo = new ForegroundInfo(); 18516 } 18517 if (mForegroundInfo.mTintInfo == null) { 18518 mForegroundInfo.mTintInfo = new TintInfo(); 18519 } 18520 mForegroundInfo.mTintInfo.mTintMode = tintMode; 18521 mForegroundInfo.mTintInfo.mHasTintMode = true; 18522 18523 applyForegroundTint(); 18524 } 18525 18526 /** 18527 * Return the blending mode used to apply the tint to the foreground 18528 * drawable, if specified. 18529 * 18530 * @return the blending mode used to apply the tint to the foreground 18531 * drawable 18532 * @attr ref android.R.styleable#View_foregroundTintMode 18533 * @see #setForegroundTintMode(PorterDuff.Mode) 18534 */ 18535 @Nullable getForegroundTintMode()18536 public PorterDuff.Mode getForegroundTintMode() { 18537 return mForegroundInfo != null && mForegroundInfo.mTintInfo != null 18538 ? mForegroundInfo.mTintInfo.mTintMode : null; 18539 } 18540 applyForegroundTint()18541 private void applyForegroundTint() { 18542 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null 18543 && mForegroundInfo.mTintInfo != null) { 18544 final TintInfo tintInfo = mForegroundInfo.mTintInfo; 18545 if (tintInfo.mHasTintList || tintInfo.mHasTintMode) { 18546 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate(); 18547 18548 if (tintInfo.mHasTintList) { 18549 mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList); 18550 } 18551 18552 if (tintInfo.mHasTintMode) { 18553 mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode); 18554 } 18555 18556 // The drawable (or one of its children) may not have been 18557 // stateful before applying the tint, so let's try again. 18558 if (mForegroundInfo.mDrawable.isStateful()) { 18559 mForegroundInfo.mDrawable.setState(getDrawableState()); 18560 } 18561 } 18562 } 18563 } 18564 18565 /** 18566 * Draw any foreground content for this view. 18567 * 18568 * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground} 18569 * drawable or other view-specific decorations. The foreground is drawn on top of the 18570 * primary view content.</p> 18571 * 18572 * @param canvas canvas to draw into 18573 */ onDrawForeground(Canvas canvas)18574 public void onDrawForeground(Canvas canvas) { 18575 onDrawScrollIndicators(canvas); 18576 onDrawScrollBars(canvas); 18577 18578 final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null; 18579 if (foreground != null) { 18580 if (mForegroundInfo.mBoundsChanged) { 18581 mForegroundInfo.mBoundsChanged = false; 18582 final Rect selfBounds = mForegroundInfo.mSelfBounds; 18583 final Rect overlayBounds = mForegroundInfo.mOverlayBounds; 18584 18585 if (mForegroundInfo.mInsidePadding) { 18586 selfBounds.set(0, 0, getWidth(), getHeight()); 18587 } else { 18588 selfBounds.set(getPaddingLeft(), getPaddingTop(), 18589 getWidth() - getPaddingRight(), getHeight() - getPaddingBottom()); 18590 } 18591 18592 final int ld = getLayoutDirection(); 18593 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(), 18594 foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld); 18595 foreground.setBounds(overlayBounds); 18596 } 18597 18598 foreground.draw(canvas); 18599 } 18600 } 18601 18602 /** 18603 * Sets the padding. The view may add on the space required to display 18604 * the scrollbars, depending on the style and visibility of the scrollbars. 18605 * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop}, 18606 * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different 18607 * from the values set in this call. 18608 * 18609 * @attr ref android.R.styleable#View_padding 18610 * @attr ref android.R.styleable#View_paddingBottom 18611 * @attr ref android.R.styleable#View_paddingLeft 18612 * @attr ref android.R.styleable#View_paddingRight 18613 * @attr ref android.R.styleable#View_paddingTop 18614 * @param left the left padding in pixels 18615 * @param top the top padding in pixels 18616 * @param right the right padding in pixels 18617 * @param bottom the bottom padding in pixels 18618 */ setPadding(int left, int top, int right, int bottom)18619 public void setPadding(int left, int top, int right, int bottom) { 18620 resetResolvedPaddingInternal(); 18621 18622 mUserPaddingStart = UNDEFINED_PADDING; 18623 mUserPaddingEnd = UNDEFINED_PADDING; 18624 18625 mUserPaddingLeftInitial = left; 18626 mUserPaddingRightInitial = right; 18627 18628 mLeftPaddingDefined = true; 18629 mRightPaddingDefined = true; 18630 18631 internalSetPadding(left, top, right, bottom); 18632 } 18633 18634 /** 18635 * @hide 18636 */ internalSetPadding(int left, int top, int right, int bottom)18637 protected void internalSetPadding(int left, int top, int right, int bottom) { 18638 mUserPaddingLeft = left; 18639 mUserPaddingRight = right; 18640 mUserPaddingBottom = bottom; 18641 18642 final int viewFlags = mViewFlags; 18643 boolean changed = false; 18644 18645 // Common case is there are no scroll bars. 18646 if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) { 18647 if ((viewFlags & SCROLLBARS_VERTICAL) != 0) { 18648 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0 18649 ? 0 : getVerticalScrollbarWidth(); 18650 switch (mVerticalScrollbarPosition) { 18651 case SCROLLBAR_POSITION_DEFAULT: 18652 if (isLayoutRtl()) { 18653 left += offset; 18654 } else { 18655 right += offset; 18656 } 18657 break; 18658 case SCROLLBAR_POSITION_RIGHT: 18659 right += offset; 18660 break; 18661 case SCROLLBAR_POSITION_LEFT: 18662 left += offset; 18663 break; 18664 } 18665 } 18666 if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) { 18667 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0 18668 ? 0 : getHorizontalScrollbarHeight(); 18669 } 18670 } 18671 18672 if (mPaddingLeft != left) { 18673 changed = true; 18674 mPaddingLeft = left; 18675 } 18676 if (mPaddingTop != top) { 18677 changed = true; 18678 mPaddingTop = top; 18679 } 18680 if (mPaddingRight != right) { 18681 changed = true; 18682 mPaddingRight = right; 18683 } 18684 if (mPaddingBottom != bottom) { 18685 changed = true; 18686 mPaddingBottom = bottom; 18687 } 18688 18689 if (changed) { 18690 requestLayout(); 18691 invalidateOutline(); 18692 } 18693 } 18694 18695 /** 18696 * Sets the relative padding. The view may add on the space required to display 18697 * the scrollbars, depending on the style and visibility of the scrollbars. 18698 * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop}, 18699 * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different 18700 * from the values set in this call. 18701 * 18702 * @attr ref android.R.styleable#View_padding 18703 * @attr ref android.R.styleable#View_paddingBottom 18704 * @attr ref android.R.styleable#View_paddingStart 18705 * @attr ref android.R.styleable#View_paddingEnd 18706 * @attr ref android.R.styleable#View_paddingTop 18707 * @param start the start padding in pixels 18708 * @param top the top padding in pixels 18709 * @param end the end padding in pixels 18710 * @param bottom the bottom padding in pixels 18711 */ setPaddingRelative(int start, int top, int end, int bottom)18712 public void setPaddingRelative(int start, int top, int end, int bottom) { 18713 resetResolvedPaddingInternal(); 18714 18715 mUserPaddingStart = start; 18716 mUserPaddingEnd = end; 18717 mLeftPaddingDefined = true; 18718 mRightPaddingDefined = true; 18719 18720 switch(getLayoutDirection()) { 18721 case LAYOUT_DIRECTION_RTL: 18722 mUserPaddingLeftInitial = end; 18723 mUserPaddingRightInitial = start; 18724 internalSetPadding(end, top, start, bottom); 18725 break; 18726 case LAYOUT_DIRECTION_LTR: 18727 default: 18728 mUserPaddingLeftInitial = start; 18729 mUserPaddingRightInitial = end; 18730 internalSetPadding(start, top, end, bottom); 18731 } 18732 } 18733 18734 /** 18735 * Returns the top padding of this view. 18736 * 18737 * @return the top padding in pixels 18738 */ getPaddingTop()18739 public int getPaddingTop() { 18740 return mPaddingTop; 18741 } 18742 18743 /** 18744 * Returns the bottom padding of this view. If there are inset and enabled 18745 * scrollbars, this value may include the space required to display the 18746 * scrollbars as well. 18747 * 18748 * @return the bottom padding in pixels 18749 */ getPaddingBottom()18750 public int getPaddingBottom() { 18751 return mPaddingBottom; 18752 } 18753 18754 /** 18755 * Returns the left padding of this view. If there are inset and enabled 18756 * scrollbars, this value may include the space required to display the 18757 * scrollbars as well. 18758 * 18759 * @return the left padding in pixels 18760 */ getPaddingLeft()18761 public int getPaddingLeft() { 18762 if (!isPaddingResolved()) { 18763 resolvePadding(); 18764 } 18765 return mPaddingLeft; 18766 } 18767 18768 /** 18769 * Returns the start padding of this view depending on its resolved layout direction. 18770 * If there are inset and enabled scrollbars, this value may include the space 18771 * required to display the scrollbars as well. 18772 * 18773 * @return the start padding in pixels 18774 */ getPaddingStart()18775 public int getPaddingStart() { 18776 if (!isPaddingResolved()) { 18777 resolvePadding(); 18778 } 18779 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ? 18780 mPaddingRight : mPaddingLeft; 18781 } 18782 18783 /** 18784 * Returns the right padding of this view. If there are inset and enabled 18785 * scrollbars, this value may include the space required to display the 18786 * scrollbars as well. 18787 * 18788 * @return the right padding in pixels 18789 */ getPaddingRight()18790 public int getPaddingRight() { 18791 if (!isPaddingResolved()) { 18792 resolvePadding(); 18793 } 18794 return mPaddingRight; 18795 } 18796 18797 /** 18798 * Returns the end padding of this view depending on its resolved layout direction. 18799 * If there are inset and enabled scrollbars, this value may include the space 18800 * required to display the scrollbars as well. 18801 * 18802 * @return the end padding in pixels 18803 */ getPaddingEnd()18804 public int getPaddingEnd() { 18805 if (!isPaddingResolved()) { 18806 resolvePadding(); 18807 } 18808 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ? 18809 mPaddingLeft : mPaddingRight; 18810 } 18811 18812 /** 18813 * Return if the padding has been set through relative values 18814 * {@link #setPaddingRelative(int, int, int, int)} or through 18815 * @attr ref android.R.styleable#View_paddingStart or 18816 * @attr ref android.R.styleable#View_paddingEnd 18817 * 18818 * @return true if the padding is relative or false if it is not. 18819 */ isPaddingRelative()18820 public boolean isPaddingRelative() { 18821 return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING); 18822 } 18823 computeOpticalInsets()18824 Insets computeOpticalInsets() { 18825 return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets(); 18826 } 18827 18828 /** 18829 * @hide 18830 */ resetPaddingToInitialValues()18831 public void resetPaddingToInitialValues() { 18832 if (isRtlCompatibilityMode()) { 18833 mPaddingLeft = mUserPaddingLeftInitial; 18834 mPaddingRight = mUserPaddingRightInitial; 18835 return; 18836 } 18837 if (isLayoutRtl()) { 18838 mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial; 18839 mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial; 18840 } else { 18841 mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial; 18842 mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial; 18843 } 18844 } 18845 18846 /** 18847 * @hide 18848 */ getOpticalInsets()18849 public Insets getOpticalInsets() { 18850 if (mLayoutInsets == null) { 18851 mLayoutInsets = computeOpticalInsets(); 18852 } 18853 return mLayoutInsets; 18854 } 18855 18856 /** 18857 * Set this view's optical insets. 18858 * 18859 * <p>This method should be treated similarly to setMeasuredDimension and not as a general 18860 * property. Views that compute their own optical insets should call it as part of measurement. 18861 * This method does not request layout. If you are setting optical insets outside of 18862 * measure/layout itself you will want to call requestLayout() yourself. 18863 * </p> 18864 * @hide 18865 */ setOpticalInsets(Insets insets)18866 public void setOpticalInsets(Insets insets) { 18867 mLayoutInsets = insets; 18868 } 18869 18870 /** 18871 * Changes the selection state of this view. A view can be selected or not. 18872 * Note that selection is not the same as focus. Views are typically 18873 * selected in the context of an AdapterView like ListView or GridView; 18874 * the selected view is the view that is highlighted. 18875 * 18876 * @param selected true if the view must be selected, false otherwise 18877 */ setSelected(boolean selected)18878 public void setSelected(boolean selected) { 18879 //noinspection DoubleNegation 18880 if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) { 18881 mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0); 18882 if (!selected) resetPressedState(); 18883 invalidate(true); 18884 refreshDrawableState(); 18885 dispatchSetSelected(selected); 18886 if (selected) { 18887 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); 18888 } else { 18889 notifyViewAccessibilityStateChangedIfNeeded( 18890 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 18891 } 18892 } 18893 } 18894 18895 /** 18896 * Dispatch setSelected to all of this View's children. 18897 * 18898 * @see #setSelected(boolean) 18899 * 18900 * @param selected The new selected state 18901 */ dispatchSetSelected(boolean selected)18902 protected void dispatchSetSelected(boolean selected) { 18903 } 18904 18905 /** 18906 * Indicates the selection state of this view. 18907 * 18908 * @return true if the view is selected, false otherwise 18909 */ 18910 @ViewDebug.ExportedProperty isSelected()18911 public boolean isSelected() { 18912 return (mPrivateFlags & PFLAG_SELECTED) != 0; 18913 } 18914 18915 /** 18916 * Changes the activated state of this view. A view can be activated or not. 18917 * Note that activation is not the same as selection. Selection is 18918 * a transient property, representing the view (hierarchy) the user is 18919 * currently interacting with. Activation is a longer-term state that the 18920 * user can move views in and out of. For example, in a list view with 18921 * single or multiple selection enabled, the views in the current selection 18922 * set are activated. (Um, yeah, we are deeply sorry about the terminology 18923 * here.) The activated state is propagated down to children of the view it 18924 * is set on. 18925 * 18926 * @param activated true if the view must be activated, false otherwise 18927 */ setActivated(boolean activated)18928 public void setActivated(boolean activated) { 18929 //noinspection DoubleNegation 18930 if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) { 18931 mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0); 18932 invalidate(true); 18933 refreshDrawableState(); 18934 dispatchSetActivated(activated); 18935 } 18936 } 18937 18938 /** 18939 * Dispatch setActivated to all of this View's children. 18940 * 18941 * @see #setActivated(boolean) 18942 * 18943 * @param activated The new activated state 18944 */ dispatchSetActivated(boolean activated)18945 protected void dispatchSetActivated(boolean activated) { 18946 } 18947 18948 /** 18949 * Indicates the activation state of this view. 18950 * 18951 * @return true if the view is activated, false otherwise 18952 */ 18953 @ViewDebug.ExportedProperty isActivated()18954 public boolean isActivated() { 18955 return (mPrivateFlags & PFLAG_ACTIVATED) != 0; 18956 } 18957 18958 /** 18959 * Returns the ViewTreeObserver for this view's hierarchy. The view tree 18960 * observer can be used to get notifications when global events, like 18961 * layout, happen. 18962 * 18963 * The returned ViewTreeObserver observer is not guaranteed to remain 18964 * valid for the lifetime of this View. If the caller of this method keeps 18965 * a long-lived reference to ViewTreeObserver, it should always check for 18966 * the return value of {@link ViewTreeObserver#isAlive()}. 18967 * 18968 * @return The ViewTreeObserver for this view's hierarchy. 18969 */ getViewTreeObserver()18970 public ViewTreeObserver getViewTreeObserver() { 18971 if (mAttachInfo != null) { 18972 return mAttachInfo.mTreeObserver; 18973 } 18974 if (mFloatingTreeObserver == null) { 18975 mFloatingTreeObserver = new ViewTreeObserver(); 18976 } 18977 return mFloatingTreeObserver; 18978 } 18979 18980 /** 18981 * <p>Finds the topmost view in the current view hierarchy.</p> 18982 * 18983 * @return the topmost view containing this view 18984 */ getRootView()18985 public View getRootView() { 18986 if (mAttachInfo != null) { 18987 final View v = mAttachInfo.mRootView; 18988 if (v != null) { 18989 return v; 18990 } 18991 } 18992 18993 View parent = this; 18994 18995 while (parent.mParent != null && parent.mParent instanceof View) { 18996 parent = (View) parent.mParent; 18997 } 18998 18999 return parent; 19000 } 19001 19002 /** 19003 * Transforms a motion event from view-local coordinates to on-screen 19004 * coordinates. 19005 * 19006 * @param ev the view-local motion event 19007 * @return false if the transformation could not be applied 19008 * @hide 19009 */ toGlobalMotionEvent(MotionEvent ev)19010 public boolean toGlobalMotionEvent(MotionEvent ev) { 19011 final AttachInfo info = mAttachInfo; 19012 if (info == null) { 19013 return false; 19014 } 19015 19016 final Matrix m = info.mTmpMatrix; 19017 m.set(Matrix.IDENTITY_MATRIX); 19018 transformMatrixToGlobal(m); 19019 ev.transform(m); 19020 return true; 19021 } 19022 19023 /** 19024 * Transforms a motion event from on-screen coordinates to view-local 19025 * coordinates. 19026 * 19027 * @param ev the on-screen motion event 19028 * @return false if the transformation could not be applied 19029 * @hide 19030 */ toLocalMotionEvent(MotionEvent ev)19031 public boolean toLocalMotionEvent(MotionEvent ev) { 19032 final AttachInfo info = mAttachInfo; 19033 if (info == null) { 19034 return false; 19035 } 19036 19037 final Matrix m = info.mTmpMatrix; 19038 m.set(Matrix.IDENTITY_MATRIX); 19039 transformMatrixToLocal(m); 19040 ev.transform(m); 19041 return true; 19042 } 19043 19044 /** 19045 * Modifies the input matrix such that it maps view-local coordinates to 19046 * on-screen coordinates. 19047 * 19048 * @param m input matrix to modify 19049 * @hide 19050 */ transformMatrixToGlobal(Matrix m)19051 public void transformMatrixToGlobal(Matrix m) { 19052 final ViewParent parent = mParent; 19053 if (parent instanceof View) { 19054 final View vp = (View) parent; 19055 vp.transformMatrixToGlobal(m); 19056 m.preTranslate(-vp.mScrollX, -vp.mScrollY); 19057 } else if (parent instanceof ViewRootImpl) { 19058 final ViewRootImpl vr = (ViewRootImpl) parent; 19059 vr.transformMatrixToGlobal(m); 19060 m.preTranslate(0, -vr.mCurScrollY); 19061 } 19062 19063 m.preTranslate(mLeft, mTop); 19064 19065 if (!hasIdentityMatrix()) { 19066 m.preConcat(getMatrix()); 19067 } 19068 } 19069 19070 /** 19071 * Modifies the input matrix such that it maps on-screen coordinates to 19072 * view-local coordinates. 19073 * 19074 * @param m input matrix to modify 19075 * @hide 19076 */ transformMatrixToLocal(Matrix m)19077 public void transformMatrixToLocal(Matrix m) { 19078 final ViewParent parent = mParent; 19079 if (parent instanceof View) { 19080 final View vp = (View) parent; 19081 vp.transformMatrixToLocal(m); 19082 m.postTranslate(vp.mScrollX, vp.mScrollY); 19083 } else if (parent instanceof ViewRootImpl) { 19084 final ViewRootImpl vr = (ViewRootImpl) parent; 19085 vr.transformMatrixToLocal(m); 19086 m.postTranslate(0, vr.mCurScrollY); 19087 } 19088 19089 m.postTranslate(-mLeft, -mTop); 19090 19091 if (!hasIdentityMatrix()) { 19092 m.postConcat(getInverseMatrix()); 19093 } 19094 } 19095 19096 /** 19097 * @hide 19098 */ 19099 @ViewDebug.ExportedProperty(category = "layout", indexMapping = { 19100 @ViewDebug.IntToString(from = 0, to = "x"), 19101 @ViewDebug.IntToString(from = 1, to = "y") 19102 }) getLocationOnScreen()19103 public int[] getLocationOnScreen() { 19104 int[] location = new int[2]; 19105 getLocationOnScreen(location); 19106 return location; 19107 } 19108 19109 /** 19110 * <p>Computes the coordinates of this view on the screen. The argument 19111 * must be an array of two integers. After the method returns, the array 19112 * contains the x and y location in that order.</p> 19113 * 19114 * @param outLocation an array of two integers in which to hold the coordinates 19115 */ getLocationOnScreen(@ize2) int[] outLocation)19116 public void getLocationOnScreen(@Size(2) int[] outLocation) { 19117 getLocationInWindow(outLocation); 19118 19119 final AttachInfo info = mAttachInfo; 19120 if (info != null) { 19121 outLocation[0] += info.mWindowLeft; 19122 outLocation[1] += info.mWindowTop; 19123 } 19124 } 19125 19126 /** 19127 * <p>Computes the coordinates of this view in its window. The argument 19128 * must be an array of two integers. After the method returns, the array 19129 * contains the x and y location in that order.</p> 19130 * 19131 * @param outLocation an array of two integers in which to hold the coordinates 19132 */ getLocationInWindow(@ize2) int[] outLocation)19133 public void getLocationInWindow(@Size(2) int[] outLocation) { 19134 if (outLocation == null || outLocation.length < 2) { 19135 throw new IllegalArgumentException("outLocation must be an array of two integers"); 19136 } 19137 19138 outLocation[0] = 0; 19139 outLocation[1] = 0; 19140 19141 transformFromViewToWindowSpace(outLocation); 19142 } 19143 19144 /** @hide */ transformFromViewToWindowSpace(@ize2) int[] inOutLocation)19145 public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) { 19146 if (inOutLocation == null || inOutLocation.length < 2) { 19147 throw new IllegalArgumentException("inOutLocation must be an array of two integers"); 19148 } 19149 19150 if (mAttachInfo == null) { 19151 // When the view is not attached to a window, this method does not make sense 19152 inOutLocation[0] = inOutLocation[1] = 0; 19153 return; 19154 } 19155 19156 float position[] = mAttachInfo.mTmpTransformLocation; 19157 position[0] = inOutLocation[0]; 19158 position[1] = inOutLocation[1]; 19159 19160 if (!hasIdentityMatrix()) { 19161 getMatrix().mapPoints(position); 19162 } 19163 19164 position[0] += mLeft; 19165 position[1] += mTop; 19166 19167 ViewParent viewParent = mParent; 19168 while (viewParent instanceof View) { 19169 final View view = (View) viewParent; 19170 19171 position[0] -= view.mScrollX; 19172 position[1] -= view.mScrollY; 19173 19174 if (!view.hasIdentityMatrix()) { 19175 view.getMatrix().mapPoints(position); 19176 } 19177 19178 position[0] += view.mLeft; 19179 position[1] += view.mTop; 19180 19181 viewParent = view.mParent; 19182 } 19183 19184 if (viewParent instanceof ViewRootImpl) { 19185 // *cough* 19186 final ViewRootImpl vr = (ViewRootImpl) viewParent; 19187 position[1] -= vr.mCurScrollY; 19188 } 19189 19190 inOutLocation[0] = Math.round(position[0]); 19191 inOutLocation[1] = Math.round(position[1]); 19192 } 19193 19194 /** 19195 * {@hide} 19196 * @param id the id of the view to be found 19197 * @return the view of the specified id, null if cannot be found 19198 */ findViewTraversal(@dRes int id)19199 protected View findViewTraversal(@IdRes int id) { 19200 if (id == mID) { 19201 return this; 19202 } 19203 return null; 19204 } 19205 19206 /** 19207 * {@hide} 19208 * @param tag the tag of the view to be found 19209 * @return the view of specified tag, null if cannot be found 19210 */ findViewWithTagTraversal(Object tag)19211 protected View findViewWithTagTraversal(Object tag) { 19212 if (tag != null && tag.equals(mTag)) { 19213 return this; 19214 } 19215 return null; 19216 } 19217 19218 /** 19219 * {@hide} 19220 * @param predicate The predicate to evaluate. 19221 * @param childToSkip If not null, ignores this child during the recursive traversal. 19222 * @return The first view that matches the predicate or null. 19223 */ findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip)19224 protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) { 19225 if (predicate.apply(this)) { 19226 return this; 19227 } 19228 return null; 19229 } 19230 19231 /** 19232 * Look for a child view with the given id. If this view has the given 19233 * id, return this view. 19234 * 19235 * @param id The id to search for. 19236 * @return The view that has the given id in the hierarchy or null 19237 */ 19238 @Nullable findViewById(@dRes int id)19239 public final View findViewById(@IdRes int id) { 19240 if (id < 0) { 19241 return null; 19242 } 19243 return findViewTraversal(id); 19244 } 19245 19246 /** 19247 * Finds a view by its unuque and stable accessibility id. 19248 * 19249 * @param accessibilityId The searched accessibility id. 19250 * @return The found view. 19251 */ findViewByAccessibilityId(int accessibilityId)19252 final View findViewByAccessibilityId(int accessibilityId) { 19253 if (accessibilityId < 0) { 19254 return null; 19255 } 19256 View view = findViewByAccessibilityIdTraversal(accessibilityId); 19257 if (view != null) { 19258 return view.includeForAccessibility() ? view : null; 19259 } 19260 return null; 19261 } 19262 19263 /** 19264 * Performs the traversal to find a view by its unuque and stable accessibility id. 19265 * 19266 * <strong>Note:</strong>This method does not stop at the root namespace 19267 * boundary since the user can touch the screen at an arbitrary location 19268 * potentially crossing the root namespace bounday which will send an 19269 * accessibility event to accessibility services and they should be able 19270 * to obtain the event source. Also accessibility ids are guaranteed to be 19271 * unique in the window. 19272 * 19273 * @param accessibilityId The accessibility id. 19274 * @return The found view. 19275 * 19276 * @hide 19277 */ findViewByAccessibilityIdTraversal(int accessibilityId)19278 public View findViewByAccessibilityIdTraversal(int accessibilityId) { 19279 if (getAccessibilityViewId() == accessibilityId) { 19280 return this; 19281 } 19282 return null; 19283 } 19284 19285 /** 19286 * Look for a child view with the given tag. If this view has the given 19287 * tag, return this view. 19288 * 19289 * @param tag The tag to search for, using "tag.equals(getTag())". 19290 * @return The View that has the given tag in the hierarchy or null 19291 */ findViewWithTag(Object tag)19292 public final View findViewWithTag(Object tag) { 19293 if (tag == null) { 19294 return null; 19295 } 19296 return findViewWithTagTraversal(tag); 19297 } 19298 19299 /** 19300 * {@hide} 19301 * Look for a child view that matches the specified predicate. 19302 * If this view matches the predicate, return this view. 19303 * 19304 * @param predicate The predicate to evaluate. 19305 * @return The first view that matches the predicate or null. 19306 */ findViewByPredicate(Predicate<View> predicate)19307 public final View findViewByPredicate(Predicate<View> predicate) { 19308 return findViewByPredicateTraversal(predicate, null); 19309 } 19310 19311 /** 19312 * {@hide} 19313 * Look for a child view that matches the specified predicate, 19314 * starting with the specified view and its descendents and then 19315 * recusively searching the ancestors and siblings of that view 19316 * until this view is reached. 19317 * 19318 * This method is useful in cases where the predicate does not match 19319 * a single unique view (perhaps multiple views use the same id) 19320 * and we are trying to find the view that is "closest" in scope to the 19321 * starting view. 19322 * 19323 * @param start The view to start from. 19324 * @param predicate The predicate to evaluate. 19325 * @return The first view that matches the predicate or null. 19326 */ findViewByPredicateInsideOut(View start, Predicate<View> predicate)19327 public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) { 19328 View childToSkip = null; 19329 for (;;) { 19330 View view = start.findViewByPredicateTraversal(predicate, childToSkip); 19331 if (view != null || start == this) { 19332 return view; 19333 } 19334 19335 ViewParent parent = start.getParent(); 19336 if (parent == null || !(parent instanceof View)) { 19337 return null; 19338 } 19339 19340 childToSkip = start; 19341 start = (View) parent; 19342 } 19343 } 19344 19345 /** 19346 * Sets the identifier for this view. The identifier does not have to be 19347 * unique in this view's hierarchy. The identifier should be a positive 19348 * number. 19349 * 19350 * @see #NO_ID 19351 * @see #getId() 19352 * @see #findViewById(int) 19353 * 19354 * @param id a number used to identify the view 19355 * 19356 * @attr ref android.R.styleable#View_id 19357 */ setId(@dRes int id)19358 public void setId(@IdRes int id) { 19359 mID = id; 19360 if (mID == View.NO_ID && mLabelForId != View.NO_ID) { 19361 mID = generateViewId(); 19362 } 19363 } 19364 19365 /** 19366 * {@hide} 19367 * 19368 * @param isRoot true if the view belongs to the root namespace, false 19369 * otherwise 19370 */ setIsRootNamespace(boolean isRoot)19371 public void setIsRootNamespace(boolean isRoot) { 19372 if (isRoot) { 19373 mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE; 19374 } else { 19375 mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE; 19376 } 19377 } 19378 19379 /** 19380 * {@hide} 19381 * 19382 * @return true if the view belongs to the root namespace, false otherwise 19383 */ isRootNamespace()19384 public boolean isRootNamespace() { 19385 return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0; 19386 } 19387 19388 /** 19389 * Returns this view's identifier. 19390 * 19391 * @return a positive integer used to identify the view or {@link #NO_ID} 19392 * if the view has no ID 19393 * 19394 * @see #setId(int) 19395 * @see #findViewById(int) 19396 * @attr ref android.R.styleable#View_id 19397 */ 19398 @IdRes 19399 @ViewDebug.CapturedViewProperty getId()19400 public int getId() { 19401 return mID; 19402 } 19403 19404 /** 19405 * Returns this view's tag. 19406 * 19407 * @return the Object stored in this view as a tag, or {@code null} if not 19408 * set 19409 * 19410 * @see #setTag(Object) 19411 * @see #getTag(int) 19412 */ 19413 @ViewDebug.ExportedProperty getTag()19414 public Object getTag() { 19415 return mTag; 19416 } 19417 19418 /** 19419 * Sets the tag associated with this view. A tag can be used to mark 19420 * a view in its hierarchy and does not have to be unique within the 19421 * hierarchy. Tags can also be used to store data within a view without 19422 * resorting to another data structure. 19423 * 19424 * @param tag an Object to tag the view with 19425 * 19426 * @see #getTag() 19427 * @see #setTag(int, Object) 19428 */ setTag(final Object tag)19429 public void setTag(final Object tag) { 19430 mTag = tag; 19431 } 19432 19433 /** 19434 * Returns the tag associated with this view and the specified key. 19435 * 19436 * @param key The key identifying the tag 19437 * 19438 * @return the Object stored in this view as a tag, or {@code null} if not 19439 * set 19440 * 19441 * @see #setTag(int, Object) 19442 * @see #getTag() 19443 */ getTag(int key)19444 public Object getTag(int key) { 19445 if (mKeyedTags != null) return mKeyedTags.get(key); 19446 return null; 19447 } 19448 19449 /** 19450 * Sets a tag associated with this view and a key. A tag can be used 19451 * to mark a view in its hierarchy and does not have to be unique within 19452 * the hierarchy. Tags can also be used to store data within a view 19453 * without resorting to another data structure. 19454 * 19455 * The specified key should be an id declared in the resources of the 19456 * application to ensure it is unique (see the <a 19457 * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>). 19458 * Keys identified as belonging to 19459 * the Android framework or not associated with any package will cause 19460 * an {@link IllegalArgumentException} to be thrown. 19461 * 19462 * @param key The key identifying the tag 19463 * @param tag An Object to tag the view with 19464 * 19465 * @throws IllegalArgumentException If they specified key is not valid 19466 * 19467 * @see #setTag(Object) 19468 * @see #getTag(int) 19469 */ setTag(int key, final Object tag)19470 public void setTag(int key, final Object tag) { 19471 // If the package id is 0x00 or 0x01, it's either an undefined package 19472 // or a framework id 19473 if ((key >>> 24) < 2) { 19474 throw new IllegalArgumentException("The key must be an application-specific " 19475 + "resource id."); 19476 } 19477 19478 setKeyedTag(key, tag); 19479 } 19480 19481 /** 19482 * Variation of {@link #setTag(int, Object)} that enforces the key to be a 19483 * framework id. 19484 * 19485 * @hide 19486 */ setTagInternal(int key, Object tag)19487 public void setTagInternal(int key, Object tag) { 19488 if ((key >>> 24) != 0x1) { 19489 throw new IllegalArgumentException("The key must be a framework-specific " 19490 + "resource id."); 19491 } 19492 19493 setKeyedTag(key, tag); 19494 } 19495 setKeyedTag(int key, Object tag)19496 private void setKeyedTag(int key, Object tag) { 19497 if (mKeyedTags == null) { 19498 mKeyedTags = new SparseArray<Object>(2); 19499 } 19500 19501 mKeyedTags.put(key, tag); 19502 } 19503 19504 /** 19505 * Prints information about this view in the log output, with the tag 19506 * {@link #VIEW_LOG_TAG}. 19507 * 19508 * @hide 19509 */ debug()19510 public void debug() { 19511 debug(0); 19512 } 19513 19514 /** 19515 * Prints information about this view in the log output, with the tag 19516 * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an 19517 * indentation defined by the <code>depth</code>. 19518 * 19519 * @param depth the indentation level 19520 * 19521 * @hide 19522 */ debug(int depth)19523 protected void debug(int depth) { 19524 String output = debugIndent(depth - 1); 19525 19526 output += "+ " + this; 19527 int id = getId(); 19528 if (id != -1) { 19529 output += " (id=" + id + ")"; 19530 } 19531 Object tag = getTag(); 19532 if (tag != null) { 19533 output += " (tag=" + tag + ")"; 19534 } 19535 Log.d(VIEW_LOG_TAG, output); 19536 19537 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) { 19538 output = debugIndent(depth) + " FOCUSED"; 19539 Log.d(VIEW_LOG_TAG, output); 19540 } 19541 19542 output = debugIndent(depth); 19543 output += "frame={" + mLeft + ", " + mTop + ", " + mRight 19544 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY 19545 + "} "; 19546 Log.d(VIEW_LOG_TAG, output); 19547 19548 if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0 19549 || mPaddingBottom != 0) { 19550 output = debugIndent(depth); 19551 output += "padding={" + mPaddingLeft + ", " + mPaddingTop 19552 + ", " + mPaddingRight + ", " + mPaddingBottom + "}"; 19553 Log.d(VIEW_LOG_TAG, output); 19554 } 19555 19556 output = debugIndent(depth); 19557 output += "mMeasureWidth=" + mMeasuredWidth + 19558 " mMeasureHeight=" + mMeasuredHeight; 19559 Log.d(VIEW_LOG_TAG, output); 19560 19561 output = debugIndent(depth); 19562 if (mLayoutParams == null) { 19563 output += "BAD! no layout params"; 19564 } else { 19565 output = mLayoutParams.debug(output); 19566 } 19567 Log.d(VIEW_LOG_TAG, output); 19568 19569 output = debugIndent(depth); 19570 output += "flags={"; 19571 output += View.printFlags(mViewFlags); 19572 output += "}"; 19573 Log.d(VIEW_LOG_TAG, output); 19574 19575 output = debugIndent(depth); 19576 output += "privateFlags={"; 19577 output += View.printPrivateFlags(mPrivateFlags); 19578 output += "}"; 19579 Log.d(VIEW_LOG_TAG, output); 19580 } 19581 19582 /** 19583 * Creates a string of whitespaces used for indentation. 19584 * 19585 * @param depth the indentation level 19586 * @return a String containing (depth * 2 + 3) * 2 white spaces 19587 * 19588 * @hide 19589 */ debugIndent(int depth)19590 protected static String debugIndent(int depth) { 19591 StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2); 19592 for (int i = 0; i < (depth * 2) + 3; i++) { 19593 spaces.append(' ').append(' '); 19594 } 19595 return spaces.toString(); 19596 } 19597 19598 /** 19599 * <p>Return the offset of the widget's text baseline from the widget's top 19600 * boundary. If this widget does not support baseline alignment, this 19601 * method returns -1. </p> 19602 * 19603 * @return the offset of the baseline within the widget's bounds or -1 19604 * if baseline alignment is not supported 19605 */ 19606 @ViewDebug.ExportedProperty(category = "layout") getBaseline()19607 public int getBaseline() { 19608 return -1; 19609 } 19610 19611 /** 19612 * Returns whether the view hierarchy is currently undergoing a layout pass. This 19613 * information is useful to avoid situations such as calling {@link #requestLayout()} during 19614 * a layout pass. 19615 * 19616 * @return whether the view hierarchy is currently undergoing a layout pass 19617 */ isInLayout()19618 public boolean isInLayout() { 19619 ViewRootImpl viewRoot = getViewRootImpl(); 19620 return (viewRoot != null && viewRoot.isInLayout()); 19621 } 19622 19623 /** 19624 * Call this when something has changed which has invalidated the 19625 * layout of this view. This will schedule a layout pass of the view 19626 * tree. This should not be called while the view hierarchy is currently in a layout 19627 * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the 19628 * end of the current layout pass (and then layout will run again) or after the current 19629 * frame is drawn and the next layout occurs. 19630 * 19631 * <p>Subclasses which override this method should call the superclass method to 19632 * handle possible request-during-layout errors correctly.</p> 19633 */ 19634 @CallSuper requestLayout()19635 public void requestLayout() { 19636 if (mMeasureCache != null) mMeasureCache.clear(); 19637 19638 if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) { 19639 // Only trigger request-during-layout logic if this is the view requesting it, 19640 // not the views in its parent hierarchy 19641 ViewRootImpl viewRoot = getViewRootImpl(); 19642 if (viewRoot != null && viewRoot.isInLayout()) { 19643 if (!viewRoot.requestLayoutDuringLayout(this)) { 19644 return; 19645 } 19646 } 19647 mAttachInfo.mViewRequestingLayout = this; 19648 } 19649 19650 mPrivateFlags |= PFLAG_FORCE_LAYOUT; 19651 mPrivateFlags |= PFLAG_INVALIDATED; 19652 19653 if (mParent != null && !mParent.isLayoutRequested()) { 19654 mParent.requestLayout(); 19655 } 19656 if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) { 19657 mAttachInfo.mViewRequestingLayout = null; 19658 } 19659 } 19660 19661 /** 19662 * Forces this view to be laid out during the next layout pass. 19663 * This method does not call requestLayout() or forceLayout() 19664 * on the parent. 19665 */ forceLayout()19666 public void forceLayout() { 19667 if (mMeasureCache != null) mMeasureCache.clear(); 19668 19669 mPrivateFlags |= PFLAG_FORCE_LAYOUT; 19670 mPrivateFlags |= PFLAG_INVALIDATED; 19671 } 19672 19673 /** 19674 * <p> 19675 * This is called to find out how big a view should be. The parent 19676 * supplies constraint information in the width and height parameters. 19677 * </p> 19678 * 19679 * <p> 19680 * The actual measurement work of a view is performed in 19681 * {@link #onMeasure(int, int)}, called by this method. Therefore, only 19682 * {@link #onMeasure(int, int)} can and must be overridden by subclasses. 19683 * </p> 19684 * 19685 * 19686 * @param widthMeasureSpec Horizontal space requirements as imposed by the 19687 * parent 19688 * @param heightMeasureSpec Vertical space requirements as imposed by the 19689 * parent 19690 * 19691 * @see #onMeasure(int, int) 19692 */ measure(int widthMeasureSpec, int heightMeasureSpec)19693 public final void measure(int widthMeasureSpec, int heightMeasureSpec) { 19694 boolean optical = isLayoutModeOptical(this); 19695 if (optical != isLayoutModeOptical(mParent)) { 19696 Insets insets = getOpticalInsets(); 19697 int oWidth = insets.left + insets.right; 19698 int oHeight = insets.top + insets.bottom; 19699 widthMeasureSpec = MeasureSpec.adjust(widthMeasureSpec, optical ? -oWidth : oWidth); 19700 heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight); 19701 } 19702 19703 // Suppress sign extension for the low bytes 19704 long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL; 19705 if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2); 19706 19707 final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT; 19708 19709 // Optimize layout by avoiding an extra EXACTLY pass when the view is 19710 // already measured as the correct size. In API 23 and below, this 19711 // extra pass is required to make LinearLayout re-distribute weight. 19712 final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec 19713 || heightMeasureSpec != mOldHeightMeasureSpec; 19714 final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY 19715 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY; 19716 final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec) 19717 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec); 19718 final boolean needsLayout = specChanged 19719 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize); 19720 19721 if (forceLayout || needsLayout) { 19722 // first clears the measured dimension flag 19723 mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET; 19724 19725 resolveRtlPropertiesIfNeeded(); 19726 19727 int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key); 19728 if (cacheIndex < 0 || sIgnoreMeasureCache) { 19729 // measure ourselves, this should set the measured dimension flag back 19730 onMeasure(widthMeasureSpec, heightMeasureSpec); 19731 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; 19732 } else { 19733 long value = mMeasureCache.valueAt(cacheIndex); 19734 // Casting a long to int drops the high 32 bits, no mask needed 19735 setMeasuredDimensionRaw((int) (value >> 32), (int) value); 19736 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; 19737 } 19738 19739 // flag not set, setMeasuredDimension() was not invoked, we raise 19740 // an exception to warn the developer 19741 if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) { 19742 throw new IllegalStateException("View with id " + getId() + ": " 19743 + getClass().getName() + "#onMeasure() did not set the" 19744 + " measured dimension by calling" 19745 + " setMeasuredDimension()"); 19746 } 19747 19748 mPrivateFlags |= PFLAG_LAYOUT_REQUIRED; 19749 } 19750 19751 mOldWidthMeasureSpec = widthMeasureSpec; 19752 mOldHeightMeasureSpec = heightMeasureSpec; 19753 19754 mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 | 19755 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension 19756 } 19757 19758 /** 19759 * <p> 19760 * Measure the view and its content to determine the measured width and the 19761 * measured height. This method is invoked by {@link #measure(int, int)} and 19762 * should be overridden by subclasses to provide accurate and efficient 19763 * measurement of their contents. 19764 * </p> 19765 * 19766 * <p> 19767 * <strong>CONTRACT:</strong> When overriding this method, you 19768 * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the 19769 * measured width and height of this view. Failure to do so will trigger an 19770 * <code>IllegalStateException</code>, thrown by 19771 * {@link #measure(int, int)}. Calling the superclass' 19772 * {@link #onMeasure(int, int)} is a valid use. 19773 * </p> 19774 * 19775 * <p> 19776 * The base class implementation of measure defaults to the background size, 19777 * unless a larger size is allowed by the MeasureSpec. Subclasses should 19778 * override {@link #onMeasure(int, int)} to provide better measurements of 19779 * their content. 19780 * </p> 19781 * 19782 * <p> 19783 * If this method is overridden, it is the subclass's responsibility to make 19784 * sure the measured height and width are at least the view's minimum height 19785 * and width ({@link #getSuggestedMinimumHeight()} and 19786 * {@link #getSuggestedMinimumWidth()}). 19787 * </p> 19788 * 19789 * @param widthMeasureSpec horizontal space requirements as imposed by the parent. 19790 * The requirements are encoded with 19791 * {@link android.view.View.MeasureSpec}. 19792 * @param heightMeasureSpec vertical space requirements as imposed by the parent. 19793 * The requirements are encoded with 19794 * {@link android.view.View.MeasureSpec}. 19795 * 19796 * @see #getMeasuredWidth() 19797 * @see #getMeasuredHeight() 19798 * @see #setMeasuredDimension(int, int) 19799 * @see #getSuggestedMinimumHeight() 19800 * @see #getSuggestedMinimumWidth() 19801 * @see android.view.View.MeasureSpec#getMode(int) 19802 * @see android.view.View.MeasureSpec#getSize(int) 19803 */ onMeasure(int widthMeasureSpec, int heightMeasureSpec)19804 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 19805 setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), 19806 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); 19807 } 19808 19809 /** 19810 * <p>This method must be called by {@link #onMeasure(int, int)} to store the 19811 * measured width and measured height. Failing to do so will trigger an 19812 * exception at measurement time.</p> 19813 * 19814 * @param measuredWidth The measured width of this view. May be a complex 19815 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 19816 * {@link #MEASURED_STATE_TOO_SMALL}. 19817 * @param measuredHeight The measured height of this view. May be a complex 19818 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 19819 * {@link #MEASURED_STATE_TOO_SMALL}. 19820 */ setMeasuredDimension(int measuredWidth, int measuredHeight)19821 protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) { 19822 boolean optical = isLayoutModeOptical(this); 19823 if (optical != isLayoutModeOptical(mParent)) { 19824 Insets insets = getOpticalInsets(); 19825 int opticalWidth = insets.left + insets.right; 19826 int opticalHeight = insets.top + insets.bottom; 19827 19828 measuredWidth += optical ? opticalWidth : -opticalWidth; 19829 measuredHeight += optical ? opticalHeight : -opticalHeight; 19830 } 19831 setMeasuredDimensionRaw(measuredWidth, measuredHeight); 19832 } 19833 19834 /** 19835 * Sets the measured dimension without extra processing for things like optical bounds. 19836 * Useful for reapplying consistent values that have already been cooked with adjustments 19837 * for optical bounds, etc. such as those from the measurement cache. 19838 * 19839 * @param measuredWidth The measured width of this view. May be a complex 19840 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 19841 * {@link #MEASURED_STATE_TOO_SMALL}. 19842 * @param measuredHeight The measured height of this view. May be a complex 19843 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 19844 * {@link #MEASURED_STATE_TOO_SMALL}. 19845 */ setMeasuredDimensionRaw(int measuredWidth, int measuredHeight)19846 private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) { 19847 mMeasuredWidth = measuredWidth; 19848 mMeasuredHeight = measuredHeight; 19849 19850 mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET; 19851 } 19852 19853 /** 19854 * Merge two states as returned by {@link #getMeasuredState()}. 19855 * @param curState The current state as returned from a view or the result 19856 * of combining multiple views. 19857 * @param newState The new view state to combine. 19858 * @return Returns a new integer reflecting the combination of the two 19859 * states. 19860 */ combineMeasuredStates(int curState, int newState)19861 public static int combineMeasuredStates(int curState, int newState) { 19862 return curState | newState; 19863 } 19864 19865 /** 19866 * Version of {@link #resolveSizeAndState(int, int, int)} 19867 * returning only the {@link #MEASURED_SIZE_MASK} bits of the result. 19868 */ resolveSize(int size, int measureSpec)19869 public static int resolveSize(int size, int measureSpec) { 19870 return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK; 19871 } 19872 19873 /** 19874 * Utility to reconcile a desired size and state, with constraints imposed 19875 * by a MeasureSpec. Will take the desired size, unless a different size 19876 * is imposed by the constraints. The returned value is a compound integer, 19877 * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and 19878 * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the 19879 * resulting size is smaller than the size the view wants to be. 19880 * 19881 * @param size How big the view wants to be. 19882 * @param measureSpec Constraints imposed by the parent. 19883 * @param childMeasuredState Size information bit mask for the view's 19884 * children. 19885 * @return Size information bit mask as defined by 19886 * {@link #MEASURED_SIZE_MASK} and 19887 * {@link #MEASURED_STATE_TOO_SMALL}. 19888 */ resolveSizeAndState(int size, int measureSpec, int childMeasuredState)19889 public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) { 19890 final int specMode = MeasureSpec.getMode(measureSpec); 19891 final int specSize = MeasureSpec.getSize(measureSpec); 19892 final int result; 19893 switch (specMode) { 19894 case MeasureSpec.AT_MOST: 19895 if (specSize < size) { 19896 result = specSize | MEASURED_STATE_TOO_SMALL; 19897 } else { 19898 result = size; 19899 } 19900 break; 19901 case MeasureSpec.EXACTLY: 19902 result = specSize; 19903 break; 19904 case MeasureSpec.UNSPECIFIED: 19905 default: 19906 result = size; 19907 } 19908 return result | (childMeasuredState & MEASURED_STATE_MASK); 19909 } 19910 19911 /** 19912 * Utility to return a default size. Uses the supplied size if the 19913 * MeasureSpec imposed no constraints. Will get larger if allowed 19914 * by the MeasureSpec. 19915 * 19916 * @param size Default size for this view 19917 * @param measureSpec Constraints imposed by the parent 19918 * @return The size this view should be. 19919 */ getDefaultSize(int size, int measureSpec)19920 public static int getDefaultSize(int size, int measureSpec) { 19921 int result = size; 19922 int specMode = MeasureSpec.getMode(measureSpec); 19923 int specSize = MeasureSpec.getSize(measureSpec); 19924 19925 switch (specMode) { 19926 case MeasureSpec.UNSPECIFIED: 19927 result = size; 19928 break; 19929 case MeasureSpec.AT_MOST: 19930 case MeasureSpec.EXACTLY: 19931 result = specSize; 19932 break; 19933 } 19934 return result; 19935 } 19936 19937 /** 19938 * Returns the suggested minimum height that the view should use. This 19939 * returns the maximum of the view's minimum height 19940 * and the background's minimum height 19941 * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}). 19942 * <p> 19943 * When being used in {@link #onMeasure(int, int)}, the caller should still 19944 * ensure the returned height is within the requirements of the parent. 19945 * 19946 * @return The suggested minimum height of the view. 19947 */ getSuggestedMinimumHeight()19948 protected int getSuggestedMinimumHeight() { 19949 return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight()); 19950 19951 } 19952 19953 /** 19954 * Returns the suggested minimum width that the view should use. This 19955 * returns the maximum of the view's minimum width 19956 * and the background's minimum width 19957 * ({@link android.graphics.drawable.Drawable#getMinimumWidth()}). 19958 * <p> 19959 * When being used in {@link #onMeasure(int, int)}, the caller should still 19960 * ensure the returned width is within the requirements of the parent. 19961 * 19962 * @return The suggested minimum width of the view. 19963 */ getSuggestedMinimumWidth()19964 protected int getSuggestedMinimumWidth() { 19965 return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth()); 19966 } 19967 19968 /** 19969 * Returns the minimum height of the view. 19970 * 19971 * @return the minimum height the view will try to be. 19972 * 19973 * @see #setMinimumHeight(int) 19974 * 19975 * @attr ref android.R.styleable#View_minHeight 19976 */ getMinimumHeight()19977 public int getMinimumHeight() { 19978 return mMinHeight; 19979 } 19980 19981 /** 19982 * Sets the minimum height of the view. It is not guaranteed the view will 19983 * be able to achieve this minimum height (for example, if its parent layout 19984 * constrains it with less available height). 19985 * 19986 * @param minHeight The minimum height the view will try to be. 19987 * 19988 * @see #getMinimumHeight() 19989 * 19990 * @attr ref android.R.styleable#View_minHeight 19991 */ 19992 @RemotableViewMethod setMinimumHeight(int minHeight)19993 public void setMinimumHeight(int minHeight) { 19994 mMinHeight = minHeight; 19995 requestLayout(); 19996 } 19997 19998 /** 19999 * Returns the minimum width of the view. 20000 * 20001 * @return the minimum width the view will try to be. 20002 * 20003 * @see #setMinimumWidth(int) 20004 * 20005 * @attr ref android.R.styleable#View_minWidth 20006 */ getMinimumWidth()20007 public int getMinimumWidth() { 20008 return mMinWidth; 20009 } 20010 20011 /** 20012 * Sets the minimum width of the view. It is not guaranteed the view will 20013 * be able to achieve this minimum width (for example, if its parent layout 20014 * constrains it with less available width). 20015 * 20016 * @param minWidth The minimum width the view will try to be. 20017 * 20018 * @see #getMinimumWidth() 20019 * 20020 * @attr ref android.R.styleable#View_minWidth 20021 */ setMinimumWidth(int minWidth)20022 public void setMinimumWidth(int minWidth) { 20023 mMinWidth = minWidth; 20024 requestLayout(); 20025 20026 } 20027 20028 /** 20029 * Get the animation currently associated with this view. 20030 * 20031 * @return The animation that is currently playing or 20032 * scheduled to play for this view. 20033 */ getAnimation()20034 public Animation getAnimation() { 20035 return mCurrentAnimation; 20036 } 20037 20038 /** 20039 * Start the specified animation now. 20040 * 20041 * @param animation the animation to start now 20042 */ startAnimation(Animation animation)20043 public void startAnimation(Animation animation) { 20044 animation.setStartTime(Animation.START_ON_FIRST_FRAME); 20045 setAnimation(animation); 20046 invalidateParentCaches(); 20047 invalidate(true); 20048 } 20049 20050 /** 20051 * Cancels any animations for this view. 20052 */ clearAnimation()20053 public void clearAnimation() { 20054 if (mCurrentAnimation != null) { 20055 mCurrentAnimation.detach(); 20056 } 20057 mCurrentAnimation = null; 20058 invalidateParentIfNeeded(); 20059 } 20060 20061 /** 20062 * Sets the next animation to play for this view. 20063 * If you want the animation to play immediately, use 20064 * {@link #startAnimation(android.view.animation.Animation)} instead. 20065 * This method provides allows fine-grained 20066 * control over the start time and invalidation, but you 20067 * must make sure that 1) the animation has a start time set, and 20068 * 2) the view's parent (which controls animations on its children) 20069 * will be invalidated when the animation is supposed to 20070 * start. 20071 * 20072 * @param animation The next animation, or null. 20073 */ setAnimation(Animation animation)20074 public void setAnimation(Animation animation) { 20075 mCurrentAnimation = animation; 20076 20077 if (animation != null) { 20078 // If the screen is off assume the animation start time is now instead of 20079 // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time 20080 // would cause the animation to start when the screen turns back on 20081 if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF 20082 && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) { 20083 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis()); 20084 } 20085 animation.reset(); 20086 } 20087 } 20088 20089 /** 20090 * Invoked by a parent ViewGroup to notify the start of the animation 20091 * currently associated with this view. If you override this method, 20092 * always call super.onAnimationStart(); 20093 * 20094 * @see #setAnimation(android.view.animation.Animation) 20095 * @see #getAnimation() 20096 */ 20097 @CallSuper onAnimationStart()20098 protected void onAnimationStart() { 20099 mPrivateFlags |= PFLAG_ANIMATION_STARTED; 20100 } 20101 20102 /** 20103 * Invoked by a parent ViewGroup to notify the end of the animation 20104 * currently associated with this view. If you override this method, 20105 * always call super.onAnimationEnd(); 20106 * 20107 * @see #setAnimation(android.view.animation.Animation) 20108 * @see #getAnimation() 20109 */ 20110 @CallSuper onAnimationEnd()20111 protected void onAnimationEnd() { 20112 mPrivateFlags &= ~PFLAG_ANIMATION_STARTED; 20113 } 20114 20115 /** 20116 * Invoked if there is a Transform that involves alpha. Subclass that can 20117 * draw themselves with the specified alpha should return true, and then 20118 * respect that alpha when their onDraw() is called. If this returns false 20119 * then the view may be redirected to draw into an offscreen buffer to 20120 * fulfill the request, which will look fine, but may be slower than if the 20121 * subclass handles it internally. The default implementation returns false. 20122 * 20123 * @param alpha The alpha (0..255) to apply to the view's drawing 20124 * @return true if the view can draw with the specified alpha. 20125 */ onSetAlpha(int alpha)20126 protected boolean onSetAlpha(int alpha) { 20127 return false; 20128 } 20129 20130 /** 20131 * This is used by the RootView to perform an optimization when 20132 * the view hierarchy contains one or several SurfaceView. 20133 * SurfaceView is always considered transparent, but its children are not, 20134 * therefore all View objects remove themselves from the global transparent 20135 * region (passed as a parameter to this function). 20136 * 20137 * @param region The transparent region for this ViewAncestor (window). 20138 * 20139 * @return Returns true if the effective visibility of the view at this 20140 * point is opaque, regardless of the transparent region; returns false 20141 * if it is possible for underlying windows to be seen behind the view. 20142 * 20143 * {@hide} 20144 */ gatherTransparentRegion(Region region)20145 public boolean gatherTransparentRegion(Region region) { 20146 final AttachInfo attachInfo = mAttachInfo; 20147 if (region != null && attachInfo != null) { 20148 final int pflags = mPrivateFlags; 20149 if ((pflags & PFLAG_SKIP_DRAW) == 0) { 20150 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to 20151 // remove it from the transparent region. 20152 final int[] location = attachInfo.mTransparentLocation; 20153 getLocationInWindow(location); 20154 region.op(location[0], location[1], location[0] + mRight - mLeft, 20155 location[1] + mBottom - mTop, Region.Op.DIFFERENCE); 20156 } else { 20157 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) { 20158 // The SKIP_DRAW flag IS set and the background drawable exists, we remove 20159 // the background drawable's non-transparent parts from this transparent region. 20160 applyDrawableToTransparentRegion(mBackground, region); 20161 } 20162 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null 20163 && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) { 20164 // Similarly, we remove the foreground drawable's non-transparent parts. 20165 applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region); 20166 } 20167 } 20168 } 20169 return true; 20170 } 20171 20172 /** 20173 * Play a sound effect for this view. 20174 * 20175 * <p>The framework will play sound effects for some built in actions, such as 20176 * clicking, but you may wish to play these effects in your widget, 20177 * for instance, for internal navigation. 20178 * 20179 * <p>The sound effect will only be played if sound effects are enabled by the user, and 20180 * {@link #isSoundEffectsEnabled()} is true. 20181 * 20182 * @param soundConstant One of the constants defined in {@link SoundEffectConstants} 20183 */ playSoundEffect(int soundConstant)20184 public void playSoundEffect(int soundConstant) { 20185 if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) { 20186 return; 20187 } 20188 mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant); 20189 } 20190 20191 /** 20192 * BZZZTT!!1! 20193 * 20194 * <p>Provide haptic feedback to the user for this view. 20195 * 20196 * <p>The framework will provide haptic feedback for some built in actions, 20197 * such as long presses, but you may wish to provide feedback for your 20198 * own widget. 20199 * 20200 * <p>The feedback will only be performed if 20201 * {@link #isHapticFeedbackEnabled()} is true. 20202 * 20203 * @param feedbackConstant One of the constants defined in 20204 * {@link HapticFeedbackConstants} 20205 */ performHapticFeedback(int feedbackConstant)20206 public boolean performHapticFeedback(int feedbackConstant) { 20207 return performHapticFeedback(feedbackConstant, 0); 20208 } 20209 20210 /** 20211 * BZZZTT!!1! 20212 * 20213 * <p>Like {@link #performHapticFeedback(int)}, with additional options. 20214 * 20215 * @param feedbackConstant One of the constants defined in 20216 * {@link HapticFeedbackConstants} 20217 * @param flags Additional flags as per {@link HapticFeedbackConstants}. 20218 */ performHapticFeedback(int feedbackConstant, int flags)20219 public boolean performHapticFeedback(int feedbackConstant, int flags) { 20220 if (mAttachInfo == null) { 20221 return false; 20222 } 20223 //noinspection SimplifiableIfStatement 20224 if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0 20225 && !isHapticFeedbackEnabled()) { 20226 return false; 20227 } 20228 return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant, 20229 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0); 20230 } 20231 20232 /** 20233 * Request that the visibility of the status bar or other screen/window 20234 * decorations be changed. 20235 * 20236 * <p>This method is used to put the over device UI into temporary modes 20237 * where the user's attention is focused more on the application content, 20238 * by dimming or hiding surrounding system affordances. This is typically 20239 * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY 20240 * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content 20241 * to be placed behind the action bar (and with these flags other system 20242 * affordances) so that smooth transitions between hiding and showing them 20243 * can be done. 20244 * 20245 * <p>Two representative examples of the use of system UI visibility is 20246 * implementing a content browsing application (like a magazine reader) 20247 * and a video playing application. 20248 * 20249 * <p>The first code shows a typical implementation of a View in a content 20250 * browsing application. In this implementation, the application goes 20251 * into a content-oriented mode by hiding the status bar and action bar, 20252 * and putting the navigation elements into lights out mode. The user can 20253 * then interact with content while in this mode. Such an application should 20254 * provide an easy way for the user to toggle out of the mode (such as to 20255 * check information in the status bar or access notifications). In the 20256 * implementation here, this is done simply by tapping on the content. 20257 * 20258 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java 20259 * content} 20260 * 20261 * <p>This second code sample shows a typical implementation of a View 20262 * in a video playing application. In this situation, while the video is 20263 * playing the application would like to go into a complete full-screen mode, 20264 * to use as much of the display as possible for the video. When in this state 20265 * the user can not interact with the application; the system intercepts 20266 * touching on the screen to pop the UI out of full screen mode. See 20267 * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code. 20268 * 20269 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java 20270 * content} 20271 * 20272 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE}, 20273 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN}, 20274 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, 20275 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE}, 20276 * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}. 20277 */ setSystemUiVisibility(int visibility)20278 public void setSystemUiVisibility(int visibility) { 20279 if (visibility != mSystemUiVisibility) { 20280 mSystemUiVisibility = visibility; 20281 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { 20282 mParent.recomputeViewAttributes(this); 20283 } 20284 } 20285 } 20286 20287 /** 20288 * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested. 20289 * @return Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE}, 20290 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN}, 20291 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, 20292 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE}, 20293 * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}. 20294 */ getSystemUiVisibility()20295 public int getSystemUiVisibility() { 20296 return mSystemUiVisibility; 20297 } 20298 20299 /** 20300 * Returns the current system UI visibility that is currently set for 20301 * the entire window. This is the combination of the 20302 * {@link #setSystemUiVisibility(int)} values supplied by all of the 20303 * views in the window. 20304 */ getWindowSystemUiVisibility()20305 public int getWindowSystemUiVisibility() { 20306 return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0; 20307 } 20308 20309 /** 20310 * Override to find out when the window's requested system UI visibility 20311 * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}. 20312 * This is different from the callbacks received through 20313 * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)} 20314 * in that this is only telling you about the local request of the window, 20315 * not the actual values applied by the system. 20316 */ onWindowSystemUiVisibilityChanged(int visible)20317 public void onWindowSystemUiVisibilityChanged(int visible) { 20318 } 20319 20320 /** 20321 * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down 20322 * the view hierarchy. 20323 */ dispatchWindowSystemUiVisiblityChanged(int visible)20324 public void dispatchWindowSystemUiVisiblityChanged(int visible) { 20325 onWindowSystemUiVisibilityChanged(visible); 20326 } 20327 20328 /** 20329 * Set a listener to receive callbacks when the visibility of the system bar changes. 20330 * @param l The {@link OnSystemUiVisibilityChangeListener} to receive callbacks. 20331 */ setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l)20332 public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) { 20333 getListenerInfo().mOnSystemUiVisibilityChangeListener = l; 20334 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { 20335 mParent.recomputeViewAttributes(this); 20336 } 20337 } 20338 20339 /** 20340 * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down 20341 * the view hierarchy. 20342 */ dispatchSystemUiVisibilityChanged(int visibility)20343 public void dispatchSystemUiVisibilityChanged(int visibility) { 20344 ListenerInfo li = mListenerInfo; 20345 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) { 20346 li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange( 20347 visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK); 20348 } 20349 } 20350 updateLocalSystemUiVisibility(int localValue, int localChanges)20351 boolean updateLocalSystemUiVisibility(int localValue, int localChanges) { 20352 int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges); 20353 if (val != mSystemUiVisibility) { 20354 setSystemUiVisibility(val); 20355 return true; 20356 } 20357 return false; 20358 } 20359 20360 /** @hide */ setDisabledSystemUiVisibility(int flags)20361 public void setDisabledSystemUiVisibility(int flags) { 20362 if (mAttachInfo != null) { 20363 if (mAttachInfo.mDisabledSystemUiVisibility != flags) { 20364 mAttachInfo.mDisabledSystemUiVisibility = flags; 20365 if (mParent != null) { 20366 mParent.recomputeViewAttributes(this); 20367 } 20368 } 20369 } 20370 } 20371 20372 /** 20373 * Creates an image that the system displays during the drag and drop 20374 * operation. This is called a "drag shadow". The default implementation 20375 * for a DragShadowBuilder based on a View returns an image that has exactly the same 20376 * appearance as the given View. The default also positions the center of the drag shadow 20377 * directly under the touch point. If no View is provided (the constructor with no parameters 20378 * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and 20379 * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the 20380 * default is an invisible drag shadow. 20381 * <p> 20382 * You are not required to use the View you provide to the constructor as the basis of the 20383 * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw 20384 * anything you want as the drag shadow. 20385 * </p> 20386 * <p> 20387 * You pass a DragShadowBuilder object to the system when you start the drag. The system 20388 * calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the 20389 * size and position of the drag shadow. It uses this data to construct a 20390 * {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()} 20391 * so that your application can draw the shadow image in the Canvas. 20392 * </p> 20393 * 20394 * <div class="special reference"> 20395 * <h3>Developer Guides</h3> 20396 * <p>For a guide to implementing drag and drop features, read the 20397 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p> 20398 * </div> 20399 */ 20400 public static class DragShadowBuilder { 20401 private final WeakReference<View> mView; 20402 20403 /** 20404 * Constructs a shadow image builder based on a View. By default, the resulting drag 20405 * shadow will have the same appearance and dimensions as the View, with the touch point 20406 * over the center of the View. 20407 * @param view A View. Any View in scope can be used. 20408 */ DragShadowBuilder(View view)20409 public DragShadowBuilder(View view) { 20410 mView = new WeakReference<View>(view); 20411 } 20412 20413 /** 20414 * Construct a shadow builder object with no associated View. This 20415 * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)} 20416 * and {@link #onDrawShadow(Canvas)} methods are also overridden in order 20417 * to supply the drag shadow's dimensions and appearance without 20418 * reference to any View object. If they are not overridden, then the result is an 20419 * invisible drag shadow. 20420 */ DragShadowBuilder()20421 public DragShadowBuilder() { 20422 mView = new WeakReference<View>(null); 20423 } 20424 20425 /** 20426 * Returns the View object that had been passed to the 20427 * {@link #View.DragShadowBuilder(View)} 20428 * constructor. If that View parameter was {@code null} or if the 20429 * {@link #View.DragShadowBuilder()} 20430 * constructor was used to instantiate the builder object, this method will return 20431 * null. 20432 * 20433 * @return The View object associate with this builder object. 20434 */ 20435 @SuppressWarnings({"JavadocReference"}) getView()20436 final public View getView() { 20437 return mView.get(); 20438 } 20439 20440 /** 20441 * Provides the metrics for the shadow image. These include the dimensions of 20442 * the shadow image, and the point within that shadow that should 20443 * be centered under the touch location while dragging. 20444 * <p> 20445 * The default implementation sets the dimensions of the shadow to be the 20446 * same as the dimensions of the View itself and centers the shadow under 20447 * the touch point. 20448 * </p> 20449 * 20450 * @param outShadowSize A {@link android.graphics.Point} containing the width and height 20451 * of the shadow image. Your application must set {@link android.graphics.Point#x} to the 20452 * desired width and must set {@link android.graphics.Point#y} to the desired height of the 20453 * image. 20454 * 20455 * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the 20456 * shadow image that should be underneath the touch point during the drag and drop 20457 * operation. Your application must set {@link android.graphics.Point#x} to the 20458 * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position. 20459 */ onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint)20460 public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) { 20461 final View view = mView.get(); 20462 if (view != null) { 20463 outShadowSize.set(view.getWidth(), view.getHeight()); 20464 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2); 20465 } else { 20466 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view"); 20467 } 20468 } 20469 20470 /** 20471 * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object 20472 * based on the dimensions it received from the 20473 * {@link #onProvideShadowMetrics(Point, Point)} callback. 20474 * 20475 * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image. 20476 */ onDrawShadow(Canvas canvas)20477 public void onDrawShadow(Canvas canvas) { 20478 final View view = mView.get(); 20479 if (view != null) { 20480 view.draw(canvas); 20481 } else { 20482 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view"); 20483 } 20484 } 20485 } 20486 20487 /** 20488 * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) 20489 * startDragAndDrop()} for newer platform versions. 20490 */ startDrag(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)20491 public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder, 20492 Object myLocalState, int flags) { 20493 return startDragAndDrop(data, shadowBuilder, myLocalState, flags); 20494 } 20495 20496 /** 20497 * Starts a drag and drop operation. When your application calls this method, it passes a 20498 * {@link android.view.View.DragShadowBuilder} object to the system. The 20499 * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)} 20500 * to get metrics for the drag shadow, and then calls the object's 20501 * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself. 20502 * <p> 20503 * Once the system has the drag shadow, it begins the drag and drop operation by sending 20504 * drag events to all the View objects in your application that are currently visible. It does 20505 * this either by calling the View object's drag listener (an implementation of 20506 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the 20507 * View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method. 20508 * Both are passed a {@link android.view.DragEvent} object that has a 20509 * {@link android.view.DragEvent#getAction()} value of 20510 * {@link android.view.DragEvent#ACTION_DRAG_STARTED}. 20511 * </p> 20512 * <p> 20513 * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, 20514 * int) startDragAndDrop()} on any attached View object. The View object does not need to be 20515 * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related 20516 * to the View the user selected for dragging. 20517 * </p> 20518 * @param data A {@link android.content.ClipData} object pointing to the data to be 20519 * transferred by the drag and drop operation. 20520 * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the 20521 * drag shadow. 20522 * @param myLocalState An {@link java.lang.Object} containing local data about the drag and 20523 * drop operation. This Object is put into every DragEvent object sent by the system during the 20524 * current drag. 20525 * <p> 20526 * myLocalState is a lightweight mechanism for the sending information from the dragged View 20527 * to the target Views. For example, it can contain flags that differentiate between a 20528 * a copy operation and a move operation. 20529 * </p> 20530 * @param flags Flags that control the drag and drop operation. This can be set to 0 for no 20531 * flags, or any combination of the following: 20532 * <ul> 20533 * <li>{@link #DRAG_FLAG_GLOBAL}</li> 20534 * <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li> 20535 * <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li> 20536 * <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li> 20537 * <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li> 20538 * <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li> 20539 * <li>{@link #DRAG_FLAG_OPAQUE}</li> 20540 * </ul> 20541 * @return {@code true} if the method completes successfully, or 20542 * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to 20543 * do a drag, and so no drag operation is in progress. 20544 */ startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)20545 public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder, 20546 Object myLocalState, int flags) { 20547 if (ViewDebug.DEBUG_DRAG) { 20548 Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags); 20549 } 20550 if (mAttachInfo == null) { 20551 Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view."); 20552 return false; 20553 } 20554 boolean okay = false; 20555 20556 Point shadowSize = new Point(); 20557 Point shadowTouchPoint = new Point(); 20558 shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint); 20559 20560 if ((shadowSize.x < 0) || (shadowSize.y < 0) || 20561 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) { 20562 throw new IllegalStateException("Drag shadow dimensions must not be negative"); 20563 } 20564 20565 if (ViewDebug.DEBUG_DRAG) { 20566 Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y 20567 + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y); 20568 } 20569 if (mAttachInfo.mDragSurface != null) { 20570 mAttachInfo.mDragSurface.release(); 20571 } 20572 mAttachInfo.mDragSurface = new Surface(); 20573 try { 20574 mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow, 20575 flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface); 20576 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" 20577 + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface); 20578 if (mAttachInfo.mDragToken != null) { 20579 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null); 20580 try { 20581 canvas.drawColor(0, PorterDuff.Mode.CLEAR); 20582 shadowBuilder.onDrawShadow(canvas); 20583 } finally { 20584 mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas); 20585 } 20586 20587 final ViewRootImpl root = getViewRootImpl(); 20588 20589 // Cache the local state object for delivery with DragEvents 20590 root.setLocalDragState(myLocalState); 20591 20592 // repurpose 'shadowSize' for the last touch point 20593 root.getLastTouchPoint(shadowSize); 20594 20595 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken, 20596 root.getLastTouchSource(), shadowSize.x, shadowSize.y, 20597 shadowTouchPoint.x, shadowTouchPoint.y, data); 20598 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay); 20599 } 20600 } catch (Exception e) { 20601 Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e); 20602 mAttachInfo.mDragSurface.destroy(); 20603 mAttachInfo.mDragSurface = null; 20604 } 20605 20606 return okay; 20607 } 20608 20609 /** 20610 * Cancels an ongoing drag and drop operation. 20611 * <p> 20612 * A {@link android.view.DragEvent} object with 20613 * {@link android.view.DragEvent#getAction()} value of 20614 * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and 20615 * {@link android.view.DragEvent#getResult()} value of {@code false} 20616 * will be sent to every 20617 * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED} 20618 * even if they are not currently visible. 20619 * </p> 20620 * <p> 20621 * This method can be called on any View in the same window as the View on which 20622 * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop} 20623 * was called. 20624 * </p> 20625 */ cancelDragAndDrop()20626 public final void cancelDragAndDrop() { 20627 if (ViewDebug.DEBUG_DRAG) { 20628 Log.d(VIEW_LOG_TAG, "cancelDragAndDrop"); 20629 } 20630 if (mAttachInfo == null) { 20631 Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view."); 20632 return; 20633 } 20634 if (mAttachInfo.mDragToken != null) { 20635 try { 20636 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken); 20637 } catch (Exception e) { 20638 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e); 20639 } 20640 mAttachInfo.mDragToken = null; 20641 } else { 20642 Log.e(VIEW_LOG_TAG, "No active drag to cancel"); 20643 } 20644 } 20645 20646 /** 20647 * Updates the drag shadow for the ongoing drag and drop operation. 20648 * 20649 * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the 20650 * new drag shadow. 20651 */ updateDragShadow(DragShadowBuilder shadowBuilder)20652 public final void updateDragShadow(DragShadowBuilder shadowBuilder) { 20653 if (ViewDebug.DEBUG_DRAG) { 20654 Log.d(VIEW_LOG_TAG, "updateDragShadow"); 20655 } 20656 if (mAttachInfo == null) { 20657 Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view."); 20658 return; 20659 } 20660 if (mAttachInfo.mDragToken != null) { 20661 try { 20662 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null); 20663 try { 20664 canvas.drawColor(0, PorterDuff.Mode.CLEAR); 20665 shadowBuilder.onDrawShadow(canvas); 20666 } finally { 20667 mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas); 20668 } 20669 } catch (Exception e) { 20670 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e); 20671 } 20672 } else { 20673 Log.e(VIEW_LOG_TAG, "No active drag"); 20674 } 20675 } 20676 20677 /** 20678 * Starts a move from {startX, startY}, the amount of the movement will be the offset 20679 * between {startX, startY} and the new cursor positon. 20680 * @param startX horizontal coordinate where the move started. 20681 * @param startY vertical coordinate where the move started. 20682 * @return whether moving was started successfully. 20683 * @hide 20684 */ startMovingTask(float startX, float startY)20685 public final boolean startMovingTask(float startX, float startY) { 20686 if (ViewDebug.DEBUG_POSITIONING) { 20687 Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}"); 20688 } 20689 try { 20690 return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY); 20691 } catch (RemoteException e) { 20692 Log.e(VIEW_LOG_TAG, "Unable to start moving", e); 20693 } 20694 return false; 20695 } 20696 20697 /** 20698 * Handles drag events sent by the system following a call to 20699 * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int) 20700 * startDragAndDrop()}. 20701 *<p> 20702 * When the system calls this method, it passes a 20703 * {@link android.view.DragEvent} object. A call to 20704 * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined 20705 * in DragEvent. The method uses these to determine what is happening in the drag and drop 20706 * operation. 20707 * @param event The {@link android.view.DragEvent} sent by the system. 20708 * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined 20709 * in DragEvent, indicating the type of drag event represented by this object. 20710 * @return {@code true} if the method was successful, otherwise {@code false}. 20711 * <p> 20712 * The method should return {@code true} in response to an action type of 20713 * {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current 20714 * operation. 20715 * </p> 20716 * <p> 20717 * The method should also return {@code true} in response to an action type of 20718 * {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or 20719 * {@code false} if it didn't. 20720 * </p> 20721 */ onDragEvent(DragEvent event)20722 public boolean onDragEvent(DragEvent event) { 20723 return false; 20724 } 20725 20726 /** 20727 * Detects if this View is enabled and has a drag event listener. 20728 * If both are true, then it calls the drag event listener with the 20729 * {@link android.view.DragEvent} it received. If the drag event listener returns 20730 * {@code true}, then dispatchDragEvent() returns {@code true}. 20731 * <p> 20732 * For all other cases, the method calls the 20733 * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler 20734 * method and returns its result. 20735 * </p> 20736 * <p> 20737 * This ensures that a drag event is always consumed, even if the View does not have a drag 20738 * event listener. However, if the View has a listener and the listener returns true, then 20739 * onDragEvent() is not called. 20740 * </p> 20741 */ dispatchDragEvent(DragEvent event)20742 public boolean dispatchDragEvent(DragEvent event) { 20743 ListenerInfo li = mListenerInfo; 20744 //noinspection SimplifiableIfStatement 20745 if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED 20746 && li.mOnDragListener.onDrag(this, event)) { 20747 return true; 20748 } 20749 return onDragEvent(event); 20750 } 20751 canAcceptDrag()20752 boolean canAcceptDrag() { 20753 return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0; 20754 } 20755 20756 /** 20757 * This needs to be a better API (NOT ON VIEW) before it is exposed. If 20758 * it is ever exposed at all. 20759 * @hide 20760 */ onCloseSystemDialogs(String reason)20761 public void onCloseSystemDialogs(String reason) { 20762 } 20763 20764 /** 20765 * Given a Drawable whose bounds have been set to draw into this view, 20766 * update a Region being computed for 20767 * {@link #gatherTransparentRegion(android.graphics.Region)} so 20768 * that any non-transparent parts of the Drawable are removed from the 20769 * given transparent region. 20770 * 20771 * @param dr The Drawable whose transparency is to be applied to the region. 20772 * @param region A Region holding the current transparency information, 20773 * where any parts of the region that are set are considered to be 20774 * transparent. On return, this region will be modified to have the 20775 * transparency information reduced by the corresponding parts of the 20776 * Drawable that are not transparent. 20777 * {@hide} 20778 */ applyDrawableToTransparentRegion(Drawable dr, Region region)20779 public void applyDrawableToTransparentRegion(Drawable dr, Region region) { 20780 if (DBG) { 20781 Log.i("View", "Getting transparent region for: " + this); 20782 } 20783 final Region r = dr.getTransparentRegion(); 20784 final Rect db = dr.getBounds(); 20785 final AttachInfo attachInfo = mAttachInfo; 20786 if (r != null && attachInfo != null) { 20787 final int w = getRight()-getLeft(); 20788 final int h = getBottom()-getTop(); 20789 if (db.left > 0) { 20790 //Log.i("VIEW", "Drawable left " + db.left + " > view 0"); 20791 r.op(0, 0, db.left, h, Region.Op.UNION); 20792 } 20793 if (db.right < w) { 20794 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w); 20795 r.op(db.right, 0, w, h, Region.Op.UNION); 20796 } 20797 if (db.top > 0) { 20798 //Log.i("VIEW", "Drawable top " + db.top + " > view 0"); 20799 r.op(0, 0, w, db.top, Region.Op.UNION); 20800 } 20801 if (db.bottom < h) { 20802 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h); 20803 r.op(0, db.bottom, w, h, Region.Op.UNION); 20804 } 20805 final int[] location = attachInfo.mTransparentLocation; 20806 getLocationInWindow(location); 20807 r.translate(location[0], location[1]); 20808 region.op(r, Region.Op.INTERSECT); 20809 } else { 20810 region.op(db, Region.Op.DIFFERENCE); 20811 } 20812 } 20813 checkForLongClick(int delayOffset, float x, float y)20814 private void checkForLongClick(int delayOffset, float x, float y) { 20815 if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) { 20816 mHasPerformedLongPress = false; 20817 20818 if (mPendingCheckForLongPress == null) { 20819 mPendingCheckForLongPress = new CheckForLongPress(); 20820 } 20821 mPendingCheckForLongPress.setAnchor(x, y); 20822 mPendingCheckForLongPress.rememberWindowAttachCount(); 20823 postDelayed(mPendingCheckForLongPress, 20824 ViewConfiguration.getLongPressTimeout() - delayOffset); 20825 } 20826 } 20827 20828 /** 20829 * Inflate a view from an XML resource. This convenience method wraps the {@link 20830 * LayoutInflater} class, which provides a full range of options for view inflation. 20831 * 20832 * @param context The Context object for your activity or application. 20833 * @param resource The resource ID to inflate 20834 * @param root A view group that will be the parent. Used to properly inflate the 20835 * layout_* parameters. 20836 * @see LayoutInflater 20837 */ inflate(Context context, @LayoutRes int resource, ViewGroup root)20838 public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) { 20839 LayoutInflater factory = LayoutInflater.from(context); 20840 return factory.inflate(resource, root); 20841 } 20842 20843 /** 20844 * Scroll the view with standard behavior for scrolling beyond the normal 20845 * content boundaries. Views that call this method should override 20846 * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the 20847 * results of an over-scroll operation. 20848 * 20849 * Views can use this method to handle any touch or fling-based scrolling. 20850 * 20851 * @param deltaX Change in X in pixels 20852 * @param deltaY Change in Y in pixels 20853 * @param scrollX Current X scroll value in pixels before applying deltaX 20854 * @param scrollY Current Y scroll value in pixels before applying deltaY 20855 * @param scrollRangeX Maximum content scroll range along the X axis 20856 * @param scrollRangeY Maximum content scroll range along the Y axis 20857 * @param maxOverScrollX Number of pixels to overscroll by in either direction 20858 * along the X axis. 20859 * @param maxOverScrollY Number of pixels to overscroll by in either direction 20860 * along the Y axis. 20861 * @param isTouchEvent true if this scroll operation is the result of a touch event. 20862 * @return true if scrolling was clamped to an over-scroll boundary along either 20863 * axis, false otherwise. 20864 */ 20865 @SuppressWarnings({"UnusedParameters"}) overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent)20866 protected boolean overScrollBy(int deltaX, int deltaY, 20867 int scrollX, int scrollY, 20868 int scrollRangeX, int scrollRangeY, 20869 int maxOverScrollX, int maxOverScrollY, 20870 boolean isTouchEvent) { 20871 final int overScrollMode = mOverScrollMode; 20872 final boolean canScrollHorizontal = 20873 computeHorizontalScrollRange() > computeHorizontalScrollExtent(); 20874 final boolean canScrollVertical = 20875 computeVerticalScrollRange() > computeVerticalScrollExtent(); 20876 final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS || 20877 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal); 20878 final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS || 20879 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical); 20880 20881 int newScrollX = scrollX + deltaX; 20882 if (!overScrollHorizontal) { 20883 maxOverScrollX = 0; 20884 } 20885 20886 int newScrollY = scrollY + deltaY; 20887 if (!overScrollVertical) { 20888 maxOverScrollY = 0; 20889 } 20890 20891 // Clamp values if at the limits and record 20892 final int left = -maxOverScrollX; 20893 final int right = maxOverScrollX + scrollRangeX; 20894 final int top = -maxOverScrollY; 20895 final int bottom = maxOverScrollY + scrollRangeY; 20896 20897 boolean clampedX = false; 20898 if (newScrollX > right) { 20899 newScrollX = right; 20900 clampedX = true; 20901 } else if (newScrollX < left) { 20902 newScrollX = left; 20903 clampedX = true; 20904 } 20905 20906 boolean clampedY = false; 20907 if (newScrollY > bottom) { 20908 newScrollY = bottom; 20909 clampedY = true; 20910 } else if (newScrollY < top) { 20911 newScrollY = top; 20912 clampedY = true; 20913 } 20914 20915 onOverScrolled(newScrollX, newScrollY, clampedX, clampedY); 20916 20917 return clampedX || clampedY; 20918 } 20919 20920 /** 20921 * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to 20922 * respond to the results of an over-scroll operation. 20923 * 20924 * @param scrollX New X scroll value in pixels 20925 * @param scrollY New Y scroll value in pixels 20926 * @param clampedX True if scrollX was clamped to an over-scroll boundary 20927 * @param clampedY True if scrollY was clamped to an over-scroll boundary 20928 */ onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY)20929 protected void onOverScrolled(int scrollX, int scrollY, 20930 boolean clampedX, boolean clampedY) { 20931 // Intentionally empty. 20932 } 20933 20934 /** 20935 * Returns the over-scroll mode for this view. The result will be 20936 * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS} 20937 * (allow over-scrolling only if the view content is larger than the container), 20938 * or {@link #OVER_SCROLL_NEVER}. 20939 * 20940 * @return This view's over-scroll mode. 20941 */ getOverScrollMode()20942 public int getOverScrollMode() { 20943 return mOverScrollMode; 20944 } 20945 20946 /** 20947 * Set the over-scroll mode for this view. Valid over-scroll modes are 20948 * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS} 20949 * (allow over-scrolling only if the view content is larger than the container), 20950 * or {@link #OVER_SCROLL_NEVER}. 20951 * 20952 * Setting the over-scroll mode of a view will have an effect only if the 20953 * view is capable of scrolling. 20954 * 20955 * @param overScrollMode The new over-scroll mode for this view. 20956 */ setOverScrollMode(int overScrollMode)20957 public void setOverScrollMode(int overScrollMode) { 20958 if (overScrollMode != OVER_SCROLL_ALWAYS && 20959 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS && 20960 overScrollMode != OVER_SCROLL_NEVER) { 20961 throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode); 20962 } 20963 mOverScrollMode = overScrollMode; 20964 } 20965 20966 /** 20967 * Enable or disable nested scrolling for this view. 20968 * 20969 * <p>If this property is set to true the view will be permitted to initiate nested 20970 * scrolling operations with a compatible parent view in the current hierarchy. If this 20971 * view does not implement nested scrolling this will have no effect. Disabling nested scrolling 20972 * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping} 20973 * the nested scroll.</p> 20974 * 20975 * @param enabled true to enable nested scrolling, false to disable 20976 * 20977 * @see #isNestedScrollingEnabled() 20978 */ setNestedScrollingEnabled(boolean enabled)20979 public void setNestedScrollingEnabled(boolean enabled) { 20980 if (enabled) { 20981 mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED; 20982 } else { 20983 stopNestedScroll(); 20984 mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED; 20985 } 20986 } 20987 20988 /** 20989 * Returns true if nested scrolling is enabled for this view. 20990 * 20991 * <p>If nested scrolling is enabled and this View class implementation supports it, 20992 * this view will act as a nested scrolling child view when applicable, forwarding data 20993 * about the scroll operation in progress to a compatible and cooperating nested scrolling 20994 * parent.</p> 20995 * 20996 * @return true if nested scrolling is enabled 20997 * 20998 * @see #setNestedScrollingEnabled(boolean) 20999 */ isNestedScrollingEnabled()21000 public boolean isNestedScrollingEnabled() { 21001 return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) == 21002 PFLAG3_NESTED_SCROLLING_ENABLED; 21003 } 21004 21005 /** 21006 * Begin a nestable scroll operation along the given axes. 21007 * 21008 * <p>A view starting a nested scroll promises to abide by the following contract:</p> 21009 * 21010 * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case 21011 * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}. 21012 * In the case of touch scrolling the nested scroll will be terminated automatically in 21013 * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}. 21014 * In the event of programmatic scrolling the caller must explicitly call 21015 * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p> 21016 * 21017 * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found. 21018 * If it returns false the caller may ignore the rest of this contract until the next scroll. 21019 * Calling startNestedScroll while a nested scroll is already in progress will return true.</p> 21020 * 21021 * <p>At each incremental step of the scroll the caller should invoke 21022 * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} 21023 * once it has calculated the requested scrolling delta. If it returns true the nested scrolling 21024 * parent at least partially consumed the scroll and the caller should adjust the amount it 21025 * scrolls by.</p> 21026 * 21027 * <p>After applying the remainder of the scroll delta the caller should invoke 21028 * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing 21029 * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat 21030 * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}. 21031 * </p> 21032 * 21033 * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or 21034 * {@link #SCROLL_AXIS_VERTICAL}. 21035 * @return true if a cooperative parent was found and nested scrolling has been enabled for 21036 * the current gesture. 21037 * 21038 * @see #stopNestedScroll() 21039 * @see #dispatchNestedPreScroll(int, int, int[], int[]) 21040 * @see #dispatchNestedScroll(int, int, int, int, int[]) 21041 */ startNestedScroll(int axes)21042 public boolean startNestedScroll(int axes) { 21043 if (hasNestedScrollingParent()) { 21044 // Already in progress 21045 return true; 21046 } 21047 if (isNestedScrollingEnabled()) { 21048 ViewParent p = getParent(); 21049 View child = this; 21050 while (p != null) { 21051 try { 21052 if (p.onStartNestedScroll(child, this, axes)) { 21053 mNestedScrollingParent = p; 21054 p.onNestedScrollAccepted(child, this, axes); 21055 return true; 21056 } 21057 } catch (AbstractMethodError e) { 21058 Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " + 21059 "method onStartNestedScroll", e); 21060 // Allow the search upward to continue 21061 } 21062 if (p instanceof View) { 21063 child = (View) p; 21064 } 21065 p = p.getParent(); 21066 } 21067 } 21068 return false; 21069 } 21070 21071 /** 21072 * Stop a nested scroll in progress. 21073 * 21074 * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p> 21075 * 21076 * @see #startNestedScroll(int) 21077 */ stopNestedScroll()21078 public void stopNestedScroll() { 21079 if (mNestedScrollingParent != null) { 21080 mNestedScrollingParent.onStopNestedScroll(this); 21081 mNestedScrollingParent = null; 21082 } 21083 } 21084 21085 /** 21086 * Returns true if this view has a nested scrolling parent. 21087 * 21088 * <p>The presence of a nested scrolling parent indicates that this view has initiated 21089 * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p> 21090 * 21091 * @return whether this view has a nested scrolling parent 21092 */ hasNestedScrollingParent()21093 public boolean hasNestedScrollingParent() { 21094 return mNestedScrollingParent != null; 21095 } 21096 21097 /** 21098 * Dispatch one step of a nested scroll in progress. 21099 * 21100 * <p>Implementations of views that support nested scrolling should call this to report 21101 * info about a scroll in progress to the current nested scrolling parent. If a nested scroll 21102 * is not currently in progress or nested scrolling is not 21103 * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p> 21104 * 21105 * <p>Compatible View implementations should also call 21106 * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before 21107 * consuming a component of the scroll event themselves.</p> 21108 * 21109 * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step 21110 * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step 21111 * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view 21112 * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view 21113 * @param offsetInWindow Optional. If not null, on return this will contain the offset 21114 * in local view coordinates of this view from before this operation 21115 * to after it completes. View implementations may use this to adjust 21116 * expected input coordinate tracking. 21117 * @return true if the event was dispatched, false if it could not be dispatched. 21118 * @see #dispatchNestedPreScroll(int, int, int[], int[]) 21119 */ dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow)21120 public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, 21121 int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) { 21122 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { 21123 if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) { 21124 int startX = 0; 21125 int startY = 0; 21126 if (offsetInWindow != null) { 21127 getLocationInWindow(offsetInWindow); 21128 startX = offsetInWindow[0]; 21129 startY = offsetInWindow[1]; 21130 } 21131 21132 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed, 21133 dxUnconsumed, dyUnconsumed); 21134 21135 if (offsetInWindow != null) { 21136 getLocationInWindow(offsetInWindow); 21137 offsetInWindow[0] -= startX; 21138 offsetInWindow[1] -= startY; 21139 } 21140 return true; 21141 } else if (offsetInWindow != null) { 21142 // No motion, no dispatch. Keep offsetInWindow up to date. 21143 offsetInWindow[0] = 0; 21144 offsetInWindow[1] = 0; 21145 } 21146 } 21147 return false; 21148 } 21149 21150 /** 21151 * Dispatch one step of a nested scroll in progress before this view consumes any portion of it. 21152 * 21153 * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch. 21154 * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested 21155 * scrolling operation to consume some or all of the scroll operation before the child view 21156 * consumes it.</p> 21157 * 21158 * @param dx Horizontal scroll distance in pixels 21159 * @param dy Vertical scroll distance in pixels 21160 * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx 21161 * and consumed[1] the consumed dy. 21162 * @param offsetInWindow Optional. If not null, on return this will contain the offset 21163 * in local view coordinates of this view from before this operation 21164 * to after it completes. View implementations may use this to adjust 21165 * expected input coordinate tracking. 21166 * @return true if the parent consumed some or all of the scroll delta 21167 * @see #dispatchNestedScroll(int, int, int, int, int[]) 21168 */ dispatchNestedPreScroll(int dx, int dy, @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow)21169 public boolean dispatchNestedPreScroll(int dx, int dy, 21170 @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) { 21171 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { 21172 if (dx != 0 || dy != 0) { 21173 int startX = 0; 21174 int startY = 0; 21175 if (offsetInWindow != null) { 21176 getLocationInWindow(offsetInWindow); 21177 startX = offsetInWindow[0]; 21178 startY = offsetInWindow[1]; 21179 } 21180 21181 if (consumed == null) { 21182 if (mTempNestedScrollConsumed == null) { 21183 mTempNestedScrollConsumed = new int[2]; 21184 } 21185 consumed = mTempNestedScrollConsumed; 21186 } 21187 consumed[0] = 0; 21188 consumed[1] = 0; 21189 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed); 21190 21191 if (offsetInWindow != null) { 21192 getLocationInWindow(offsetInWindow); 21193 offsetInWindow[0] -= startX; 21194 offsetInWindow[1] -= startY; 21195 } 21196 return consumed[0] != 0 || consumed[1] != 0; 21197 } else if (offsetInWindow != null) { 21198 offsetInWindow[0] = 0; 21199 offsetInWindow[1] = 0; 21200 } 21201 } 21202 return false; 21203 } 21204 21205 /** 21206 * Dispatch a fling to a nested scrolling parent. 21207 * 21208 * <p>This method should be used to indicate that a nested scrolling child has detected 21209 * suitable conditions for a fling. Generally this means that a touch scroll has ended with a 21210 * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds 21211 * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity} 21212 * along a scrollable axis.</p> 21213 * 21214 * <p>If a nested scrolling child view would normally fling but it is at the edge of 21215 * its own content, it can use this method to delegate the fling to its nested scrolling 21216 * parent instead. The parent may optionally consume the fling or observe a child fling.</p> 21217 * 21218 * @param velocityX Horizontal fling velocity in pixels per second 21219 * @param velocityY Vertical fling velocity in pixels per second 21220 * @param consumed true if the child consumed the fling, false otherwise 21221 * @return true if the nested scrolling parent consumed or otherwise reacted to the fling 21222 */ dispatchNestedFling(float velocityX, float velocityY, boolean consumed)21223 public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { 21224 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { 21225 return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed); 21226 } 21227 return false; 21228 } 21229 21230 /** 21231 * Dispatch a fling to a nested scrolling parent before it is processed by this view. 21232 * 21233 * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch 21234 * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code> 21235 * offsets an opportunity for the parent view in a nested fling to fully consume the fling 21236 * before the child view consumes it. If this method returns <code>true</code>, a nested 21237 * parent view consumed the fling and this view should not scroll as a result.</p> 21238 * 21239 * <p>For a better user experience, only one view in a nested scrolling chain should consume 21240 * the fling at a time. If a parent view consumed the fling this method will return false. 21241 * Custom view implementations should account for this in two ways:</p> 21242 * 21243 * <ul> 21244 * <li>If a custom view is paged and needs to settle to a fixed page-point, do not 21245 * call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid 21246 * position regardless.</li> 21247 * <li>If a nested parent does consume the fling, this view should not scroll at all, 21248 * even to settle back to a valid idle position.</li> 21249 * </ul> 21250 * 21251 * <p>Views should also not offer fling velocities to nested parent views along an axis 21252 * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView} 21253 * should not offer a horizontal fling velocity to its parents since scrolling along that 21254 * axis is not permitted and carrying velocity along that motion does not make sense.</p> 21255 * 21256 * @param velocityX Horizontal fling velocity in pixels per second 21257 * @param velocityY Vertical fling velocity in pixels per second 21258 * @return true if a nested scrolling parent consumed the fling 21259 */ dispatchNestedPreFling(float velocityX, float velocityY)21260 public boolean dispatchNestedPreFling(float velocityX, float velocityY) { 21261 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { 21262 return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY); 21263 } 21264 return false; 21265 } 21266 21267 /** 21268 * Gets a scale factor that determines the distance the view should scroll 21269 * vertically in response to {@link MotionEvent#ACTION_SCROLL}. 21270 * @return The vertical scroll scale factor. 21271 * @hide 21272 */ getVerticalScrollFactor()21273 protected float getVerticalScrollFactor() { 21274 if (mVerticalScrollFactor == 0) { 21275 TypedValue outValue = new TypedValue(); 21276 if (!mContext.getTheme().resolveAttribute( 21277 com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) { 21278 throw new IllegalStateException( 21279 "Expected theme to define listPreferredItemHeight."); 21280 } 21281 mVerticalScrollFactor = outValue.getDimension( 21282 mContext.getResources().getDisplayMetrics()); 21283 } 21284 return mVerticalScrollFactor; 21285 } 21286 21287 /** 21288 * Gets a scale factor that determines the distance the view should scroll 21289 * horizontally in response to {@link MotionEvent#ACTION_SCROLL}. 21290 * @return The horizontal scroll scale factor. 21291 * @hide 21292 */ getHorizontalScrollFactor()21293 protected float getHorizontalScrollFactor() { 21294 // TODO: Should use something else. 21295 return getVerticalScrollFactor(); 21296 } 21297 21298 /** 21299 * Return the value specifying the text direction or policy that was set with 21300 * {@link #setTextDirection(int)}. 21301 * 21302 * @return the defined text direction. It can be one of: 21303 * 21304 * {@link #TEXT_DIRECTION_INHERIT}, 21305 * {@link #TEXT_DIRECTION_FIRST_STRONG}, 21306 * {@link #TEXT_DIRECTION_ANY_RTL}, 21307 * {@link #TEXT_DIRECTION_LTR}, 21308 * {@link #TEXT_DIRECTION_RTL}, 21309 * {@link #TEXT_DIRECTION_LOCALE}, 21310 * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR}, 21311 * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL} 21312 * 21313 * @attr ref android.R.styleable#View_textDirection 21314 * 21315 * @hide 21316 */ 21317 @ViewDebug.ExportedProperty(category = "text", mapping = { 21318 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"), 21319 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"), 21320 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"), 21321 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"), 21322 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"), 21323 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"), 21324 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"), 21325 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL") 21326 }) getRawTextDirection()21327 public int getRawTextDirection() { 21328 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT; 21329 } 21330 21331 /** 21332 * Set the text direction. 21333 * 21334 * @param textDirection the direction to set. Should be one of: 21335 * 21336 * {@link #TEXT_DIRECTION_INHERIT}, 21337 * {@link #TEXT_DIRECTION_FIRST_STRONG}, 21338 * {@link #TEXT_DIRECTION_ANY_RTL}, 21339 * {@link #TEXT_DIRECTION_LTR}, 21340 * {@link #TEXT_DIRECTION_RTL}, 21341 * {@link #TEXT_DIRECTION_LOCALE} 21342 * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR}, 21343 * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}, 21344 * 21345 * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution 21346 * proceeds up the parent chain of the view to get the value. If there is no parent, then it will 21347 * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}. 21348 * 21349 * @attr ref android.R.styleable#View_textDirection 21350 */ setTextDirection(int textDirection)21351 public void setTextDirection(int textDirection) { 21352 if (getRawTextDirection() != textDirection) { 21353 // Reset the current text direction and the resolved one 21354 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK; 21355 resetResolvedTextDirection(); 21356 // Set the new text direction 21357 mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK); 21358 // Do resolution 21359 resolveTextDirection(); 21360 // Notify change 21361 onRtlPropertiesChanged(getLayoutDirection()); 21362 // Refresh 21363 requestLayout(); 21364 invalidate(true); 21365 } 21366 } 21367 21368 /** 21369 * Return the resolved text direction. 21370 * 21371 * @return the resolved text direction. Returns one of: 21372 * 21373 * {@link #TEXT_DIRECTION_FIRST_STRONG}, 21374 * {@link #TEXT_DIRECTION_ANY_RTL}, 21375 * {@link #TEXT_DIRECTION_LTR}, 21376 * {@link #TEXT_DIRECTION_RTL}, 21377 * {@link #TEXT_DIRECTION_LOCALE}, 21378 * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR}, 21379 * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL} 21380 * 21381 * @attr ref android.R.styleable#View_textDirection 21382 */ 21383 @ViewDebug.ExportedProperty(category = "text", mapping = { 21384 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"), 21385 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"), 21386 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"), 21387 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"), 21388 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"), 21389 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"), 21390 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"), 21391 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL") 21392 }) getTextDirection()21393 public int getTextDirection() { 21394 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT; 21395 } 21396 21397 /** 21398 * Resolve the text direction. 21399 * 21400 * @return true if resolution has been done, false otherwise. 21401 * 21402 * @hide 21403 */ resolveTextDirection()21404 public boolean resolveTextDirection() { 21405 // Reset any previous text direction resolution 21406 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK); 21407 21408 if (hasRtlSupport()) { 21409 // Set resolved text direction flag depending on text direction flag 21410 final int textDirection = getRawTextDirection(); 21411 switch(textDirection) { 21412 case TEXT_DIRECTION_INHERIT: 21413 if (!canResolveTextDirection()) { 21414 // We cannot do the resolution if there is no parent, so use the default one 21415 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 21416 // Resolution will need to happen again later 21417 return false; 21418 } 21419 21420 // Parent has not yet resolved, so we still return the default 21421 try { 21422 if (!mParent.isTextDirectionResolved()) { 21423 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 21424 // Resolution will need to happen again later 21425 return false; 21426 } 21427 } catch (AbstractMethodError e) { 21428 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 21429 " does not fully implement ViewParent", e); 21430 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED | 21431 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 21432 return true; 21433 } 21434 21435 // Set current resolved direction to the same value as the parent's one 21436 int parentResolvedDirection; 21437 try { 21438 parentResolvedDirection = mParent.getTextDirection(); 21439 } catch (AbstractMethodError e) { 21440 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 21441 " does not fully implement ViewParent", e); 21442 parentResolvedDirection = TEXT_DIRECTION_LTR; 21443 } 21444 switch (parentResolvedDirection) { 21445 case TEXT_DIRECTION_FIRST_STRONG: 21446 case TEXT_DIRECTION_ANY_RTL: 21447 case TEXT_DIRECTION_LTR: 21448 case TEXT_DIRECTION_RTL: 21449 case TEXT_DIRECTION_LOCALE: 21450 case TEXT_DIRECTION_FIRST_STRONG_LTR: 21451 case TEXT_DIRECTION_FIRST_STRONG_RTL: 21452 mPrivateFlags2 |= 21453 (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT); 21454 break; 21455 default: 21456 // Default resolved direction is "first strong" heuristic 21457 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 21458 } 21459 break; 21460 case TEXT_DIRECTION_FIRST_STRONG: 21461 case TEXT_DIRECTION_ANY_RTL: 21462 case TEXT_DIRECTION_LTR: 21463 case TEXT_DIRECTION_RTL: 21464 case TEXT_DIRECTION_LOCALE: 21465 case TEXT_DIRECTION_FIRST_STRONG_LTR: 21466 case TEXT_DIRECTION_FIRST_STRONG_RTL: 21467 // Resolved direction is the same as text direction 21468 mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT); 21469 break; 21470 default: 21471 // Default resolved direction is "first strong" heuristic 21472 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 21473 } 21474 } else { 21475 // Default resolved direction is "first strong" heuristic 21476 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 21477 } 21478 21479 // Set to resolved 21480 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED; 21481 return true; 21482 } 21483 21484 /** 21485 * Check if text direction resolution can be done. 21486 * 21487 * @return true if text direction resolution can be done otherwise return false. 21488 */ canResolveTextDirection()21489 public boolean canResolveTextDirection() { 21490 switch (getRawTextDirection()) { 21491 case TEXT_DIRECTION_INHERIT: 21492 if (mParent != null) { 21493 try { 21494 return mParent.canResolveTextDirection(); 21495 } catch (AbstractMethodError e) { 21496 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 21497 " does not fully implement ViewParent", e); 21498 } 21499 } 21500 return false; 21501 21502 default: 21503 return true; 21504 } 21505 } 21506 21507 /** 21508 * Reset resolved text direction. Text direction will be resolved during a call to 21509 * {@link #onMeasure(int, int)}. 21510 * 21511 * @hide 21512 */ resetResolvedTextDirection()21513 public void resetResolvedTextDirection() { 21514 // Reset any previous text direction resolution 21515 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK); 21516 // Set to default value 21517 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 21518 } 21519 21520 /** 21521 * @return true if text direction is inherited. 21522 * 21523 * @hide 21524 */ isTextDirectionInherited()21525 public boolean isTextDirectionInherited() { 21526 return (getRawTextDirection() == TEXT_DIRECTION_INHERIT); 21527 } 21528 21529 /** 21530 * @return true if text direction is resolved. 21531 */ isTextDirectionResolved()21532 public boolean isTextDirectionResolved() { 21533 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED; 21534 } 21535 21536 /** 21537 * Return the value specifying the text alignment or policy that was set with 21538 * {@link #setTextAlignment(int)}. 21539 * 21540 * @return the defined text alignment. It can be one of: 21541 * 21542 * {@link #TEXT_ALIGNMENT_INHERIT}, 21543 * {@link #TEXT_ALIGNMENT_GRAVITY}, 21544 * {@link #TEXT_ALIGNMENT_CENTER}, 21545 * {@link #TEXT_ALIGNMENT_TEXT_START}, 21546 * {@link #TEXT_ALIGNMENT_TEXT_END}, 21547 * {@link #TEXT_ALIGNMENT_VIEW_START}, 21548 * {@link #TEXT_ALIGNMENT_VIEW_END} 21549 * 21550 * @attr ref android.R.styleable#View_textAlignment 21551 * 21552 * @hide 21553 */ 21554 @ViewDebug.ExportedProperty(category = "text", mapping = { 21555 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"), 21556 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"), 21557 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"), 21558 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"), 21559 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"), 21560 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"), 21561 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END") 21562 }) 21563 @TextAlignment getRawTextAlignment()21564 public int getRawTextAlignment() { 21565 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT; 21566 } 21567 21568 /** 21569 * Set the text alignment. 21570 * 21571 * @param textAlignment The text alignment to set. Should be one of 21572 * 21573 * {@link #TEXT_ALIGNMENT_INHERIT}, 21574 * {@link #TEXT_ALIGNMENT_GRAVITY}, 21575 * {@link #TEXT_ALIGNMENT_CENTER}, 21576 * {@link #TEXT_ALIGNMENT_TEXT_START}, 21577 * {@link #TEXT_ALIGNMENT_TEXT_END}, 21578 * {@link #TEXT_ALIGNMENT_VIEW_START}, 21579 * {@link #TEXT_ALIGNMENT_VIEW_END} 21580 * 21581 * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution 21582 * proceeds up the parent chain of the view to get the value. If there is no parent, then it 21583 * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}. 21584 * 21585 * @attr ref android.R.styleable#View_textAlignment 21586 */ setTextAlignment(@extAlignment int textAlignment)21587 public void setTextAlignment(@TextAlignment int textAlignment) { 21588 if (textAlignment != getRawTextAlignment()) { 21589 // Reset the current and resolved text alignment 21590 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK; 21591 resetResolvedTextAlignment(); 21592 // Set the new text alignment 21593 mPrivateFlags2 |= 21594 ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK); 21595 // Do resolution 21596 resolveTextAlignment(); 21597 // Notify change 21598 onRtlPropertiesChanged(getLayoutDirection()); 21599 // Refresh 21600 requestLayout(); 21601 invalidate(true); 21602 } 21603 } 21604 21605 /** 21606 * Return the resolved text alignment. 21607 * 21608 * @return the resolved text alignment. Returns one of: 21609 * 21610 * {@link #TEXT_ALIGNMENT_GRAVITY}, 21611 * {@link #TEXT_ALIGNMENT_CENTER}, 21612 * {@link #TEXT_ALIGNMENT_TEXT_START}, 21613 * {@link #TEXT_ALIGNMENT_TEXT_END}, 21614 * {@link #TEXT_ALIGNMENT_VIEW_START}, 21615 * {@link #TEXT_ALIGNMENT_VIEW_END} 21616 * 21617 * @attr ref android.R.styleable#View_textAlignment 21618 */ 21619 @ViewDebug.ExportedProperty(category = "text", mapping = { 21620 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"), 21621 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"), 21622 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"), 21623 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"), 21624 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"), 21625 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"), 21626 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END") 21627 }) 21628 @TextAlignment getTextAlignment()21629 public int getTextAlignment() { 21630 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >> 21631 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT; 21632 } 21633 21634 /** 21635 * Resolve the text alignment. 21636 * 21637 * @return true if resolution has been done, false otherwise. 21638 * 21639 * @hide 21640 */ resolveTextAlignment()21641 public boolean resolveTextAlignment() { 21642 // Reset any previous text alignment resolution 21643 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK); 21644 21645 if (hasRtlSupport()) { 21646 // Set resolved text alignment flag depending on text alignment flag 21647 final int textAlignment = getRawTextAlignment(); 21648 switch (textAlignment) { 21649 case TEXT_ALIGNMENT_INHERIT: 21650 // Check if we can resolve the text alignment 21651 if (!canResolveTextAlignment()) { 21652 // We cannot do the resolution if there is no parent so use the default 21653 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 21654 // Resolution will need to happen again later 21655 return false; 21656 } 21657 21658 // Parent has not yet resolved, so we still return the default 21659 try { 21660 if (!mParent.isTextAlignmentResolved()) { 21661 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 21662 // Resolution will need to happen again later 21663 return false; 21664 } 21665 } catch (AbstractMethodError e) { 21666 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 21667 " does not fully implement ViewParent", e); 21668 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED | 21669 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 21670 return true; 21671 } 21672 21673 int parentResolvedTextAlignment; 21674 try { 21675 parentResolvedTextAlignment = mParent.getTextAlignment(); 21676 } catch (AbstractMethodError e) { 21677 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 21678 " does not fully implement ViewParent", e); 21679 parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY; 21680 } 21681 switch (parentResolvedTextAlignment) { 21682 case TEXT_ALIGNMENT_GRAVITY: 21683 case TEXT_ALIGNMENT_TEXT_START: 21684 case TEXT_ALIGNMENT_TEXT_END: 21685 case TEXT_ALIGNMENT_CENTER: 21686 case TEXT_ALIGNMENT_VIEW_START: 21687 case TEXT_ALIGNMENT_VIEW_END: 21688 // Resolved text alignment is the same as the parent resolved 21689 // text alignment 21690 mPrivateFlags2 |= 21691 (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT); 21692 break; 21693 default: 21694 // Use default resolved text alignment 21695 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 21696 } 21697 break; 21698 case TEXT_ALIGNMENT_GRAVITY: 21699 case TEXT_ALIGNMENT_TEXT_START: 21700 case TEXT_ALIGNMENT_TEXT_END: 21701 case TEXT_ALIGNMENT_CENTER: 21702 case TEXT_ALIGNMENT_VIEW_START: 21703 case TEXT_ALIGNMENT_VIEW_END: 21704 // Resolved text alignment is the same as text alignment 21705 mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT); 21706 break; 21707 default: 21708 // Use default resolved text alignment 21709 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 21710 } 21711 } else { 21712 // Use default resolved text alignment 21713 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 21714 } 21715 21716 // Set the resolved 21717 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED; 21718 return true; 21719 } 21720 21721 /** 21722 * Check if text alignment resolution can be done. 21723 * 21724 * @return true if text alignment resolution can be done otherwise return false. 21725 */ canResolveTextAlignment()21726 public boolean canResolveTextAlignment() { 21727 switch (getRawTextAlignment()) { 21728 case TEXT_DIRECTION_INHERIT: 21729 if (mParent != null) { 21730 try { 21731 return mParent.canResolveTextAlignment(); 21732 } catch (AbstractMethodError e) { 21733 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 21734 " does not fully implement ViewParent", e); 21735 } 21736 } 21737 return false; 21738 21739 default: 21740 return true; 21741 } 21742 } 21743 21744 /** 21745 * Reset resolved text alignment. Text alignment will be resolved during a call to 21746 * {@link #onMeasure(int, int)}. 21747 * 21748 * @hide 21749 */ resetResolvedTextAlignment()21750 public void resetResolvedTextAlignment() { 21751 // Reset any previous text alignment resolution 21752 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK); 21753 // Set to default 21754 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 21755 } 21756 21757 /** 21758 * @return true if text alignment is inherited. 21759 * 21760 * @hide 21761 */ isTextAlignmentInherited()21762 public boolean isTextAlignmentInherited() { 21763 return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT); 21764 } 21765 21766 /** 21767 * @return true if text alignment is resolved. 21768 */ isTextAlignmentResolved()21769 public boolean isTextAlignmentResolved() { 21770 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED; 21771 } 21772 21773 /** 21774 * Generate a value suitable for use in {@link #setId(int)}. 21775 * This value will not collide with ID values generated at build time by aapt for R.id. 21776 * 21777 * @return a generated ID value 21778 */ generateViewId()21779 public static int generateViewId() { 21780 for (;;) { 21781 final int result = sNextGeneratedId.get(); 21782 // aapt-generated IDs have the high byte nonzero; clamp to the range under that. 21783 int newValue = result + 1; 21784 if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0. 21785 if (sNextGeneratedId.compareAndSet(result, newValue)) { 21786 return result; 21787 } 21788 } 21789 } 21790 21791 /** 21792 * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions. 21793 * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and 21794 * a normal View or a ViewGroup with 21795 * {@link android.view.ViewGroup#isTransitionGroup()} true. 21796 * @hide 21797 */ captureTransitioningViews(List<View> transitioningViews)21798 public void captureTransitioningViews(List<View> transitioningViews) { 21799 if (getVisibility() == View.VISIBLE) { 21800 transitioningViews.add(this); 21801 } 21802 } 21803 21804 /** 21805 * Adds all Views that have {@link #getTransitionName()} non-null to namedElements. 21806 * @param namedElements Will contain all Views in the hierarchy having a transitionName. 21807 * @hide 21808 */ findNamedViews(Map<String, View> namedElements)21809 public void findNamedViews(Map<String, View> namedElements) { 21810 if (getVisibility() == VISIBLE || mGhostView != null) { 21811 String transitionName = getTransitionName(); 21812 if (transitionName != null) { 21813 namedElements.put(transitionName, this); 21814 } 21815 } 21816 } 21817 21818 /** 21819 * Returns the pointer icon for the motion event, or null if it doesn't specify the icon. 21820 * The default implementation does not care the location or event types, but some subclasses 21821 * may use it (such as WebViews). 21822 * @param event The MotionEvent from a mouse 21823 * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}. 21824 * This will be between 0 and {@link MotionEvent#getPointerCount()}. 21825 * @see PointerIcon 21826 */ onResolvePointerIcon(MotionEvent event, int pointerIndex)21827 public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) { 21828 final float x = event.getX(pointerIndex); 21829 final float y = event.getY(pointerIndex); 21830 if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) { 21831 return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW); 21832 } 21833 return mPointerIcon; 21834 } 21835 21836 /** 21837 * Set the pointer icon for the current view. 21838 * Passing {@code null} will restore the pointer icon to its default value. 21839 * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers. 21840 */ setPointerIcon(PointerIcon pointerIcon)21841 public void setPointerIcon(PointerIcon pointerIcon) { 21842 mPointerIcon = pointerIcon; 21843 if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) { 21844 return; 21845 } 21846 try { 21847 mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow); 21848 } catch (RemoteException e) { 21849 } 21850 } 21851 21852 /** 21853 * Gets the pointer icon for the current view. 21854 */ getPointerIcon()21855 public PointerIcon getPointerIcon() { 21856 return mPointerIcon; 21857 } 21858 21859 // 21860 // Properties 21861 // 21862 /** 21863 * A Property wrapper around the <code>alpha</code> functionality handled by the 21864 * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods. 21865 */ 21866 public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") { 21867 @Override 21868 public void setValue(View object, float value) { 21869 object.setAlpha(value); 21870 } 21871 21872 @Override 21873 public Float get(View object) { 21874 return object.getAlpha(); 21875 } 21876 }; 21877 21878 /** 21879 * A Property wrapper around the <code>translationX</code> functionality handled by the 21880 * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods. 21881 */ 21882 public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") { 21883 @Override 21884 public void setValue(View object, float value) { 21885 object.setTranslationX(value); 21886 } 21887 21888 @Override 21889 public Float get(View object) { 21890 return object.getTranslationX(); 21891 } 21892 }; 21893 21894 /** 21895 * A Property wrapper around the <code>translationY</code> functionality handled by the 21896 * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods. 21897 */ 21898 public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") { 21899 @Override 21900 public void setValue(View object, float value) { 21901 object.setTranslationY(value); 21902 } 21903 21904 @Override 21905 public Float get(View object) { 21906 return object.getTranslationY(); 21907 } 21908 }; 21909 21910 /** 21911 * A Property wrapper around the <code>translationZ</code> functionality handled by the 21912 * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods. 21913 */ 21914 public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") { 21915 @Override 21916 public void setValue(View object, float value) { 21917 object.setTranslationZ(value); 21918 } 21919 21920 @Override 21921 public Float get(View object) { 21922 return object.getTranslationZ(); 21923 } 21924 }; 21925 21926 /** 21927 * A Property wrapper around the <code>x</code> functionality handled by the 21928 * {@link View#setX(float)} and {@link View#getX()} methods. 21929 */ 21930 public static final Property<View, Float> X = new FloatProperty<View>("x") { 21931 @Override 21932 public void setValue(View object, float value) { 21933 object.setX(value); 21934 } 21935 21936 @Override 21937 public Float get(View object) { 21938 return object.getX(); 21939 } 21940 }; 21941 21942 /** 21943 * A Property wrapper around the <code>y</code> functionality handled by the 21944 * {@link View#setY(float)} and {@link View#getY()} methods. 21945 */ 21946 public static final Property<View, Float> Y = new FloatProperty<View>("y") { 21947 @Override 21948 public void setValue(View object, float value) { 21949 object.setY(value); 21950 } 21951 21952 @Override 21953 public Float get(View object) { 21954 return object.getY(); 21955 } 21956 }; 21957 21958 /** 21959 * A Property wrapper around the <code>z</code> functionality handled by the 21960 * {@link View#setZ(float)} and {@link View#getZ()} methods. 21961 */ 21962 public static final Property<View, Float> Z = new FloatProperty<View>("z") { 21963 @Override 21964 public void setValue(View object, float value) { 21965 object.setZ(value); 21966 } 21967 21968 @Override 21969 public Float get(View object) { 21970 return object.getZ(); 21971 } 21972 }; 21973 21974 /** 21975 * A Property wrapper around the <code>rotation</code> functionality handled by the 21976 * {@link View#setRotation(float)} and {@link View#getRotation()} methods. 21977 */ 21978 public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") { 21979 @Override 21980 public void setValue(View object, float value) { 21981 object.setRotation(value); 21982 } 21983 21984 @Override 21985 public Float get(View object) { 21986 return object.getRotation(); 21987 } 21988 }; 21989 21990 /** 21991 * A Property wrapper around the <code>rotationX</code> functionality handled by the 21992 * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods. 21993 */ 21994 public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") { 21995 @Override 21996 public void setValue(View object, float value) { 21997 object.setRotationX(value); 21998 } 21999 22000 @Override 22001 public Float get(View object) { 22002 return object.getRotationX(); 22003 } 22004 }; 22005 22006 /** 22007 * A Property wrapper around the <code>rotationY</code> functionality handled by the 22008 * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods. 22009 */ 22010 public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") { 22011 @Override 22012 public void setValue(View object, float value) { 22013 object.setRotationY(value); 22014 } 22015 22016 @Override 22017 public Float get(View object) { 22018 return object.getRotationY(); 22019 } 22020 }; 22021 22022 /** 22023 * A Property wrapper around the <code>scaleX</code> functionality handled by the 22024 * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods. 22025 */ 22026 public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") { 22027 @Override 22028 public void setValue(View object, float value) { 22029 object.setScaleX(value); 22030 } 22031 22032 @Override 22033 public Float get(View object) { 22034 return object.getScaleX(); 22035 } 22036 }; 22037 22038 /** 22039 * A Property wrapper around the <code>scaleY</code> functionality handled by the 22040 * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods. 22041 */ 22042 public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") { 22043 @Override 22044 public void setValue(View object, float value) { 22045 object.setScaleY(value); 22046 } 22047 22048 @Override 22049 public Float get(View object) { 22050 return object.getScaleY(); 22051 } 22052 }; 22053 22054 /** 22055 * A MeasureSpec encapsulates the layout requirements passed from parent to child. 22056 * Each MeasureSpec represents a requirement for either the width or the height. 22057 * A MeasureSpec is comprised of a size and a mode. There are three possible 22058 * modes: 22059 * <dl> 22060 * <dt>UNSPECIFIED</dt> 22061 * <dd> 22062 * The parent has not imposed any constraint on the child. It can be whatever size 22063 * it wants. 22064 * </dd> 22065 * 22066 * <dt>EXACTLY</dt> 22067 * <dd> 22068 * The parent has determined an exact size for the child. The child is going to be 22069 * given those bounds regardless of how big it wants to be. 22070 * </dd> 22071 * 22072 * <dt>AT_MOST</dt> 22073 * <dd> 22074 * The child can be as large as it wants up to the specified size. 22075 * </dd> 22076 * </dl> 22077 * 22078 * MeasureSpecs are implemented as ints to reduce object allocation. This class 22079 * is provided to pack and unpack the <size, mode> tuple into the int. 22080 */ 22081 public static class MeasureSpec { 22082 private static final int MODE_SHIFT = 30; 22083 private static final int MODE_MASK = 0x3 << MODE_SHIFT; 22084 22085 /** @hide */ 22086 @IntDef({UNSPECIFIED, EXACTLY, AT_MOST}) 22087 @Retention(RetentionPolicy.SOURCE) 22088 public @interface MeasureSpecMode {} 22089 22090 /** 22091 * Measure specification mode: The parent has not imposed any constraint 22092 * on the child. It can be whatever size it wants. 22093 */ 22094 public static final int UNSPECIFIED = 0 << MODE_SHIFT; 22095 22096 /** 22097 * Measure specification mode: The parent has determined an exact size 22098 * for the child. The child is going to be given those bounds regardless 22099 * of how big it wants to be. 22100 */ 22101 public static final int EXACTLY = 1 << MODE_SHIFT; 22102 22103 /** 22104 * Measure specification mode: The child can be as large as it wants up 22105 * to the specified size. 22106 */ 22107 public static final int AT_MOST = 2 << MODE_SHIFT; 22108 22109 /** 22110 * Creates a measure specification based on the supplied size and mode. 22111 * 22112 * The mode must always be one of the following: 22113 * <ul> 22114 * <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li> 22115 * <li>{@link android.view.View.MeasureSpec#EXACTLY}</li> 22116 * <li>{@link android.view.View.MeasureSpec#AT_MOST}</li> 22117 * </ul> 22118 * 22119 * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's 22120 * implementation was such that the order of arguments did not matter 22121 * and overflow in either value could impact the resulting MeasureSpec. 22122 * {@link android.widget.RelativeLayout} was affected by this bug. 22123 * Apps targeting API levels greater than 17 will get the fixed, more strict 22124 * behavior.</p> 22125 * 22126 * @param size the size of the measure specification 22127 * @param mode the mode of the measure specification 22128 * @return the measure specification based on size and mode 22129 */ makeMeasureSpec(@ntRangefrom = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size, @MeasureSpecMode int mode)22130 public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size, 22131 @MeasureSpecMode int mode) { 22132 if (sUseBrokenMakeMeasureSpec) { 22133 return size + mode; 22134 } else { 22135 return (size & ~MODE_MASK) | (mode & MODE_MASK); 22136 } 22137 } 22138 22139 /** 22140 * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED 22141 * will automatically get a size of 0. Older apps expect this. 22142 * 22143 * @hide internal use only for compatibility with system widgets and older apps 22144 */ makeSafeMeasureSpec(int size, int mode)22145 public static int makeSafeMeasureSpec(int size, int mode) { 22146 if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) { 22147 return 0; 22148 } 22149 return makeMeasureSpec(size, mode); 22150 } 22151 22152 /** 22153 * Extracts the mode from the supplied measure specification. 22154 * 22155 * @param measureSpec the measure specification to extract the mode from 22156 * @return {@link android.view.View.MeasureSpec#UNSPECIFIED}, 22157 * {@link android.view.View.MeasureSpec#AT_MOST} or 22158 * {@link android.view.View.MeasureSpec#EXACTLY} 22159 */ 22160 @MeasureSpecMode getMode(int measureSpec)22161 public static int getMode(int measureSpec) { 22162 //noinspection ResourceType 22163 return (measureSpec & MODE_MASK); 22164 } 22165 22166 /** 22167 * Extracts the size from the supplied measure specification. 22168 * 22169 * @param measureSpec the measure specification to extract the size from 22170 * @return the size in pixels defined in the supplied measure specification 22171 */ getSize(int measureSpec)22172 public static int getSize(int measureSpec) { 22173 return (measureSpec & ~MODE_MASK); 22174 } 22175 adjust(int measureSpec, int delta)22176 static int adjust(int measureSpec, int delta) { 22177 final int mode = getMode(measureSpec); 22178 int size = getSize(measureSpec); 22179 if (mode == UNSPECIFIED) { 22180 // No need to adjust size for UNSPECIFIED mode. 22181 return makeMeasureSpec(size, UNSPECIFIED); 22182 } 22183 size += delta; 22184 if (size < 0) { 22185 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size + 22186 ") spec: " + toString(measureSpec) + " delta: " + delta); 22187 size = 0; 22188 } 22189 return makeMeasureSpec(size, mode); 22190 } 22191 22192 /** 22193 * Returns a String representation of the specified measure 22194 * specification. 22195 * 22196 * @param measureSpec the measure specification to convert to a String 22197 * @return a String with the following format: "MeasureSpec: MODE SIZE" 22198 */ toString(int measureSpec)22199 public static String toString(int measureSpec) { 22200 int mode = getMode(measureSpec); 22201 int size = getSize(measureSpec); 22202 22203 StringBuilder sb = new StringBuilder("MeasureSpec: "); 22204 22205 if (mode == UNSPECIFIED) 22206 sb.append("UNSPECIFIED "); 22207 else if (mode == EXACTLY) 22208 sb.append("EXACTLY "); 22209 else if (mode == AT_MOST) 22210 sb.append("AT_MOST "); 22211 else 22212 sb.append(mode).append(" "); 22213 22214 sb.append(size); 22215 return sb.toString(); 22216 } 22217 } 22218 22219 private final class CheckForLongPress implements Runnable { 22220 private int mOriginalWindowAttachCount; 22221 private float mX; 22222 private float mY; 22223 22224 @Override run()22225 public void run() { 22226 if (isPressed() && (mParent != null) 22227 && mOriginalWindowAttachCount == mWindowAttachCount) { 22228 if (performLongClick(mX, mY)) { 22229 mHasPerformedLongPress = true; 22230 } 22231 } 22232 } 22233 setAnchor(float x, float y)22234 public void setAnchor(float x, float y) { 22235 mX = x; 22236 mY = y; 22237 } 22238 rememberWindowAttachCount()22239 public void rememberWindowAttachCount() { 22240 mOriginalWindowAttachCount = mWindowAttachCount; 22241 } 22242 } 22243 22244 private final class CheckForTap implements Runnable { 22245 public float x; 22246 public float y; 22247 22248 @Override run()22249 public void run() { 22250 mPrivateFlags &= ~PFLAG_PREPRESSED; 22251 setPressed(true, x, y); 22252 checkForLongClick(ViewConfiguration.getTapTimeout(), x, y); 22253 } 22254 } 22255 22256 private final class PerformClick implements Runnable { 22257 @Override run()22258 public void run() { 22259 performClick(); 22260 } 22261 } 22262 22263 /** 22264 * This method returns a ViewPropertyAnimator object, which can be used to animate 22265 * specific properties on this View. 22266 * 22267 * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View. 22268 */ animate()22269 public ViewPropertyAnimator animate() { 22270 if (mAnimator == null) { 22271 mAnimator = new ViewPropertyAnimator(this); 22272 } 22273 return mAnimator; 22274 } 22275 22276 /** 22277 * Sets the name of the View to be used to identify Views in Transitions. 22278 * Names should be unique in the View hierarchy. 22279 * 22280 * @param transitionName The name of the View to uniquely identify it for Transitions. 22281 */ setTransitionName(String transitionName)22282 public final void setTransitionName(String transitionName) { 22283 mTransitionName = transitionName; 22284 } 22285 22286 /** 22287 * Returns the name of the View to be used to identify Views in Transitions. 22288 * Names should be unique in the View hierarchy. 22289 * 22290 * <p>This returns null if the View has not been given a name.</p> 22291 * 22292 * @return The name used of the View to be used to identify Views in Transitions or null 22293 * if no name has been given. 22294 */ 22295 @ViewDebug.ExportedProperty getTransitionName()22296 public String getTransitionName() { 22297 return mTransitionName; 22298 } 22299 22300 /** 22301 * @hide 22302 */ requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId)22303 public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) { 22304 // Do nothing. 22305 } 22306 22307 /** 22308 * Interface definition for a callback to be invoked when a hardware key event is 22309 * dispatched to this view. The callback will be invoked before the key event is 22310 * given to the view. This is only useful for hardware keyboards; a software input 22311 * method has no obligation to trigger this listener. 22312 */ 22313 public interface OnKeyListener { 22314 /** 22315 * Called when a hardware key is dispatched to a view. This allows listeners to 22316 * get a chance to respond before the target view. 22317 * <p>Key presses in software keyboards will generally NOT trigger this method, 22318 * although some may elect to do so in some situations. Do not assume a 22319 * software input method has to be key-based; even if it is, it may use key presses 22320 * in a different way than you expect, so there is no way to reliably catch soft 22321 * input key presses. 22322 * 22323 * @param v The view the key has been dispatched to. 22324 * @param keyCode The code for the physical key that was pressed 22325 * @param event The KeyEvent object containing full information about 22326 * the event. 22327 * @return True if the listener has consumed the event, false otherwise. 22328 */ onKey(View v, int keyCode, KeyEvent event)22329 boolean onKey(View v, int keyCode, KeyEvent event); 22330 } 22331 22332 /** 22333 * Interface definition for a callback to be invoked when a touch event is 22334 * dispatched to this view. The callback will be invoked before the touch 22335 * event is given to the view. 22336 */ 22337 public interface OnTouchListener { 22338 /** 22339 * Called when a touch event is dispatched to a view. This allows listeners to 22340 * get a chance to respond before the target view. 22341 * 22342 * @param v The view the touch event has been dispatched to. 22343 * @param event The MotionEvent object containing full information about 22344 * the event. 22345 * @return True if the listener has consumed the event, false otherwise. 22346 */ onTouch(View v, MotionEvent event)22347 boolean onTouch(View v, MotionEvent event); 22348 } 22349 22350 /** 22351 * Interface definition for a callback to be invoked when a hover event is 22352 * dispatched to this view. The callback will be invoked before the hover 22353 * event is given to the view. 22354 */ 22355 public interface OnHoverListener { 22356 /** 22357 * Called when a hover event is dispatched to a view. This allows listeners to 22358 * get a chance to respond before the target view. 22359 * 22360 * @param v The view the hover event has been dispatched to. 22361 * @param event The MotionEvent object containing full information about 22362 * the event. 22363 * @return True if the listener has consumed the event, false otherwise. 22364 */ onHover(View v, MotionEvent event)22365 boolean onHover(View v, MotionEvent event); 22366 } 22367 22368 /** 22369 * Interface definition for a callback to be invoked when a generic motion event is 22370 * dispatched to this view. The callback will be invoked before the generic motion 22371 * event is given to the view. 22372 */ 22373 public interface OnGenericMotionListener { 22374 /** 22375 * Called when a generic motion event is dispatched to a view. This allows listeners to 22376 * get a chance to respond before the target view. 22377 * 22378 * @param v The view the generic motion event has been dispatched to. 22379 * @param event The MotionEvent object containing full information about 22380 * the event. 22381 * @return True if the listener has consumed the event, false otherwise. 22382 */ onGenericMotion(View v, MotionEvent event)22383 boolean onGenericMotion(View v, MotionEvent event); 22384 } 22385 22386 /** 22387 * Interface definition for a callback to be invoked when a view has been clicked and held. 22388 */ 22389 public interface OnLongClickListener { 22390 /** 22391 * Called when a view has been clicked and held. 22392 * 22393 * @param v The view that was clicked and held. 22394 * 22395 * @return true if the callback consumed the long click, false otherwise. 22396 */ onLongClick(View v)22397 boolean onLongClick(View v); 22398 } 22399 22400 /** 22401 * Interface definition for a callback to be invoked when a drag is being dispatched 22402 * to this view. The callback will be invoked before the hosting view's own 22403 * onDrag(event) method. If the listener wants to fall back to the hosting view's 22404 * onDrag(event) behavior, it should return 'false' from this callback. 22405 * 22406 * <div class="special reference"> 22407 * <h3>Developer Guides</h3> 22408 * <p>For a guide to implementing drag and drop features, read the 22409 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p> 22410 * </div> 22411 */ 22412 public interface OnDragListener { 22413 /** 22414 * Called when a drag event is dispatched to a view. This allows listeners 22415 * to get a chance to override base View behavior. 22416 * 22417 * @param v The View that received the drag event. 22418 * @param event The {@link android.view.DragEvent} object for the drag event. 22419 * @return {@code true} if the drag event was handled successfully, or {@code false} 22420 * if the drag event was not handled. Note that {@code false} will trigger the View 22421 * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler. 22422 */ onDrag(View v, DragEvent event)22423 boolean onDrag(View v, DragEvent event); 22424 } 22425 22426 /** 22427 * Interface definition for a callback to be invoked when the focus state of 22428 * a view changed. 22429 */ 22430 public interface OnFocusChangeListener { 22431 /** 22432 * Called when the focus state of a view has changed. 22433 * 22434 * @param v The view whose state has changed. 22435 * @param hasFocus The new focus state of v. 22436 */ onFocusChange(View v, boolean hasFocus)22437 void onFocusChange(View v, boolean hasFocus); 22438 } 22439 22440 /** 22441 * Interface definition for a callback to be invoked when a view is clicked. 22442 */ 22443 public interface OnClickListener { 22444 /** 22445 * Called when a view has been clicked. 22446 * 22447 * @param v The view that was clicked. 22448 */ onClick(View v)22449 void onClick(View v); 22450 } 22451 22452 /** 22453 * Interface definition for a callback to be invoked when a view is context clicked. 22454 */ 22455 public interface OnContextClickListener { 22456 /** 22457 * Called when a view is context clicked. 22458 * 22459 * @param v The view that has been context clicked. 22460 * @return true if the callback consumed the context click, false otherwise. 22461 */ onContextClick(View v)22462 boolean onContextClick(View v); 22463 } 22464 22465 /** 22466 * Interface definition for a callback to be invoked when the context menu 22467 * for this view is being built. 22468 */ 22469 public interface OnCreateContextMenuListener { 22470 /** 22471 * Called when the context menu for this view is being built. It is not 22472 * safe to hold onto the menu after this method returns. 22473 * 22474 * @param menu The context menu that is being built 22475 * @param v The view for which the context menu is being built 22476 * @param menuInfo Extra information about the item for which the 22477 * context menu should be shown. This information will vary 22478 * depending on the class of v. 22479 */ onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)22480 void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo); 22481 } 22482 22483 /** 22484 * Interface definition for a callback to be invoked when the status bar changes 22485 * visibility. This reports <strong>global</strong> changes to the system UI 22486 * state, not what the application is requesting. 22487 * 22488 * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener) 22489 */ 22490 public interface OnSystemUiVisibilityChangeListener { 22491 /** 22492 * Called when the status bar changes visibility because of a call to 22493 * {@link View#setSystemUiVisibility(int)}. 22494 * 22495 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE}, 22496 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}. 22497 * This tells you the <strong>global</strong> state of these UI visibility 22498 * flags, not what your app is currently applying. 22499 */ onSystemUiVisibilityChange(int visibility)22500 public void onSystemUiVisibilityChange(int visibility); 22501 } 22502 22503 /** 22504 * Interface definition for a callback to be invoked when this view is attached 22505 * or detached from its window. 22506 */ 22507 public interface OnAttachStateChangeListener { 22508 /** 22509 * Called when the view is attached to a window. 22510 * @param v The view that was attached 22511 */ onViewAttachedToWindow(View v)22512 public void onViewAttachedToWindow(View v); 22513 /** 22514 * Called when the view is detached from a window. 22515 * @param v The view that was detached 22516 */ onViewDetachedFromWindow(View v)22517 public void onViewDetachedFromWindow(View v); 22518 } 22519 22520 /** 22521 * Listener for applying window insets on a view in a custom way. 22522 * 22523 * <p>Apps may choose to implement this interface if they want to apply custom policy 22524 * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener 22525 * is set, its 22526 * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets} 22527 * method will be called instead of the View's own 22528 * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener 22529 * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply 22530 * the View's normal behavior as part of its own.</p> 22531 */ 22532 public interface OnApplyWindowInsetsListener { 22533 /** 22534 * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set} 22535 * on a View, this listener method will be called instead of the view's own 22536 * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. 22537 * 22538 * @param v The view applying window insets 22539 * @param insets The insets to apply 22540 * @return The insets supplied, minus any insets that were consumed 22541 */ onApplyWindowInsets(View v, WindowInsets insets)22542 public WindowInsets onApplyWindowInsets(View v, WindowInsets insets); 22543 } 22544 22545 private final class UnsetPressedState implements Runnable { 22546 @Override run()22547 public void run() { 22548 setPressed(false); 22549 } 22550 } 22551 22552 /** 22553 * Base class for derived classes that want to save and restore their own 22554 * state in {@link android.view.View#onSaveInstanceState()}. 22555 */ 22556 public static class BaseSavedState extends AbsSavedState { 22557 String mStartActivityRequestWhoSaved; 22558 22559 /** 22560 * Constructor used when reading from a parcel. Reads the state of the superclass. 22561 * 22562 * @param source parcel to read from 22563 */ BaseSavedState(Parcel source)22564 public BaseSavedState(Parcel source) { 22565 this(source, null); 22566 } 22567 22568 /** 22569 * Constructor used when reading from a parcel using a given class loader. 22570 * Reads the state of the superclass. 22571 * 22572 * @param source parcel to read from 22573 * @param loader ClassLoader to use for reading 22574 */ BaseSavedState(Parcel source, ClassLoader loader)22575 public BaseSavedState(Parcel source, ClassLoader loader) { 22576 super(source, loader); 22577 mStartActivityRequestWhoSaved = source.readString(); 22578 } 22579 22580 /** 22581 * Constructor called by derived classes when creating their SavedState objects 22582 * 22583 * @param superState The state of the superclass of this view 22584 */ BaseSavedState(Parcelable superState)22585 public BaseSavedState(Parcelable superState) { 22586 super(superState); 22587 } 22588 22589 @Override writeToParcel(Parcel out, int flags)22590 public void writeToParcel(Parcel out, int flags) { 22591 super.writeToParcel(out, flags); 22592 out.writeString(mStartActivityRequestWhoSaved); 22593 } 22594 22595 public static final Parcelable.Creator<BaseSavedState> CREATOR 22596 = new Parcelable.ClassLoaderCreator<BaseSavedState>() { 22597 @Override 22598 public BaseSavedState createFromParcel(Parcel in) { 22599 return new BaseSavedState(in); 22600 } 22601 22602 @Override 22603 public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) { 22604 return new BaseSavedState(in, loader); 22605 } 22606 22607 @Override 22608 public BaseSavedState[] newArray(int size) { 22609 return new BaseSavedState[size]; 22610 } 22611 }; 22612 } 22613 22614 /** 22615 * A set of information given to a view when it is attached to its parent 22616 * window. 22617 */ 22618 final static class AttachInfo { 22619 interface Callbacks { playSoundEffect(int effectId)22620 void playSoundEffect(int effectId); performHapticFeedback(int effectId, boolean always)22621 boolean performHapticFeedback(int effectId, boolean always); 22622 } 22623 22624 /** 22625 * InvalidateInfo is used to post invalidate(int, int, int, int) messages 22626 * to a Handler. This class contains the target (View) to invalidate and 22627 * the coordinates of the dirty rectangle. 22628 * 22629 * For performance purposes, this class also implements a pool of up to 22630 * POOL_LIMIT objects that get reused. This reduces memory allocations 22631 * whenever possible. 22632 */ 22633 static class InvalidateInfo { 22634 private static final int POOL_LIMIT = 10; 22635 22636 private static final SynchronizedPool<InvalidateInfo> sPool = 22637 new SynchronizedPool<InvalidateInfo>(POOL_LIMIT); 22638 22639 View target; 22640 22641 int left; 22642 int top; 22643 int right; 22644 int bottom; 22645 obtain()22646 public static InvalidateInfo obtain() { 22647 InvalidateInfo instance = sPool.acquire(); 22648 return (instance != null) ? instance : new InvalidateInfo(); 22649 } 22650 recycle()22651 public void recycle() { 22652 target = null; 22653 sPool.release(this); 22654 } 22655 } 22656 22657 final IWindowSession mSession; 22658 22659 final IWindow mWindow; 22660 22661 final IBinder mWindowToken; 22662 22663 final Display mDisplay; 22664 22665 final Callbacks mRootCallbacks; 22666 22667 IWindowId mIWindowId; 22668 WindowId mWindowId; 22669 22670 /** 22671 * The top view of the hierarchy. 22672 */ 22673 View mRootView; 22674 22675 IBinder mPanelParentWindowToken; 22676 22677 boolean mHardwareAccelerated; 22678 boolean mHardwareAccelerationRequested; 22679 ThreadedRenderer mHardwareRenderer; 22680 List<RenderNode> mPendingAnimatingRenderNodes; 22681 22682 /** 22683 * The state of the display to which the window is attached, as reported 22684 * by {@link Display#getState()}. Note that the display state constants 22685 * declared by {@link Display} do not exactly line up with the screen state 22686 * constants declared by {@link View} (there are more display states than 22687 * screen states). 22688 */ 22689 int mDisplayState = Display.STATE_UNKNOWN; 22690 22691 /** 22692 * Scale factor used by the compatibility mode 22693 */ 22694 float mApplicationScale; 22695 22696 /** 22697 * Indicates whether the application is in compatibility mode 22698 */ 22699 boolean mScalingRequired; 22700 22701 /** 22702 * Left position of this view's window 22703 */ 22704 int mWindowLeft; 22705 22706 /** 22707 * Top position of this view's window 22708 */ 22709 int mWindowTop; 22710 22711 /** 22712 * Indicates whether views need to use 32-bit drawing caches 22713 */ 22714 boolean mUse32BitDrawingCache; 22715 22716 /** 22717 * For windows that are full-screen but using insets to layout inside 22718 * of the screen areas, these are the current insets to appear inside 22719 * the overscan area of the display. 22720 */ 22721 final Rect mOverscanInsets = new Rect(); 22722 22723 /** 22724 * For windows that are full-screen but using insets to layout inside 22725 * of the screen decorations, these are the current insets for the 22726 * content of the window. 22727 */ 22728 final Rect mContentInsets = new Rect(); 22729 22730 /** 22731 * For windows that are full-screen but using insets to layout inside 22732 * of the screen decorations, these are the current insets for the 22733 * actual visible parts of the window. 22734 */ 22735 final Rect mVisibleInsets = new Rect(); 22736 22737 /** 22738 * For windows that are full-screen but using insets to layout inside 22739 * of the screen decorations, these are the current insets for the 22740 * stable system windows. 22741 */ 22742 final Rect mStableInsets = new Rect(); 22743 22744 /** 22745 * For windows that include areas that are not covered by real surface these are the outsets 22746 * for real surface. 22747 */ 22748 final Rect mOutsets = new Rect(); 22749 22750 /** 22751 * In multi-window we force show the navigation bar. Because we don't want that the surface 22752 * size changes in this mode, we instead have a flag whether the navigation bar size should 22753 * always be consumed, so the app is treated like there is no virtual navigation bar at all. 22754 */ 22755 boolean mAlwaysConsumeNavBar; 22756 22757 /** 22758 * The internal insets given by this window. This value is 22759 * supplied by the client (through 22760 * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will 22761 * be given to the window manager when changed to be used in laying 22762 * out windows behind it. 22763 */ 22764 final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets 22765 = new ViewTreeObserver.InternalInsetsInfo(); 22766 22767 /** 22768 * Set to true when mGivenInternalInsets is non-empty. 22769 */ 22770 boolean mHasNonEmptyGivenInternalInsets; 22771 22772 /** 22773 * All views in the window's hierarchy that serve as scroll containers, 22774 * used to determine if the window can be resized or must be panned 22775 * to adjust for a soft input area. 22776 */ 22777 final ArrayList<View> mScrollContainers = new ArrayList<View>(); 22778 22779 final KeyEvent.DispatcherState mKeyDispatchState 22780 = new KeyEvent.DispatcherState(); 22781 22782 /** 22783 * Indicates whether the view's window currently has the focus. 22784 */ 22785 boolean mHasWindowFocus; 22786 22787 /** 22788 * The current visibility of the window. 22789 */ 22790 int mWindowVisibility; 22791 22792 /** 22793 * Indicates the time at which drawing started to occur. 22794 */ 22795 long mDrawingTime; 22796 22797 /** 22798 * Indicates whether or not ignoring the DIRTY_MASK flags. 22799 */ 22800 boolean mIgnoreDirtyState; 22801 22802 /** 22803 * This flag tracks when the mIgnoreDirtyState flag is set during draw(), 22804 * to avoid clearing that flag prematurely. 22805 */ 22806 boolean mSetIgnoreDirtyState = false; 22807 22808 /** 22809 * Indicates whether the view's window is currently in touch mode. 22810 */ 22811 boolean mInTouchMode; 22812 22813 /** 22814 * Indicates whether the view has requested unbuffered input dispatching for the current 22815 * event stream. 22816 */ 22817 boolean mUnbufferedDispatchRequested; 22818 22819 /** 22820 * Indicates that ViewAncestor should trigger a global layout change 22821 * the next time it performs a traversal 22822 */ 22823 boolean mRecomputeGlobalAttributes; 22824 22825 /** 22826 * Always report new attributes at next traversal. 22827 */ 22828 boolean mForceReportNewAttributes; 22829 22830 /** 22831 * Set during a traveral if any views want to keep the screen on. 22832 */ 22833 boolean mKeepScreenOn; 22834 22835 /** 22836 * Set during a traveral if the light center needs to be updated. 22837 */ 22838 boolean mNeedsUpdateLightCenter; 22839 22840 /** 22841 * Bitwise-or of all of the values that views have passed to setSystemUiVisibility(). 22842 */ 22843 int mSystemUiVisibility; 22844 22845 /** 22846 * Hack to force certain system UI visibility flags to be cleared. 22847 */ 22848 int mDisabledSystemUiVisibility; 22849 22850 /** 22851 * Last global system UI visibility reported by the window manager. 22852 */ 22853 int mGlobalSystemUiVisibility; 22854 22855 /** 22856 * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener 22857 * attached. 22858 */ 22859 boolean mHasSystemUiListeners; 22860 22861 /** 22862 * Set if the window has requested to extend into the overscan region 22863 * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN. 22864 */ 22865 boolean mOverscanRequested; 22866 22867 /** 22868 * Set if the visibility of any views has changed. 22869 */ 22870 boolean mViewVisibilityChanged; 22871 22872 /** 22873 * Set to true if a view has been scrolled. 22874 */ 22875 boolean mViewScrollChanged; 22876 22877 /** 22878 * Set to true if high contrast mode enabled 22879 */ 22880 boolean mHighContrastText; 22881 22882 /** 22883 * Set to true if a pointer event is currently being handled. 22884 */ 22885 boolean mHandlingPointerEvent; 22886 22887 /** 22888 * Global to the view hierarchy used as a temporary for dealing with 22889 * x/y points in the transparent region computations. 22890 */ 22891 final int[] mTransparentLocation = new int[2]; 22892 22893 /** 22894 * Global to the view hierarchy used as a temporary for dealing with 22895 * x/y points in the ViewGroup.invalidateChild implementation. 22896 */ 22897 final int[] mInvalidateChildLocation = new int[2]; 22898 22899 /** 22900 * Global to the view hierarchy used as a temporary for dealng with 22901 * computing absolute on-screen location. 22902 */ 22903 final int[] mTmpLocation = new int[2]; 22904 22905 /** 22906 * Global to the view hierarchy used as a temporary for dealing with 22907 * x/y location when view is transformed. 22908 */ 22909 final float[] mTmpTransformLocation = new float[2]; 22910 22911 /** 22912 * The view tree observer used to dispatch global events like 22913 * layout, pre-draw, touch mode change, etc. 22914 */ 22915 final ViewTreeObserver mTreeObserver = new ViewTreeObserver(); 22916 22917 /** 22918 * A Canvas used by the view hierarchy to perform bitmap caching. 22919 */ 22920 Canvas mCanvas; 22921 22922 /** 22923 * The view root impl. 22924 */ 22925 final ViewRootImpl mViewRootImpl; 22926 22927 /** 22928 * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This 22929 * handler can be used to pump events in the UI events queue. 22930 */ 22931 final Handler mHandler; 22932 22933 /** 22934 * Temporary for use in computing invalidate rectangles while 22935 * calling up the hierarchy. 22936 */ 22937 final Rect mTmpInvalRect = new Rect(); 22938 22939 /** 22940 * Temporary for use in computing hit areas with transformed views 22941 */ 22942 final RectF mTmpTransformRect = new RectF(); 22943 22944 /** 22945 * Temporary for use in computing hit areas with transformed views 22946 */ 22947 final RectF mTmpTransformRect1 = new RectF(); 22948 22949 /** 22950 * Temporary list of rectanges. 22951 */ 22952 final List<RectF> mTmpRectList = new ArrayList<>(); 22953 22954 /** 22955 * Temporary for use in transforming invalidation rect 22956 */ 22957 final Matrix mTmpMatrix = new Matrix(); 22958 22959 /** 22960 * Temporary for use in transforming invalidation rect 22961 */ 22962 final Transformation mTmpTransformation = new Transformation(); 22963 22964 /** 22965 * Temporary for use in querying outlines from OutlineProviders 22966 */ 22967 final Outline mTmpOutline = new Outline(); 22968 22969 /** 22970 * Temporary list for use in collecting focusable descendents of a view. 22971 */ 22972 final ArrayList<View> mTempArrayList = new ArrayList<View>(24); 22973 22974 /** 22975 * The id of the window for accessibility purposes. 22976 */ 22977 int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID; 22978 22979 /** 22980 * Flags related to accessibility processing. 22981 * 22982 * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS 22983 * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS 22984 */ 22985 int mAccessibilityFetchFlags; 22986 22987 /** 22988 * The drawable for highlighting accessibility focus. 22989 */ 22990 Drawable mAccessibilityFocusDrawable; 22991 22992 /** 22993 * Show where the margins, bounds and layout bounds are for each view. 22994 */ 22995 boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false); 22996 22997 /** 22998 * Point used to compute visible regions. 22999 */ 23000 final Point mPoint = new Point(); 23001 23002 /** 23003 * Used to track which View originated a requestLayout() call, used when 23004 * requestLayout() is called during layout. 23005 */ 23006 View mViewRequestingLayout; 23007 23008 /** 23009 * Used to track views that need (at least) a partial relayout at their current size 23010 * during the next traversal. 23011 */ 23012 List<View> mPartialLayoutViews = new ArrayList<>(); 23013 23014 /** 23015 * Swapped with mPartialLayoutViews during layout to avoid concurrent 23016 * modification. Lazily assigned during ViewRootImpl layout. 23017 */ 23018 List<View> mEmptyPartialLayoutViews; 23019 23020 /** 23021 * Used to track the identity of the current drag operation. 23022 */ 23023 IBinder mDragToken; 23024 23025 /** 23026 * The drag shadow surface for the current drag operation. 23027 */ 23028 public Surface mDragSurface; 23029 23030 /** 23031 * Creates a new set of attachment information with the specified 23032 * events handler and thread. 23033 * 23034 * @param handler the events handler the view must use 23035 */ AttachInfo(IWindowSession session, IWindow window, Display display, ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer)23036 AttachInfo(IWindowSession session, IWindow window, Display display, 23037 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) { 23038 mSession = session; 23039 mWindow = window; 23040 mWindowToken = window.asBinder(); 23041 mDisplay = display; 23042 mViewRootImpl = viewRootImpl; 23043 mHandler = handler; 23044 mRootCallbacks = effectPlayer; 23045 } 23046 } 23047 23048 /** 23049 * <p>ScrollabilityCache holds various fields used by a View when scrolling 23050 * is supported. This avoids keeping too many unused fields in most 23051 * instances of View.</p> 23052 */ 23053 private static class ScrollabilityCache implements Runnable { 23054 23055 /** 23056 * Scrollbars are not visible 23057 */ 23058 public static final int OFF = 0; 23059 23060 /** 23061 * Scrollbars are visible 23062 */ 23063 public static final int ON = 1; 23064 23065 /** 23066 * Scrollbars are fading away 23067 */ 23068 public static final int FADING = 2; 23069 23070 public boolean fadeScrollBars; 23071 23072 public int fadingEdgeLength; 23073 public int scrollBarDefaultDelayBeforeFade; 23074 public int scrollBarFadeDuration; 23075 23076 public int scrollBarSize; 23077 public ScrollBarDrawable scrollBar; 23078 public float[] interpolatorValues; 23079 public View host; 23080 23081 public final Paint paint; 23082 public final Matrix matrix; 23083 public Shader shader; 23084 23085 public final Interpolator scrollBarInterpolator = new Interpolator(1, 2); 23086 23087 private static final float[] OPAQUE = { 255 }; 23088 private static final float[] TRANSPARENT = { 0.0f }; 23089 23090 /** 23091 * When fading should start. This time moves into the future every time 23092 * a new scroll happens. Measured based on SystemClock.uptimeMillis() 23093 */ 23094 public long fadeStartTime; 23095 23096 23097 /** 23098 * The current state of the scrollbars: ON, OFF, or FADING 23099 */ 23100 public int state = OFF; 23101 23102 private int mLastColor; 23103 23104 public final Rect mScrollBarBounds = new Rect(); 23105 23106 public static final int NOT_DRAGGING = 0; 23107 public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1; 23108 public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2; 23109 public int mScrollBarDraggingState = NOT_DRAGGING; 23110 23111 public float mScrollBarDraggingPos = 0; 23112 ScrollabilityCache(ViewConfiguration configuration, View host)23113 public ScrollabilityCache(ViewConfiguration configuration, View host) { 23114 fadingEdgeLength = configuration.getScaledFadingEdgeLength(); 23115 scrollBarSize = configuration.getScaledScrollBarSize(); 23116 scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay(); 23117 scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration(); 23118 23119 paint = new Paint(); 23120 matrix = new Matrix(); 23121 // use use a height of 1, and then wack the matrix each time we 23122 // actually use it. 23123 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP); 23124 paint.setShader(shader); 23125 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); 23126 23127 this.host = host; 23128 } 23129 setFadeColor(int color)23130 public void setFadeColor(int color) { 23131 if (color != mLastColor) { 23132 mLastColor = color; 23133 23134 if (color != 0) { 23135 shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000, 23136 color & 0x00FFFFFF, Shader.TileMode.CLAMP); 23137 paint.setShader(shader); 23138 // Restore the default transfer mode (src_over) 23139 paint.setXfermode(null); 23140 } else { 23141 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP); 23142 paint.setShader(shader); 23143 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); 23144 } 23145 } 23146 } 23147 run()23148 public void run() { 23149 long now = AnimationUtils.currentAnimationTimeMillis(); 23150 if (now >= fadeStartTime) { 23151 23152 // the animation fades the scrollbars out by changing 23153 // the opacity (alpha) from fully opaque to fully 23154 // transparent 23155 int nextFrame = (int) now; 23156 int framesCount = 0; 23157 23158 Interpolator interpolator = scrollBarInterpolator; 23159 23160 // Start opaque 23161 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE); 23162 23163 // End transparent 23164 nextFrame += scrollBarFadeDuration; 23165 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT); 23166 23167 state = FADING; 23168 23169 // Kick off the fade animation 23170 host.invalidate(true); 23171 } 23172 } 23173 } 23174 23175 /** 23176 * Resuable callback for sending 23177 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event. 23178 */ 23179 private class SendViewScrolledAccessibilityEvent implements Runnable { 23180 public volatile boolean mIsPending; 23181 run()23182 public void run() { 23183 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED); 23184 mIsPending = false; 23185 } 23186 } 23187 23188 /** 23189 * <p> 23190 * This class represents a delegate that can be registered in a {@link View} 23191 * to enhance accessibility support via composition rather via inheritance. 23192 * It is specifically targeted to widget developers that extend basic View 23193 * classes i.e. classes in package android.view, that would like their 23194 * applications to be backwards compatible. 23195 * </p> 23196 * <div class="special reference"> 23197 * <h3>Developer Guides</h3> 23198 * <p>For more information about making applications accessible, read the 23199 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a> 23200 * developer guide.</p> 23201 * </div> 23202 * <p> 23203 * A scenario in which a developer would like to use an accessibility delegate 23204 * is overriding a method introduced in a later API version then the minimal API 23205 * version supported by the application. For example, the method 23206 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available 23207 * in API version 4 when the accessibility APIs were first introduced. If a 23208 * developer would like his application to run on API version 4 devices (assuming 23209 * all other APIs used by the application are version 4 or lower) and take advantage 23210 * of this method, instead of overriding the method which would break the application's 23211 * backwards compatibility, he can override the corresponding method in this 23212 * delegate and register the delegate in the target View if the API version of 23213 * the system is high enough i.e. the API version is same or higher to the API 23214 * version that introduced 23215 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}. 23216 * </p> 23217 * <p> 23218 * Here is an example implementation: 23219 * </p> 23220 * <code><pre><p> 23221 * if (Build.VERSION.SDK_INT >= 14) { 23222 * // If the API version is equal of higher than the version in 23223 * // which onInitializeAccessibilityNodeInfo was introduced we 23224 * // register a delegate with a customized implementation. 23225 * View view = findViewById(R.id.view_id); 23226 * view.setAccessibilityDelegate(new AccessibilityDelegate() { 23227 * public void onInitializeAccessibilityNodeInfo(View host, 23228 * AccessibilityNodeInfo info) { 23229 * // Let the default implementation populate the info. 23230 * super.onInitializeAccessibilityNodeInfo(host, info); 23231 * // Set some other information. 23232 * info.setEnabled(host.isEnabled()); 23233 * } 23234 * }); 23235 * } 23236 * </code></pre></p> 23237 * <p> 23238 * This delegate contains methods that correspond to the accessibility methods 23239 * in View. If a delegate has been specified the implementation in View hands 23240 * off handling to the corresponding method in this delegate. The default 23241 * implementation the delegate methods behaves exactly as the corresponding 23242 * method in View for the case of no accessibility delegate been set. Hence, 23243 * to customize the behavior of a View method, clients can override only the 23244 * corresponding delegate method without altering the behavior of the rest 23245 * accessibility related methods of the host view. 23246 * </p> 23247 * <p> 23248 * <strong>Note:</strong> On platform versions prior to 23249 * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on 23250 * views in the {@code android.widget.*} package are called <i>before</i> 23251 * host methods. This prevents certain properties such as class name from 23252 * being modified by overriding 23253 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}, 23254 * as any changes will be overwritten by the host class. 23255 * <p> 23256 * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate 23257 * methods are called <i>after</i> host methods, which all properties to be 23258 * modified without being overwritten by the host class. 23259 */ 23260 public static class AccessibilityDelegate { 23261 23262 /** 23263 * Sends an accessibility event of the given type. If accessibility is not 23264 * enabled this method has no effect. 23265 * <p> 23266 * The default implementation behaves as {@link View#sendAccessibilityEvent(int) 23267 * View#sendAccessibilityEvent(int)} for the case of no accessibility delegate 23268 * been set. 23269 * </p> 23270 * 23271 * @param host The View hosting the delegate. 23272 * @param eventType The type of the event to send. 23273 * 23274 * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int) 23275 */ sendAccessibilityEvent(View host, int eventType)23276 public void sendAccessibilityEvent(View host, int eventType) { 23277 host.sendAccessibilityEventInternal(eventType); 23278 } 23279 23280 /** 23281 * Performs the specified accessibility action on the view. For 23282 * possible accessibility actions look at {@link AccessibilityNodeInfo}. 23283 * <p> 23284 * The default implementation behaves as 23285 * {@link View#performAccessibilityAction(int, Bundle) 23286 * View#performAccessibilityAction(int, Bundle)} for the case of 23287 * no accessibility delegate been set. 23288 * </p> 23289 * 23290 * @param action The action to perform. 23291 * @return Whether the action was performed. 23292 * 23293 * @see View#performAccessibilityAction(int, Bundle) 23294 * View#performAccessibilityAction(int, Bundle) 23295 */ performAccessibilityAction(View host, int action, Bundle args)23296 public boolean performAccessibilityAction(View host, int action, Bundle args) { 23297 return host.performAccessibilityActionInternal(action, args); 23298 } 23299 23300 /** 23301 * Sends an accessibility event. This method behaves exactly as 23302 * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an 23303 * empty {@link AccessibilityEvent} and does not perform a check whether 23304 * accessibility is enabled. 23305 * <p> 23306 * The default implementation behaves as 23307 * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent) 23308 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for 23309 * the case of no accessibility delegate been set. 23310 * </p> 23311 * 23312 * @param host The View hosting the delegate. 23313 * @param event The event to send. 23314 * 23315 * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent) 23316 * View#sendAccessibilityEventUnchecked(AccessibilityEvent) 23317 */ sendAccessibilityEventUnchecked(View host, AccessibilityEvent event)23318 public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) { 23319 host.sendAccessibilityEventUncheckedInternal(event); 23320 } 23321 23322 /** 23323 * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then 23324 * to its children for adding their text content to the event. 23325 * <p> 23326 * The default implementation behaves as 23327 * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 23328 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for 23329 * the case of no accessibility delegate been set. 23330 * </p> 23331 * 23332 * @param host The View hosting the delegate. 23333 * @param event The event. 23334 * @return True if the event population was completed. 23335 * 23336 * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 23337 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 23338 */ dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event)23339 public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) { 23340 return host.dispatchPopulateAccessibilityEventInternal(event); 23341 } 23342 23343 /** 23344 * Gives a chance to the host View to populate the accessibility event with its 23345 * text content. 23346 * <p> 23347 * The default implementation behaves as 23348 * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent) 23349 * View#onPopulateAccessibilityEvent(AccessibilityEvent)} for 23350 * the case of no accessibility delegate been set. 23351 * </p> 23352 * 23353 * @param host The View hosting the delegate. 23354 * @param event The accessibility event which to populate. 23355 * 23356 * @see View#onPopulateAccessibilityEvent(AccessibilityEvent) 23357 * View#onPopulateAccessibilityEvent(AccessibilityEvent) 23358 */ onPopulateAccessibilityEvent(View host, AccessibilityEvent event)23359 public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) { 23360 host.onPopulateAccessibilityEventInternal(event); 23361 } 23362 23363 /** 23364 * Initializes an {@link AccessibilityEvent} with information about the 23365 * the host View which is the event source. 23366 * <p> 23367 * The default implementation behaves as 23368 * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent) 23369 * View#onInitializeAccessibilityEvent(AccessibilityEvent)} for 23370 * the case of no accessibility delegate been set. 23371 * </p> 23372 * 23373 * @param host The View hosting the delegate. 23374 * @param event The event to initialize. 23375 * 23376 * @see View#onInitializeAccessibilityEvent(AccessibilityEvent) 23377 * View#onInitializeAccessibilityEvent(AccessibilityEvent) 23378 */ onInitializeAccessibilityEvent(View host, AccessibilityEvent event)23379 public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { 23380 host.onInitializeAccessibilityEventInternal(event); 23381 } 23382 23383 /** 23384 * Initializes an {@link AccessibilityNodeInfo} with information about the host view. 23385 * <p> 23386 * The default implementation behaves as 23387 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 23388 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for 23389 * the case of no accessibility delegate been set. 23390 * </p> 23391 * 23392 * @param host The View hosting the delegate. 23393 * @param info The instance to initialize. 23394 * 23395 * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 23396 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 23397 */ onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info)23398 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { 23399 host.onInitializeAccessibilityNodeInfoInternal(info); 23400 } 23401 23402 /** 23403 * Called when a child of the host View has requested sending an 23404 * {@link AccessibilityEvent} and gives an opportunity to the parent (the host) 23405 * to augment the event. 23406 * <p> 23407 * The default implementation behaves as 23408 * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent) 23409 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for 23410 * the case of no accessibility delegate been set. 23411 * </p> 23412 * 23413 * @param host The View hosting the delegate. 23414 * @param child The child which requests sending the event. 23415 * @param event The event to be sent. 23416 * @return True if the event should be sent 23417 * 23418 * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent) 23419 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent) 23420 */ onRequestSendAccessibilityEvent(ViewGroup host, View child, AccessibilityEvent event)23421 public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child, 23422 AccessibilityEvent event) { 23423 return host.onRequestSendAccessibilityEventInternal(child, event); 23424 } 23425 23426 /** 23427 * Gets the provider for managing a virtual view hierarchy rooted at this View 23428 * and reported to {@link android.accessibilityservice.AccessibilityService}s 23429 * that explore the window content. 23430 * <p> 23431 * The default implementation behaves as 23432 * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for 23433 * the case of no accessibility delegate been set. 23434 * </p> 23435 * 23436 * @return The provider. 23437 * 23438 * @see AccessibilityNodeProvider 23439 */ getAccessibilityNodeProvider(View host)23440 public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) { 23441 return null; 23442 } 23443 23444 /** 23445 * Returns an {@link AccessibilityNodeInfo} representing the host view from the 23446 * point of view of an {@link android.accessibilityservice.AccessibilityService}. 23447 * This method is responsible for obtaining an accessibility node info from a 23448 * pool of reusable instances and calling 23449 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host 23450 * view to initialize the former. 23451 * <p> 23452 * <strong>Note:</strong> The client is responsible for recycling the obtained 23453 * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object 23454 * creation. 23455 * </p> 23456 * <p> 23457 * The default implementation behaves as 23458 * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for 23459 * the case of no accessibility delegate been set. 23460 * </p> 23461 * @return A populated {@link AccessibilityNodeInfo}. 23462 * 23463 * @see AccessibilityNodeInfo 23464 * 23465 * @hide 23466 */ createAccessibilityNodeInfo(View host)23467 public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) { 23468 return host.createAccessibilityNodeInfoInternal(); 23469 } 23470 } 23471 23472 private class MatchIdPredicate implements Predicate<View> { 23473 public int mId; 23474 23475 @Override apply(View view)23476 public boolean apply(View view) { 23477 return (view.mID == mId); 23478 } 23479 } 23480 23481 private class MatchLabelForPredicate implements Predicate<View> { 23482 private int mLabeledId; 23483 23484 @Override apply(View view)23485 public boolean apply(View view) { 23486 return (view.mLabelForId == mLabeledId); 23487 } 23488 } 23489 23490 private class SendViewStateChangedAccessibilityEvent implements Runnable { 23491 private int mChangeTypes = 0; 23492 private boolean mPosted; 23493 private boolean mPostedWithDelay; 23494 private long mLastEventTimeMillis; 23495 23496 @Override run()23497 public void run() { 23498 mPosted = false; 23499 mPostedWithDelay = false; 23500 mLastEventTimeMillis = SystemClock.uptimeMillis(); 23501 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 23502 final AccessibilityEvent event = AccessibilityEvent.obtain(); 23503 event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); 23504 event.setContentChangeTypes(mChangeTypes); 23505 sendAccessibilityEventUnchecked(event); 23506 } 23507 mChangeTypes = 0; 23508 } 23509 runOrPost(int changeType)23510 public void runOrPost(int changeType) { 23511 mChangeTypes |= changeType; 23512 23513 // If this is a live region or the child of a live region, collect 23514 // all events from this frame and send them on the next frame. 23515 if (inLiveRegion()) { 23516 // If we're already posted with a delay, remove that. 23517 if (mPostedWithDelay) { 23518 removeCallbacks(this); 23519 mPostedWithDelay = false; 23520 } 23521 // Only post if we're not already posted. 23522 if (!mPosted) { 23523 post(this); 23524 mPosted = true; 23525 } 23526 return; 23527 } 23528 23529 if (mPosted) { 23530 return; 23531 } 23532 23533 final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis; 23534 final long minEventIntevalMillis = 23535 ViewConfiguration.getSendRecurringAccessibilityEventsInterval(); 23536 if (timeSinceLastMillis >= minEventIntevalMillis) { 23537 removeCallbacks(this); 23538 run(); 23539 } else { 23540 postDelayed(this, minEventIntevalMillis - timeSinceLastMillis); 23541 mPostedWithDelay = true; 23542 } 23543 } 23544 } 23545 inLiveRegion()23546 private boolean inLiveRegion() { 23547 if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) { 23548 return true; 23549 } 23550 23551 ViewParent parent = getParent(); 23552 while (parent instanceof View) { 23553 if (((View) parent).getAccessibilityLiveRegion() 23554 != View.ACCESSIBILITY_LIVE_REGION_NONE) { 23555 return true; 23556 } 23557 parent = parent.getParent(); 23558 } 23559 23560 return false; 23561 } 23562 23563 /** 23564 * Dump all private flags in readable format, useful for documentation and 23565 * sanity checking. 23566 */ dumpFlags()23567 private static void dumpFlags() { 23568 final HashMap<String, String> found = Maps.newHashMap(); 23569 try { 23570 for (Field field : View.class.getDeclaredFields()) { 23571 final int modifiers = field.getModifiers(); 23572 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) { 23573 if (field.getType().equals(int.class)) { 23574 final int value = field.getInt(null); 23575 dumpFlag(found, field.getName(), value); 23576 } else if (field.getType().equals(int[].class)) { 23577 final int[] values = (int[]) field.get(null); 23578 for (int i = 0; i < values.length; i++) { 23579 dumpFlag(found, field.getName() + "[" + i + "]", values[i]); 23580 } 23581 } 23582 } 23583 } 23584 } catch (IllegalAccessException e) { 23585 throw new RuntimeException(e); 23586 } 23587 23588 final ArrayList<String> keys = Lists.newArrayList(); 23589 keys.addAll(found.keySet()); 23590 Collections.sort(keys); 23591 for (String key : keys) { 23592 Log.d(VIEW_LOG_TAG, found.get(key)); 23593 } 23594 } 23595 dumpFlag(HashMap<String, String> found, String name, int value)23596 private static void dumpFlag(HashMap<String, String> found, String name, int value) { 23597 // Sort flags by prefix, then by bits, always keeping unique keys 23598 final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' '); 23599 final int prefix = name.indexOf('_'); 23600 final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name; 23601 final String output = bits + " " + name; 23602 found.put(key, output); 23603 } 23604 23605 /** {@hide} */ encode(@onNull ViewHierarchyEncoder stream)23606 public void encode(@NonNull ViewHierarchyEncoder stream) { 23607 stream.beginObject(this); 23608 encodeProperties(stream); 23609 stream.endObject(); 23610 } 23611 23612 /** {@hide} */ 23613 @CallSuper encodeProperties(@onNull ViewHierarchyEncoder stream)23614 protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) { 23615 Object resolveId = ViewDebug.resolveId(getContext(), mID); 23616 if (resolveId instanceof String) { 23617 stream.addProperty("id", (String) resolveId); 23618 } else { 23619 stream.addProperty("id", mID); 23620 } 23621 23622 stream.addProperty("misc:transformation.alpha", 23623 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0); 23624 stream.addProperty("misc:transitionName", getTransitionName()); 23625 23626 // layout 23627 stream.addProperty("layout:left", mLeft); 23628 stream.addProperty("layout:right", mRight); 23629 stream.addProperty("layout:top", mTop); 23630 stream.addProperty("layout:bottom", mBottom); 23631 stream.addProperty("layout:width", getWidth()); 23632 stream.addProperty("layout:height", getHeight()); 23633 stream.addProperty("layout:layoutDirection", getLayoutDirection()); 23634 stream.addProperty("layout:layoutRtl", isLayoutRtl()); 23635 stream.addProperty("layout:hasTransientState", hasTransientState()); 23636 stream.addProperty("layout:baseline", getBaseline()); 23637 23638 // layout params 23639 ViewGroup.LayoutParams layoutParams = getLayoutParams(); 23640 if (layoutParams != null) { 23641 stream.addPropertyKey("layoutParams"); 23642 layoutParams.encode(stream); 23643 } 23644 23645 // scrolling 23646 stream.addProperty("scrolling:scrollX", mScrollX); 23647 stream.addProperty("scrolling:scrollY", mScrollY); 23648 23649 // padding 23650 stream.addProperty("padding:paddingLeft", mPaddingLeft); 23651 stream.addProperty("padding:paddingRight", mPaddingRight); 23652 stream.addProperty("padding:paddingTop", mPaddingTop); 23653 stream.addProperty("padding:paddingBottom", mPaddingBottom); 23654 stream.addProperty("padding:userPaddingRight", mUserPaddingRight); 23655 stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft); 23656 stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom); 23657 stream.addProperty("padding:userPaddingStart", mUserPaddingStart); 23658 stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd); 23659 23660 // measurement 23661 stream.addProperty("measurement:minHeight", mMinHeight); 23662 stream.addProperty("measurement:minWidth", mMinWidth); 23663 stream.addProperty("measurement:measuredWidth", mMeasuredWidth); 23664 stream.addProperty("measurement:measuredHeight", mMeasuredHeight); 23665 23666 // drawing 23667 stream.addProperty("drawing:elevation", getElevation()); 23668 stream.addProperty("drawing:translationX", getTranslationX()); 23669 stream.addProperty("drawing:translationY", getTranslationY()); 23670 stream.addProperty("drawing:translationZ", getTranslationZ()); 23671 stream.addProperty("drawing:rotation", getRotation()); 23672 stream.addProperty("drawing:rotationX", getRotationX()); 23673 stream.addProperty("drawing:rotationY", getRotationY()); 23674 stream.addProperty("drawing:scaleX", getScaleX()); 23675 stream.addProperty("drawing:scaleY", getScaleY()); 23676 stream.addProperty("drawing:pivotX", getPivotX()); 23677 stream.addProperty("drawing:pivotY", getPivotY()); 23678 stream.addProperty("drawing:opaque", isOpaque()); 23679 stream.addProperty("drawing:alpha", getAlpha()); 23680 stream.addProperty("drawing:transitionAlpha", getTransitionAlpha()); 23681 stream.addProperty("drawing:shadow", hasShadow()); 23682 stream.addProperty("drawing:solidColor", getSolidColor()); 23683 stream.addProperty("drawing:layerType", mLayerType); 23684 stream.addProperty("drawing:willNotDraw", willNotDraw()); 23685 stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated()); 23686 stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing()); 23687 stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled()); 23688 stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering()); 23689 23690 // focus 23691 stream.addProperty("focus:hasFocus", hasFocus()); 23692 stream.addProperty("focus:isFocused", isFocused()); 23693 stream.addProperty("focus:isFocusable", isFocusable()); 23694 stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode()); 23695 23696 stream.addProperty("misc:clickable", isClickable()); 23697 stream.addProperty("misc:pressed", isPressed()); 23698 stream.addProperty("misc:selected", isSelected()); 23699 stream.addProperty("misc:touchMode", isInTouchMode()); 23700 stream.addProperty("misc:hovered", isHovered()); 23701 stream.addProperty("misc:activated", isActivated()); 23702 23703 stream.addProperty("misc:visibility", getVisibility()); 23704 stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows()); 23705 stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured()); 23706 23707 stream.addProperty("misc:enabled", isEnabled()); 23708 stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled()); 23709 stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled()); 23710 23711 // theme attributes 23712 Resources.Theme theme = getContext().getTheme(); 23713 if (theme != null) { 23714 stream.addPropertyKey("theme"); 23715 theme.encode(stream); 23716 } 23717 23718 // view attribute information 23719 int n = mAttributes != null ? mAttributes.length : 0; 23720 stream.addProperty("meta:__attrCount__", n/2); 23721 for (int i = 0; i < n; i += 2) { 23722 stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]); 23723 } 23724 23725 stream.addProperty("misc:scrollBarStyle", getScrollBarStyle()); 23726 23727 // text 23728 stream.addProperty("text:textDirection", getTextDirection()); 23729 stream.addProperty("text:textAlignment", getTextAlignment()); 23730 23731 // accessibility 23732 CharSequence contentDescription = getContentDescription(); 23733 stream.addProperty("accessibility:contentDescription", 23734 contentDescription == null ? "" : contentDescription.toString()); 23735 stream.addProperty("accessibility:labelFor", getLabelFor()); 23736 stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility()); 23737 } 23738 } 23739